Class: GDAL::RasterBandClassifier
- Inherits:
-
Object
- Object
- GDAL::RasterBandClassifier
- Includes:
- Logger
- Defined in:
- lib/gdal/extensions/raster_band_classifier.rb
Overview
Takes a list of Ranges of color values and remaps them. Note that these values are directly written to the raster band, overwriting all existing values.
Constant Summary collapse
- MIN_GAP_PERCENTAGE =
0.005
Instance Attribute Summary collapse
-
#ranges ⇒ Object
readonly
Returns the value of attribute ranges.
Instance Method Summary collapse
- #add_range(range, map_to_value) ⇒ Object
- #add_ranges(range_array) ⇒ Object
-
#classify! ⇒ Object
Uses the ranges that have been added to remap ranges to map_to values.
-
#equal_count_ranges(range_count) ⇒ Array<Hash>?
Uses the max value of the associated RasterBand and
range_count
to calculate evenly-weighted ranges. -
#initialize(raster_band) ⇒ RasterBandClassifier
constructor
A new instance of RasterBandClassifier.
-
#nodata_is_nan? ⇒ Boolean
True if NODATA is NaN.
-
#nodata_value ⇒ Numeric
NODATA value for the @raster_band.
Constructor Details
#initialize(raster_band) ⇒ RasterBandClassifier
Returns a new instance of RasterBandClassifier.
30 31 32 33 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 30 def initialize(raster_band) @raster_band = raster_band @ranges = [] end |
Instance Attribute Details
#ranges ⇒ Object (readonly)
Returns the value of attribute ranges.
27 28 29 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 27 def ranges @ranges end |
Instance Method Details
#add_range(range, map_to_value) ⇒ Object
37 38 39 40 41 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 37 def add_range(range, map_to_value) raise "range must be a Ruby Range" unless range.is_a? Range @ranges << { range: range, map_to: map_to_value } end |
#add_ranges(range_array) ⇒ Object
44 45 46 47 48 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 44 def add_ranges(range_array) range_array.each do |range| add_range range[:range], range[:map_to] end end |
#classify! ⇒ Object
Uses the ranges that have been added to remap ranges to map_to values. Note that this will overwrite the associated RasterBand with these values, so if you don’t want to overwrite the Dataset you’re working with, you should copy it first.
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 94 def classify! band_pixels = @raster_band.to_nna new_band_pixels = band_pixels.clone data_pixels = if nodata_value nodata_is_nan? ? ~band_pixels.isnan : band_pixels.ne(nodata_value) else Numo::Bit.cast(band_pixels.new_ones) end @ranges.each do |r| new_band_pixels[data_pixels & band_pixels.le(r[:range].max) & band_pixels.ge(r[:range].min)] = r[:map_to] end mask_nan(new_band_pixels, data_pixels) if nodata_is_nan? @raster_band.write_xy_narray(new_band_pixels) end |
#equal_count_ranges(range_count) ⇒ Array<Hash>?
Uses the max value of the associated RasterBand and range_count
to calculate evenly-weighted ranges. If there are remainder values at the max end of the values, those get lumped in with the last range.
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 56 def equal_count_ranges(range_count) pixels = @raster_band.to_nna masked_pixels = masked_pixels(pixels) return [] if masked_pixels.empty? sorted_and_masked_pixels = masked_pixels.to_a.sort range_size = (sorted_and_masked_pixels.size / range_count).to_i log "Masked pixel count/total pixel count: #{sorted_and_masked_pixels.size}/#{pixels.size}" log "Min pixel value: #{sorted_and_masked_pixels.min}" log "Max pixel value: #{sorted_and_masked_pixels.max}" log "Range size: #{range_size}" break_values = [*Array.new(range_count) { |i| sorted_and_masked_pixels[range_size * i] }.uniq, sorted_and_masked_pixels.max] ensure_min_gap(break_values) log "Break values: #{break_values}" return if range_count != 1 && break_values.uniq.size - 1 != range_count breakpoint_calculator = lambda do |range_number| min = break_values[range_number] max = break_values[range_number + 1] range_for_type(min, max) end Array.new(range_count) do |i| range = breakpoint_calculator.call(i) { range: range, map_to: (i + 1).to_data_type(@raster_band.data_type) } end end |
#nodata_is_nan? ⇒ Boolean
Returns True if NODATA is NaN.
117 118 119 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 117 def nodata_is_nan? nodata_value.is_a?(Float) && nodata_value.nan? end |
#nodata_value ⇒ Numeric
Returns NODATA value for the @raster_band.
112 113 114 |
# File 'lib/gdal/extensions/raster_band_classifier.rb', line 112 def nodata_value @raster_band.no_data_value[:value] end |