Class: RTKIT::DoseDistribution
- Inherits:
-
Object
- Object
- RTKIT::DoseDistribution
- Defined in:
- lib/rtkit/dose_distribution.rb
Overview
Contains DICOM data and methods related to a DoseDistribution, a collection of dose points extracted from a dose volume.
Relations
-
A DoseDistribution belongs to the DoseVolume from which it was created.
-
A DoseDistribution contains various methods to return a Dose (point) instance.
Instance Attribute Summary collapse
-
#doses ⇒ Object
readonly
The doses values belonging to this distribution (array of floats).
-
#volume ⇒ Object
readonly
The DoseVolume that the DoseDistribution is derived from.
Class Method Summary collapse
-
.create(bin_volume) ⇒ Object
Creates a new DoseDistribution instance from a BinVolume.
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #eql?)
Returns true if the argument is an instance with attributes equal to self.
-
#d(percent) ⇒ Object
Calculates the dose that at least the specified percentage of the volume receives.
-
#hash ⇒ Object
Generates a Fixnum hash value for this instance.
-
#hindex ⇒ Object
Calculates the homogeneity index of the dose distribution.
-
#initialize(doses, volume) ⇒ DoseDistribution
constructor
Creates a new DoseDistribution instance.
-
#length ⇒ Object
(also: #size)
Returns the number of dose values in the DoseDistribution.
-
#max ⇒ Object
Calculates the maximum dose.
-
#mean ⇒ Object
Calculates the arithmethic mean (average) dose.
-
#median ⇒ Object
Calculates the median dose.
-
#min ⇒ Object
Calculates the minimum dose.
-
#rmsdev ⇒ Object
Calculates the root mean square deviation (the population standard deviation).
-
#stddev ⇒ Object
Calculates the sample standard deviation of the dose distribution.
-
#to_dose_distribution ⇒ Object
Returns self.
-
#v(dose) ⇒ Object
Calculates the percentage of the volume that receives a dose higher than or equal to the specified dose.
Constructor Details
#initialize(doses, volume) ⇒ DoseDistribution
Creates a new DoseDistribution instance.
Parameters
-
doses
– An array/NArray of doses (floats). -
volume
– The DoseVolume which this DoseDistribution belongs to.
49 50 51 52 53 54 55 56 |
# File 'lib/rtkit/dose_distribution.rb', line 49 def initialize(doses, volume) #raise ArgumentError, "Invalid argument 'doses'. Expected Array, got #{doses.class}." unless doses.is_a?(Array) raise ArgumentError, "Invalid argument 'volume'. Expected DoseVolume, got #{volume.class}." unless volume.is_a?(DoseVolume) # Store doses as a sorted (float) NArray: @doses = NArray.to_na(doses).sort.to_type(4) # Set references: @volume = volume end |
Instance Attribute Details
#doses ⇒ Object (readonly)
The doses values belonging to this distribution (array of floats).
14 15 16 |
# File 'lib/rtkit/dose_distribution.rb', line 14 def doses @doses end |
#volume ⇒ Object (readonly)
The DoseVolume that the DoseDistribution is derived from.
16 17 18 |
# File 'lib/rtkit/dose_distribution.rb', line 16 def volume @volume end |
Class Method Details
.create(bin_volume) ⇒ Object
Creates a new DoseDistribution instance from a BinVolume. The BinVolume is typically defined from a ROI delineation against a DoseVolume. Returns the DoseDistribution instance.
Parameters
-
bin_volume
– A BinVolume, referencing a DoseVolume, from which to extract a DoseDistribution.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/rtkit/dose_distribution.rb', line 26 def self.create(bin_volume) raise ArgumentError, "Invalid argument 'bin_volume'. Expected BinVolume, got #{bin_volume.class}." unless bin_volume.is_a?(BinVolume) raise ArgumentError, "Invalid argument 'bin_volume'. It must reference a DoseVolume, got #{bin_volume.bin_images.first.image.series.class}." unless bin_volume.bin_images.first.image.series.is_a?(DoseVolume) dose_volume = bin_volume.bin_images.first.image.series # Extract a selection of pixel values from the dose images based on the provided binary volume: dose_values = NArray.sfloat(0) bin_volume.bin_images.each do |bin_image| slice_pixel_values = bin_image.image.pixel_values(bin_image.selection) slice_dose_values = slice_pixel_values.to_type(4) * bin_image.image.series.scaling dose_values = NArray[*dose_values, *slice_dose_values] end # Create the DoseDistribution instance: dd = self.new(dose_values, dose_volume) return dd end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
Returns true if the argument is an instance with attributes equal to self.
60 61 62 63 64 |
# File 'lib/rtkit/dose_distribution.rb', line 60 def ==(other) if other.respond_to?(:to_dose_distribution) other.send(:state) == state end end |
#d(percent) ⇒ Object
Calculates the dose that at least the specified percentage of the volume receives. Returns a dose (Float) in units of Gy.
Parameters
-
percent
– Integer/Float. The percent of the volume which receives a dose higher than the returned dose.
Examples
# Calculate the near minimum dose (e.g. up to 2 % of the volume receives a dose less than this):
near_min = ptv_distribution.d(98)
# Calculate the near maximum dose (e.g. at most 2 % of the volume receives a dose higher than this):
near_max = ptv_distribution.d(2)
83 84 85 86 87 |
# File 'lib/rtkit/dose_distribution.rb', line 83 def d(percent) raise RangeError, "Argument 'percent' must be in the range [0-100]." if percent.to_f < 0 or percent.to_f > 100 d_index = ((@doses.length - 1) * (1 - percent.to_f * 0.01)).round return @doses[d_index] end |
#hash ⇒ Object
Generates a Fixnum hash value for this instance.
91 92 93 |
# File 'lib/rtkit/dose_distribution.rb', line 91 def hash state.hash end |
#hindex ⇒ Object
Calculates the homogeneity index of the dose distribution. A low (near zero) value corresponds to high homogeneity (e.q. 0.1). Returns the index value as a float.
Notes
-
The homogeneity index is defined as:
HI = ( d(2) - d(98) ) / d(50)
For more details, refer to ICRU Report No. 83, Chapter 3.7.1.
Examples
# Calculate the homogeneity index of the dose distribution of a PTV ROI for a given plan:
homogeneity_index = ptv_distribution.hindex
110 111 112 |
# File 'lib/rtkit/dose_distribution.rb', line 110 def hindex return (d(2) - d(98)) / d(50).to_f end |
#length ⇒ Object Also known as: size
Returns the number of dose values in the DoseDistribution.
116 117 118 |
# File 'lib/rtkit/dose_distribution.rb', line 116 def length @doses.length end |
#max ⇒ Object
Calculates the maximum dose.
124 125 126 |
# File 'lib/rtkit/dose_distribution.rb', line 124 def max @doses.max end |
#mean ⇒ Object
Calculates the arithmethic mean (average) dose.
130 131 132 |
# File 'lib/rtkit/dose_distribution.rb', line 130 def mean @doses.mean end |
#median ⇒ Object
Calculates the median dose.
136 137 138 |
# File 'lib/rtkit/dose_distribution.rb', line 136 def median @doses.median end |
#min ⇒ Object
Calculates the minimum dose.
142 143 144 |
# File 'lib/rtkit/dose_distribution.rb', line 142 def min @doses.min end |
#rmsdev ⇒ Object
Calculates the root mean square deviation (the population standard deviation).
Notes
-
Uses N in the denominator for calculating the standard deviation of the sample.
152 153 154 |
# File 'lib/rtkit/dose_distribution.rb', line 152 def rmsdev @doses.rmsdev end |
#stddev ⇒ Object
Calculates the sample standard deviation of the dose distribution.
Notes
-
Uses Bessel’s correction (N-1 in the denominator).
162 163 164 |
# File 'lib/rtkit/dose_distribution.rb', line 162 def stddev @doses.stddev end |
#to_dose_distribution ⇒ Object
Returns self.
168 169 170 |
# File 'lib/rtkit/dose_distribution.rb', line 168 def to_dose_distribution self end |
#v(dose) ⇒ Object
Calculates the percentage of the volume that receives a dose higher than or equal to the specified dose. Returns a percentage (Float).
Parameters
-
dose
– Integer/Float. The dose threshold value to apply to the dose distribution.
Examples
# Calculate the low dose spread (e.g. the percentage of the lung that receives a dose higher than 5 Gy):
coverage_low = lung_distribution.v(5)
# Calculate the high dose spread (e.g. the percentage of the lung that receives a dose higher than 20 Gy):
coverage_high = lung_distribution.v(20)
187 188 189 190 191 192 193 |
# File 'lib/rtkit/dose_distribution.rb', line 187 def v(dose) raise RangeError, "Argument 'dose' cannot be negative." if dose.to_f < 0 # How many dose values are higher than the threshold? num_above = (@doses.ge dose.to_f).where.length # Divide by total number of elements and convert to percentage: return num_above / @doses.length.to_f * 100 end |