portpy.photon package

Subpackages

Submodules

portpy.photon.beam module

class portpy.photon.beam.Beams(beams_dict)[source]

Bases: object

A class representing beams_dict.

  • Attributes

    :param beams_dict: beams_dict dictionary that contains information about the beams_dict in the format of
    dict: {
               'ID': list(int),
               'gantry_angle': list(float),
               'collimator_angle': list(float) }
              }
    
    :type beams_dict: dict
    
  • Methods

    :get_gantry_angle(beam_id: Optional(int, List[int]):
        Get gantry angle in degrees
    :get_collimator_angle(beam_id):
        Get collimator angle in degrees
    
create_beamlet_idx_2d_grid(beam_id: int) → ndarray[source]

Create 2d grid for the beamlets where each element is 2.5mm*2.5mm for the given beam id from x and y coordinates of beamlets.

Parameters:

beam_id – beam_id for the beam

Returns:

2d grid of beamlets for the beam

get_all_beam_ids() → List[int][source]
get_beamlet_height() → float[source]
Returns:

beamlet height in the original beam

get_beamlet_idx_2dgrid(beam_id: int) → ndarray[source]
Parameters:

beam_id – beam_id for the beam

Returns:

2d grid of beamlets in 2.5*2.5 resolution

get_beamlet_width() → float[source]
Returns:

beamlet width in the original beam

get_collimator_angle(beam_id: Union[int, List[int]]) → Union[int, List[int]][source]

Get collimator angle

Parameters:

beam_id – beam_id for the beam

Returns:

collimator angle for the beam_id

get_gantry_angle(beam_id: Union[int, List[int]]) → Union[int, List[int]][source]

Get gantry angle

Parameters:

beam_id – beam_id for the beam

Returns:

gantry angle for the beam_id

static get_original_map(beam_map)[source]
preprocess_beams()[source]
static sort_beamlets(b_map)[source]

portpy.photon.clinical_criteria module

class portpy.photon.clinical_criteria.ClinicalCriteria(clinical_criteria)[source]

Bases: object

A class representing clinical criteria.

  • Attributes

    :param clinical_criteria_dict: dictionary containing metadata about clinical criteria
    
    :Example
            dict = {"disease_site": "Lung",
            "protocol_name": "Lung_Default_2Gy_30Fr",
            "pres_per_fraction_gy": 2,
            "num_of_fractions": 30,
            "criteria": [
                {
                  "name": "max_dose",
                  "parameters": {
                    "struct": "GTV"
                  }}
    
  • Methods ::

    :add_criterion(criterion:str, parameters:dict, constraints:dict) :modify_criterion(criterion:str, parameters:dict, constraints:dict)

add_criterion(criterion: str, parameters: dict, constraints: dict) → None[source]

Add criterion to the clinical criteria dictionary

Parameters:
  • criterion – criterion name. e.g. max_dose

  • parameters – parameters dictionary e.g. parameters = {‘struct’:’PTV’}

  • constraints – constraints dictionary e.g. constraints = {‘limit_dose_gy’:66, ‘goal_dose_gy’:60}

Returns:

add the criteria to clinical criteria dictionary

static create_criterion(criterion: str, parameters: dict, constraints: dict)[source]

Create criterion and return list

Parameters:
  • criterion – criterion name. e.g. max_dose

  • parameters – parameters dictionary e.g. parameters = {‘struct’:’PTV’}

  • constraints – constraints dictionary e.g. constraints = {‘limit_dose_gy’:66, ‘goal_dose_gy’:60}

Returns:

add the criteria to clinical criteria dictionary

get_criteria(name: Optional[str] = None) → List[dict][source]

Returns all the clinical criteria :return:

modify_criterion(criterion: str, parameters: dict, constraints: dict) → None[source]

Modify the criterion in clinical criteria dictionary

Parameters:
  • criterion – criterion name. e.g. max_dose

  • parameters – parameters dictionary e.g. parameters = {‘struct’:’PTV’}

  • constraints – constraints dictionary e.g. constraints = {‘limit_dose_gy’:66, ‘goal_dose_gy’:60}

Returns:

add the criteria to clinical criteria dictionary

portpy.photon.cvxpy_prob module

class portpy.photon.cvxpy_prob.CvxPyProb(my_plan: Plan, inf_matrix: InfluenceMatrix = None, max_constraints: List[dict] = None, mean_constraints: List[dict] = None, **opt_params)[source]

Bases: object

Optimization class for creating cvxpy problem object

add_boo(num_beams: int)[source]

Select optimal beams from set of beams using MIP :param num_beams: number of beams to be selected :return:

add_constraints(constraints: list)[source]

Add constraint to the problem :param constraints: list of constraints :return:

add_dvh(dvh_constraint: list)[source]
add_max(struct: str, dose_gy: float)[source]

Add max constraints to the problem :param struct: structure name :param dose_gy: dose in Gy per fraction. :return:

add_mean(struct: str, dose_gy: float)[source]

Add mean constraints to the problem :param struct: structure name :param dose_gy: dose in Gy per fraction. :return:

add_objective(obj)[source]

Add objective function to the problem :param obj: objective function expression using cvxpy :return:

add_overdose_quad(struct: str, dose_gy: float, weight: float = 10000)[source]

Add quadratic loss for the overdose voxels of the structure :param struct: structure name :param dose_gy: dose in Gy per fraction. :param weight: penalty/weight in the objective for overdose :return:

add_quad(struct: Optional[str] = None, voxels: Optional[ndarray] = None, weight: float = 10, voxels_weight: Optional[ndarray] = None)[source]

Add quadratic objective to the optimization problem :param struct: structure for which quadratic loss is added to objective function :param voxels: Default to None. If set, quadratic loss will be added for the given voxels :param weight: Default to 10. penalty in the objective function for the given structure. :param voxels_weight: weight for each voxel in the objective function :return:

add_smoothness_quad(weight: int = 10, smoothness_X_weight: int = 0.6, smoothness_Y_weight: int = 0.4)[source]

Add quadratic smoothness to the optimization problem :param weight: smoothness weight :param smoothness_X_weight: weight in X direction of MLC (parallel to MLC) :param smoothness_Y_weight: weight in Y direction of MLC (perpendicular to MLC) :return:

add_underdose_quad(struct: str, dose_gy: float, weight: float = 100000)[source]

Add quadratic loss for the underdose voxels of the structure :param struct: structure name :param dose_gy: dose in Gy per fraction. :param weight: penalty/weight in the objective for underdose :return:

static get_smoothness_matrix(beamReq: List[dict])[source]

Create smoothness matrix so that adjacent beamlets are smooth out to reduce MU

Parameters:

beamReq – beamlets dictionary from the object of influence matrix class

Returns:

tuple(Qx, Qy) where Qx: first matrix have values 1 and -1 for neighbouring beamlets in X direction Qy: second matrix with values 1 and -1 for neighbouring beamlets in Y direction

Example:

Qx = [[1 -1 0 0 0 0]

[0 0 1 -1 0 0] [0 0 0 0 1 -1]]

get_sol() → dict[source]

Return optimal solution and influence matrix associated with it in the form of dictionary :return:

static matching_keys(dictionary, search_string)[source]
solve(*args, **kwargs)[source]

portpy.photon.evaluation module

class portpy.photon.evaluation.Evaluation[source]

Bases: object

static get_dose(sol: dict, struct: str, volume_per: float, dose_1d: Optional[ndarray] = None, weight_flag: bool = True) → float[source]

Get dose_1d at volume percentage

Parameters:
  • sol – solution dictionary

  • dose_1d – dose_1d in 1d

  • struct – structure name for which to get the dose_1d

  • volume_per – query the dose_1d at percentage volume

  • weight_flag – for non uniform voxels weight flag always True

Returns:

dose_1d at volume_percentage

Example:

>>> Evaluation.get_dose(sol=sol, struct='PTV', volume_per=90)
static get_dvh(sol: dict, struct: str, dose_1d: Optional[ndarray] = None, weight_flag: bool = True)[source]

Get dvh for the structure

Parameters:
  • sol – optimal solution dictionary

  • dose_1d – dose_1d which is not in solution dictionary

  • struct – structure name

  • weight_flag – for non uniform voxels weight flag always True

Returns:

x, y –> dvh for the structure

Example:

>>> Evaluation.get_dvh(sol=sol, struct='PTV')
static get_max_dose(sol: dict, struct: str, dose_1d=None) → float[source]

Get maximum dose_1d for the structure

Parameters:
  • sol – optimal solution dictionary

  • dose_1d – dose_1d which is not in solution dictionary

  • struct – structure name

Returns:

maximum dose_1d for the structure

static get_mean_dose(sol: dict, struct: str, dose_1d=None) → ndarray[source]

Get mean dose_1d for the structure

Parameters:
  • sol – optimal solution dictionary

  • dose_1d – dose_1d which is not in solution dictionary

  • struct – structure name

Returns:

mean dose_1d for the structure

static get_volume(sol: dict, struct: str, dose_value_gy: float, dose_1d: Optional[ndarray] = None, weight_flag: bool = True) → float[source]

Get volume at dose_1d value in Gy

Parameters:
  • sol – solution dictionary

  • dose_1d – dose_1d in 1d

  • struct – structure name for which to get the dose_1d

  • dose_value_gy – query the volume at dose_value

  • weight_flag – for non uniform voxels weight flag always True

Returns:

dose_1d at volume_percentage

Example:

>>> Evaluation.get_volume(sol=sol, struct='PTV', dose_value_gy=60)

portpy.photon.influence_matrix module

class portpy.photon.influence_matrix.InfluenceMatrix(plan_obj, beamlet_width_mm: float = 2.5, beamlet_height_mm: float = 2.5, opt_vox_xyz_res_mm: Optional[List[float]] = None, is_full: bool = False, structure: str = 'PTV')[source]

Bases: object

class of influence matrix

  • Attributes

    :param beamlet_width_mm: The width of each beamlet in millimeters. Default is 2.5. Must be a multiple of 2.5.
    :param beamlet_height_mm: The height of each beamlet in millimeters. Default is 2.5. Must be a multiple of 2.5.
    :param down_sample_xyz: A list of integers representing the downsampling factors for the x, y, and z axes. When set to None, the original optimization voxel resolution will be used.
    :param structure: The target structure for creating the beamlets in the influence matrix. Default is 'PTV'.
    :param opt_voxels_dict: A dictionary containing the voxels that were used in the optimization process.
    :param beamlets_dict: A dictionary containing the information about beamlets used in the plan.
    :param opt_beamlets_PTV_margin_mm: A float value representing the margin_mm around the PTV that was used in creating beamlets
    :param A: influence matrix that is generated by the get_influence_matrix() method.
    :param dose_3d: 3D dose_1d distribution. It is saved as attribute once the method dose_1d_to_3d() is called
            so that it doesnt have to be computed again
    
  • Methods ::
    :dose_1d_to_3d(sol)

    Convert dose_1d from 1d to 3d and return dose_1d in 3d

    :dose_3d_to_1d(dose_3d)

    Convert dose_1d from 3d to 1d voxels and return dose_1d in 1d

    :fluence_2d_to_1d(fluence_2d)

    Create vector of intensities from 2d fluence maps

    :fluence_1d_to_2d(fluence_1d)

    From vector of intensities create 2d fluence maps

create_BEV_mask_from_contours(plan_obj, ind: int, structure: str = 'PTV', margin_mm: Optional[float] = None) → ndarray[source]

Since beams object contain projection of structure contours on BEV, this function helps to create mask from those contours on BEV

Parameters:
  • plan_obj – object of class Plan

  • ind – indices of the beam in beamlet dictionary

  • structure – structure for which contours to be converted to mask

  • margin_mm – expand the contours in mm. defaults to None. If it is not none, it will expand the contours

Returns:

create_beamlet_idx_2d_grid(ind: int) → ndarray[source]

Create beamlet idx in 2d grid of 2.5mm resolution. i.e. each element in matrix is 2.5mm*2.5mm

Parameters:

ind – indices for the beam in beamlets dictionary

Returns:

dose_1d_to_3d(sol: Optional[dict] = None, dose_1d: Optional[array] = None) → ndarray[source]

Create 3d dose_1d from dose_1d in 1d voxels. 3d array have same resolution as CT

Parameters:
  • sol – solution dictionary from optimization

  • dose_1d – dose_1d in 1d. Optional

Returns:

dose_1d in 3d

dose_3d_to_1d(dose_3d: ndarray) → array[source]

Get dose_1d in 1d voxels for the given influence matrix from 3d dose_1d

Parameters:

dose_3d – 3d dose_1d

Returns:

dose_1d in 1d voxel indices

down_sample_2d_grid(ind: int, beamlet_width_mm: float = 5.0, beamlet_height_mm: float = 5.0) → ndarray[source]

create down sample beam map based on beamlet width and height

Parameters:
  • ind – indices for the beam in beamlets dictionary

  • beamlet_width_mm –

  • beamlet_height_mm –

Returns:

down sampled 2d grid

down_sample_voxels(down_sample_xyz: Optional[List[int]] = None)[source]

This method creates new ct to dose_1d voxel map array based on down sampled voxels. It also outputs map between down sampled voxel indices to original voxel indices for down sampling influence matrix :param down_sample_xyz: It down-samples optimization voxels as factor of ct resolution

e.g. down_sample_xyz = [5,5,1]. It will down-sample optimization voxels with 5 * ct res. in x direction, 5 * ct res. in y direction and 1*ct res. in z direction. defaults to None. When None it will use the original optimization voxel resolution.

Returns:

voxel map(list containing map between down-sampled indices to original indices), voxel weight (weighted average of voxels in down sample and ct to dose_1d voxel map

fluence_1d_to_2d(fluence_1d: Optional[array] = None, sol: Optional[dict] = None) → List[ndarray][source]

Create 2d fluence maps from vector of intensities.

Parameters:
  • fluence_1d – 2d fluence as vector

  • sol – solution from optimization

Returns:

2d fluence as a list for each beam

fluence_2d_to_1d(fluence_2d: List[ndarray]) → array[source]

Create vector of intensities from 2d fluence maps

Parameters:

fluence_2d – 2d fluence as list of nd array with same length as number of beams_dict

Returns:

fluence in 1d for beamlet indices

get_all_beam_ids() → List[int][source]
get_beamlet_info(col_number: int) → dict[source]
Parameters:

col_number – col number/beamlet number in influence matrix

Returns:

dictionary containing information about the beamlet

get_bev_2d_grid(beam_id: Optional[Union[int, List[int]]] = None, ind: Optional[int] = None, finest_grid: bool = False) → Union[ndarray, List[ndarray]][source]

get BEV in 2d grid in original resolution where beamlet index is the column number in influence matrix

Parameters:

ind – idx of the beam in beamlets_dict.

It can be int or List[int]. If int, ndarray is return, If List[int], list[ndarray] is returned :param beam_id: beam_id of the beam. It can be int or List[int]. If int, ndarray is return, If List[int], list[ndarray] is returned :param finest_grid:Default to False. If set to true, it will return 2d grid in finest resolution :return: ndarray/List[ndarray]

get_influence_matrix(plan, is_full=False)[source]

Load influence matrix based on the beamlets and voxels. :param plan: object of class Plan :param is_full: get full or sparse matrix. Default to True. :return: full or sparse matrix

get_opt_voxels_idx(structure_name: str) → ndarray[source]

Get voxel index for structure :param structure_name: name of the structure in plan :return: voxel indexes for the structure

get_opt_voxels_size(structure_name: str)[source]
Parameters:

structure_name – name of the structure in plan

Returns:

voxel size for the structure

get_orig_res_2d_grid(ind: int) → ndarray[source]

Create beam map 2d grid in the original resolution where each element in matrix is the size of respective beamlet.

Parameters:

ind – indices for the beam in beamlets dictionary

Returns:

beam map 2d grid in original resolution

get_voxel_info(row_number)[source]
plot_fluence_2d(beam_id: int, optimal_fluence_2d: Optional[List[ndarray]] = None, sol: Optional[dict] = None, **options) → None[source]

Displays fluence in 2d for the given beam_id

Parameters:
  • optimal_fluence_2d –

  • beam_id – beam_id of the beam

  • sol – solution dictionary after optimization

Returns:

2d optimal fluence plot

Example:

>>> Visualization.plot_fluence_2d(beam_id=0, sol=sol)
plot_fluence_3d(beam_id: int, optimal_fluence_2d: Optional[List[ndarray]] = None, sol: Optional[dict] = None, **options) → None[source]

Displays fluence in 3d for the given beam_id

Parameters:
  • optimal_fluence_2d –

  • sol – solution after optimization

  • beam_id – beam_id of the beam

Returns:

3d optimal fluence plot

Example:

>>> Visualization.plot_fluence_3d(beam_id=0, sol=sol)
pre_process_voxels(plan_obj)[source]

Updates opt_voxels_dict based upon ct to dose_1d voxel map

Parameters:

plan_obj – object if class Plan

Returns:

preprocess_beams(plan_obj, structure='PTV', remove_corner_beamlets=False)[source]

Preprocess beams to create beamlets dictionary based on beamlet resolution.

Parameters:
  • plan_obj – object of class Plan

  • structure – projection of the structure on BEV for which beamlets to be considered for creating influence matrix. defaults to PTV

  • remove_corner_beamlets – If remove corner beamlet is true, it will remove the corner beamlets during down sampling.

Returns:

beamlets for processing influence matrix

set_opt_voxel_idx(plan_obj, structure_name: str) → None[source]

Set opt_voxel_idx for the structure based upon ct_dose_voxel_map and structure mask

Parameters:
  • plan_obj – object of class Plan

  • structure_name – structure name

Returns:

set the voxel idx in opt_voxels_dict for the structure

static sort_beamlets(b_map)[source]
static surface_plot(matrix, ax=None, figsize=(8, 8), **kwargs)[source]

portpy.photon.optimization module

class portpy.photon.optimization.Optimization[source]

Bases: object

Optimization class for optimizing and creating the plan

static create_rinds(my_plan, inf_matrix=None, size_mm: Optional[list] = None, base_structure='PTV')[source]
Parameters:
  • inf_matrix – object of class inf_matrix

  • my_plan – object of class Plan

  • size_mm – size in mm. default size = [5,5,20,30, inf]. It means rind_0 is 5mm after PTV, rind_2 is 5 mm after rind_1, and so on..

  • base_structure – structure from which rinds should be created

Returns:

save rinds to plan object

static get_smoothness_matrix(beamReq: List[dict])[source]

Create smoothness matrix so that adjacent beamlets are smooth out to reduce MU

Parameters:

beamReq – beamlets dictionary from the object of influence matrix class

Returns:

tuple(Qx, Qy) where Qx: first matrix have values 1 and -1 for neighbouring beamlets in X direction Qy: second matrix with values 1 and -1 for neighbouring beamlets in Y direction

Example:

Qx = [[1 -1 0 0 0 0]

[0 0 1 -1 0 0] [0 0 0 0 1 -1]]

static matching_keys(dictionary, search_string)[source]
static run_IMRT_fluence_map_CVXPy(my_plan: Plan, inf_matrix: InfluenceMatrix = None, solver: str = 'MOSEK', verbose: bool = True, cvxpy_options: dict = None, **opt_params) → dict[source]

It runs optimization to create optimal plan based upon clinical criteria

Parameters:
  • my_plan – object of class Plan

  • inf_matrix – object of class InfluenceMatrix

  • solver – default solver ‘MOSEK’. check cvxpy website for available solvers

  • verbose – Default to True. If set to False, it will not print the solver iterations.

  • cvxpy_options – cvxpy and the solver settings

  • opt_params – optimization parameters for modifying parameters of problem statement

Returns:

returns the solution dictionary in format of: dict: {

’optimal_intensity’: list(float), ‘dose_1d’: list(float), ‘inf_matrix’: Pointer to object of InfluenceMatrix }

}

Example:

>>> Optimization.run_IMRT_fluence_map_CVXPy(my_plan=my_plan,inf_matrix=inf_matrix,solver='MOSEK')
static run_IMRT_fluence_map_CVXPy_BOO_benchmark(my_plan, inf_matrix=None, num_beams: int = 7, solver: str = 'MOSEK', verbose: bool = True, cvxpy_options: Optional[dict] = None, **opt_params)[source]

Creates MIP problem for selecting optimal beam angles

Parameters:
  • inf_matrix – object of class InfluenceMatrix

  • my_plan – object of class Plan

  • solver – default solver ‘MOSEK’. check cvxpy website for available solvers.

  • num_beams – Default to 7. Numbers of beams to be selected from the pool of beams

  • verbose – Default to True. If set to False, it will not print the solver iterations.

  • cvxpy_options – cvxpy and the solver settings

Returns:

save optimal solution to plan object called opt_sol

static run_IMRT_fluence_map_CVXPy_dvh_benchmark(my_plan: Plan, inf_matrix: InfluenceMatrix = None, dvh_criteria: List[dict] = None, solver: str = 'MOSEK', verbose: bool = True, cvxpy_options: dict = None, **opt_params) → dict[source]

Add dvh constraints and solve the optimization for getting ground truth solution

Parameters:
  • inf_matrix – object of class InfluenceMatrix

  • my_plan – object of class Plan

  • solver – default solver ‘MOSEK’. check cvxpy website for available solvers

  • dvh_criteria – dvh criteria to be met in optimization. Defaults to None.

If None, it will optimize for all the dvh criteria in clinical criteria. :param verbose: Default to True. If set to False, it will not print the solver iterations. :param cvxpy_options: cvxpy and the solver settings :return: save optimal solution to plan object called opt_sol

static set_rinds_opt_voxel_idx(plan_obj: Plan, inf_matrix: InfluenceMatrix)[source]
Parameters:
  • plan_obj – object of class plan

  • inf_matrix – object of class influence matrix

Returns:

set rinds index based upon the influence matrix

portpy.photon.plan module

class portpy.photon.plan.Plan(patient_id: str, data_dir: Optional[str] = None, beam_ids: Optional[List[int]] = None, opt_beamlets_PTV_margin_mm: int = 3, load_inf_matrix_full: bool = False, protocol_name='Lung_Default_2Gy_30Fr', protocol_type='Default')[source]

Bases: object

A class representing a plan

  • Attributes

    :param opt_beamlets_PTV_margin_mm: For each beam, we often only include the beamlets that are within
        few millimetres of the projection of the PTV (tumor) into that beam. It is because the beamlets
        that are far from the PTV projection mainly deliver radiation to the healthy tissues not PTV. Default is 3mm
    :type opt_beamlets_PTV_margin_mm: int
    :param beams_dict: an object of class Beams that contains information about the beams_dict used in the treatment plan.
    :type beams: object
    :param structures: an object of class Structures that contains information about the structures present in the patient's CT scan.
    :type structures: object
    :param inf_matrix: object of class Influence matrix
    :type inf_matrix: object
    :param clinial_criteria: an object of class ClincialCriteria that contains information about the goals and constraints of the treatment plan
    :type inf_matrix: object
    :param ct: dictionary containing ct metadata. It includes metadata about important ct parameters like resolution, ct in HU etc.
    :type ct: dict
    
  • Methods

    :create_inf_matrix(beamlet_width_mm, beamlet_height_mm,
                      down_sample_xyz):
        Create object of Influence Matrix class
    :get_prescription():
        Return prescription for the plan
    :get_num_of_fractions()
        Return number of fractions for the plan
    
add_rinds(rind_params: List[dict], inf_matrix=None)[source]

Example for rind_params = [{‘rind_name’: ‘RIND_0’, ‘ref_structure’: ‘PTV, ‘margin_start_mm’: 2, ‘margin_end_mm’: 10, ‘max_dose_gy’: 10}]

Parameters:
  • rind_params – rind_params as dictionary

  • inf_matrix – object of class inf_matrix

Returns:

save rinds to plan object

create_inf_matrix(beamlet_width_mm: float = 2.5, beamlet_height_mm: float = 2.5, opt_vox_xyz_res_mm: Optional[List[float]] = None, structure: str = 'PTV', is_full: bool = False) → InfluenceMatrix[source]

Create a influence matrix object for Influence Matrix class

Parameters:
  • is_full – Defaults to False. If True, it will create full influence matrix

  • beamlet_width_mm – beamlet width in mm. It should be multiple of 2.5, defaults to 2.5

  • beamlet_height_mm – beamlet height in mm. It should be multiple of 2.5, defaults to 2.5

  • structure – target structure for creating BEV beamlets, defaults to ‘PTV’

  • opt_vox_xyz_res_mm – It down-samples optimization voxels as factor of ct resolution e.g. opt_vox_xyz_res = [5*ct.res.x,5*ct.res.y,1*ct.res.z]. It will down-sample optimization voxels with 5 * ct res. in x direction, 5 * ct res. in y direction and 1*ct res. in z direction. defaults to None. When None it will use the original optimization voxel resolution.

Returns:

object of influence Matrix class

Example:

>>> inf_matrix = my_plan.create_inf_matrix(beamlet_width_mm=5, beamlet_height_mm=5, opt_vox_xyz_res_mm=[5,5,1], structure=structure)
get_ct_res_xyz_mm() → List[float][source]
Returns:

number of fractions to be delivered

get_disease_site() → float[source]
Returns:

number of fractions to be delivered

get_num_of_fractions() → float[source]
Returns:

number of fractions to be delivered

static get_plan_beams(beam_ids: Optional[List[int]] = None, meta_data: Optional[dict] = None) → dict[source]

Create and return a copy of meta_data with only including the requested beams_dict (beam_ids)

Parameters:
  • beam_ids – the indices of the beams_dict to be included. If None, the planner’s beams_dict are used

  • meta_data – the dictionary including all the beams_dict

Returns:

returns the meta_data dictionary only including the requested beams_dict in format of: dict: {

’structures’: {‘name’: list(str), ‘volume_cc’: list(float), } ‘opt_voxels’: {‘_ct_voxel_resolution_xyz_mm’: list(float),}

}

get_prescription() → float[source]
Returns:

prescription in Gy

static load_optimal_sol(sol_name: str, path: Optional[str] = None) → dict[source]

Load optimal solution dictionary got from optimization

Parameters:
  • sol_name – name of the optimal solution to be loaded.

  • path – if path is set, plan object will be load from path directory else current directory

Returns:

load solution

Example:

>>> sol = Plan.load_optimal_sol(sol_name='sol', path=r'path/for/loading_sol')
static load_plan(plan_name: Optional[str] = None, path: Optional[str] = None)[source]

Load pickle file of the plan object.

Parameters:
  • plan_name – plan_name of the object of class Plan. It None, it will try to look for plan name called ‘my_plan’

  • path – if path is set, plan object will be load from path directory else current project directory

Returns:

load pickled object of class Plan

Example:

>>> Plan.load_plan(plan_name='my_plan', path=r"path/for/loading_plan")
plot_dvh(sol, dose_1d=None, structs=None, dose_scale: typing_extensions.Literal[Absolute(Gy), Relative(%)] = 'Absolute(Gy)', volume_scale: typing_extensions.Literal[Absolute(cc), Relative(%)] = 'Relative(%)', **options)[source]

Create dvh plot for the selected structures

Parameters:
  • sol – optimal sol dictionary

  • dose_1d – dose_1d in 1d voxels

  • structs – structures to be included in dvh plot

  • volume_scale – volume scale on y-axis. Default= Absolute(cc). e.g. volume_scale = “Absolute(cc)” or volume_scale = “Relative(%)”

  • dose_scale – dose_1d scale on x axis. Default= Absolute(Gy). e.g. dose_scale = “Absolute(Gy)” or dose_scale = “Relative(%)”

Keyword Arguments:
  • (str) (style) – line style for dvh curve. default “solid”. can be “dotted”, “dash-dotted”.

  • (int) (width) – width of line. Default 2

  • colors(list) – list of colors

  • legend_font_size – Set legend_font_size. default 10

  • figsize – Set figure size for the plot. Default figure size (12,8)

  • create_fig – Create a new figure. Default True. If False, append to the previous figure

  • title – Title for the figure

  • filename – Name of the file to save the figure in current directory

  • show – Show the figure. Default is True. If false, next plot can be append to it

  • norm_flag – Use to normalize the plan. Default is False.

  • norm_volume – Use to set normalization volume. default is 90 percentile.

Returns:

dvh plot for the selected structures

static plot_fluence_2d(beam_id: int, sol: Optional[dict] = None, **options)[source]

plot fluence in 2d for beam_id :param beam_id: beam_id of the beam :param sol: solution dictionary after optimization :return: 2d optimal fluence plot

static plot_fluence_3d(beam_id: int, sol: Optional[dict] = None, **options)[source]

plot fluence in 3d for beam_id :param sol: solution after optimization :param beam_id: beam_id of the beam :return: 3d optimal fluence plot

run_IMRT_fluence_map_CVXPy(inf_matrix: Optional[InfluenceMatrix] = None, solver='MOSEK')[source]
save_nrrd(sol: dict, data_dir: Optional[str] = None)[source]

save nrrd in the path directory else save in patient data directory :param sol: optimal solution dict :param data_dir: save nrrd images of ct, dose_1d and structure set in path directory :return: save nrrd images in path

static save_optimal_sol(sol: dict, sol_name: str, path: Optional[str] = None) → None[source]

Save the optimal solution dictionary from optimization

Parameters:
  • sol – optimal solution dictionary

  • sol_name – name of the optimal solution saved

  • path – if path is set, plan object will be load from path directory else current directory

Returns:

save pickled file of optimal solution dictionary

Example:

>>> my_plan.save_optimal_sol(sol=sol, sol_name='sol', path=r'path/to/save_solution')
save_plan(plan_name: Optional[str] = None, path: Optional[str] = None) → None[source]

Save pickled file for plan object

Parameters:
  • plan_name – create the name of the pickled file of plan object. If none, it will save with the name as ‘my_plan’

  • path – if path is set, plan object will be pickled and saved in path directory else it will save current project directory

Returns:

save pickled object of class Plan

Example:

>>> my_plan.save_plan(plan_name='my_plan', path=r"path/to/save_plan")
view_in_slicer(slicer_path=None, img_dir=None)[source]

view ct, dose_1d and structures in slicer :param slicer_path: :param img_dir: :return:

portpy.photon.structures module

class portpy.photon.structures.Structures(structures: dict, opt_voxels: dict)[source]

Bases: object

A class representing structures.

  • Attributes

    :param structures_dict: structure dictionary that contains information about the structures present in the patient's CT scan.
    :type structures_dict: dict
    :param opt_voxels_dict: It contains information about optimization voxels in the form of dictionary
    :type opt_voxels_dict: dict
    
  • Methods

    :get_volume_cc(struct):
        Get volume in cc for the structure
    :expand(structure, margin_mm, new_structure):
        Expand the structure with margin_mm in mm
    :shrink(structure, margin_mm, new_structure):
        Shrink the structure with margin_mm in mm
    :union(str_1, str_2, str1_or_str2):
        Create union of two structures str_1 and str_2
    :intersect(str_1, str_2, str1_and_str2):
        Create intersect of two structures str_1 and str_2
    
create_structure(new_structure: str, mask_3d: ndarray) → None[source]

Create a new structure and append its mask to the structures_dict

Parameters:
  • new_structure – name of the new structure

  • mask_3d – 3d mask for the structure

Returns:

create new_structure

delete_structure(structure: str)[source]
Parameters:

structure – structure to be removed

Returns:

expand(structure: str, margin_mm: float, new_structure: str) → None[source]

Expand the structure with the given margin_mm.

Parameters:
  • structure – structure name to expand

  • margin_mm – margin_mm in mm

  • new_structure – new structure name. if same as structure name,

expand the same structure. else create new structure :return: expand and save the structure mask in structures dictionary

get_fraction_of_vol_in_calc_box(structure_name: str)[source]

Get fraction of volume in calc box for the structure

param structure_name:

name of the structure in plan

return:

volume of the structure

get_structures() → list[source]

Returns all the structure names as list :return:

get_volume_cc(structure_name: str)[source]

Get volume in cc for the structure

param structure_name:

name of the structure in plan

return:

volume of the structure

intersect(str_1: str, str_2: str, str1_and_str2: str) → None[source]

Create intersection of two structures str_1 and str_2. If str1_and_str2 is not in structures dict, it will create new structures. If str1_and_str2 is in structure_dict, it will modify the structure

Parameters:
  • str_1 – structure name for the 1st structure

  • str_2 – structure name for the 2nd structure

  • str1_and_str2 – structure name for the intersection of structure 1 and 2

Returns:

create intersection of the structures and save it to structures list

modify_structure(structure: str, mask_3d: ndarray)[source]
Parameters:
  • structure – name of the structure to be modified

  • mask_3d – 3d mask for the structure

Returns:

modify structure

preprocess_structures()[source]

preprocess structures to create optimization voxel indices for the structure :return:

shrink(structure: str, margin_mm: float, new_structure: str) → None[source]

Shrink the structure with margin_mm.

param structure:

structure name to shrink

param margin_mm:

margin_mm in mm

param new_structure:

new structure name. if same as structure, shrink the same structure. else create new structure

return:

shrink and save the structure in structures_dictionary

subtract(str_1: str, str_2: str, str1_sub_str2: str) → None[source]
Parameters:
  • str_1 – structure name for the 1st structure

  • str_2 – structure name for the 2nd structure

  • str1_sub_str2 – structure name for subtracting 2 from 1

Returns:

create structure1 - structure2 and save it to list

union(str_1: str, str_2: str, str1_or_str2: str) → None[source]

Create union of two structures str_1 and str_2. If str1_or_str2 is not in structures dict, it will create new structures. If str1_or_str2 is in structure_dict, it will modify the structure

Parameters:
  • str_1 – structure name for the 1st structure

  • str_2 – structure name for the 2nd structure

  • str1_or_str2 – structure name for the union of structure 1 and 2

Returns:

create union of the structures and save it to structures list

portpy.photon.visualization module

class portpy.photon.visualization.Visualization[source]

Bases: object

static display_patient_metadata(patient_id: str, data_dir: Optional[str] = None, in_browser: bool = False, return_beams_df: bool = False, return_structs_df: bool = False)[source]

Displays the patient information in console or html format. If in_browswer is enabled it creates a temporary html file and lnunches your browser

Parameters:
  • patient_id – the patient id

  • data_dir – the folder path where data located, defaults to None. If path = None, then it assumes the data is in sub-folder named data in the current directory

  • in_browser – visualize in pretty way in browser. default to False. If false, plot table in console

  • return_beams_df – return dataframe containing beams metadata

  • return_structs_df – return dataframe containing structures metadata

Raises:

invalid directory error – raises an exception if invalid data directory

Example:

>>> Visualization.display_patient_metadata(patient_id=patient_id, data_dir='path/to/data', in_browser=True)
static display_patients(data_dir: Optional[str] = None, in_browser: bool = False, return_df: bool = False)[source]

Displays the list of patients included in data_dir folder

Parameters:
  • data_dir – folder including patient data. If it is None, then it assumes the data is in the current directory under sub-folder named “data”

  • in_browser – visualize in pretty way in browser. default to False. If false, plot table in console

  • return_df – return dataframe instead of visualization

Raises:

invalid directory error – raises an exception if invalid data directory.

:return display patient information in table

dose_type

alias of Literal[Absolute(Gy), Relative(%)]

static get_cmap_colors(n, name='hsv')[source]

Returns a function that maps each index in 0, 1, …, n-1 to a distinct RGB color; the keyword argument name must be a standard mpl colormap name.

static get_colors()[source]
Returns:

return list of 20 colors

static is_notebook() → bool[source]
static legend_dose_storage(my_plan: Plan) → dict[source]
static plan_metrics(my_plan: Plan, sol: Union[dict, List[dict]], html_file_name='temp.html', sol_names: List[str] = None, return_df: bool = False)[source]

Visualize the plan metrics for clinical criteria in browser. It evaluate the plan by comparing the metrics against required criteria.

If plan value is green color. It meets all the Limits and Goals If plan value is yellow color. It meets limits but not goals If plan value is red color. It violates both limit and goals

Parameters:
  • my_plan – object of class Plan

  • sol – optimal solution dictionary

  • html_file_name – name of the html file to be launched in browser

  • sol_names – Default to Plan Value. column names for the plan evaluation

  • return_df – return df instead of visualization

Returns:

plan metrics in browser

static plot_2d_dose(my_plan: Plan, sol: dict, slice_num: int = 40, structs: List[str] = None, show_dose: bool = True, show_struct: bool = True, show_isodose: bool = False, **options) → None[source]

Plot 2d view of ct, dose_1d, isodose and structure contours

Parameters:
  • sol – solution to optimization

  • my_plan – object of class Plan

  • slice_num – slice number

  • structs – structures for which contours to be displayed on the slice view. e.g. structs = [‘PTV, ESOPHAGUS’]

  • show_dose – view dose_1d on the slice

  • show_struct – view structure on the slice

  • show_isodose – view isodose

  • dpi – Default dpi=100 for figure

Returns:

plot 2d view of ct, dose_1d, isodose and structure contours

Example:

>>> Visualization.plot_2d_dose(my_plan, sol=sol, slice_num=50, structs=['PTV'], show_isodose=False)
static plot_binary_mask_points(my_plan, structure: str, show: bool = True, color: Optional[List[str]] = None)[source]
static plot_dvh(my_plan: Plan, sol: dict = None, dose_1d: np.ndarray = None, structs: List[str] = None, dose_scale: dose_type = 'Absolute(Gy)', volume_scale: volume_type = 'Relative(%)', **options)[source]

Create dvh plot for the selected structures

Parameters:
  • my_plan – object of class Plan

  • sol – optimal sol dictionary

  • dose_1d – dose_1d in 1d voxels

  • structs – structures to be included in dvh plot

  • volume_scale – volume scale on y-axis. Default= Absolute(cc). e.g. volume_scale = “Absolute(cc)” or volume_scale = “Relative(%)”

  • dose_scale – dose_1d scale on x axis. Default= Absolute(Gy). e.g. dose_scale = “Absolute(Gy)” or dose_scale = “Relative(%)”

Keyword Arguments:
  • (str) (style) – line style for dvh curve. default “solid”. can be “dotted”, “dash-dotted”.

  • (int) (width) – width of line. Default 2

  • colors(list) – list of colors

  • legend_font_size – Set legend_font_size. default 10

  • figsize – Set figure size for the plot. Default figure size (12,8)

  • create_fig – Create a new figure. Default True. If False, append to the previous figure

  • title – Title for the figure

  • filename – Name of the file to save the figure in current directory

  • show – Show the figure. Default is True. If false, next plot can be append to it

  • norm_flag – Use to normalize the plan. Default is False.

  • norm_volume – Use to set normalization volume. default is 90 percentile.

Returns:

dvh plot for the selected structures

Example:

>>> Visualization.plot_dvh(my_plan, sol=sol, structs=['PTV', 'ESOPHAGUS'], dose_scale='Absolute(Gy)',volume_scale="Relative(%)", show=False, create_fig=True )
static plot_fluence_2d(beam_id: int, sol: dict, **options)[source]

Displays fluence in 2d for the given beam_id

Parameters:
  • beam_id – beam_id of the beam

  • sol – solution dictionary after optimization

Returns:

2d optimal fluence plot

Example:

>>> Visualization.plot_fluence_2d(beam_id=0, sol=sol, **options)
static plot_fluence_3d(beam_id: int, sol: dict, **options)[source]

Displays fluence in 3d for the given beam_id

Parameters:
  • sol – solution after optimization

  • beam_id – beam_id of the beam

Returns:

3d optimal fluence plot

Example:

>>> Visualization.plot_fluence_3d(beam_id=0, sol=sol, **options)
static plot_robust_dvh(my_plan, dose_list, structs=None, style='solid', norm_flag=False, norm_volume=90, norm_struct='PTV', weight_flag=True, plot_scenario=None, width=None, colors=None, figsize=(12, 8), legend_font_size=10, title=None, filename=None, show=False, *args, **kwargs)[source]
static surface_plot(matrix: ndarray, **kwargs)[source]
static view_in_slicer(my_plan: Plan, slicer_path: str = None, data_dir: str = None) → None[source]
Parameters:
  • my_plan – object of class Plan

  • slicer_path – slicer executable path on your local machine

  • data_dir – the folder path where data located, defaults to None. If path = None, then it assumes the data is in sub-folder named data in the current directory

Returns:

plot the images in 3d slicer

view ct, dose_1d and structure set images in 3d slicer

Example:

>>> Visualization.view_in_slicer(my_plan, slicer_path='C:/Slicer/Slicer.exe', data_dir='path/to/nrrd/image')
static view_in_slicer_jupyter(my_plan: Plan, dose_1d: np.ndarray = None, sol: dict = None, ct_name: str = 'ct', dose_name: str = 'dose', struct_set_name: str = 'rt_struct', show_ct: bool = True, show_dose: bool = True, show_structs: bool = True)[source]

This method helps to visualize CT, Dose and Rt struct in 3d slicer

Parameters:
  • my_plan – object of class plan

  • dose_1d – dose in 1d

  • sol – solution dictionary

  • ct_name – Default to ‘ct’. name of the ct node in 3D slicer

  • dose_name – Default to ‘dose’. name of the dose node in 3D slicer

  • struct_set_name – name of the rtstruct

  • show_structs – default to True. If false, will not create structure node

  • show_dose – default to True. If false, will not create dose node

:param show_ct:default to True. If false, will not create ct node :return: visualize in slicer jupyter

volume_type

alias of Literal[Absolute(cc), Relative(%)]

Module contents