Class: RTKIT::BinMatcher
- Inherits:
-
Object
- Object
- RTKIT::BinMatcher
- Defined in:
- lib/rtkit/bin_matcher.rb
Overview
Contains the DICOM data and methods related to the comparison of binary volumes (i.e. segmented volumes).
Instance Attribute Summary collapse
-
#master ⇒ Object
The reference (master) BinVolume.
-
#volumes ⇒ Object
readonly
An array of BinVolumes.
Instance Method Summary collapse
-
#==(other) ⇒ Object
(also: #eql?)
Returns true if the argument is an instance with attributes equal to self.
-
#add(volume) ⇒ Object
Adds a BinVolume instance to the matcher.
-
#by_sensitivity ⇒ Object
Returns an array of volumes, (reversly) sorted by their sensitivity score.
-
#by_specificity ⇒ Object
Returns an array of volumes, (reversly) sorted by their specificity score.
-
#fill_blanks ⇒ Object
Ensures that a valid comparison can be done by making sure that every volume has a BinImage for any image that is referenced among the BinVolumes.
-
#hash ⇒ Object
Generates a Fixnum hash value for this instance.
-
#initialize(volumes = nil, master = nil) ⇒ BinMatcher
constructor
Creates a new BinMatcher instance.
-
#narrays(sort_slices = true) ⇒ Object
Returns an array of NArrays from the BinVolumes of this instance.
-
#score_dice ⇒ Object
Scores the volumes of the BinMatcher instance against the reference (master) volume, by using Dice’s coeffecient.
-
#score_ss ⇒ Object
Scores the volumes of the BinMatcher instance against the reference (master) volume, by using Sensitivity and Specificity.
-
#sort_volumes ⇒ Object
Rearranges the BinImages belonging to the BinVolumes of this instance, by matching the BinImages by their Image instance references, to ensure that the NArrays extracted from these volumes are truly comparable.
-
#to_bin_matcher ⇒ Object
Returns self.
Constructor Details
#initialize(volumes = nil, master = nil) ⇒ BinMatcher
Creates a new BinMatcher instance.
Parameters
-
volumes
– An array of BinVolume instances to be matched. -
master
– A master BinVolume which the other volumes will be compared against.
19 20 21 22 23 24 25 |
# File 'lib/rtkit/bin_matcher.rb', line 19 def initialize(volumes=nil, master=nil) raise ArgumentError, "Invalid argument 'volumes'. Expected Array, got #{volumes.class}." if volumes && volumes.class != Array raise ArgumentError, "Invalid argument 'master'. Expected BinVolume, got #{master.class}." if master && master.class != BinVolume raise ArgumentError, "Invalid argument 'volumes'. Expected array to contain only BinVolume instances, got #{volumes.collect{|i| i.class}.uniq}." if volumes && volumes.collect{|i| i.class}.uniq != [BinVolume] @volumes = volumes || Array.new @master = master end |
Instance Attribute Details
#master ⇒ Object
The reference (master) BinVolume.
8 9 10 |
# File 'lib/rtkit/bin_matcher.rb', line 8 def master @master end |
#volumes ⇒ Object (readonly)
An array of BinVolumes.
10 11 12 |
# File 'lib/rtkit/bin_matcher.rb', line 10 def volumes @volumes end |
Instance Method Details
#==(other) ⇒ Object Also known as: eql?
Returns true if the argument is an instance with attributes equal to self.
29 30 31 32 33 |
# File 'lib/rtkit/bin_matcher.rb', line 29 def ==(other) if other.respond_to?(:to_bin_matcher) other.send(:state) == state end end |
#add(volume) ⇒ Object
Adds a BinVolume instance to the matcher.
39 40 41 42 |
# File 'lib/rtkit/bin_matcher.rb', line 39 def add(volume) raise ArgumentError, "Invalid argument 'volume'. Expected BinVolume, got #{volume.class}." unless volume.is_a?(BinVolume) @volumes << volume end |
#by_sensitivity ⇒ Object
Returns an array of volumes, (reversly) sorted by their sensitivity score. The volumes are sorted in such a way that the best scoring volume (highest sensitivity) appears first. If no volumes are defined, an empty array is returned.
48 49 50 |
# File 'lib/rtkit/bin_matcher.rb', line 48 def by_sensitivity return (@volumes.sort_by {|v| v.sensitivity}).reverse end |
#by_specificity ⇒ Object
Returns an array of volumes, (reversly) sorted by their specificity score. The volumes are sorted in such a way that the best scoring volume (highest specificity) appears first. If no volumes are defined, an empty array is returned.
56 57 58 |
# File 'lib/rtkit/bin_matcher.rb', line 56 def by_specificity return (@volumes.sort_by {|v| v.specificity}).reverse end |
#fill_blanks ⇒ Object
Ensures that a valid comparison can be done by making sure that every volume has a BinImage for any image that is referenced among the BinVolumes. If one or more BinVolumes are missing one or more BinImages, empty BinImages will be created for these BinVolumes.
Notes
-
The master volume (if present) is also processed in this method.
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 |
# File 'lib/rtkit/bin_matcher.rb', line 69 def fill_blanks if @volumes.length > 0 # Register all unique images referenced by the various volumes: images = Set.new # Include the master volume (if it is present): [@volumes, @master].flatten.compact.each do |volume| volume.bin_images.each do |bin_image| images << bin_image.image unless images.include?(bin_image.image) end end # Check if any of the volumes have images missing, and if so, create empty images: images.each do |image| [@volumes, @master].flatten.compact.each do |volume| match = false volume.bin_images.each do |bin_image| match = true if bin_image.image == image end unless match # Create BinImage: bin_img = BinImage.new(NArray.byte(image.columns, image.rows), image) volume.add(bin_img) end end end end end |
#hash ⇒ Object
Generates a Fixnum hash value for this instance.
98 99 100 |
# File 'lib/rtkit/bin_matcher.rb', line 98 def hash state.hash end |
#narrays(sort_slices = true) ⇒ Object
Returns an array of NArrays from the BinVolumes of this instance. Returns an empty array if no volumes are defined.
Notes
-
Only the volumes are returned. The master volume (if present) is not returned with this method.
116 117 118 119 120 121 122 |
# File 'lib/rtkit/bin_matcher.rb', line 116 def narrays(sort_slices=true) n = Array.new @volumes.each do |volume| n << volume.narray(sort_slices) end return n end |
#score_dice ⇒ Object
Scores the volumes of the BinMatcher instance against the reference (master) volume, by using Dice’s coeffecient.
For more information, see: en.wikipedia.org/wiki/Dice%27s_coefficient
166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/rtkit/bin_matcher.rb', line 166 def score_dice if @master # Find the voxel-indices for the master where the decisions are 1 and 0: pos_indices_master = (@master.narray.eq 1).where @volumes.each do |bin_vol| pos_indices_vol = (bin_vol.narray.eq 1).where num_common = (@master.narray[pos_indices_vol].eq 1).where.length bin_vol.dice = 2 * num_common / (pos_indices_master.length + pos_indices_vol.length).to_f end end end |
#score_ss ⇒ Object
Scores the volumes of the BinMatcher instance against the reference (master) volume, by using Sensitivity and Specificity.
For more information, see: en.wikipedia.org/wiki/Sensitivity_and_specificity
184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/rtkit/bin_matcher.rb', line 184 def score_ss if @master # Find the voxel-indices for the master where the decisions are 1 and 0: pos_indices, neg_indices = (@master.narray.eq 1).where2 @volumes.each do |bin_vol| narr = bin_vol.narray bin_vol.sensitivity = (narr[pos_indices].eq 1).where.length / pos_indices.length.to_f bin_vol.specificity = (narr[neg_indices].eq 0).where.length / neg_indices.length.to_f end end end |
#sort_volumes ⇒ Object
Rearranges the BinImages belonging to the BinVolumes of this instance, by matching the BinImages by their Image instance references, to ensure that the NArrays extracted from these volumes are truly comparable.
Notes
-
The master volume (if present) is not processed in this method.
-
Raises an exception if any irregularities in number of BinImages or Image references occurs.
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/rtkit/bin_matcher.rb', line 205 def sort_volumes # It only makes sense to sort if we have at least two volumes: if @volumes.length > 1 raise "All volumes of the BinMatcher isntance must have the same number of BinImages (got lengths #{@volumes.collect {|v| v.bin_images.length}})." if @volumes.collect {|v| v.bin_images.length}.uniq.length > 1 # Collect the Image references of the BinImage's of the first volume: desired_image_order = Array.new @volumes.first.bin_images.collect {|bin_image| desired_image_order << bin_image.image} raise "One (or more) Image references were nil in the first BinVolume instance of the BinMatcher. Unable to sort BinImages when they lack Image reference." if desired_image_order.compact.length != desired_image_order.length # Sort the BinImages of the remaining volumes so that their order of images are equal to that of the first volume: (1...@volumes.length).each do |i| current_image_order = Array.new @volumes[i].bin_images.collect {|bin_image| current_image_order << bin_image.image} sort_order = current_image_order.compare_with(desired_image_order) @volumes[i].bin_images.sort_by_order!(sort_order) #@volumes[i].reorder_images(sort_order) end end end |
#to_bin_matcher ⇒ Object
Returns self.
226 227 228 |
# File 'lib/rtkit/bin_matcher.rb', line 226 def to_bin_matcher self end |