class Colors::LinearSegmentedColormap
Attributes
gamma[R]
segmented_data[R]
Public Class Methods
new(name, segmented_data, n_colors: 256, gamma: 1.0)
click to toggle source
Calls superclass method
Colors::Colormap::new
# File lib/colors/linear_segmented_colormap.rb, line 3 def initialize(name, segmented_data, n_colors: 256, gamma: 1.0) super(name, n_colors) @monochrome = false @segmented_data = segmented_data @gamma = gamma end
new_from_list(name, colors, n_colors: 256, gamma: 1.0)
click to toggle source
# File lib/colors/linear_segmented_colormap.rb, line 13 def self.new_from_list(name, colors, n_colors: 256, gamma: 1.0) case colors when Enumerable colors = colors.to_a else ary = Array.try_convert(colors) if ary.nil? raise ArgumentError, "colors must be convertible to an array: %p for %s" % [colors, name] else colors = ary end end case colors[0] when Array unless colors.all? {|a| a.length == 2 } raise ArgumentError, "colors array has invalid items" end vals, colors = colors.transpose else vals = Utils.linspace(0r, 1r, colors.length) end r, g, b, a = colors.map { |c| Utils.make_color(c).to_rgba.components }.transpose segmented_data = { red: [vals, r, r].transpose, green: [vals, g, g].transpose, blue: [vals, b, b].transpose, alpha: [vals, a, a].transpose } new(name, segmented_data, n_colors: n_colors, gamma: gamma) end
Public Instance Methods
gamma=(val)
click to toggle source
# File lib/colors/linear_segmented_colormap.rb, line 50 def gamma=(val) @gamma = val @initialized = false end
Private Instance Methods
create_lookup_table(n, data, gamma=1.0)
click to toggle source
# File lib/colors/linear_segmented_colormap.rb, line 69 def create_lookup_table(n, data, gamma=1.0) if data.respond_to?(:call) xind = Utils.linspace(0r, 1r, n).map {|x| x ** gamma } lut = xind.map {|i| data.(i).clamp(0, 1).to_f } return lut end ary = Array.try_convert(data) if ary.nil? raise ArgumentError, "data must be convertible to an array" elsif ary.any? {|sub| sub.length != 3 } raise ArgumentError, "data array must consist of 3-length arrays" end x, y0, y1 = ary.transpose if x[0] != 0.0 || x[-1] != 1.0 raise ArgumentError, "data mapping points must start with x=0 and end with x=1" end unless x.each_cons(2).all? {|a, b| a < b } raise ArgumentError, "data mapping points must have x in increasing order" end if n == 1 # Use the `y = f(x=1)` value for a 1-element lookup table lut = [y0[-1]] else x.map! {|v| v.to_f * (n - 1) } xind = Utils.linspace(0r, 1r, n).map {|i| (n - 1) * i ** gamma } ind = (0 ... n).map {|i| x.find_index {|v| xind[i] < v } }[1 ... -1] distance = ind.map.with_index do |i, j| (xind[j+1] - x[i - 1]) / (x[i] - x[i - 1]) end lut = [ y1[0], *ind.map.with_index {|i, j| distance[j] * (y0[i] - y1[i - 1]) + y1[i - 1] }, y0[-1] ] end return lut.map {|v| v.clamp(0, 1).to_f } end
init_colormap()
click to toggle source
# File lib/colors/linear_segmented_colormap.rb, line 55 def init_colormap red = create_lookup_table(self.n_colors, @segmented_data[:red], @gamma) green = create_lookup_table(self.n_colors, @segmented_data[:green], @gamma) blue = create_lookup_table(self.n_colors, @segmented_data[:blue], @gamma) alpha = if @segmented_data.key?(:alpha) create_lookup_table(self.n_colors, @segmented_data[:alpha], @gamma) end @lookup_table = Array.new(self.n_colors) do |i| Colors::RGBA.new(red[i], green[i], blue[i], alpha ? alpha[i] : 1r) end @initialized = true update_extreme_colors end
make_inverse_func(f)
click to toggle source
# File lib/colors/linear_segmented_colormap.rb, line 131 def make_inverse_func(f) ->(x) { f(1 - x) } end
make_reverse_colormap(name)
click to toggle source
# File lib/colors/linear_segmented_colormap.rb, line 117 def make_reverse_colormap(name) segmented_data_r = self.segmented_data.map { |key, data| data_r = if data.respond_to?(:call) make_inverse_func(data) else data.reverse_each.map do |x, y0, y1| [1r - x, y1, y0] end end [key, data_r] }.to_h LinearSegmentedColormap.new(name, segmented_data_r, n_colors: self.n_colors, gamma: self.gamma) end