rtp-connect 1.8 → 1.9

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.
@@ -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