rtp-connect 1.8 → 1.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,8 +8,11 @@ module RTP
8
8
  #
9
9
  class ControlPoint < Record
10
10
 
11
+ # The number of attributes not having their own variable for this record (200 - 2).
12
+ NR_SURPLUS_ATTRIBUTES = 198
13
+
11
14
  # The Record which this instance belongs to.
12
- attr_reader :parent
15
+ attr_accessor :parent
13
16
  # The MLC shape record (if any) that belongs to this ControlPoint.
14
17
  attr_reader :mlc_shape
15
18
  attr_reader :field_id
@@ -144,15 +147,7 @@ module RTP
144
147
  # @return [Float] the DICOM-formatted collimator_x1 attribute
145
148
  #
146
149
  def dcm_collimator_x1(scale=nil)
147
- coeff = 1
148
- axis = :x
149
- if scale == :elekta
150
- axis = :y
151
- coeff = -1
152
- elsif scale == :varian
153
- coeff = -1
154
- end
155
- dcm_collimator1(axis, coeff)
150
+ dcm_collimator_1(scale, default_axis=:x)
156
151
  end
157
152
 
158
153
  # Converts the collimator_x2 attribute to proper DICOM format.
@@ -162,7 +157,7 @@ module RTP
162
157
  #
163
158
  def dcm_collimator_x2(scale=nil)
164
159
  axis = (scale == :elekta ? :y : :x)
165
- dcm_collimator2(axis, coeff=1)
160
+ dcm_collimator(axis, coeff=1, side=2)
166
161
  end
167
162
 
168
163
  # Converts the collimator_y1 attribute to proper DICOM format.
@@ -171,15 +166,7 @@ module RTP
171
166
  # @return [Float] the DICOM-formatted collimator_y1 attribute
172
167
  #
173
168
  def dcm_collimator_y1(scale=nil)
174
- coeff = 1
175
- axis = :y
176
- if scale == :elekta
177
- axis = :x
178
- coeff = -1
179
- elsif scale == :varian
180
- coeff = -1
181
- end
182
- dcm_collimator1(axis, coeff)
169
+ dcm_collimator_1(scale, default_axis=:y)
183
170
  end
184
171
 
185
172
  # Converts the collimator_y2 attribute to proper DICOM format.
@@ -189,7 +176,7 @@ module RTP
189
176
  #
190
177
  def dcm_collimator_y2(scale=nil)
191
178
  axis = (scale == :elekta ? :x : :y)
192
- dcm_collimator2(axis, coeff=1)
179
+ dcm_collimator(axis, coeff=1, side=2)
193
180
  end
194
181
 
195
182
  # Converts the mlc_lp_a & mlc_lp_b attributes to a proper DICOM formatted string.
@@ -276,25 +263,6 @@ module RTP
276
263
  self
277
264
  end
278
265
 
279
- # Encodes the ControlPoint object + any hiearchy of child objects,
280
- # to a properly formatted RTPConnect ascii string.
281
- #
282
- # @param [Hash] options an optional hash parameter
283
- # @option options [Float] :version the Mosaiq compatibility version number (e.g. 2.4) used for the output
284
- # @return [String] an RTP string with a single or multiple lines/records
285
- #
286
- def to_s(options={})
287
- str = encode(options)
288
- if children
289
- children.each do |child|
290
- str += child.to_s(options)
291
- end
292
- end
293
- return str
294
- end
295
-
296
- alias :to_str :to_s
297
-
298
266
  # Sets the mlc_lp_a attribute.
299
267
  #
300
268
  # @note As opposed to the ordinary (string) attributes, this attribute
@@ -578,74 +546,49 @@ module RTP
578
546
  #
579
547
  # @param [Symbol] axis a representation for the axis of interest (x or y)
580
548
  # @param [Integer] coeff a coeffecient (of -1 or 1) which the attribute is multiplied with
549
+ # @param [Integer] nr collimator side/index (1 or 2)
581
550
  # @return [Float] the DICOM-formatted collimator attribute
