rtkit 0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +10 -0
- data/COPYING +674 -0
- data/README.rdoc +107 -0
- data/lib/rtkit.rb +68 -0
- data/lib/rtkit/beam.rb +346 -0
- data/lib/rtkit/bin_image.rb +578 -0
- data/lib/rtkit/bin_matcher.rb +241 -0
- data/lib/rtkit/bin_volume.rb +263 -0
- data/lib/rtkit/collimator.rb +157 -0
- data/lib/rtkit/collimator_setup.rb +143 -0
- data/lib/rtkit/constants.rb +215 -0
- data/lib/rtkit/contour.rb +213 -0
- data/lib/rtkit/control_point.rb +371 -0
- data/lib/rtkit/coordinate.rb +83 -0
- data/lib/rtkit/data_set.rb +264 -0
- data/lib/rtkit/dose.rb +70 -0
- data/lib/rtkit/dose_distribution.rb +206 -0
- data/lib/rtkit/dose_volume.rb +280 -0
- data/lib/rtkit/frame.rb +164 -0
- data/lib/rtkit/image.rb +372 -0
- data/lib/rtkit/image_series.rb +290 -0
- data/lib/rtkit/logging.rb +158 -0
- data/lib/rtkit/methods.rb +105 -0
- data/lib/rtkit/mixins/image_parent.rb +40 -0
- data/lib/rtkit/patient.rb +229 -0
- data/lib/rtkit/pixel_data.rb +237 -0
- data/lib/rtkit/plan.rb +259 -0
- data/lib/rtkit/plane.rb +165 -0
- data/lib/rtkit/roi.rb +388 -0
- data/lib/rtkit/rt_dose.rb +237 -0
- data/lib/rtkit/rt_image.rb +179 -0
- data/lib/rtkit/ruby_extensions.rb +165 -0
- data/lib/rtkit/selection.rb +189 -0
- data/lib/rtkit/series.rb +77 -0
- data/lib/rtkit/setup.rb +198 -0
- data/lib/rtkit/slice.rb +184 -0
- data/lib/rtkit/staple.rb +305 -0
- data/lib/rtkit/structure_set.rb +442 -0
- data/lib/rtkit/study.rb +214 -0
- data/lib/rtkit/variables.rb +23 -0
- data/lib/rtkit/version.rb +6 -0
- metadata +159 -0
data/README.rdoc
ADDED
@@ -0,0 +1,107 @@
|
|
1
|
+
= RTKIT
|
2
|
+
|
3
|
+
== <em>The Radiotherapy DICOM toolkit</em>
|
4
|
+
|
5
|
+
RTKIT is a toolkit for processing information from the various DICOM modalities
|
6
|
+
encountered in radiotherapy. It contains a number of classes and convenience methods
|
7
|
+
designed to make it easy to extract and manipulate radiotherapy information of
|
8
|
+
interest, like e.g. segmentation, plan, image and dose data.
|
9
|
+
|
10
|
+
Note that the toolkit is in an early state of release, and as such, may
|
11
|
+
be a bit rough in the edges. If you are interested in using RTKIT, please feel free
|
12
|
+
to send me an email with a brief explanation of what you would like to do, and I'll
|
13
|
+
be happy to assist you in getting started with Ruby and RTKIT.
|
14
|
+
|
15
|
+
=== Supported DICOM Modalities
|
16
|
+
|
17
|
+
* CT
|
18
|
+
* MR
|
19
|
+
* RTSTRUCT
|
20
|
+
* RTPLAN
|
21
|
+
* RTDOSE
|
22
|
+
* RTIMAGE
|
23
|
+
|
24
|
+
|
25
|
+
== INSTALLATION
|
26
|
+
|
27
|
+
gem install rtkit
|
28
|
+
|
29
|
+
|
30
|
+
== REQUIREMENTS
|
31
|
+
|
32
|
+
* Ruby 1.9.2 (or higher)
|
33
|
+
* ruby-dicom
|
34
|
+
* NArray
|
35
|
+
|
36
|
+
|
37
|
+
== BASIC USAGE
|
38
|
+
|
39
|
+
=== Load & Include
|
40
|
+
|
41
|
+
require 'rtkit'
|
42
|
+
include RTKIT
|
43
|
+
|
44
|
+
=== Load a set of DICOM files from a folder
|
45
|
+
|
46
|
+
# Load files:
|
47
|
+
ds = RTKIT::DataSet.read("C:/phantom_study/")
|
48
|
+
|
49
|
+
=== Example: Merge two structure sets
|
50
|
+
|
51
|
+
# Locate the structure set objects:
|
52
|
+
structs = ds.patient.study.iseries.structs
|
53
|
+
# Extract the two structure sets:
|
54
|
+
s1 = structs.first
|
55
|
+
s2 = structs.last
|
56
|
+
# Transfer all ROIs except the external contour:
|
57
|
+
s2.rois.each do |roi|
|
58
|
+
s1.add_roi(roi) unless roi.name.downcase.include?('external')
|
59
|
+
end
|
60
|
+
# Ensure unique ROI Numbers:
|
61
|
+
s1.set_numbers
|
62
|
+
# Write the composed structure set object to file:
|
63
|
+
s1.write("fusion_struct.dcm")
|
64
|
+
|
65
|
+
=== IRB Tip
|
66
|
+
|
67
|
+
When working with RTKIT in irb, you may be annoyed with all the
|
68
|
+
information that is printed to screen. This is because in irb every
|
69
|
+
variable loaded in the program is automatically printed to the screen.
|
70
|
+
A useful hack to avoid this effect is to append ";0" after a command.
|
71
|
+
Example:
|
72
|
+
ds = RTKIT::DataSet.read(folder) ;0
|
73
|
+
|
74
|
+
|
75
|
+
== RESOURCES
|
76
|
+
|
77
|
+
* {Source code repository}[https://github.com/dicom/rtkit]
|
78
|
+
* {RTKIT gem}[http://rubygems.org/gems/rtkit]
|
79
|
+
* {DICOM in Ruby}[http://dicom.rubyforge.org/]
|
80
|
+
* {ruby-dicom forum}[http://groups.google.com/group/ruby-dicom]
|
81
|
+
|
82
|
+
|
83
|
+
== COPYRIGHT
|
84
|
+
|
85
|
+
Copyright 2012 Christoffer Lervåg
|
86
|
+
|
87
|
+
This program is free software: you can redistribute it and/or modify
|
88
|
+
it under the terms of the GNU General Public License as published by
|
89
|
+
the Free Software Foundation, either version 3 of the License, or
|
90
|
+
(at your option) any later version.
|
91
|
+
|
92
|
+
This program is distributed in the hope that it will be useful,
|
93
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
94
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
95
|
+
GNU General Public License for more details.
|
96
|
+
|
97
|
+
You should have received a copy of the GNU General Public License
|
98
|
+
along with this program. If not, see http://www.gnu.org/licenses/ .
|
99
|
+
|
100
|
+
|
101
|
+
== ABOUT THE AUTHOR
|
102
|
+
|
103
|
+
* Name: Christoffer Lervåg
|
104
|
+
* Location: Norway
|
105
|
+
* Email: chris.lervag [@nospam.com] @gmail.com
|
106
|
+
|
107
|
+
Please don't hesitate to email me if you have any feedback related to this project!
|
data/lib/rtkit.rb
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
# Loads files and libraries that are used by RTKIT.
|
2
|
+
# Configures some DICOM and UID settings.
|
3
|
+
#
|
4
|
+
|
5
|
+
# Logging:
|
6
|
+
require_relative 'rtkit/logging'
|
7
|
+
# Super classes/modules:
|
8
|
+
require_relative 'rtkit/series'
|
9
|
+
require_relative 'rtkit/pixel_data'
|
10
|
+
require_relative 'rtkit/mixins/image_parent'
|
11
|
+
# Subclasses and independent classes:
|
12
|
+
# Collection classes:
|
13
|
+
require_relative 'rtkit/data_set'
|
14
|
+
require_relative 'rtkit/frame'
|
15
|
+
require_relative 'rtkit/patient'
|
16
|
+
require_relative 'rtkit/study'
|
17
|
+
require_relative 'rtkit/image_series'
|
18
|
+
require_relative 'rtkit/structure_set'
|
19
|
+
require_relative 'rtkit/plan'
|
20
|
+
require_relative 'rtkit/rt_dose'
|
21
|
+
require_relative 'rtkit/rt_image'
|
22
|
+
# Image related:
|
23
|
+
require_relative 'rtkit/dose_volume'
|
24
|
+
require_relative 'rtkit/image'
|
25
|
+
require_relative 'rtkit/plane'
|
26
|
+
# Dose related:
|
27
|
+
require_relative 'rtkit/dose_distribution'
|
28
|
+
require_relative 'rtkit/dose'
|
29
|
+
# Segmentation related:
|
30
|
+
require_relative 'rtkit/roi'
|
31
|
+
require_relative 'rtkit/slice'
|
32
|
+
require_relative 'rtkit/contour'
|
33
|
+
require_relative 'rtkit/coordinate'
|
34
|
+
require_relative 'rtkit/bin_matcher'
|
35
|
+
require_relative 'rtkit/bin_volume'
|
36
|
+
require_relative 'rtkit/bin_image'
|
37
|
+
require_relative 'rtkit/staple'
|
38
|
+
require_relative 'rtkit/selection'
|
39
|
+
# Plan related:
|
40
|
+
require_relative 'rtkit/setup'
|
41
|
+
require_relative 'rtkit/beam'
|
42
|
+
require_relative 'rtkit/control_point'
|
43
|
+
require_relative 'rtkit/collimator'
|
44
|
+
require_relative 'rtkit/collimator_setup'
|
45
|
+
# Module settings:
|
46
|
+
require_relative 'rtkit/version'
|
47
|
+
require_relative 'rtkit/constants'
|
48
|
+
require_relative 'rtkit/variables'
|
49
|
+
require_relative 'rtkit/methods'
|
50
|
+
# Extensions to the Ruby library:
|
51
|
+
require_relative 'rtkit/ruby_extensions'
|
52
|
+
|
53
|
+
# Ruby Standard Library dependencies:
|
54
|
+
require 'find'
|
55
|
+
require 'matrix'
|
56
|
+
require 'set'
|
57
|
+
|
58
|
+
# External dependencies:
|
59
|
+
require 'dicom'
|
60
|
+
require 'narray'
|
61
|
+
|
62
|
+
# Modify the source application entity title of the DICOM module:
|
63
|
+
DICOM.source_app_title = "RTKIT"
|
64
|
+
# Set a high threshold for the log level of the DICOM module's logger:
|
65
|
+
DICOM.logger.level = Logger::FATAL
|
66
|
+
|
67
|
+
# Use ruby-dicom's UID as our DICOM Root UID:
|
68
|
+
RTKIT.dicom_root = DICOM::UID
|
data/lib/rtkit/beam.rb
ADDED
@@ -0,0 +1,346 @@
|
|
1
|
+
module RTKIT
|
2
|
+
|
3
|
+
# Contains DICOM data and methods related to a Beam, defined in a Plan.
|
4
|
+
#
|
5
|
+
# === Relations
|
6
|
+
#
|
7
|
+
# * A Plan has many Beams.
|
8
|
+
# * A Beam has many ControlPoints.
|
9
|
+
#
|
10
|
+
class Beam
|
11
|
+
|
12
|
+
# An array containing the beam's ControlPoints.
|
13
|
+
attr_reader :control_points
|
14
|
+
# Treatment delivery type.
|
15
|
+
attr_reader :delivery_type
|
16
|
+
# Beam description.
|
17
|
+
attr_reader :description
|
18
|
+
# Treatment machine name.
|
19
|
+
attr_reader :machine
|
20
|
+
# Beam meterset.
|
21
|
+
attr_reader :meterset
|
22
|
+
# Beam Name.
|
23
|
+
attr_reader :name
|
24
|
+
# Beam Number (Integer).
|
25
|
+
attr_reader :number
|
26
|
+
# The Plan that the Beam is defined in.
|
27
|
+
attr_reader :plan
|
28
|
+
# Radiation type.
|
29
|
+
attr_reader :rad_type
|
30
|
+
# Source-axis distance.
|
31
|
+
attr_reader :sad
|
32
|
+
# Beam type.
|
33
|
+
attr_reader :type
|
34
|
+
# Primary dosimeter unit.
|
35
|
+
attr_reader :unit
|
36
|
+
|
37
|
+
# Creates a new beam instance from the beam item of the RTPlan file
|
38
|
+
# which contains the information related to a particular beam.
|
39
|
+
# This method also creates and connects any child structures as indicated in the items (e.g. ControlPoints).
|
40
|
+
# Returns the Beam instance.
|
41
|
+
#
|
42
|
+
# === Parameters
|
43
|
+
#
|
44
|
+
# * <tt>beam_item</tt> -- The Beam's Item from the Beam Sequence in the DObject of a RTPlan file.
|
45
|
+
# * <tt>meterset</tt> -- The Beam's meterset (e.g. monitor units) value.
|
46
|
+
# * <tt>plan</tt> -- The Plan instance that this Beam belongs to.
|
47
|
+
#
|
48
|
+
def self.create_from_item(beam_item, meterset, plan)
|
49
|
+
raise ArgumentError, "Invalid argument 'beam_item'. Expected DICOM::Item, got #{beam_item.class}." unless beam_item.is_a?(DICOM::Item)
|
50
|
+
raise ArgumentError, "Invalid argument 'meterset'. Expected Float, got #{meterset.class}." unless meterset.is_a?(Float)
|
51
|
+
raise ArgumentError, "Invalid argument 'plan'. Expected Plan, got #{plan.class}." unless plan.is_a?(Plan)
|
52
|
+
options = Hash.new
|
53
|
+
# Values from the Structure Set ROI Sequence Item:
|
54
|
+
name = beam_item.value(BEAM_NAME) || ''
|
55
|
+
number = beam_item.value(BEAM_NUMBER).to_i
|
56
|
+
machine = beam_item.value(MACHINE_NAME) || ''
|
57
|
+
options[:type] = beam_item.value(BEAM_TYPE)
|
58
|
+
options[:delivery_type] = beam_item.value(DELIVERY_TYPE)
|
59
|
+
options[:description] = beam_item.value(BEAM_DESCR)
|
60
|
+
options[:rad_type] = beam_item.value(RAD_TYPE)
|
61
|
+
options[:sad] = beam_item.value(SAD).to_f
|
62
|
+
options[:unit] = beam_item.value(DOSIMETER_UNIT)
|
63
|
+
# Create the Beam instance:
|
64
|
+
beam = self.new(name, number, machine, meterset, plan, options)
|
65
|
+
# Iterate the RT Beam Limiting Device items and create Collimator instances:
|
66
|
+
if beam_item.exists?(COLL_SQ)
|
67
|
+
beam_item[COLL_SQ].each do |coll_item|
|
68
|
+
Collimator.create_from_item(coll_item, beam)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
# Iterate the control point items and create ControlPoint instances:
|
72
|
+
beam_item[CONTROL_POINT_SQ].each do |cp_item|
|
73
|
+
ControlPoint.create_from_item(cp_item, beam)
|
74
|
+
end
|
75
|
+
return beam
|
76
|
+
end
|
77
|
+
|
78
|
+
# Creates a new Beam instance.
|
79
|
+
#
|
80
|
+
# === Parameters
|
81
|
+
#
|
82
|
+
# * <tt>name</tt> -- String. The Beam name.
|
83
|
+
# * <tt>number</tt> -- Integer. The Beam number.
|
84
|
+
# * <tt>machine</tt> -- The name of the treatment machine.
|
85
|
+
# * <tt>meterset</tt> -- The Beam's meterset (e.g. monitor units) value.
|
86
|
+
# * <tt>plan</tt> -- The Plan instance that this Beam belongs to.
|
87
|
+
# * <tt>options</tt> -- A hash of parameters.
|
88
|
+
#
|
89
|
+
# === Options
|
90
|
+
#
|
91
|
+
# * <tt>:type</tt> -- String. Beam type. Defaults to 'STATIC'.
|
92
|
+
# * <tt>:delivery_type</tt> -- String. Treatment delivery type. Defaults to 'TREATMENT'.
|
93
|
+
# * <tt>:description</tt> -- String. Beam description. Defaults to the 'name' attribute.
|
94
|
+
# * <tt>:rad_type</tt> -- String. Radiation type. Defaults to 'PHOTON'.
|
95
|
+
# * <tt>:sad</tt> -- Float. Source-axis distance. Defaults to 1000.0.
|
96
|
+
# * <tt>:unit</tt> -- String. The primary dosimeter unit. Defaults to 'MU'.
|
97
|
+
#
|
98
|
+
def initialize(name, number, machine, meterset, plan, options={})
|
99
|
+
raise ArgumentError, "Invalid argument 'plan'. Expected Plan, got #{plan.class}." unless plan.is_a?(Plan)
|
100
|
+
@control_points = Array.new
|
101
|
+
@collimators = Array.new
|
102
|
+
@associated_control_points = Hash.new
|
103
|
+
@associated_collimators = Hash.new
|
104
|
+
# Set values:
|
105
|
+
self.name = name
|
106
|
+
self.number = number
|
107
|
+
self.machine = machine
|
108
|
+
self.meterset = meterset
|
109
|
+
# Set options/defaults:
|
110
|
+
self.type = options[:type] || 'STATIC'
|
111
|
+
self.delivery_type = options[:delivery_type] || 'TREATMENT'
|
112
|
+
self.description = options[:description] || @name
|
113
|
+
self.rad_type = options[:rad_type] || 'PHOTON'
|
114
|
+
self.sad = options[:sad] ? options[:sad] : 1000.0
|
115
|
+
self.unit = options[:unit] || 'MU'
|
116
|
+
# Set references:
|
117
|
+
@plan = plan
|
118
|
+
# Register ourselves with the Plan:
|
119
|
+
@plan.add_beam(self)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Returns true if the argument is an instance with attributes equal to self.
|
123
|
+
#
|
124
|
+
def ==(other)
|
125
|
+
if other.respond_to?(:to_beam)
|
126
|
+
other.send(:state) == state
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
alias_method :eql?, :==
|
131
|
+
|
132
|
+
# Adds a Collimator instance to this Beam.
|
133
|
+
#
|
134
|
+
def add_collimator(coll)
|
135
|
+
raise ArgumentError, "Invalid argument 'coll'. Expected Collimator, got #{coll.class}." unless coll.is_a?(Collimator)
|
136
|
+
@collimators << coll unless @associated_collimators[coll.type]
|
137
|
+
@associated_collimators[coll.type] = coll
|
138
|
+
end
|
139
|
+
|
140
|
+
# Adds a ControlPoint instance to this Beam.
|
141
|
+
#
|
142
|
+
def add_control_point(cp)
|
143
|
+
raise ArgumentError, "Invalid argument 'cp'. Expected ControlPoint, got #{cp.class}." unless cp.is_a?(ControlPoint)
|
144
|
+
@control_points << cp unless @associated_control_points[cp]
|
145
|
+
@associated_control_points[cp] = true
|
146
|
+
end
|
147
|
+
|
148
|
+
# Creates and returns a Beam Sequence Item from the attributes of the Beam.
|
149
|
+
#
|
150
|
+
def beam_item
|
151
|
+
item = DICOM::Item.new
|
152
|
+
item.add(DICOM::Element.new(ROI_COLOR, @color))
|
153
|
+
s = DICOM::Sequence.new(CONTOUR_SQ)
|
154
|
+
item.add(s)
|
155
|
+
item.add(DICOM::Element.new(REF_ROI_NUMBER, @number.to_s))
|
156
|
+
# Add Contour items to the Contour Sequence (one or several items per Slice):
|
157
|
+
@slices.each do |slice|
|
158
|
+
slice.contours.each do |contour|
|
159
|
+
s.add_item(contour.to_item)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
return item
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns the Collimator instance mathcing the specified type (if an argument is used).
|
166
|
+
# If a specified type doesn't match, nil is returned.
|
167
|
+
# If no argument is passed, the first Collimator instance associated with the Beam is returned.
|
168
|
+
#
|
169
|
+
# === Parameters
|
170
|
+
#
|
171
|
+
# * <tt>type</tt> -- Integer. The Collimator's type.
|
172
|
+
#
|
173
|
+
def collimator(*args)
|
174
|
+
raise ArgumentError, "Expected one or none arguments, got #{args.length}." unless [0, 1].include?(args.length)
|
175
|
+
if args.length == 1
|
176
|
+
return @associated_collimators[args.first && args.first.to_s]
|
177
|
+
else
|
178
|
+
# No argument used, therefore we return the first instance:
|
179
|
+
return @collimators.first
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Returns the ControlPoint instance mathcing the specified index (if an argument is used).
|
184
|
+
# If a specified index doesn't match, nil is returned.
|
185
|
+
# If no argument is passed, the first ControlPoint instance associated with the Beam is returned.
|
186
|
+
#
|
187
|
+
# === Parameters
|
188
|
+
#
|
189
|
+
# * <tt>index</tt> -- Integer. The ControlPoint's index.
|
190
|
+
#
|
191
|
+
def control_point(*args)
|
192
|
+
raise ArgumentError, "Expected one or none arguments, got #{args.length}." unless [0, 1].include?(args.length)
|
193
|
+
if args.length == 1
|
194
|
+
raise ArgumentError, "Invalid argument 'index'. Expected Integer (or nil), got #{args.first.class}." unless [Integer, NilClass].include?(args.first.class)
|
195
|
+
return @associated_control_points[args.first]
|
196
|
+
else
|
197
|
+
# No argument used, therefore we return the first instance:
|
198
|
+
return @control_points.first
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
# Sets a new treatment delivery type for this Beam.
|
203
|
+
#
|
204
|
+
# === Parameters
|
205
|
+
#
|
206
|
+
# * <tt>value</tt> -- String. The treatment delivery type.
|
207
|
+
#
|
208
|
+
def delivery_type=(value)
|
209
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
210
|
+
@delivery_type = value
|
211
|
+
end
|
212
|
+
|
213
|
+
# Sets a new description for this Beam.
|
214
|
+
#
|
215
|
+
# === Parameters
|
216
|
+
#
|
217
|
+
# * <tt>value</tt> -- String. The beam description.
|
218
|
+
#
|
219
|
+
def description=(value)
|
220
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
221
|
+
@description = value
|
222
|
+
end
|
223
|
+
|
224
|
+
# Generates a Fixnum hash value for this instance.
|
225
|
+
#
|
226
|
+
def hash
|
227
|
+
state.hash
|
228
|
+
end
|
229
|
+
|
230
|
+
# Sets a new machine for this Beam.
|
231
|
+
#
|
232
|
+
# === Parameters
|
233
|
+
#
|
234
|
+
# * <tt>value</tt> -- String. The machine of the beam.
|
235
|
+
#
|
236
|
+
def machine=(value)
|
237
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
238
|
+
@machine = value
|
239
|
+
end
|
240
|
+
|
241
|
+
# Sets a new meterset for this Beam.
|
242
|
+
#
|
243
|
+
# === Parameters
|
244
|
+
#
|
245
|
+
# * <tt>value</tt> -- Float. The beam meterset.
|
246
|
+
#
|
247
|
+
def meterset=(value)
|
248
|
+
raise ArgumentError, "Invalid argument 'value'. Expected Float, got #{value.class}." unless value.is_a?(Float)
|
249
|
+
@meterset = value
|
250
|
+
end
|
251
|
+
|
252
|
+
# Sets a new name for this Beam.
|
253
|
+
#
|
254
|
+
# === Parameters
|
255
|
+
#
|
256
|
+
# * <tt>value</tt> -- String. The beam name.
|
257
|
+
#
|
258
|
+
def name=(value)
|
259
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
260
|
+
@name = value
|
261
|
+
end
|
262
|
+
|
263
|
+
# Sets a new number for this Beam.
|
264
|
+
#
|
265
|
+
# === Parameters
|
266
|
+
#
|
267
|
+
# * <tt>value</tt> -- Integer. The beam number.
|
268
|
+
#
|
269
|
+
def number=(value)
|
270
|
+
raise ArgumentError, "Invalid argument 'value'. Expected Integer, got #{value.class}." unless value.is_a?(Integer)
|
271
|
+
@number = value
|
272
|
+
end
|
273
|
+
|
274
|
+
# Sets a new radiation type for this Beam.
|
275
|
+
#
|
276
|
+
# === Parameters
|
277
|
+
#
|
278
|
+
# * <tt>value</tt> -- String. The radiation type.
|
279
|
+
#
|
280
|
+
def rad_type=(value)
|
281
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
282
|
+
@rad_type = value
|
283
|
+
end
|
284
|
+
|
285
|
+
# Creates and returns a Referenced Beam Sequence Item from the attributes of the Beam.
|
286
|
+
#
|
287
|
+
def ref_beam_item
|
288
|
+
item = DICOM::Item.new
|
289
|
+
item.add(DICOM::Element.new(OBS_NUMBER, @number.to_s))
|
290
|
+
item.add(DICOM::Element.new(REF_ROI_NUMBER, @number.to_s))
|
291
|
+
item.add(DICOM::Element.new(ROI_TYPE, @type))
|
292
|
+
item.add(DICOM::Element.new(ROI_INTERPRETER, @interpreter))
|
293
|
+
return item
|
294
|
+
end
|
295
|
+
|
296
|
+
# Sets a new source-axis distance for this Beam.
|
297
|
+
#
|
298
|
+
# === Parameters
|
299
|
+
#
|
300
|
+
# * <tt>value</tt> -- Float. The source-axis distance.
|
301
|
+
#
|
302
|
+
def sad=(value)
|
303
|
+
raise ArgumentError, "Invalid argument 'value'. Expected Float, got #{value.class}." unless value.is_a?(Float)
|
304
|
+
@sad = value
|
305
|
+
end
|
306
|
+
|
307
|
+
# Returns self.
|
308
|
+
#
|
309
|
+
def to_beam
|
310
|
+
self
|
311
|
+
end
|
312
|
+
|
313
|
+
# Sets a new beam type for this Beam.
|
314
|
+
#
|
315
|
+
# === Parameters
|
316
|
+
#
|
317
|
+
# * <tt>value</tt> -- String. The beam type.
|
318
|
+
#
|
319
|
+
def type=(value)
|
320
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
321
|
+
@type = value
|
322
|
+
end
|
323
|
+
|
324
|
+
# Sets a new primary dosimeter unit for this Beam.
|
325
|
+
#
|
326
|
+
# === Parameters
|
327
|
+
#
|
328
|
+
# * <tt>value</tt> -- String. The primary dosimeter unit.
|
329
|
+
#
|
330
|
+
def unit=(value)
|
331
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
332
|
+
@unit = value
|
333
|
+
end
|
334
|
+
|
335
|
+
|
336
|
+
private
|
337
|
+
|
338
|
+
|
339
|
+
# Returns the attributes of this instance in an array (for comparison purposes).
|
340
|
+
#
|
341
|
+
def state
|
342
|
+
[@delivery_type, @description, @machine, @meterset, @name, @number, @rad_type, @sad, @type, @unit, @control_points]
|
343
|
+
end
|
344
|
+
|
345
|
+
end
|
346
|
+
end
|