rtp-connect 1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,218 @@
1
+ module RTP
2
+
3
+ # The Prescription site class.
4
+ #
5
+ # === Relations
6
+ #
7
+ # * Parent: Plan
8
+ # * Children: SiteSetup, (SimulationField), Field
9
+ #
10
+ class Prescription < Record
11
+
12
+ # The Record which this instance belongs to.
13
+ attr_reader :parent
14
+ # The SiteSetup record (if any) that belongs to this Prescription.
15
+ attr_reader :site_setup
16
+ # An array of Field records (if any) that belongs to this Prescription.
17
+ attr_reader :fields
18
+ attr_reader :course_id
19
+ attr_reader :rx_site_name
20
+ attr_reader :technique
21
+ attr_reader :modality
22
+ attr_reader :dose_spec
23
+ attr_reader :rx_depth
24
+ attr_reader :dose_ttl
25
+ attr_reader :dose_tx
26
+ attr_reader :pattern
27
+ attr_reader :rx_note
28
+ attr_reader :number_of_fields
29
+
30
+ # Creates a new Prescription site by parsing a RTPConnect string line.
31
+ #
32
+ # === Parameters
33
+ #
34
+ # * <tt>string</tt> -- A string containing a prescription site record.
35
+ # * <tt>parent</tt> -- A Record which is used to determine the proper parent of this instance.
36
+ #
37
+ def self.load(string, parent)
38
+ raise ArgumentError, "Invalid argument 'string'. Expected String, got #{string.class}." unless string.is_a?(String)
39
+ raise ArgumentError, "Invalid argument 'parent'. Expected RTP::Record, got #{parent.class}." unless parent.is_a?(RTP::Record)
40
+ # Get the quote-less values:
41
+ values = string.values
42
+ raise ArgumentError, "Invalid argument 'string': Expected exactly 13 elements, got #{values.length}." unless values.length == 13
43
+ p = self.new(parent)
44
+ # Assign the values to attributes:
45
+ p.keyword = values[0]
46
+ p.course_id = values[1]
47
+ p.rx_site_name = values[2]
48
+ p.technique = values[3]
49
+ p.modality = values[4]
50
+ p.dose_spec = values[5]
51
+ p.rx_depth = values[6]
52
+ p.dose_ttl = values[7]
53
+ p.dose_tx = values[8]
54
+ p.pattern = values[9]
55
+ p.rx_note = values[10]
56
+ p.number_of_fields = values[11]
57
+ p.crc = values[12]
58
+ return p
59
+ end
60
+
61
+ # Creates a new Prescription site.
62
+ #
63
+ # === Parameters
64
+ #
65
+ # * <tt>parent</tt> -- A Record which is used to determine the proper parent of this instance.
66
+ #
67
+ def initialize(parent)
68
+ raise ArgumentError, "Invalid argument 'parent'. Expected RTP::Record, got #{parent.class}." unless parent.is_a?(RTP::Record)
69
+ # Child objects:
70
+ @site_setup = nil
71
+ @fields = Array.new
72
+ # Parent relation:
73
+ @parent = get_parent(parent, Plan)
74
+ @parent.add_prescription(self)
75
+ @keyword = 'RX_DEF'
76
+ end
77
+
78
+ # Adds a treatment Field record to this instance.
79
+ #
80
+ def add_field(child)
81
+ raise ArgumentError, "Invalid argument 'child'. Expected RTP::Field, got #{child.class}." unless child.is_a?(RTP::Field)
82
+ @fields << child
83
+ end
84
+
85
+ # Connects a Site setup record to this instance.
86
+ #
87
+ def add_site_setup(child)
88
+ raise ArgumentError, "Invalid argument 'child'. Expected RTP::SiteSetup, got #{child.class}." unless child.is_a?(RTP::SiteSetup)
89
+ @site_setup = child
90
+ end
91
+
92
+ # Returns the a properly sorted array of the child records of this instance.
93
+ #
94
+ def children
95
+ return [@site_setup, @fields].flatten.compact
96
+ end
97
+
98
+ # Returns the values of this instance in an array.
99
+ # The values does not include the CRC.
100
+ #
101
+ def values
102
+ return [
103
+ @keyword,
104
+ @course_id,
105
+ @rx_site_name,
106
+ @technique,
107
+ @modality,
108
+ @dose_spec,
109
+ @rx_depth,
110
+ @dose_ttl,
111
+ @dose_tx,
112
+ @pattern,
113
+ @rx_note,
114
+ @number_of_fields
115
+ ]
116
+ end
117
+
118
+ # Writes the Prescription object + any hiearchy of child objects,
119
+ # to a properly formatted RTPConnect ascii string.
120
+ #
121
+ def to_str
122
+ str = encode
123
+ if children
124
+ children.each do |child|
125
+ str += child.to_str
126
+ end
127
+ end
128
+ return str
129
+ end
130
+
131
+ # Sets the keyword attribute.
132
+ #
133
+ def keyword=(value)
134
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
135
+ raise ArgumentError, "Invalid keyword. Expected 'RX_DEF', got #{value}." unless value.upcase == "RX_DEF"
136
+ @keyword = value
137
+ end
138
+
139
+ # Sets the course_id attribute.
140
+ #
141
+ def course_id=(value)
142
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
143
+ @course_id = value
144
+ end
145
+
146
+ # Sets the rx_site_name attribute.
147
+ #
148
+ def rx_site_name=(value)
149
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
150
+ @rx_site_name = value
151
+ end
152
+
153
+ # Sets the technique attribute.
154
+ #
155
+ def technique=(value)
156
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
157
+ @technique = value
158
+ end
159
+
160
+ # Sets the modality attribute.
161
+ #
162
+ def modality=(value)
163
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
164
+ @modality = value
165
+ end
166
+
167
+ # Sets the dose_spec attribute.
168
+ #
169
+ def dose_spec=(value)
170
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
171
+ @dose_spec = value
172
+ end
173
+
174
+ # Sets the rx_depth attribute.
175
+ #
176
+ def rx_depth=(value)
177
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
178
+ @rx_depth = value
179
+ end
180
+
181
+ # Sets the dose_ttl attribute.
182
+ #
183
+ def dose_ttl=(value)
184
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
185
+ @dose_ttl = value
186
+ end
187
+
188
+ # Sets the dose_tx attribute.
189
+ #
190
+ def dose_tx=(value)
191
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
192
+ @dose_tx = value
193
+ end
194
+
195
+ # Sets the pattern attribute.
196
+ #
197
+ def pattern=(value)
198
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
199
+ @pattern = value
200
+ end
201
+
202
+ # Sets the rx_note attribute.
203
+ #
204
+ def rx_note=(value)
205
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
206
+ @rx_note = value
207
+ end
208
+
209
+ # Sets the number_of_fields attribute.
210
+ #
211
+ def number_of_fields=(value)
212
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
213
+ @number_of_fields = value
214
+ end
215
+
216
+ end
217
+
218
+ end
@@ -0,0 +1,37 @@
1
+ module RTP
2
+
3
+ class Record
4
+
5
+ attr_reader :keyword
6
+ attr_reader :crc
7
+
8
+ # Encodes a string from the contents of this instance.
9
+ # This produces the full line, including a computed CRC checksum.
10
+ #
11
+ def encode
12
+ content = values.encode + ","
13
+ checksum = content.checksum
14
+ # Complete string is content + checksum (in double quotes) + carriage return + line feed
15
+ return content + checksum.to_s.wrap + "\r\n"
16
+ end
17
+
18
+ # Follows the tree of parents until the appropriate parent of the requesting record is found.
19
+ #
20
+ def get_parent(last_parent, klass)
21
+ if last_parent.is_a?(klass)
22
+ return last_parent
23
+ else
24
+ return last_parent.get_parent(last_parent.parent, klass)
25
+ end
26
+ end
27
+
28
+ # Setting the keyword attribute.
29
+ #
30
+ def crc=(value)
31
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
32
+ @crc = value
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: UTF-8
2
+
3
+ # This file contains extensions to the Ruby library which are used by the RTPConnect library.
4
+
5
+ # Extension to the String class. These extensions are focused on analyzing RTPConnect strings.
6
+ #
7
+ class String
8
+
9
+ # Returns the CRC checksum (16 bit unsigned integer) for a given string.
10
+ #
11
+ def checksum
12
+ crc = RTP::CRC_SEED
13
+ self.each_codepoint do |byte|
14
+ crc = RTP::CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >> 8)
15
+ end
16
+ return crc
17
+ end
18
+
19
+ # Returns the elements of a line from the RTPConnect ascii string.
20
+ # The line consists of elements (surrounded by double quotes), separated by comma.
21
+ # This method performs a split based on comma and returns the element strings in an array.
22
+ #
23
+ def elements
24
+ return self.split(',')
25
+ end
26
+
27
+ # Removes double quotes from a string.
28
+ # Returns the quote-less string.
29
+ #
30
+ def value
31
+ return self.gsub('"', '')
32
+ end
33
+
34
+ # Returns the element values of a line from the RTPConnect ascii string.
35
+ # The line consists of values (surrounded by double quotes), separated by comma.
36
+ # This method performs a split based on comma and removes the quotes from each value,
37
+ # and the resulting quote-less value strings are returned in an array.
38
+ #
39
+ def values
40
+ original = self.split(',')
41
+ processed = Array.new
42
+ original.collect {|element| processed << element.gsub('"', '')}
43
+ return processed
44
+ end
45
+
46
+ # Wraps double quotes around the string.
47
+ #
48
+ def wrap
49
+ return '"' + self + '"'
50
+ end
51
+
52
+ end
53
+
54
+
55
+ # Extension to the Array class. These extensions are focused on creating RTPConnect
56
+ # strings from an array of values.
57
+ #
58
+ class Array
59
+
60
+ # Encodes an RTPConnect string from an array of values.
61
+ # Each value in the array is wrapped with double quotes,
62
+ # before the values are joined with a comma separator.
63
+ #
64
+ def encode
65
+ wrapped = self.collect{|value| value.wrap}
66
+ return wrapped.join(',')
67
+ end
68
+
69
+ end
70
+
71
+ # An extension to the NilClass, facilitating a transformation from nil to
72
+ # an empty (double quoted) string in the case of undefined attributes.
73
+ #
74
+ class NilClass
75
+
76
+ # Returns a double quoted, but otherwise empty string.
77
+ #
78
+ def wrap
79
+ return '""'
80
+ end
81
+
82
+ end
@@ -0,0 +1,227 @@
1
+ module RTP
2
+
3
+ # The SiteSetup class.
4
+ #
5
+ # === Relations
6
+ #
7
+ # * Parent: Prescription
8
+ # * Children: none
9
+ #
10
+ class SiteSetup < Record
11
+
12
+ # The Record which this instance belongs to.
13
+ attr_reader :parent
14
+ attr_reader :rx_site_name
15
+ attr_reader :patient_orientation
16
+ attr_reader :treatment_machine
17
+ attr_reader :tolerance_table
18
+ attr_reader :iso_pos_x
19
+ attr_reader :iso_pos_y
20
+ attr_reader :iso_pos_z
21
+ attr_reader :structure_set_uid
22
+ attr_reader :frame_of_ref_uid
23
+ attr_reader :couch_vertical
24
+ attr_reader :couch_lateral
25
+ attr_reader :couch_longitudinal
26
+ attr_reader :couch_angle
27
+ attr_reader :couch_pedestal
28
+
29
+ # Creates a new SiteSetup setup by parsing a RTPConnect string line.
30
+ #
31
+ # === Parameters
32
+ #
33
+ # * <tt>string</tt> -- A string containing a site setup record.
34
+ # * <tt>parent</tt> -- A Record which is used to determine the proper parent of this instance.
35
+ #
36
+ def self.load(string, parent)
37
+ raise ArgumentError, "Invalid argument 'string'. Expected String, got #{string.class}." unless string.is_a?(String)
38
+ raise ArgumentError, "Invalid argument 'parent'. Expected RTP::Prescription, got #{parent.class}." unless parent.is_a?(RTP::Prescription)
39
+ # Get the quote-less values:
40
+ values = string.values
41
+ raise ArgumentError, "Invalid argument 'string': Expected exactly 16 elements, got #{values.length}." unless values.length == 16
42
+ s = self.new(parent)
43
+ # Assign the values to attributes:
44
+ s.keyword = values[0]
45
+ s.rx_site_name = values[1]
46
+ s.patient_orientation = values[2]
47
+ s.treatment_machine = values[3]
48
+ s.tolerance_table = values[4]
49
+ s.iso_pos_x = values[5]
50
+ s.iso_pos_y = values[6]
51
+ s.iso_pos_z = values[7]
52
+ s.structure_set_uid = values[8]
53
+ s.frame_of_ref_uid = values[9]
54
+ s.couch_vertical = values[10]
55
+ s.couch_lateral = values[11]
56
+ s.couch_longitudinal = values[12]
57
+ s.couch_angle = values[13]
58
+ s.couch_pedestal = values[14]
59
+ s.crc = values[15]
60
+ return s
61
+ end
62
+
63
+ # Creates a new SiteSetup.
64
+ #
65
+ # === Parameters
66
+ #
67
+ # * <tt>parent</tt> -- A Record which is used to determine the proper parent of this instance.
68
+ #
69
+ def initialize(parent)
70
+ raise ArgumentError, "Invalid argument 'parent'. Expected RTP::Prescription, got #{parent.class}." unless parent.is_a?(RTP::Prescription)
71
+ # Parent relation:
72
+ @parent = get_parent(parent, Prescription)
73
+ @parent.add_site_setup(self)
74
+ @keyword = 'SITE_SETUP_DEF'
75
+ end
76
+
77
+ # Returns an empty array, as these instances are child-less by definition.
78
+ #
79
+ def children
80
+ return Array.new
81
+ end
82
+
83
+ # Returns the values of this instance in an array.
84
+ # The values does not include the CRC.
85
+ #
86
+ def values
87
+ return [
88
+ @keyword,
89
+ @rx_site_name,
90
+ @patient_orientation,
91
+ @treatment_machine,
92
+ @tolerance_table,
93
+ @iso_pos_x,
94
+ @iso_pos_y,
95
+ @iso_pos_z,
96
+ @structure_set_uid,
97
+ @frame_of_ref_uid,
98
+ @couch_vertical,
99
+ @couch_lateral,
100
+ @couch_longitudinal,
101
+ @couch_angle,
102
+ @couch_pedestal
103
+ ]
104
+ end
105
+
106
+ # Writes the SiteSetup object + any hiearchy of child objects,
107
+ # to a properly formatted RTPConnect ascii string.
108
+ #
109
+ def to_str
110
+ str = encode
111
+ if children
112
+ children.each do |child|
113
+ str += child.to_str
114
+ end
115
+ end
116
+ return str
117
+ end
118
+
119
+ # Sets the keyword attribute.
120
+ #
121
+ def keyword=(value)
122
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
123
+ raise ArgumentError, "Invalid keyword. Expected 'SITE_SETUP_DEF', got #{value}." unless value.upcase == "SITE_SETUP_DEF"
124
+ @keyword = value
125
+ end
126
+
127
+ # Sets the rx_site_name attribute.
128
+ #
129
+ def rx_site_name=(value)
130
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
131
+ @rx_site_name = value
132
+ end
133
+
134
+ # Sets the patient_orientation attribute.
135
+ #
136
+ def patient_orientation=(value)
137
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
138
+ @patient_orientation = value
139
+ end
140
+
141
+ # Sets the treatment_machine attribute.
142
+ #
143
+ def treatment_machine=(value)
144
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
145
+ @treatment_machine = value
146
+ end
147
+
148
+ # Sets the tolerance_table attribute.
149
+ #
150
+ def tolerance_table=(value)
151
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
152
+ @tolerance_table = value
153
+ end
154
+
155
+ # Sets the iso_pos_x attribute.
156
+ #
157
+ def iso_pos_x=(value)
158
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
159
+ @iso_pos_x = value
160
+ end
161
+
162
+ # Sets the iso_pos_y attribute.
163
+ #
164
+ def iso_pos_y=(value)
165
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
166
+ @iso_pos_y = value
167
+ end
168
+
169
+ # Sets the iso_pos_z attribute.
170
+ #
171
+ def iso_pos_z=(value)
172
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
173
+ @iso_pos_z = value
174
+ end
175
+
176
+ # Sets the structure_set_uid attribute.
177
+ #
178
+ def structure_set_uid=(value)
179
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
180
+ @structure_set_uid = value
181
+ end
182
+
183
+ # Sets the frame_of_ref_uid attribute.
184
+ #
185
+ def frame_of_ref_uid=(value)
186
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
187
+ @frame_of_ref_uid = value
188
+ end
189
+
190
+ # Sets the couch_vertical attribute.
191
+ #
192
+ def couch_vertical=(value)
193
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
194
+ @couch_vertical = value
195
+ end
196
+
197
+ # Sets the couch_lateral attribute.
198
+ #
199
+ def couch_lateral=(value)
200
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
201
+ @couch_lateral = value
202
+ end
203
+
204
+ # Sets the couch_longitudinal attribute.
205
+ #
206
+ def couch_longitudinal=(value)
207
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
208
+ @couch_longitudinal = value
209
+ end
210
+
211
+ # Sets the couch_angle attribute.
212
+ #
213
+ def couch_angle=(value)
214
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
215
+ @couch_angle = value
216
+ end
217
+
218
+ # Sets the couch_pedestal attribute.
219
+ #
220
+ def couch_pedestal=(value)
221
+ raise ArgumentError, "Invalid argument 'value'. Expected String, got #{value.class}." unless value.is_a?(String)
222
+ @couch_pedestal = value
223
+ end
224
+
225
+ end
226
+
227
+ end