582
551
  #
583
- def dcm_collimator1(axis, coeff)
552
+ def dcm_collimator(axis, coeff, nr)
584
553
  mode = self.send("field_#{axis}_mode")
585
554
  if mode && !mode.empty?
586
555
  target = self
587
556
  else
588
557
  target = @parent
589
558
  end
590
- target.send("collimator_#{axis}1").to_f * 10 * coeff
559
+ target.send("collimator_#{axis}#{nr}").to_f * 10 * coeff
591
560
  end
592
561
 
593
- # Converts the collimator attribute to proper DICOM format.
562
+ # Converts the collimator1 attribute to proper DICOM format.
594
563
  #
595
- # @param [Symbol] axis a representation for the axis of interest (x or y)
596
- # @param [Integer] coeff a coeffecient (of -1 or 1) which the attribute is multiplied with
597
- # @return [Float] the DICOM-formatted collimator attribute
564
+ # @param [Symbol] scale if set, relevant device parameters are converted from a native readout format to IEC1217 (supported values are :elekta & :varian)
565
+ # @return [Float] the DICOM-formatted collimator_x1 attribute
598
566
  #
599
- def dcm_collimator2(axis, coeff)
600
- mode = self.send("field_#{axis}_mode")
601
- if mode && !mode.empty?
602
- target = self
603
- else
604
- target = @parent
567
+ def dcm_collimator_1(scale=nil, axis)
568
+ coeff = 1
569
+ if scale == :elekta
570
+ axis = (axis == :x ? :y : :x)
571
+ coeff = -1
572
+ elsif scale == :varian
573
+ coeff = -1
605
574
  end
606
- target.send("collimator_#{axis}2").to_f * 10 * coeff
607
- end
608
-
609
- # Sets the attributes of the record instance.
610
- #
611
- # @param [Array<String>] values the record attributes (as parsed from a record string)
612
- #
613
- def set_attributes(values)
614
- self.keyword = values[0]
615
- @field_id = values[1]
616
- @mlc_type = values[2]
617
- @mlc_leaves = values[3]
618
- @total_control_points = values[4]
619
- @control_pt_number = values[5]
620
- @mu_convention = values[6]
621
- @monitor_units = values[7]
622
- @wedge_position = values[8]
623
- @energy = values[9]
624
- @doserate = values[10]
625
- @ssd = values[11]
626
- @scale_convention = values[12]
627
- @gantry_angle = values[13]
628
- @gantry_dir = values[14]
629
- @collimator_angle = values[15]
630
- @collimator_dir = values[16]
631
- @field_x_mode = values[17]
632
- @field_x = values[18]
633
- @collimator_x1 = values[19]
634
- @collimator_x2 = values[20]
635
- @field_y_mode = values[21]
636
- @field_y = values[22]
637
- @collimator_y1 = values[23]
638
- @collimator_y2 = values[24]
639
- @couch_vertical = values[25]
640
- @couch_lateral = values[26]
641
- @couch_longitudinal = values[27]
642
- @couch_angle = values[28]
643
- @couch_dir = values[29]
644
- @couch_pedestal = values[30]
645
- @couch_ped_dir = values[31]
646
- @mlc_lp_a = [*values[32..131]]
647
- @mlc_lp_b = [*values[132..231]]
648
- @crc = values[-1]
575
+ dcm_collimator(axis, coeff, side=1)
576
+ end
577
+
578
+ # Gives an array of indices indicating where the attributes of this record gets its
579
+ # values from in the comma separated string which the instance is created from.
580
+ #
581
+ # @param [Integer] length the number of elements to create in the indices array
582
+ #
583
+ def import_indices(length)
584
+ # Note that this method is defined in the parent Record class, where it is
585
+ # used for most record types. However, because this record has two attributes
586
+ # which contain an array of values, we use a custom import_indices method.
587
+ ind = Array.new(length - NR_SURPLUS_ATTRIBUTES) { |i| [i] }
588
+ # Override indices for mlc_pl_a and mlc_lp_b:
589
+ ind[32] = (32..131).to_a
590
+ ind[33] = (132..231).to_a
591
+ ind
649
592
  end
