rtp-connect 1.1 → 1.2
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 +30 -19
- data/COPYING +674 -674
- data/Gemfile +3 -0
- data/Gemfile.lock +35 -0
- data/README.rdoc +12 -6
- data/lib/rtp-connect.rb +24 -22
- data/lib/rtp-connect/constants.rb +57 -57
- data/lib/rtp-connect/control_point.rb +176 -86
- data/lib/rtp-connect/dose_tracking.rb +222 -0
- data/lib/rtp-connect/extended_field.rb +56 -26
- data/lib/rtp-connect/field.rb +163 -43
- data/lib/rtp-connect/logging.rb +155 -158
- data/lib/rtp-connect/methods.rb +3 -4
- data/lib/rtp-connect/plan.rb +136 -52
- data/lib/rtp-connect/plan_to_dcm.rb +503 -0
- data/lib/rtp-connect/prescription.rb +71 -23
- data/lib/rtp-connect/record.rb +18 -2
- data/lib/rtp-connect/ruby_extensions.rb +90 -81
- data/lib/rtp-connect/site_setup.rb +78 -28
- data/lib/rtp-connect/version.rb +5 -5
- data/rakefile.rb +29 -0
- data/rtp-connect.gemspec +29 -0
- metadata +105 -53
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
rtp-connect (1.1)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: http://www.rubygems.org/
|
8
|
+
specs:
|
9
|
+
dicom (0.9.3)
|
10
|
+
diff-lcs (1.1.3)
|
11
|
+
metaclass (0.0.1)
|
12
|
+
mocha (0.12.0)
|
13
|
+
metaclass (~> 0.0.1)
|
14
|
+
rake (0.9.2.2)
|
15
|
+
rspec (2.11.0)
|
16
|
+
rspec-core (~> 2.11.0)
|
17
|
+
rspec-expectations (~> 2.11.0)
|
18
|
+
rspec-mocks (~> 2.11.0)
|
19
|
+
rspec-core (2.11.0)
|
20
|
+
rspec-expectations (2.11.1)
|
21
|
+
diff-lcs (~> 1.1.3)
|
22
|
+
rspec-mocks (2.11.1)
|
23
|
+
yard (0.8.2.1)
|
24
|
+
|
25
|
+
PLATFORMS
|
26
|
+
x86-mingw32
|
27
|
+
|
28
|
+
DEPENDENCIES
|
29
|
+
bundler (>= 1.0.0)
|
30
|
+
dicom (>= 0.9.3)
|
31
|
+
mocha (>= 0.10.5)
|
32
|
+
rake (>= 0.9.2.2)
|
33
|
+
rspec (>= 2.9.0)
|
34
|
+
rtp-connect!
|
35
|
+
yard (>= 0.8.2)
|
data/README.rdoc
CHANGED
@@ -26,23 +26,29 @@ external dependencies.
|
|
26
26
|
=== Read, modify and write
|
27
27
|
|
28
28
|
# Read file:
|
29
|
-
rtp = Plan.read(
|
29
|
+
rtp = Plan.read('some_file.rtp')
|
30
30
|
# Extract the Patient's Name:
|
31
31
|
name = rtp.patient_last_name
|
32
32
|
# Modify the Patient's Name:
|
33
|
-
rtp.patient_last_name =
|
33
|
+
rtp.patient_last_name = 'Anonymous'
|
34
34
|
# Write to file:
|
35
|
-
rtp.write(
|
35
|
+
rtp.write('new_file.rtp')
|
36
36
|
|
37
37
|
=== Create a new Plan Definition Record from scratch
|
38
38
|
|
39
39
|
# Create the instance:
|
40
40
|
rtp = Plan.new
|
41
41
|
# Set the Patient's ID attribute:
|
42
|
-
rtp.patient_id =
|
42
|
+
rtp.patient_id = '12345'
|
43
43
|
# Export the instance to an RTP string (with CRC):
|
44
44
|
output = rtp.to_s
|
45
45
|
|
46
|
+
=== Convert an RTP file to DICOM:
|
47
|
+
|
48
|
+
p = Plan.read('some_file.rtp')
|
49
|
+
dcm = p.to_dcm
|
50
|
+
dcm.write('rtplan.dcm')
|
51
|
+
|
46
52
|
=== Log settings
|
47
53
|
|
48
54
|
# Change the log level so that only error messages are displayed:
|
@@ -69,7 +75,7 @@ automatically printed to the screen. A useful hack to avoid this effect is
|
|
69
75
|
to append ";0" after a command.
|
70
76
|
|
71
77
|
Example:
|
72
|
-
rtp = Plan.read(
|
78
|
+
rtp = Plan.read('some_file.rtp') ;0
|
73
79
|
|
74
80
|
|
75
81
|
== RESOURCES
|
@@ -89,6 +95,7 @@ Example:
|
|
89
95
|
* Treatment field [FIELD_DEF]
|
90
96
|
* Extended treatment field [EXTENDED_FIELD_DEF]
|
91
97
|
* Control point record [CONTROL_PT_DEF]
|
98
|
+
* Dose tracking record [DOSE_DEF]
|
92
99
|
|
93
100
|
=== Unsupported records
|
94
101
|
|
@@ -96,7 +103,6 @@ Example:
|
|
96
103
|
* Document based treatment field [PDF_FIELD_DEF]
|
97
104
|
* Multileaf collimator [MLC_DEF]
|
98
105
|
* MLC shape [MLC_SHAPE_DEF]
|
99
|
-
* Dose tracking record [DOSE_DEF]
|
100
106
|
* Dose action points [DOSE_ACTION]
|
101
107
|
|
102
108
|
If you encounter an RTP file with an unsupported record type, please contact me.
|
data/lib/rtp-connect.rb
CHANGED
@@ -1,23 +1,25 @@
|
|
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/
|
10
|
-
require_relative 'rtp-connect/
|
11
|
-
require_relative 'rtp-connect/
|
12
|
-
require_relative 'rtp-connect/
|
13
|
-
require_relative 'rtp-connect/
|
14
|
-
|
15
|
-
require_relative 'rtp-connect/
|
16
|
-
#
|
17
|
-
require_relative 'rtp-connect/
|
18
|
-
|
19
|
-
require_relative 'rtp-connect/
|
20
|
-
require_relative 'rtp-connect/
|
21
|
-
|
22
|
-
|
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/plan_to_dcm'
|
10
|
+
require_relative 'rtp-connect/prescription'
|
11
|
+
require_relative 'rtp-connect/site_setup'
|
12
|
+
require_relative 'rtp-connect/field'
|
13
|
+
require_relative 'rtp-connect/extended_field'
|
14
|
+
require_relative 'rtp-connect/control_point'
|
15
|
+
require_relative 'rtp-connect/dose_tracking'
|
16
|
+
# Extensions to the Ruby library:
|
17
|
+
require_relative 'rtp-connect/ruby_extensions'
|
18
|
+
# Module settings:
|
19
|
+
require_relative 'rtp-connect/version'
|
20
|
+
require_relative 'rtp-connect/constants'
|
21
|
+
require_relative 'rtp-connect/methods'
|
22
|
+
require_relative 'rtp-connect/variables'
|
23
|
+
|
24
|
+
# Load the CSV library:
|
23
25
|
require 'csv'
|
@@ -1,58 +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
|
-
|
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
58
|
end
|
@@ -2,10 +2,9 @@ module RTP
|
|
2
2
|
|
3
3
|
# The ControlPoint class.
|
4
4
|
#
|
5
|
-
#
|
6
|
-
#
|
7
|
-
#
|
8
|
-
# * Children: MLCShape
|
5
|
+
# @note Relations:
|
6
|
+
# * Parent: Field
|
7
|
+
# * Children: none
|
9
8
|
#
|
10
9
|
class ControlPoint < Record
|
11
10
|
|
@@ -51,60 +50,58 @@ module RTP
|
|
51
50
|
|
52
51
|
# Creates a new ControlPoint by parsing a RTPConnect string line.
|
53
52
|
#
|
54
|
-
#
|
55
|
-
#
|
56
|
-
#
|
57
|
-
#
|
53
|
+
# @param [#to_s] string the control point definition record string line
|
54
|
+
# @param [Record] parent a record which is used to determine the proper parent of this instance
|
55
|
+
# @return [ControlPoint] the created ControlPoint instance
|
56
|
+
# @raise [ArgumentError] if given a string containing an invalid number of elements
|
58
57
|
#
|
59
58
|
def self.load(string, parent)
|
60
59
|
# Get the quote-less values:
|
61
60
|
values = string.to_s.values
|
62
61
|
raise ArgumentError, "Invalid argument 'string': Expected exactly 233 elements, got #{values.length}." unless values.length == 233
|
63
|
-
|
62
|
+
cp = self.new(parent)
|
64
63
|
# Assign the values to attributes:
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
return
|
64
|
+
cp.keyword = values[0]
|
65
|
+
cp.field_id = values[1]
|
66
|
+
cp.mlc_type = values[2]
|
67
|
+
cp.mlc_leaves = values[3]
|
68
|
+
cp.total_control_points = values[4]
|
69
|
+
cp.control_pt_number = values[5]
|
70
|
+
cp.mu_convention = values[6]
|
71
|
+
cp.monitor_units = values[7]
|
72
|
+
cp.wedge_position = values[8]
|
73
|
+
cp.energy = values[9]
|
74
|
+
cp.doserate = values[10]
|
75
|
+
cp.ssd = values[11]
|
76
|
+
cp.scale_convention = values[12]
|
77
|
+
cp.gantry_angle = values[13]
|
78
|
+
cp.gantry_dir = values[14]
|
79
|
+
cp.collimator_angle = values[15]
|
80
|
+
cp.collimator_dir = values[16]
|
81
|
+
cp.field_x_mode = values[17]
|
82
|
+
cp.field_x = values[18]
|
83
|
+
cp.collimator_x1 = values[19]
|
84
|
+
cp.collimator_x2 = values[20]
|
85
|
+
cp.field_y_mode = values[21]
|
86
|
+
cp.field_y = values[22]
|
87
|
+
cp.collimator_y1 = values[23]
|
88
|
+
cp.collimator_y2 = values[24]
|
89
|
+
cp.couch_vertical = values[25]
|
90
|
+
cp.couch_lateral = values[26]
|
91
|
+
cp.couch_longitudinal = values[27]
|
92
|
+
cp.couch_angle = values[28]
|
93
|
+
cp.couch_dir = values[29]
|
94
|
+
cp.couch_pedestal = values[30]
|
95
|
+
cp.couch_ped_dir = values[31]
|
96
|
+
cp.mlc_lp_a = [*values[32..131]]
|
97
|
+
cp.mlc_lp_b = [*values[132..231]]
|
98
|
+
cp.crc = values[232]
|
99
|
+
return cp
|
101
100
|
end
|
102
101
|
|
103
102
|
# Creates a new ControlPoint.
|
104
103
|
#
|
105
|
-
#
|
106
|
-
#
|
107
|
-
# * <tt>parent</tt> -- A Record which is used to determine the proper parent of this instance.
|
104
|
+
# @param [Record] parent a record which is used to determine the proper parent of this instance
|
108
105
|
#
|
109
106
|
def initialize(parent)
|
110
107
|
# Child:
|
@@ -117,7 +114,13 @@ module RTP
|
|
117
114
|
@mlc_lp_b = Array.new(100)
|
118
115
|
end
|
119
116
|
|
120
|
-
#
|
117
|
+
# Checks for equality.
|
118
|
+
#
|
119
|
+
# Other and self are considered equivalent if they are
|
120
|
+
# of compatible types and their attributes are equivalent.
|
121
|
+
#
|
122
|
+
# @param other an object to be compared with self.
|
123
|
+
# @return [Boolean] true if self and other are considered equivalent
|
121
124
|
#
|
122
125
|
def ==(other)
|
123
126
|
if other.respond_to?(:to_control_point)
|
@@ -127,23 +130,39 @@ module RTP
|
|
127
130
|
|
128
131
|
alias_method :eql?, :==
|
129
132
|
|
130
|
-
# As of now,
|
131
|
-
#
|
132
|
-
#
|
133
|
+
# As of now, gives an empty array. However, by definition, this record may
|
134
|
+
# have an mlc shape record as child, but this is not implemented yet.
|
135
|
+
#
|
136
|
+
# @return [Array] an emtpy array
|
133
137
|
#
|
134
138
|
def children
|
135
139
|
#return [@mlc_shape]
|
136
140
|
return Array.new
|
137
141
|
end
|
138
142
|
|
139
|
-
#
|
143
|
+
# Computes a hash code for this object.
|
144
|
+
#
|
145
|
+
# @note Two objects with the same attributes will have the same hash code.
|
146
|
+
#
|
147
|
+
# @return [Fixnum] the object's hash code
|
140
148
|
#
|
141
149
|
def hash
|
142
150
|
state.hash
|
143
151
|
end
|
144
152
|
|
145
|
-
#
|
146
|
-
#
|
153
|
+
# Gives the index of this ControlPoint
|
154
|
+
# (i.e. its index among the control points belonging to the parent Field).
|
155
|
+
#
|
156
|
+
# @return [Fixnum] the control point's index
|
157
|
+
#
|
158
|
+
def index
|
159
|
+
@parent.control_points.index(self)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Collects the values (attributes) of this instance.
|
163
|
+
#
|
164
|
+
# @note The CRC is not considered part of the actual values and is excluded.
|
165
|
+
# @return [Array<String>] an array of attributes (in the same order as they appear in the RTP string)
|
147
166
|
#
|
148
167
|
def values
|
149
168
|
return [
|
@@ -186,13 +205,17 @@ module RTP
|
|
186
205
|
|
187
206
|
# Returns self.
|
188
207
|
#
|
208
|
+
# @return [ControlPoint] self
|
209
|
+
#
|
189
210
|
def to_control_point
|
190
211
|
self
|
191
212
|
end
|
192
213
|
|
193
|
-
#
|
214
|
+
# Encodes the ControlPoint object + any hiearchy of child objects,
|
194
215
|
# to a properly formatted RTPConnect ascii string.
|
195
216
|
#
|
217
|
+
# @return [String] an RTP string with a single or multiple lines/records
|
218
|
+
#
|
196
219
|
def to_s
|
197
220
|
str = encode
|
198
221
|
if children
|
@@ -205,34 +228,36 @@ module RTP
|
|
205
228
|
|
206
229
|
alias :to_str :to_s
|
207
230
|
|
208
|
-
# Sets the
|
209
|
-
#
|
210
|
-
# === Notes
|
231
|
+
# Sets the mlc_lp_a attribute.
|
211
232
|
#
|
212
|
-
# As opposed to the ordinary (string) attributes, this attribute
|
213
|
-
#
|
233
|
+
# @note As opposed to the ordinary (string) attributes, this attribute
|
234
|
+
# contains an array holding all 100 MLC leaf 'A' string values.
|
235
|
+
# @param [Array<nil, #to_s>] array the new attribute values
|
214
236
|
#
|
215
237
|
def mlc_lp_a=(array)
|
216
238
|
array = array.to_a
|
217
239
|
raise ArgumentError, "Invalid argument 'array'. Expected length 100, got #{array.length}." unless array.length == 100
|
218
|
-
@mlc_lp_a = array.collect! {|e| e && e.to_s}
|
240
|
+
@mlc_lp_a = array.collect! {|e| e && e.to_s.strip}
|
219
241
|
end
|
220
242
|
|
221
|
-
# Sets the
|
243
|
+
# Sets the mlc_lp_b attribute.
|
222
244
|
#
|
223
|
-
#
|
224
|
-
#
|
225
|
-
#
|
226
|
-
# contains an array holding all 100 MLC leaf 'A' string values.
|
245
|
+
# @note As opposed to the ordinary (string) attributes, this attribute
|
246
|
+
# contains an array holding all 100 MLC leaf 'B' string values.
|
247
|
+
# @param [Array<nil, #to_s>] array the new attribute values
|
227
248
|
#
|
228
249
|
def mlc_lp_b=(array)
|
229
250
|
array = array.to_a
|
230
251
|
raise ArgumentError, "Invalid argument 'array'. Expected length 100, got #{array.length}." unless array.length == 100
|
231
|
-
@mlc_lp_b = array.collect! {|e| e && e.to_s}
|
252
|
+
@mlc_lp_b = array.collect! {|e| e && e.to_s.strip}
|
232
253
|
end
|
233
254
|
|
234
255
|
# Sets the keyword attribute.
|
235
256
|
#
|
257
|
+
# @note Since only a specific string is accepted, this is more of an argument check than a traditional setter method
|
258
|
+
# @param [#to_s] value the new attribute value
|
259
|
+
# @raise [ArgumentError] if given an unexpected keyword
|
260
|
+
#
|
236
261
|
def keyword=(value)
|
237
262
|
value = value.to_s.upcase
|
238
263
|
raise ArgumentError, "Invalid keyword. Expected 'CONTROL_PT_DEF', got #{value}." unless value == "CONTROL_PT_DEF"
|
@@ -241,186 +266,248 @@ module RTP
|
|
241
266
|
|
242
267
|
# Sets the field_id attribute.
|
243
268
|
#
|
269
|
+
# @param [nil, #to_s] value the new attribute value
|
270
|
+
#
|
244
271
|
def field_id=(value)
|
245
272
|
@field_id = value && value.to_s
|
246
273
|
end
|
247
274
|
|
248
275
|
# Sets the mlc_type attribute.
|
249
276
|
#
|
277
|
+
# @param [nil, #to_s] value the new attribute value
|
278
|
+
#
|
250
279
|
def mlc_type=(value)
|
251
280
|
@mlc_type = value && value.to_s
|
252
281
|
end
|
253
282
|
|
254
283
|
# Sets the mlc_leaves attribute.
|
255
284
|
#
|
285
|
+
# @param [nil, #to_s] value the new attribute value
|
286
|
+
#
|
256
287
|
def mlc_leaves=(value)
|
257
|
-
@mlc_leaves = value && value.to_s
|
288
|
+
@mlc_leaves = value && value.to_s.strip
|
258
289
|
end
|
259
290
|
|
260
291
|
# Sets the total_control_points attribute.
|
261
292
|
#
|
293
|
+
# @param [nil, #to_s] value the new attribute value
|
294
|
+
#
|
262
295
|
def total_control_points=(value)
|
263
|
-
@total_control_points = value && value.to_s
|
296
|
+
@total_control_points = value && value.to_s.strip
|
264
297
|
end
|
265
298
|
|
266
299
|
# Sets the control_pt_number attribute.
|
267
300
|
#
|
301
|
+
# @param [nil, #to_s] value the new attribute value
|
302
|
+
#
|
268
303
|
def control_pt_number=(value)
|
269
|
-
@control_pt_number = value && value.to_s
|
304
|
+
@control_pt_number = value && value.to_s.strip
|
270
305
|
end
|
271
306
|
|
272
307
|
# Sets the mu_convention attribute.
|
273
308
|
#
|
309
|
+
# @param [nil, #to_s] value the new attribute value
|
310
|
+
#
|
274
311
|
def mu_convention=(value)
|
275
312
|
@mu_convention = value && value.to_s
|
276
313
|
end
|
277
314
|
|
278
315
|
# Sets the monitor_units attribute.
|
279
316
|
#
|
317
|
+
# @param [nil, #to_s] value the new attribute value
|
318
|
+
#
|
280
319
|
def monitor_units=(value)
|
281
320
|
@monitor_units = value && value.to_s
|
282
321
|
end
|
283
322
|
|
284
323
|
# Sets the wedge_position attribute.
|
285
324
|
#
|
325
|
+
# @param [nil, #to_s] value the new attribute value
|
326
|
+
#
|
286
327
|
def wedge_position=(value)
|
287
328
|
@wedge_position = value && value.to_s
|
288
329
|
end
|
289
330
|
|
290
331
|
# Sets the energy attribute.
|
291
332
|
#
|
333
|
+
# @param [nil, #to_s] value the new attribute value
|
334
|
+
#
|
292
335
|
def energy=(value)
|
293
336
|
@energy = value && value.to_s
|
294
337
|
end
|
295
338
|
|
296
339
|
# Sets the doserate attribute.
|
297
340
|
#
|
341
|
+
# @param [nil, #to_s] value the new attribute value
|
342
|
+
#
|
298
343
|
def doserate=(value)
|
299
|
-
@doserate = value && value.to_s
|
344
|
+
@doserate = value && value.to_s.strip
|
300
345
|
end
|
301
346
|
|
302
347
|
# Sets the ssd attribute.
|
303
348
|
#
|
349
|
+
# @param [nil, #to_s] value the new attribute value
|
350
|
+
#
|
304
351
|
def ssd=(value)
|
305
352
|
@ssd = value && value.to_s
|
306
353
|
end
|
307
354
|
|
308
355
|
# Sets the scale_convention attribute.
|
309
356
|
#
|
357
|
+
# @param [nil, #to_s] value the new attribute value
|
358
|
+
#
|
310
359
|
def scale_convention=(value)
|
311
360
|
@scale_convention = value && value.to_s
|
312
361
|
end
|
313
362
|
|
314
363
|
# Sets the gantry_angle attribute.
|
315
364
|
#
|
365
|
+
# @param [nil, #to_s] value the new attribute value
|
366
|
+
#
|
316
367
|
def gantry_angle=(value)
|
317
|
-
@gantry_angle = value && value.to_s
|
368
|
+
@gantry_angle = value && value.to_s.strip
|
318
369
|
end
|
319
370
|
|
320
371
|
# Sets the gantry_dir attribute.
|
321
372
|
#
|
373
|
+
# @param [nil, #to_s] value the new attribute value
|
374
|
+
#
|
322
375
|
def gantry_dir=(value)
|
323
376
|
@gantry_dir = value && value.to_s
|
324
377
|
end
|
325
378
|
|
326
379
|
# Sets the collimator_angle attribute.
|
327
380
|
#
|
381
|
+
# @param [nil, #to_s] value the new attribute value
|
382
|
+
#
|
328
383
|
def collimator_angle=(value)
|
329
|
-
@collimator_angle = value && value.to_s
|
384
|
+
@collimator_angle = value && value.to_s.strip
|
330
385
|
end
|
331
386
|
|
332
387
|
# Sets the collimator_dir attribute.
|
333
388
|
#
|
389
|
+
# @param [nil, #to_s] value the new attribute value
|
390
|
+
#
|
334
391
|
def collimator_dir=(value)
|
335
392
|
@collimator_dir = value && value.to_s
|
336
393
|
end
|
337
394
|
|
338
395
|
# Sets the field_x_mode attribute.
|
339
396
|
#
|
397
|
+
# @param [nil, #to_s] value the new attribute value
|
398
|
+
#
|
340
399
|
def field_x_mode=(value)
|
341
400
|
@field_x_mode = value && value.to_s
|
342
401
|
end
|
343
402
|
|
344
403
|
# Sets the field_x attribute.
|
345
404
|
#
|
405
|
+
# @param [nil, #to_s] value the new attribute value
|
406
|
+
#
|
346
407
|
def field_x=(value)
|
347
|
-
@field_x = value && value.to_s
|
408
|
+
@field_x = value && value.to_s.strip
|
348
409
|
end
|
349
410
|
|
350
411
|
# Sets the collimator_x1 attribute.
|
351
412
|
#
|
413
|
+
# @param [nil, #to_s] value the new attribute value
|
414
|
+
#
|
352
415
|
def collimator_x1=(value)
|
353
|
-
@collimator_x1 = value && value.to_s
|
416
|
+
@collimator_x1 = value && value.to_s.strip
|
354
417
|
end
|
355
418
|
|
356
419
|
# Sets the collimator_x2 attribute.
|
357
420
|
#
|
421
|
+
# @param [nil, #to_s] value the new attribute value
|
422
|
+
#
|
358
423
|
def collimator_x2=(value)
|
359
|
-
@collimator_x2 = value && value.to_s
|
424
|
+
@collimator_x2 = value && value.to_s.strip
|
360
425
|
end
|
361
426
|
|
362
427
|
# Sets the field_y_mode attribute.
|
363
428
|
#
|
429
|
+
# @param [nil, #to_s] value the new attribute value
|
430
|
+
#
|
364
431
|
def field_y_mode=(value)
|
365
432
|
@field_y_mode = value && value.to_s
|
366
433
|
end
|
367
434
|
|
368
435
|
# Sets the field_y attribute.
|
369
436
|
#
|
437
|
+
# @param [nil, #to_s] value the new attribute value
|
438
|
+
#
|
370
439
|
def field_y=(value)
|
371
|
-
@field_y = value && value.to_s
|
440
|
+
@field_y = value && value.to_s.strip
|
372
441
|
end
|
373
442
|
|
374
443
|
# Sets the collimator_y1 attribute.
|
375
444
|
#
|
445
|
+
# @param [nil, #to_s] value the new attribute value
|
446
|
+
#
|
376
447
|
def collimator_y1=(value)
|
377
|
-
@collimator_y1 = value && value.to_s
|
448
|
+
@collimator_y1 = value && value.to_s.strip
|
378
449
|
end
|
379
450
|
|
380
451
|
# Sets the collimator_y2 attribute.
|
381
452
|
#
|
453
|
+
# @param [nil, #to_s] value the new attribute value
|
454
|
+
#
|
382
455
|
def collimator_y2=(value)
|
383
|
-
@collimator_y2 = value && value.to_s
|
456
|
+
@collimator_y2 = value && value.to_s.strip
|
384
457
|
end
|
385
458
|
|
386
459
|
# Sets the couch_vertical attribute.
|
387
460
|
#
|
461
|
+
# @param [nil, #to_s] value the new attribute value
|
462
|
+
#
|
388
463
|
def couch_vertical=(value)
|
389
|
-
@couch_vertical = value && value.to_s
|
464
|
+
@couch_vertical = value && value.to_s.strip
|
390
465
|
end
|
391
466
|
|
392
467
|
# Sets the couch_lateral attribute.
|
393
468
|
#
|
469
|
+
# @param [nil, #to_s] value the new attribute value
|
470
|
+
#
|
394
471
|
def couch_lateral=(value)
|
395
|
-
@couch_lateral = value && value.to_s
|
472
|
+
@couch_lateral = value && value.to_s.strip
|
396
473
|
end
|
397
474
|
|
398
475
|
# Sets the couch_longitudinal attribute.
|
399
476
|
#
|
477
|
+
# @param [nil, #to_s] value the new attribute value
|
478
|
+
#
|
400
479
|
def couch_longitudinal=(value)
|
401
|
-
@couch_longitudinal = value && value.to_s
|
480
|
+
@couch_longitudinal = value && value.to_s.strip
|
402
481
|
end
|
403
482
|
|
404
483
|
# Sets the couch_angle attribute.
|
405
484
|
#
|
485
|
+
# @param [nil, #to_s] value the new attribute value
|
486
|
+
#
|
406
487
|
def couch_angle=(value)
|
407
|
-
@couch_angle = value && value.to_s
|
488
|
+
@couch_angle = value && value.to_s.strip
|
408
489
|
end
|
409
490
|
|
410
491
|
# Sets the couch_dir attribute.
|
411
492
|
#
|
493
|
+
# @param [nil, #to_s] value the new attribute value
|
494
|
+
#
|
412
495
|
def couch_dir=(value)
|
413
496
|
@couch_dir = value && value.to_s
|
414
497
|
end
|
415
498
|
|
416
499
|
# Sets the couch_pedestal attribute.
|
417
500
|
#
|
501
|
+
# @param [nil, #to_s] value the new attribute value
|
502
|
+
#
|
418
503
|
def couch_pedestal=(value)
|
419
|
-
@couch_pedestal = value && value.to_s
|
504
|
+
@couch_pedestal = value && value.to_s.strip
|
420
505
|
end
|
421
506
|
|
422
507
|
# Sets the couch_ped_dir attribute.
|
423
508
|
#
|
509
|
+
# @param [nil, #to_s] value the new attribute value
|
510
|
+
#
|
424
511
|
def couch_ped_dir=(value)
|
425
512
|
@couch_ped_dir = value && value.to_s
|
426
513
|
end
|
@@ -429,7 +516,10 @@ module RTP
|
|
429
516
|
private
|
430
517
|
|
431
518
|
|
432
|
-
#
|
519
|
+
# Collects the attributes of this instance.
|
520
|
+
#
|
521
|
+
# @note The CRC is not considered part of the attributes of interest and is excluded
|
522
|
+
# @return [Array<String>] an array of attributes
|
433
523
|
#
|
434
524
|
alias_method :state, :values
|
435
525
|
|