Class: RTKIT::RTDose
Overview
The RTDose class contains methods that are specific for this modality (RTDOSE).
Inheritance
-
RTDose inherits all methods and attributes from the Series class.
Instance Attribute Summary collapse
-
#plan ⇒ Object
readonly
The Plan which this RTDose series belongs to.
-
#volumes ⇒ Object
An array of dose Volume instances associated with this RTDose series.
Attributes inherited from Series
#class_uid, #date, #description, #modality, #series_uid, #study, #time
Class Method Summary collapse
-
.load(dcm, study) ⇒ Object
Creates a new RTDose instance by loading the relevant information from the specified DICOM object.
-
.plan(dcm, study) ⇒ Object
Identifies the Plan that the RTDose object belongs to.
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #eql?)
Returns true if the argument is an instance with attributes equal to self.
-
#add(dcm) ⇒ Object
Registers a DICOM Object to the RTDose series, and processes it to create (and reference) a DoseVolume instance linked to this RTDose series.
-
#add_volume(volume) ⇒ Object
Adds a DoseVolume instance to this RTDose series.
-
#hash ⇒ Object
Generates a Fixnum hash value for this instance.
-
#initialize(series_uid, plan, options = {}) ⇒ RTDose
constructor
Creates a new RTDose instance.
-
#sum ⇒ Object
Returns a DoseVolume which is the sum of the volumes of this instance.
-
#to_rt_dose ⇒ Object
Returns self.
-
#volume(*args) ⇒ Object
Returns the Volume instance mathcing the specified SOP Instance UID (if an argument is used).
Methods inherited from Series
Constructor Details
#initialize(series_uid, plan, options = {}) ⇒ RTDose
Creates a new RTDose instance.
Parameters
-
series_uid
– The Series Instance UID string. -
plan
– The Plan instance that this RTDose series belongs to. -
options
– A hash of parameters.
Options
-
:date
– String. The Series Date (DICOM tag ‘0008,0021’). -
:time
– String. The Series Time (DICOM tag ‘0008,0031’). -
:description
– String. The Series Description (DICOM tag ‘0008,103E’).
96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/rtkit/rt_dose.rb', line 96 def initialize(series_uid, plan, ={}) raise ArgumentError, "Invalid argument 'series_uid'. Expected String, got #{series_uid.class}." unless series_uid.is_a?(String) raise ArgumentError, "Invalid argument 'plan'. Expected Plan, got #{plan.class}." unless plan.is_a?(Plan) # Pass attributes to Series initialization: [:class_uid] = '1.2.840.10008.5.1.4.1.1.481.2' # RT Dose Storage super(series_uid, 'RTDOSE', plan.study, ) @plan = plan # Default attributes: @volumes = Array.new @associated_volumes = Hash.new # Register ourselves with the Plan: @plan.add_rt_dose(self) end |
Instance Attribute Details
#plan ⇒ Object (readonly)
The Plan which this RTDose series belongs to.
12 13 14 |
# File 'lib/rtkit/rt_dose.rb', line 12 def plan @plan end |
#volumes ⇒ Object
An array of dose Volume instances associated with this RTDose series.
14 15 16 |
# File 'lib/rtkit/rt_dose.rb', line 14 def volumes @volumes end |
Class Method Details
.load(dcm, study) ⇒ Object
Creates a new RTDose instance by loading the relevant information from the specified DICOM object. The Series Instance UID string value is used to uniquely identify a RTDose instance.
Parameters
-
dcm
– An instance of a DICOM object (DICOM::DObject) with modality ‘RTDOSE’. -
study
– The Study instance that this RTDose belongs to.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
# File 'lib/rtkit/rt_dose.rb', line 24 def self.load(dcm, study) raise ArgumentError, "Invalid argument 'dcm'. Expected DObject, got #{dcm.class}." unless dcm.is_a?(DICOM::DObject) raise ArgumentError, "Invalid argument 'study'. Expected Study, got #{study.class}." unless study.is_a?(Study) raise ArgumentError, "Invalid argument 'dcm'. Expected DObject with modality 'RTDOSE', got #{dcm.value(MODALITY)}." unless dcm.value(MODALITY) == 'RTDOSE' # Required attributes: series_uid = dcm.value(SERIES_UID) # Optional attributes: class_uid = dcm.value(SOP_CLASS) date = dcm.value(SERIES_DATE) time = dcm.value(SERIES_TIME) description = dcm.value(SERIES_DESCR) series_uid = dcm.value(SERIES_UID) # Get the corresponding Plan: plan = self.plan(dcm, study) # Create the RTDose instance: dose = self.new(series_uid, plan, :class_uid => class_uid, :date => date, :time => time, :description => description) dose.add(dcm) return dose end |
.plan(dcm, study) ⇒ Object
Identifies the Plan that the RTDose object belongs to. If the referenced instances (Plan, StructureSet, ImageSeries & Frame) does not exist, they are created by this method.
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/rtkit/rt_dose.rb', line 47 def self.plan(dcm, study) raise ArgumentError, "Invalid argument 'dcm'. Expected DObject, got #{dcm.class}." unless dcm.is_a?(DICOM::DObject) raise ArgumentError, "Invalid argument 'study'. Expected Study, got #{study.class}." unless study.is_a?(Study) raise ArgumentError, "Invalid argument 'dcm'. Expected DObject with modality 'RTDOSE', got #{dcm.value(MODALITY)}." unless dcm.value(MODALITY) == 'RTDOSE' # Extract the Frame of Reference UID: begin frame_of_ref = dcm.value(FRAME_OF_REF) rescue frame_of_ref = nil end # Extract referenced Plan SOP Instance UID: begin ref_plan_uid = dcm[REF_PLAN_SQ][0].value(REF_SOP_UID) rescue ref_plan_uid = nil end # Create the Frame if it doesn't exist: f = study.patient.dataset.frame(frame_of_ref) f = Frame.new(frame_of_ref, study.patient) unless f # Create the Plan, StructureSet & ImageSeries if the referenced Plan doesn't exist: plan = study.fseries(ref_plan_uid) unless plan # Create ImageSeries (assuming modality CT): is = ImageSeries.new(RTKIT.series_uid, 'CT', f, study) study.add_series(is) # Create StructureSet: struct = StructureSet.new(RTKIT.sop_uid, is) study.add_series(struct) # Create Plan: plan = Plan.new(ref_plan_uid, struct) study.add_series(plan) end return plan end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
Returns true if the argument is an instance with attributes equal to self.
112 113 114 115 116 |
# File 'lib/rtkit/rt_dose.rb', line 112 def ==(other) if other.respond_to?(:to_rt_dose) other.send(:state) == state end end |
#add(dcm) ⇒ Object
Registers a DICOM Object to the RTDose series, and processes it to create (and reference) a DoseVolume instance linked to this RTDose series.
123 124 125 126 |
# File 'lib/rtkit/rt_dose.rb', line 123 def add(dcm) raise ArgumentError, "Invalid argument 'dcm'. Expected DObject, got #{dcm.class}." unless dcm.is_a?(DICOM::DObject) DoseVolume.load(dcm, self) end |
#add_volume(volume) ⇒ Object
Adds a DoseVolume instance to this RTDose series.
130 131 132 133 134 |
# File 'lib/rtkit/rt_dose.rb', line 130 def add_volume(volume) raise ArgumentError, "Invalid argument 'volume'. Expected DoseVolume, got #{volume.class}." unless volume.is_a?(DoseVolume) @volumes << volume unless @associated_volumes[volume.uid] @associated_volumes[volume.uid] = volume end |
#hash ⇒ Object
Generates a Fixnum hash value for this instance.
138 139 140 |
# File 'lib/rtkit/rt_dose.rb', line 138 def hash state.hash end |
#sum ⇒ Object
Returns a DoseVolume which is the sum of the volumes of this instance. With the individual DoseVolumes corresponding to the dose for a particular beam, the sum DoseVolume corresponds to the summed dose of the entire treatment plan.
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/rtkit/rt_dose.rb', line 147 def sum if @sum # If the sum volume has already been created, return it instead of recreating: return @sum else if @volumes.length > 0 nr_frames = @volumes.first.images.length # Create the sum DoseVolume instance: sop_uid = @volumes.first.sop_uid + ".1" @sum = DoseVolume.new(sop_uid, @volumes.first.frame, @volumes.first.dose_series, :sum => true) # Sum the dose of the various DoseVolumes: dose_sum = NArray.int(nr_frames, @volumes.first.images.first.columns, @volumes.first.images.first.rows) @volumes.each { |volume| dose_sum += volume.dose_arr } # Convert dose float array to integer pixel values of a suitable range, # along with a corresponding scaling factor: sum_scaling_coeff = dose_sum.max / 65000.0 if sum_scaling_coeff == 0.0 pixel_values = NArray.int(nr_frames, @volumes.first.images.first.columns, @volumes.first.images.first.rows) else pixel_values = dose_sum * (1 / sum_scaling_coeff) end # Set the scaling coeffecient: @sum.scaling = sum_scaling_coeff # Collect the rest of the image information needed to create new dose images: sop_uids = RTKIT.sop_uids(nr_frames) slice_positions = @volumes.first.images.collect {|img| img.pos_slice} columns = @volumes.first.images.first.columns rows = @volumes.first.images.first.rows pos_x = @volumes.first.images.first.pos_x pos_y = @volumes.first.images.first.pos_y col_spacing = @volumes.first.images.first.col_spacing row_spacing = @volumes.first.images.first.row_spacing cosines = @volumes.first.images.first.cosines # Create dose images for our sum dose volume: nr_frames.times do |i| img = Image.new(sop_uids[i], @sum) # Fill in image information: img.columns = columns img.rows = rows img.pos_x = pos_x img.pos_y = pos_y img.pos_slice = slice_positions[i] img.col_spacing = col_spacing img.row_spacing = row_spacing img.cosines = cosines # Fill in the pixel frame data: img.narray = pixel_values[i, true, true] end return @sum end end end |
#to_rt_dose ⇒ Object
Returns self.
202 203 204 |
# File 'lib/rtkit/rt_dose.rb', line 202 def to_rt_dose self end |
#volume(*args) ⇒ Object
Returns the Volume instance mathcing the specified SOP Instance UID (if an argument is used). If a specified UID doesn’t match, nil is returned. If no argument is passed, the first Volume instance associated with the RTDose is returned.
Parameters
-
uid
– String. The value of the SOP Instance UID element.
214 215 216 217 218 219 220 221 222 223 |
# File 'lib/rtkit/rt_dose.rb', line 214 def volume(*args) raise ArgumentError, "Expected one or none arguments, got #{args.length}." unless [0, 1].include?(args.length) if args.length == 1 raise ArgumentError, "Expected String (or nil), got #{args.first.class}." unless [String, NilClass].include?(args.first.class) return @associated_volumes[args.first] else # No argument used, therefore we return the first Volume instance: return @volumes.first end end |