650
593
 
651
594
  end
@@ -8,8 +8,11 @@ module RTP
8
8
  #
9
9
  class DoseTracking < Record
10
10
 
11
+ # The number of attributes not having their own variable for this record (20 - 2).
12
+ NR_SURPLUS_ATTRIBUTES = 18
13
+
11
14
  # The Record which this instance belongs to.
12
- attr_reader :parent
15
+ attr_accessor :parent
13
16
  # The DoseAction records (if any) that belongs to this DoseTracking.
14
17
  attr_reader :dose_actions
15
18
  attr_reader :region_name
@@ -120,25 +123,6 @@ module RTP
120
123
  self
121
124
  end
122
125
 
123
- # Encodes the DoseTracking object + any hiearchy of child objects,
124
- # to a properly formatted RTPConnect ascii string.
125
- #
126
- # @param [Hash] options an optional hash parameter
127
- # @option options [Float] :version the Mosaiq compatibility version number (e.g. 2.4) used for the output
128
- # @return [String] an RTP string with a single or multiple lines/records
129
- #
130
- def to_s(options={})
131
- str = encode(options)
132
- if children
133
- children.each do |child|
134
- str += child.to_s(options)
135
- end
136
- end
137
- return str
138
- end
139
-
140
- alias :to_str :to_s
141
-
142
126
  # Sets the field_ids attribute.
143
127
  #
144
128
  # @note As opposed to the ordinary (string) attributes, this attribute
@@ -202,19 +186,21 @@ module RTP
202
186
  #
203
187
  alias_method :state, :values
204
188
 
205
- # Sets the attributes of the record instance.
206
- #
207
- # @param [Array<String>] values the record attributes (as parsed from a record string)
208
- #
209
- def set_attributes(values)
210
- self.keyword = values[0]
211
- @region_name = values[1]
212
- @region_prior_dose = values[2]
213
- @field_ids = values.values_at(3, 5, 7, 9, 11, 13, 15, 17, 19, 21)
214
- @region_coeffs = values.values_at(4, 6, 8, 10, 12, 14, 16, 18, 20, 22)
215
- @actual_dose = values[23]
216
- @actual_fractions = values[24]
217
- @crc = values[-1]
189
+ # Gives an array of indices indicating where the attributes of this record gets its
190
+ # values from in the comma separated string which the instance is created from.
191
+ #
192
+ # @param [Integer] length the number of elements to create in the indices array
193
+ #
194
+ def import_indices(length)
195
+ # Note that this method is defined in the parent Record class, where it is
196
+ # used for most record types. However, because this record has two attributes
197
+ # which contain an array of values, we use a custom import_indices method.
198
+ ind = Array.new(length - NR_SURPLUS_ATTRIBUTES) { |i| i }
199
+ # Override indices for field_ids and region_coeffs:
200
+ ind[3] = [3, 5, 7, 9, 11, 13, 15, 17, 19, 21]
201
+ ind[4] = [4, 6, 8, 10, 12, 14, 16, 18, 20, 22]
202
+ ind[5, 6] = [23, 24]
203
+ ind
218
204
  end
219
205
 
220
206
  end
@@ -9,7 +9,7 @@ module RTP
9
9
  class ExtendedField < Record
10
10
 
11
11
  # The Record which this instance belongs to.
12
- attr_reader :parent
12
+ attr_accessor :parent
13
13
  attr_reader :field_id
14
14
  attr_reader :original_plan_uid
15
15
  attr_reader :original_beam_number
@@ -97,25 +97,6 @@ module RTP
97
97
  self
98
98
  end
99
99
 
