rtp-connect 1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +9 -0
- data/COPYING +674 -0
- data/README.rdoc +128 -0
- data/lib/rtp-connect.rb +20 -0
- data/lib/rtp-connect/constants.rb +58 -0
- data/lib/rtp-connect/control_point.rb +444 -0
- data/lib/rtp-connect/extended_field.rb +127 -0
- data/lib/rtp-connect/field.rb +578 -0
- data/lib/rtp-connect/logging.rb +158 -0
- data/lib/rtp-connect/methods.rb +31 -0
- data/lib/rtp-connect/plan.rb +545 -0
- data/lib/rtp-connect/prescription.rb +218 -0
- data/lib/rtp-connect/record.rb +37 -0
- data/lib/rtp-connect/ruby_extensions.rb +82 -0
- data/lib/rtp-connect/site_setup.rb +227 -0
- data/lib/rtp-connect/variables.rb +19 -0
- data/lib/rtp-connect/version.rb +6 -0
- metadata +113 -0
data/README.rdoc
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
= RTPConnect
|
2
|
+
|
3
|
+
The RTPConnect library allows you to read, edit and write RTPConnect files in Ruby.
|
4
|
+
RTPConnect is a file format used in radiotherapy (e.g. Mosaiq) for export & import
|
5
|
+
of treatment planning data. The library is written entirely in Ruby and has no
|
6
|
+
external dependencies.
|
7
|
+
|
8
|
+
|
9
|
+
== INSTALLATION
|
10
|
+
|
11
|
+
gem install rtp-connect
|
12
|
+
|
13
|
+
|
14
|
+
== REQUIREMENTS
|
15
|
+
|
16
|
+
* Ruby 1.9.2
|
17
|
+
|
18
|
+
|
19
|
+
== BASIC USAGE
|
20
|
+
|
21
|
+
=== Load & Include
|
22
|
+
|
23
|
+
require 'rtp-connect'
|
24
|
+
include RTP
|
25
|
+
|
26
|
+
=== Read, modify and write
|
27
|
+
|
28
|
+
# Read file:
|
29
|
+
rtp = Plan.read("some_file.rtp")
|
30
|
+
# Extract the Patient's Name:
|
31
|
+
name = rtp.patient_last_name
|
32
|
+
# Modify the Patient's Name:
|
33
|
+
rtp.patient_last_name = "Anonymous"
|
34
|
+
# Write to file:
|
35
|
+
rtp.write("new_file.rtp")
|
36
|
+
|
37
|
+
=== Create a new Plan Definition Record from scratch
|
38
|
+
|
39
|
+
# Create the instance:
|
40
|
+
rtp = Plan.new
|
41
|
+
# Set the Patient's ID attribute:
|
42
|
+
rtp.patient_id = "12345"
|
43
|
+
# Export the instance to an RTP string (with CRC):
|
44
|
+
output = rtp.to_str
|
45
|
+
|
46
|
+
=== Log settings
|
47
|
+
|
48
|
+
# Change the log level so that only error messages are displayed:
|
49
|
+
RTP.logger.level = Logger::ERROR
|
50
|
+
# Setting up a simple file log:
|
51
|
+
l = Logger.new('my_logfile.log')
|
52
|
+
RTP.logger = l
|
53
|
+
# Create a logger which ages logfile daily/monthly:
|
54
|
+
RTP.logger = Logger.new('foo.log', 'daily')
|
55
|
+
RTP.logger = Logger.new('foo.log', 'monthly')
|
56
|
+
|
57
|
+
=== Scripts
|
58
|
+
|
59
|
+
For more thorough examples, check out the scripts folder which contains
|
60
|
+
numerous ruby scripts that shows of real world usage scenarios of the
|
61
|
+
RTPConnect library.
|
62
|
+
|
63
|
+
=== IRB Tip
|
64
|
+
|
65
|
+
When working with the RTPConnect library in irb, you may be annoyed with all
|
66
|
+
the information that is printed to screen, regardless of your log level.
|
67
|
+
This is because in irb every variable loaded in the program is
|
68
|
+
automatically printed to the screen. A useful hack to avoid this effect is
|
69
|
+
to append ";0" after a command.
|
70
|
+
|
71
|
+
Example:
|
72
|
+
rtp = Plan.read("some_file.rtp") ;0
|
73
|
+
|
74
|
+
|
75
|
+
== RESOURCES
|
76
|
+
|
77
|
+
* {Rubygems download}[https://rubygems.org/gems/rtp-connect]
|
78
|
+
* {Source code repository}[https://github.com/dicom/rtp-connect]
|
79
|
+
|
80
|
+
|
81
|
+
== RESTRICTIONS
|
82
|
+
|
83
|
+
=== Supported records
|
84
|
+
|
85
|
+
* Plan definition [PLAN_DEF]
|
86
|
+
* Prescription site [RX_DEF]
|
87
|
+
* Site setup [SITE_SETUP_DEF]
|
88
|
+
* Treatment field [FIELD_DEF]
|
89
|
+
* Extended treatment field [EXTENDED_FIELD_DEF]
|
90
|
+
* Control point record [CONTROL_PT_DEF]
|
91
|
+
|
92
|
+
=== Unsupported records
|
93
|
+
|
94
|
+
* Simulation field [SIM_DEF]
|
95
|
+
* Document based treatment field [PDF_FIELD_DEF]
|
96
|
+
* Multileaf collimator [MLC_DEF]
|
97
|
+
* MLC shape [MLC_SHAPE_DEF]
|
98
|
+
* Dose tracking record [DOSE_DEF]
|
99
|
+
* Dose action points [DOSE_ACTION]
|
100
|
+
|
101
|
+
If you encounter an RTP file with an unsupported record type, please contact me.
|
102
|
+
|
103
|
+
|
104
|
+
== COPYRIGHT
|
105
|
+
|
106
|
+
Copyright 2011 Christoffer Lervag
|
107
|
+
|
108
|
+
This program is free software: you can redistribute it and/or modify
|
109
|
+
it under the terms of the GNU General Public License as published by
|
110
|
+
the Free Software Foundation, either version 3 of the License, or
|
111
|
+
(at your option) any later version.
|
112
|
+
|
113
|
+
This program is distributed in the hope that it will be useful,
|
114
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
115
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
116
|
+
GNU General Public License for more details.
|
117
|
+
|
118
|
+
You should have received a copy of the GNU General Public License
|
119
|
+
along with this program. If not, see http://www.gnu.org/licenses/ .
|
120
|
+
|
121
|
+
|
122
|
+
== ABOUT THE AUTHOR
|
123
|
+
|
124
|
+
* Name: Christoffer Lervag
|
125
|
+
* Location: Norway
|
126
|
+
* Email: chris.lervag [@nospam.com] @gmail.com
|
127
|
+
|
128
|
+
Please don't hesitate to email me if you have any feedback related to this project!
|
data/lib/rtp-connect.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Loads the files that are used by the RTPConnect library.
|
2
|
+
|
3
|
+
# Logging:
|
4
|
+
require_relative 'rtp-connect/logging'
|
5
|
+
# Super classes:
|
6
|
+
require_relative 'rtp-connect/record'
|
7
|
+
# Core library:
|
8
|
+
require_relative 'rtp-connect/plan'
|
9
|
+
require_relative 'rtp-connect/prescription'
|
10
|
+
require_relative 'rtp-connect/site_setup'
|
11
|
+
require_relative 'rtp-connect/field'
|
12
|
+
require_relative 'rtp-connect/extended_field'
|
13
|
+
require_relative 'rtp-connect/control_point'
|
14
|
+
# Extensions to the Ruby library:
|
15
|
+
require_relative 'rtp-connect/ruby_extensions'
|
16
|
+
# Module settings:
|
17
|
+
require_relative 'rtp-connect/version'
|
18
|
+
require_relative 'rtp-connect/constants'
|
19
|
+
require_relative 'rtp-connect/methods'
|
20
|
+
require_relative 'rtp-connect/variables'
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module RTP
|
2
|
+
|
3
|
+
# The seed value used in the RTPConnect implementation of the CCITT algorithm.
|
4
|
+
CRC_SEED = 0x0521
|
5
|
+
|
6
|
+
# The table & values used in the RTPConnect implementation of the CCITT algorithm.
|
7
|
+
CRC_TABLE = [
|
8
|
+
0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
|
9
|
+
0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
|
10
|
+
0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
|
11
|
+
0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
|
12
|
+
0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
|
13
|
+
0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
|
14
|
+
0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
|
15
|
+
0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
|
16
|
+
0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
|
17
|
+
0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
|
18
|
+
0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
|
19
|
+
0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
|
20
|
+
0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
|
21
|
+
0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
|
22
|
+
0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
|
23
|
+
0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
|
24
|
+
0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
|
25
|
+
0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
|
26
|
+
0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
|
27
|
+
0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
|
28
|
+
0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
|
29
|
+
0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
|
30
|
+
0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
|
31
|
+
0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
|
32
|
+
0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
|
33
|
+
0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
|
34
|
+
0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
|
35
|
+
0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
|
36
|
+
0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
|
37
|
+
0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
|
38
|
+
0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
|
39
|
+
0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
|
40
|
+
]
|
41
|
+
|
42
|
+
# Pairs of RTPConnect keywords and parse method names.
|
43
|
+
PARSE_METHOD = {
|
44
|
+
"PLAN_DEF" => :plan_definition,
|
45
|
+
"RX_DEF" => :prescription_site,
|
46
|
+
"SITE_SETUP_DEF" => :site_setup,
|
47
|
+
"SIM_DEF" => :simulation_field,
|
48
|
+
"FIELD_DEF" => :treatment_field,
|
49
|
+
"EXTENDED_FIELD_DEF" => :extended_treatment_field,
|
50
|
+
"PDF_FIELD_DEF" => :document_based_treatment_field,
|
51
|
+
"MLC_DEF" => :multileaf_collimator,
|
52
|
+
"CONTROL_PT_DEF" => :control_point,
|
53
|
+
"MLC_SHAPE_DEF" => :mlc_shape,
|
54
|
+
"DOSE_DEF" => :dose_tracking,
|
55
|
+
"DOSE_ACTION" => :dose_action,
|
56
|
+
}
|
57
|
+
|
58
|
+
end
|
@@ -0,0 +1,444 @@
|
|
1
|
+
module RTP
|
2
|
+
|
3
|
+
# The ControlPoint class.
|
4
|
+
#
|
5
|
+
# === Relations
|
6
|
+
#
|
7
|
+
# * Parent: Field
|
8
|
+
# * Children: MLCShape
|
9
|
+
#
|
10
|
+
class ControlPoint < Record
|
11
|
+
|
12
|
+
# The Record which this instance belongs to.
|
13
|
+
attr_reader :parent
|
14
|
+
# The MLC shape record (if any) that belongs to this ControlPoint.
|
15
|
+
attr_reader :mlc_shape
|
16
|
+
attr_reader :field_id
|
17
|
+
attr_reader :mlc_type
|
18
|
+
attr_reader :mlc_leaves
|
19
|
+
attr_reader :total_control_points
|
20
|
+
attr_reader :control_pt_number
|
21
|
+
attr_reader :mu_convention
|
22
|
+
attr_reader :monitor_units
|
23
|
+
attr_reader :wedge_position
|
24
|
+
attr_reader :energy
|
25
|
+
attr_reader :doserate
|
26
|
+
attr_reader :ssd
|
27
|
+
attr_reader :scale_convention
|
28
|
+
attr_reader :gantry_angle
|
29
|
+
attr_reader :gantry_dir
|
30
|
+
attr_reader :collimator_angle
|
31
|
+
attr_reader :collimator_dir
|
32
|
+
attr_reader :field_x_mode
|
33
|
+
attr_reader :field_x
|
34
|
+
attr_reader :collimator_x1
|
35
|
+
attr_reader :collimator_x2
|
36
|
+
attr_reader :field_y_mode
|
37
|
+
attr_reader :field_y
|
38
|
+
attr_reader :collimator_y1
|
39
|
+
attr_reader :collimator_y2
|
40
|
+
attr_reader :couch_vertical
|
41
|
+
attr_reader :couch_lateral
|
42
|
+
attr_reader :couch_longitudinal
|
43
|
+
attr_reader :couch_angle
|
44
|
+
attr_reader :couch_dir
|
45
|
+
attr_reader :couch_pedestal
|
46
|
+
attr_reader :couch_ped_dir
|
47
|
+
# Note: This attribute contains an array of all MLC LP A values (leaves 1..100).
|
48
|
+
attr_reader :mlc_lp_a
|
49
|
+
# Note: This attribute contains an array of all MLC LP B values (leaves 1..100).
|
50
|
+
attr_reader :mlc_lp_b
|
51
|
+
|
52
|
+
# Creates a new ControlPoint by parsing a RTPConnect string line.
|
53
|
+
#
|
54
|
+
# === Parameters
|
55
|
+
#
|
56
|
+
# * <tt>string</tt> -- A string containing a control point record.
|
57
|
+
# * <tt>parent</tt> -- A Record which is used to determine the proper parent of this instance.
|
58
|
+
#
|
59
|
+
def self.load(string, parent)
|
60
|
+
raise ArgumentError, "Invalid argument 'string'. Expected String, got #{string.class}." unless string.is_a?(String)
|
61
|
+
raise ArgumentError, "Invalid argument 'parent'. Expected RTP::Record, got #{parent.class}." unless parent.is_a?(RTP::Record)
|
62
|
+
# Get the quote-less values:
|
63
|
+
values = string.values
|
64
|
+
raise ArgumentError, "Invalid argument 'string': Expected exactly 233 elements, got #{values.length}." unless values.length == 233
|
65
|
+
f = self.new(parent)
|
66
|
+
# Assign the values to attributes:
|
67
|
+
f.keyword = values[0]
|
68
|
+
f.field_id = values[1]
|
69
|
+
f.mlc_type = values[2]
|
70
|
+
f.mlc_leaves = values[3]
|
71
|
+
f.total_control_points = values[4]
|
72
|
+
f.control_pt_number = values[5]
|
73
|
+
f.mu_convention = values[6]
|
74
|
+
f.monitor_units = values[7]
|
75
|
+
f.wedge_position = values[8]
|
76
|
+
f.energy = values[9]
|
77
|
+
f.doserate = values[10]
|
78
|
+
f.ssd = values[11]
|
79
|
+
f.scale_convention = values[12]
|
80
|
+
f.gantry_angle = values[13]
|
81
|
+
f.gantry_dir = values[14]
|
82
|
+
f.collimator_angle = values[15]
|
83
|
+
f.collimator_dir = values[16]
|
84
|
+
f.field_x_mode = values[17]
|
85
|
+
f.field_x = values[18]
|
86
|
+
f.collimator_x1 = values[19]
|
87
|
+
f.collimator_x2 = values[20]
|
88
|
+
f.field_y_mode = values[21]
|
89
|
+
f.field_y = values[22]
|
90
|
+
f.collimator_y1 = values[23]
|
91
|
+
f.collimator_y2 = values[24]
|
92
|
+
f.couch_vertical = values[25]
|
93
|
+
f.couch_lateral = values[26]
|
94
|
+
f.couch_longitudinal = values[27]
|
95
|
+
f.couch_angle = values[28]
|
96
|
+
f.couch_dir = values[29]
|
97
|
+
f.couch_pedestal = values[30]
|
98
|
+
f.couch_ped_dir = values[31]
|
99
|
+
f.mlc_lp_a = [*values[32..131]]
|
100
|
+
f.mlc_lp_b = [*values[132..231]]
|
101
|
+
f.crc = values[232]
|
102
|
+
return f
|
103
|
+
end
|
104
|
+
|
105
|
+
# Creates a new ControlPoint.
|
106
|
+
#
|
107
|
+
# === Parameters
|
108
|
+
#
|
109
|
+
# * <tt>parent</tt> -- A Record which is used to determine the proper parent of this instance.
|
110
|
+
#
|
111
|
+
def initialize(parent)
|
112
|
+
raise ArgumentError, "Invalid argument 'parent'. Expected RTP::Record, got #{parent.class}." unless parent.is_a?(RTP::Record)
|
113
|
+
# Child:
|
114
|
+
@mlc_shape = nil
|
115
|
+
# Parent relation:
|
116
|
+
@parent = get_parent(parent, Field)
|
117
|
+
@parent.add_control_point(self)
|
118
|
+
@keyword = 'CONTROL_PT_DEF'
|
119
|
+
@mlc_lp_a = Array.new(100)
|
120
|
+
@mlc_lp_b = Array.new(100)
|
121
|
+
end
|
122
|
+
|
123
|
+
# As of now, returns an empty array.
|
124
|
+
# However, by definition, this record may have an mlc shape record as child,
|
125
|
+
# but this is not implemented yet.
|
126
|
+
#
|
127
|
+
def children
|
128
|
+
#return [@mlc_shape]
|
129
|
+
return Array.new
|
130
|
+
end
|
131
|
+
|
132
|
+
# Returns the values of this instance in an array.
|
133
|
+
# The values does not include the CRC.
|
134
|
+
#
|
135
|
+
def values
|
136
|
+
return [
|
137
|
+
@keyword,
|
138
|
+
@field_id,
|
139
|
+
@mlc_type,
|
140
|
+
@mlc_leaves,
|
141
|
+
@total_control_points,
|
142
|
+
@control_pt_number,
|
143
|
+
@mu_convention,
|
144
|
+
@monitor_units,
|
145
|
+
@wedge_position,
|
146
|
+
@energy,
|
147
|
+
@doserate,
|
148
|
+
@ssd,
|
149
|
+
@scale_convention,
|
150
|
+
@gantry_angle,
|
151
|
+
@gantry_dir,
|
152
|
+
@collimator_angle,
|
153
|
+
@collimator_dir,
|
154
|
+
@field_x_mode,
|
155
|
+
@field_x,
|
156
|
+
@collimator_x1,
|
157
|
+
@collimator_x2,
|
158
|
+
@field_y_mode,
|
159
|
+
@field_y,
|
160
|
+
@collimator_y1,
|
161
|
+
@collimator_y2,
|
162
|
+
@couch_vertical,
|
163
|
+
@couch_lateral,
|
164
|
+
@couch_longitudinal,
|
165
|
+
@couch_angle,
|
166
|
+
@couch_dir,
|
167
|
+
@couch_pedestal,
|
168
|
+
@couch_ped_dir,
|
169
|
+
*@mlc_lp_a,
|
170
|
+
*@mlc_lp_b
|
171
|
+
]
|
172
|
+
end
|
173
|
+
|
174
|
+
# Writes the ControlPoint object + any hiearchy of child objects,
|
175
|
+
# to a properly formatted RTPConnect ascii string.
|
176
|
+
#
|
177
|
+
def to_str
|
178
|
+
str = encode
|
179
|
+
if children
|
180
|
+
children.each do |child|
|
181
|
+
str += child.to_str
|
182
|
+
end
|
183
|
+
end
|
184
|
+
return str
|
185
|
+
end
|
186
|
+
|
187
|
+
# Sets the mlc_a attribute.
|
188
|
+
#
|
189
|
+
# === Notes
|
190
|
+
#
|
191
|
+
# As opposed to the ordinary (string) attributes, this attribute
|
192
|
+
# contains an array holding all 100 MLC leaf 'A' string values.
|
193
|
+
#
|
194
|
+
def mlc_lp_a=(array)
|
195
|
+
raise ArgumentError, "Invalid argument 'array'. Expected Array, got #{array.class}." unless array.is_a?(Array)
|
196
|
+
raise ArgumentError, "Invalid argument 'array'. Expected array with length 100, got #{array.length}." unless array.length == 100
|
197
|
+
unexpected_types = array.collect{|i| i.class}.uniq - [String, NilClass]
|
198
|
+
raise ArgumentError, "Invalid argument 'array'. Array must contain only string or nil values, got unexpected class #{unexpected_types}." if unexpected_types.length > 0
|
199
|
+
@mlc_lp_a = array
|
200
|
+
end
|
201
|
+
|
202
|
+
# Sets the mlc_b attribute.
|
203
|
+
#
|
204
|
+
# === Notes
|
205
|
+
#
|
206
|
+
# As opposed to the ordinary (string) attributes, this attribute
|
207
|
+
# contains an array holding all 100 MLC leaf 'A' string values.
|
208
|
+
#
|
209
|
+
def mlc_lp_b=(array)
|
210
|
+
raise ArgumentError, "Invalid argument 'array'. Expected Array, got #{array.class}." unless array.is_a?(Array)
|
211
|
+
raise ArgumentError, "Invalid argument 'array'. Expected array with length 100, got #{array.length}." unless array.length == 100
|
212
|
+
unexpected_types = array.collect{|i| i.class}.uniq - [String, NilClass]
|
213
|
+
raise ArgumentError, "Invalid argument 'array'. Array must contain only string or nil values, got unexpected class #{unexpected_types}." if unexpected_types.length > 0
|
214
|
+
@mlc_lp_b = array
|
215
|
+
end
|
216
|
+
|
217
|
+
# Sets the keyword attribute.
|
218
|
+
#
|
219
|
+
def keyword=(value)
|
220
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
221
|
+
raise ArgumentError, "Invalid keyword. Expected 'CONTROL_PT_DEF', got #{value}." unless value.upcase == "CONTROL_PT_DEF"
|
222
|
+
@keyword = value
|
223
|
+
end
|
224
|
+
|
225
|
+
# Sets the field_id attribute.
|
226
|
+
#
|
227
|
+
def field_id=(value)
|
228
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
229
|
+
@field_id = value
|
230
|
+
end
|
231
|
+
|
232
|
+
# Sets the mlc_type attribute.
|
233
|
+
#
|
234
|
+
def mlc_type=(value)
|
235
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
236
|
+
@mlc_type = value
|
237
|
+
end
|
238
|
+
|
239
|
+
# Sets the mlc_leaves attribute.
|
240
|
+
#
|
241
|
+
def mlc_leaves=(value)
|
242
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
243
|
+
@mlc_leaves = value
|
244
|
+
end
|
245
|
+
|
246
|
+
# Sets the total_control_points attribute.
|
247
|
+
#
|
248
|
+
def total_control_points=(value)
|
249
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
250
|
+
@total_control_points = value
|
251
|
+
end
|
252
|
+
|
253
|
+
# Sets the control_pt_number attribute.
|
254
|
+
#
|
255
|
+
def control_pt_number=(value)
|
256
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
257
|
+
@control_pt_number = value
|
258
|
+
end
|
259
|
+
|
260
|
+
# Sets the mu_convention attribute.
|
261
|
+
#
|
262
|
+
def mu_convention=(value)
|
263
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
264
|
+
@mu_convention = value
|
265
|
+
end
|
266
|
+
|
267
|
+
# Sets the monitor_units attribute.
|
268
|
+
#
|
269
|
+
def monitor_units=(value)
|
270
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
271
|
+
@monitor_units = value
|
272
|
+
end
|
273
|
+
|
274
|
+
# Sets the wedge_position attribute.
|
275
|
+
#
|
276
|
+
def wedge_position=(value)
|
277
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
278
|
+
@wedge_position = value
|
279
|
+
end
|
280
|
+
|
281
|
+
# Sets the energy attribute.
|
282
|
+
#
|
283
|
+
def energy=(value)
|
284
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
285
|
+
@energy = value
|
286
|
+
end
|
287
|
+
|
288
|
+
# Sets the doserate attribute.
|
289
|
+
#
|
290
|
+
def doserate=(value)
|
291
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
292
|
+
@doserate = value
|
293
|
+
end
|
294
|
+
|
295
|
+
# Sets the ssd attribute.
|
296
|
+
#
|
297
|
+
def ssd=(value)
|
298
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
299
|
+
@ssd = value
|
300
|
+
end
|
301
|
+
|
302
|
+
# Sets the scale_convention attribute.
|
303
|
+
#
|
304
|
+
def scale_convention=(value)
|
305
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
306
|
+
@scale_convention = value
|
307
|
+
end
|
308
|
+
|
309
|
+
# Sets the gantry_angle attribute.
|
310
|
+
#
|
311
|
+
def gantry_angle=(value)
|
312
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
313
|
+
@gantry_angle = value
|
314
|
+
end
|
315
|
+
|
316
|
+
# Sets the gantry_dir attribute.
|
317
|
+
#
|
318
|
+
def gantry_dir=(value)
|
319
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
320
|
+
@gantry_dir = value
|
321
|
+
end
|
322
|
+
|
323
|
+
# Sets the collimator_angle attribute.
|
324
|
+
#
|
325
|
+
def collimator_angle=(value)
|
326
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
327
|
+
@collimator_angle = value
|
328
|
+
end
|
329
|
+
|
330
|
+
# Sets the collimator_dir attribute.
|
331
|
+
#
|
332
|
+
def collimator_dir=(value)
|
333
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
334
|
+
@collimator_dir = value
|
335
|
+
end
|
336
|
+
|
337
|
+
# Sets the field_x_mode attribute.
|
338
|
+
#
|
339
|
+
def field_x_mode=(value)
|
340
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
341
|
+
@field_x_mode = value
|
342
|
+
end
|
343
|
+
|
344
|
+
# Sets the field_x attribute.
|
345
|
+
#
|
346
|
+
def field_x=(value)
|
347
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
348
|
+
@field_x = value
|
349
|
+
end
|
350
|
+
|
351
|
+
# Sets the collimator_x1 attribute.
|
352
|
+
#
|
353
|
+
def collimator_x1=(value)
|
354
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
355
|
+
@collimator_x1 = value
|
356
|
+
end
|
357
|
+
|
358
|
+
# Sets the collimator_x2 attribute.
|
359
|
+
#
|
360
|
+
def collimator_x2=(value)
|
361
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
362
|
+
@collimator_x2 = value
|
363
|
+
end
|
364
|
+
|
365
|
+
# Sets the field_y_mode attribute.
|
366
|
+
#
|
367
|
+
def field_y_mode=(value)
|
368
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
369
|
+
@field_y_mode = value
|
370
|
+
end
|
371
|
+
|
372
|
+
# Sets the field_y attribute.
|
373
|
+
#
|
374
|
+
def field_y=(value)
|
375
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
376
|
+
@field_y = value
|
377
|
+
end
|
378
|
+
|
379
|
+
# Sets the collimator_y1 attribute.
|
380
|
+
#
|
381
|
+
def collimator_y1=(value)
|
382
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
383
|
+
@collimator_y1 = value
|
384
|
+
end
|
385
|
+
|
386
|
+
# Sets the collimator_y2 attribute.
|
387
|
+
#
|
388
|
+
def collimator_y2=(value)
|
389
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
390
|
+
@collimator_y2 = value
|
391
|
+
end
|
392
|
+
|
393
|
+
# Sets the couch_vertical attribute.
|
394
|
+
#
|
395
|
+
def couch_vertical=(value)
|
396
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
397
|
+
@couch_vertical = value
|
398
|
+
end
|
399
|
+
|
400
|
+
# Sets the couch_lateral attribute.
|
401
|
+
#
|
402
|
+
def couch_lateral=(value)
|
403
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
404
|
+
@couch_lateral = value
|
405
|
+
end
|
406
|
+
|
407
|
+
# Sets the couch_longitudinal attribute.
|
408
|
+
#
|
409
|
+
def couch_longitudinal=(value)
|
410
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
411
|
+
@couch_longitudinal = value
|
412
|
+
end
|
413
|
+
|
414
|
+
# Sets the couch_angle attribute.
|
415
|
+
#
|
416
|
+
def couch_angle=(value)
|
417
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
418
|
+
@couch_angle = value
|
419
|
+
end
|
420
|
+
|
421
|
+
# Sets the couch_dir attribute.
|
422
|
+
#
|
423
|
+
def couch_dir=(value)
|
424
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
425
|
+
@couch_dir = value
|
426
|
+
end
|
427
|
+
|
428
|
+
# Sets the couch_pedestal attribute.
|
429
|
+
#
|
430
|
+
def couch_pedestal=(value)
|
431
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
432
|
+
@couch_pedestal = value
|
433
|
+
end
|
434
|
+
|
435
|
+
# Sets the couch_ped_dir attribute.
|
436
|
+
#
|
437
|
+
def couch_ped_dir=(value)
|
438
|
+
raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
|
439
|
+
@couch_ped_dir = value
|
440
|
+
end
|
441
|
+
|
442
|
+
end
|
443
|
+
|
444
|
+
end
|