33from portpy .photon .influence_matrix import InfluenceMatrix
44import json
55from copy import deepcopy
6+ from typing import Union , List
67
78class Arcs :
89 """
@@ -18,13 +19,23 @@ class Arcs:
1819 }
1920
2021 :type arcs_dict: dict
22+ :param inf_matrix: object of InfluenceMatrix class
23+ :type inf_matrix: object
24+ :param file_name: json file containing arcs information
25+ :type file_name: str
26+ :param data: object of DataExplorer class
27+ :type data: object
28+
2129
2230 - **Methods** ::
2331
24- :get_gantry_angle(beam_id: Optional(int, List[int]):
25- Get gantry angle in degrees
26- :get_collimator_angle(beam_id):
27- Get collimator angle in degrees
32+ method get_all_arcs: Get all arcs as a list
33+ method get_arc: Get arc based upon arc id
34+ method get_initial_leaf_pos: Get initial leaf position based upon BEV or other user defined criteria to start SCP
35+ method gen_interior_and_boundary_beamlets: Generate interior and boundary beamlets based upon step size
36+ method calc_actual_from_intermediate_sol: Calculate actual solution from intermediate solution
37+
38+
2839
2940 """
3041
@@ -53,6 +64,32 @@ def load_json(self, arcs_json_file):
5364 f .close ()
5465 return arcs_dict
5566
67+ def get_all_arcs (self ):
68+ """
69+ Get all arcs as a list
70+
71+ """
72+ return self .arcs_dict ['arcs' ]
73+
74+ def get_arc (self , arc_id : Union [Union [int , str ], List [Union [int , str ]]]):
75+ """
76+ Get arc based upon arc id
77+ :param arc_id: arc id for the arc needed
78+ :return: list of arcs
79+
80+ """
81+ ind = []
82+ if isinstance (arc_id , int ) or isinstance (arc_id , str ):
83+ ind = [i for i in range (len (self .arcs_dict ['arcs' ])) if
84+ self .arcs_dict ['arcs' ][i ]['arc_id' ] == arc_id ]
85+ if not ind :
86+ raise ValueError ("invalid arc id {}" .format (arc_id ))
87+ arcs = []
88+ for a in ind :
89+ arc = self .arcs_dict ['arcs' ][a ]
90+ arcs .append (arc )
91+ return arcs
92+
5693 def get_max_cols (self ):
5794 max_cols = 0
5895 arcs = self .arcs_dict ['arcs' ]
@@ -73,11 +110,12 @@ def preprocess(self):
73110 arc ['vmat_opt' ] = beams_list
74111
75112 def get_initial_leaf_pos (self , initial_leaf_pos = 'BEV' ):
76- arcs_dict = self .arcs_dict
77113 """
78- Initialize leaf positions for the scp
114+ Initialize leaf positions for the scp.
115+ :param initial_leaf_pos: initial leaf position. Default is BEV
116+ :return: None
79117 """
80-
118+ arcs_dict = self . arcs_dict
81119 for i , arc in enumerate ((arcs_dict ['arcs' ])):
82120 beams_list = arc ['vmat_opt' ]
83121 for j , beam in enumerate (beams_list ):
@@ -119,6 +157,11 @@ def gen_interior_and_boundary_beamlets(self, forward_backward: int = 1, step_siz
119157 """
120158 Create interior and boundary beamlets based upon step_size and forward backward
121159
160+ :param forward_backward: forward backward value. Default is 1. If 1, forward, if 0, backward
161+ :param step_size_f: step size for forward. Default is 8
162+ :param step_size_b: step size for backward. Default is 8
163+ :return: None
164+
122165 """
123166 arcs_dict = self .arcs_dict
124167 for a , arc in enumerate (arcs_dict ['arcs' ]):
@@ -210,7 +253,12 @@ def gen_interior_and_boundary_beamlets(self, forward_backward: int = 1, step_siz
210253 vmat [b ]['int_ind' ] = int_ind
211254
212255 def calc_actual_from_intermediate_sol (self , sol : dict ):
256+ """
257+ Create actual solution from intermediate solution.
258+ :param sol: solution dictionary
259+ :return: None
213260
261+ """
214262 int_v = sol ['int_v' ]
215263 bound_v_l = sol ['bound_v_l' ]
216264 bound_v_r = sol ['bound_v_r' ]
@@ -266,6 +314,10 @@ def update_leaf_pos(self, forward_backward: int, update_reference_leaf_pos: bool
266314 1 ] * (1 - forward_backward )
267315
268316 def update_best_solution (self ):
317+ """
318+ Update best solution if the current solution is better than the best solution.
319+ :return: None
320+ """
269321 arcs = self .arcs_dict ['arcs' ]
270322 for a , arc in enumerate (arcs ):
271323 for b , beam in enumerate (arc ['vmat_opt' ]):
@@ -274,6 +326,11 @@ def update_best_solution(self):
274326 arc ['best_w_beamlet_act' ] = arc ['w_beamlet_act' ]
275327
276328 def calculate_beamlet_value (self ):
329+ """
330+ Calculate beamlet values between (0-1) for the intermediate solution.
331+ :return: None
332+
333+ """
277334 # calculates the beamlet values between (0-1)
278335 arcs = self .arcs_dict ['arcs' ]
279336 num_beamlets_so_far = 0
@@ -297,6 +354,16 @@ def calculate_beamlet_value(self):
297354 return arcs
298355
299356 def calculate_dose (self , inf_matrix : InfluenceMatrix , sol : dict , vmat_params : dict , best_plan : bool = False ):
357+ """
358+
359+ Calculate dose from the solution.
360+ :param inf_matrix: object of InfluenceMatrix class
361+ :param sol: solution dictionary
362+ :param vmat_params: vmat parameters
363+ :param best_plan: if True, calculate dose for best plan. Default is False
364+ :return: solution dictionary containing dose values
365+
366+ """
300367 A = inf_matrix .A
301368 arcs = self .arcs_dict ['arcs' ]
302369 adj1 = vmat_params ['second_beam_adj' ]
@@ -339,6 +406,10 @@ def calculate_dose(self, inf_matrix: InfluenceMatrix, sol: dict, vmat_params: di
339406 return sol
340407
341408 def intermediate_to_actual (self ):
409+ """
410+ Convert intermediate solution to actual feasible solution.
411+
412+ """
342413 arcs = self .arcs_dict ['arcs' ]
343414 beamlet_so_far = 0
344415 # Convert intermediate solution to actual feasible solution
@@ -407,6 +478,13 @@ def intermediate_to_actual(self):
407478 beamlet_so_far = beamlet_so_far + num_beamlets
408479
409480 def _update_reference_leaf_pos (self ):
481+ """
482+ Update reference leaf position in forward and backward direction. The following leaf positions are updated only if a solution is accepted
483+ they are necessary because if a solution is rejected and forward/backward
484+ is changed then you need to go back to this reference leaf positions to
485+ update your leaf positions
486+
487+ """
410488 arcs = self .arcs_dict ['arcs' ]
411489 for arc in arcs :
412490
@@ -434,6 +512,12 @@ def _update_reference_leaf_pos(self):
434512 beam ['leaf_pos_f' ][r ][1 ] = beam ['leaf_pos_right' ][r ]
435513
436514 def _get_leaf_pos_in_beamlet (self , sol ):
515+ """
516+ Get leaf position relative to beamlets.
517+ :param sol: solution dictionary
518+ :return: None
519+
520+ """
437521 arcs = self .arcs_dict ['arcs' ]
438522 leaf_pos_mu_l = sol ['leaf_pos_mu_l' ]
439523 leaf_pos_mu_r = sol ['leaf_pos_mu_r' ]
0 commit comments