100
- # Encodes the ExtendedField object + any hiearchy of child objects,
101
- # to a properly formatted RTPConnect ascii string.
102
- #
103
- # @param [Hash] options an optional hash parameter
104
- # @option options [Float] :version the Mosaiq compatibility version number (e.g. 2.4) used for the output
105
- # @return [String] an RTP string with a single or multiple lines/records
106
- #
107
- def to_s(options={})
108
- str = encode(options)
109
- if children
110
- children.each do |child|
111
- str += child.to_s(options)
112
- end
113
- end
114
- return str
115
- end
116
-
117
- alias :to_str :to_s
118
-
119
100
  # Sets the field_id attribute.
120
101
  #
121
102
  # @param [nil, #to_s] value the new attribute value
@@ -1,135 +1,116 @@
1
- module RTP
2
-
3
- # The Extended plan class.
4
- #
5
- # @note Relations:
6
- # * Parent: Plan
7
- # * Children: none
8
- #
9
- class ExtendedPlan < Record
10
-
11
- # The Record which this instance belongs to.
12
- attr_reader :parent
13
- attr_reader :encoding
14
- attr_reader :fullname
15
-
16
- # Creates a new ExtendedPlan by parsing a RTPConnect string line.
17
- #
18
- # @param [#to_s] string the extended plan definition record string line
19
- # @param [Record] parent a record which is used to determine the proper parent of this instance
20
- # @return [ExtendedPlan] the created ExtendedPlan instance
21
- # @raise [ArgumentError] if given a string containing an invalid number of elements
22
- #
23
- def self.load(string, parent)
24
- ep = self.new(parent)
25
- ep.load(string)
26
- end
27
-
28
- # Creates a new ExtendedPlan.
29
- #
30
- # @param [Record] parent a record which is used to determine the proper parent of this instance
31
- #
32
- def initialize(parent)
33
- super('EXTENDED_PLAN_DEF', 4, 4)
34
- # Parent relation (may get more than one type of record here):
35
- @parent = get_parent(parent.to_record, Plan)
36
- @parent.add_extended_plan(self)
37
- @attributes = [
38
- # Required:
39
- :keyword,
40
- :encoding,
41
- :fullname
42
- ]
43
- end
44
-
45
- # Checks for equality.
46
- #
47
- # Other and self are considered equivalent if they are
48
- # of compatible types and their attributes are equivalent.
49
- #
50
- # @param other an object to be compared with self.
51
- # @return [Boolean] true if self and other are considered equivalent
52
- #
53
- def ==(other)
54
- if other.respond_to?(:to_extended_plan)
55
- other.send(:state) == state
56
- end
57
- end
58
-
59
- alias_method :eql?, :==
60
-
61
- # Gives an empty array, as these instances are child-less by definition.
62
- #
63
- # @return [Array] an emtpy array
64
- #
65
- def children
66
- return Array.new
67
- end
68
-
69
- # Computes a hash code for this object.
70
- #
71
- # @note Two objects with the same attributes will have the same hash code.
72
- #
73
- # @return [Fixnum] the object's hash code
74
- #
75
- def hash
76
- state.hash
77
- end
78
-
79
- # Returns self.
80
- #
81
- # @return [ExtendedPlan] self
82
- #
83
- def to_extended_plan
84
- self
85
- end
86
-
87
- # Encodes the ExtendedPlan object + any hiearchy of child objects,
88
- # to a properly formatted RTPConnect ascii string.
89
- #
90
- # @param [Hash] options an optional hash parameter
91
- # @option options [Float] :version the Mosaiq compatibility version number (e.g. 2.4) used for the output
92
- # @return [String] an RTP string with a single or multiple lines/records
93
- #
94
- def to_s(options={})
95
- str = encode(options)
96
- if children
97
- children.each do |child|
98
- str += child.to_s(options)
99
- end
100
- end
101
- return str
102
- end
103
-
104
- alias :to_str :to_s
105
-
106
- # Sets the encoding attribute.
107
- #
108
- # @param [nil, #to_s] value the new attribute value
109
- #
110
- def encoding=(value)
111
- @encoding = value && value.to_s
112
- end
113
-
114
- # Sets the fullname attribute.
115
- #
116
- # @param [nil, #to_s] value the new attribute value
117
- #
118
- def fullname=(value)
119
- @fullname = value && value.to_s
120
- end
121
-
122
-
123
- private
124
-
125
-
126
- # Collects the attributes of this instance.
127
- #
128
- # @note The CRC is not considered part of the attributes of interest and is excluded
129
- # @return [Array<String>] an array of attributes
130
- #
131
- alias_method :state, :values
132
-
133
- end
134
-
1
+ module RTP
2
+
3
+ # The Extended plan class.
4
+ #
5
+ # @note Relations:
6
+ # * Parent: Plan
7
+ # * Children: none
8
+ #
9
+ class ExtendedPlan < Record
10
+
11
+ # The Record which this instance belongs to.
12
+ attr_accessor :parent
13
+ attr_reader :encoding
14
+ attr_reader :fullname
15
+
16
+ # Creates a new ExtendedPlan by parsing a RTPConnect string line.
17
+ #
18
+ # @param [#to_s] string the extended plan definition record string line
19
+ # @param [Record] parent a record which is used to determine the proper parent of this instance
20
+ # @return [ExtendedPlan] the created ExtendedPlan instance
21
+ # @raise [ArgumentError] if given a string containing an invalid number of elements
22
+ #
23
+ def self.load(string, parent)
24
+ ep = self.new(parent)
25
+ ep.load(string)
26
+ end
27
+
28
+ # Creates a new ExtendedPlan.
29
+ #
30
+ # @param [Record] parent a record which is used to determine the proper parent of this instance
31
+ #
32
+ def initialize(parent)
33
+ super('EXTENDED_PLAN_DEF', 4, 4)
34
+ # Parent relation (may get more than one type of record here):
35
+ @parent = get_parent(parent.to_record, Plan)
36
+ @parent.add_extended_plan(self)
37
+ @attributes = [
38
+ # Required:
39
+ :keyword,
40
+ :encoding,
41
+ :fullname
42
+ ]
43
+ end
44
+
45
+ # Checks for equality.
46
+ #
47
+ # Other and self are considered equivalent if they are
48
+ # of compatible types and their attributes are equivalent.
49
+ #
50
+ # @param other an object to be compared with self.
51
+ # @return [Boolean] true if self and other are considered equivalent
52
+ #
53
+ def ==(other)
54
+ if other.respond_to?(:to_extended_plan)
55
+ other.send(:state) == state
56
+ end
57
+ end
58
+
59
+ alias_method :eql?, :==
60
+
61
+ # Gives an empty array, as these instances are child-less by definition.
62
+ #
63
+ # @return [Array] an emtpy array
64
+ #
65
+ def children
66
+ return Array.new
67
+ end
68
+
69
+ # Computes a hash code for this object.
70
+ #
71
+ # @note Two objects with the same attributes will have the same hash code.
72
+ #
73
+ # @return [Fixnum] the object's hash code
74
+ #
75
+ def hash
76
+ state.hash
77
+ end
78
+
79
+ # Returns self.
80
+ #
81
+ # @return [ExtendedPlan] self
82
+ #
83
+ def to_extended_plan
84
+ self
85
+ end
86
+
87
+ # Sets the encoding attribute.
88
+ #
89
+ # @param [nil, #to_s] value the new attribute value
90
+ #
91
+ def encoding=(value)
92
+ @encoding = value && value.to_s
93
+ end
94
+
95
+ # Sets the fullname attribute.
96
+ #
97
+ # @param [nil, #to_s] value the new attribute value
98
+ #
99
+ def fullname=(value)
100
+ @fullname = value && value.to_s
101
+ end
102
+
103
+
104
+ private
105
+
106
+
107
+ # Collects the attributes of this instance.
108
+ #
109
+ # @note The CRC is not considered part of the attributes of interest and is excluded
110
+ # @return [Array<String>] an array of attributes
111
+ #
112
+ alias_method :state, :values
113
+
114
+ end
115
+
135
116
  end