0

I am setting the colour value based on range from 0 to 100 (red to green)

As of now, a simple snippet

value = 5
colour = ""
if value <= 25:
   colour = "#FF0000"  # red
elif value > 25 and value <= 50:
    colour = "FF8000" # orange
elif value > 50 and value <=75:
    colour = "#FFFF00"  # yellow
elif value > 75 and value < 100:
    colour = "#53d926" # light green

Is it possible to set colour automatically (gradient pattern, from red > orange > yellow > not complete green)? as 100 indicates complete success (green).

Right now, only four colours. But based on varying percentage, it should set the colour accordingly for any value (combination of colours from red > orange > yellow > not complete green, with respective to values) Any smart way to handle this ?

stack
  • 17
  • 6

1 Answers1

0

It appears you have 5 well defined points and you want a smooth gradient for values between them.

  • 0: red.
  • 25: orange.
  • 50: yellow.
  • 75: light green.
  • 100: green.

You can use linear interpolation to get the colors between those defined points. For example a value that is exactly halfway between two points would just be the average of those two colors. The function lerp below provides this.

def all_channels2(func):
    def wrapper(channel1, channel2, *args, **kwargs):
        try:
            return func(channel1, channel2, *args, **kwargs)
        except TypeError:
            return tuple(func(c1, c2, *args, **kwargs) for c1,c2 in zip(channel1, channel2))
    return wrapper

@all_channels2
def lerp(color1, color2, frac):
    return color1 * (1 - frac) + color2 * frac

And here's how you would use it:

def hexcolor(rgb):
    return f'#{int(rgb[0]):0>2X}{int(rgb[1]):0>2X}{int(rgb[2]):0>2X}'

if value < 25:
   colour = hexcolor(lerp((0xff, 0x00, 0x00), (0xff, 0x80, 0x00), value / 25))
elif value < 50:
    colour = hexcolor(lerp((0xFF, 0x80, 0x00), (0xFF, 0xFF, 0x00), (value - 25) / 25))
elif value < 75:
    colour = hexcolor(lerp((0xFF, 0xFF, 0x00), (0x53, 0xd9, 0x26), (value - 50) / 25))
else:
    colour = hexcolor(lerp((0x53, 0xd9, 0x26), (0x00, 0xff, 0x00), (value - 75) / 25))

enter image description here

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Thanks Mark. it takes me time to understand and analyse. For time being executed this code (value = 5, int) but getting error as ValueError: Unknown format code 'X' for object of type int/float' (Python 3.9.2) – stack Mar 15 '21 at 06:50
  • And also conditional loop can be modified as per need, otherwise above snippet encounters first 'if' statement (value < 25) always. – stack Mar 15 '21 at 06:58
  • @stack according to the [format spec for f-strings](https://docs.python.org/3/library/string.html#formatspec) `X` should produce upper-case hex values, and it does on my system Python 3.8. Which version of Python do you have? – Mark Ransom Mar 15 '21 at 15:07
  • @stack of course you can modify the conditionals as needed, but there's nothing wrong with what I gave here. The example at the bottom was generated with that code, running through all the values 0 to 99. – Mark Ransom Mar 15 '21 at 15:10
  • I am using Python 3.9.2 – stack Mar 16 '21 at 04:23
  • Tried edited solution, it worked. Thank you so much Mark, will understand these concepts. – stack Mar 16 '21 at 05:53
  • What would be the input to use these functions? Can either of you post the code you used with this to produce something, like the color bar? – Doda Aug 11 '22 at 00:45
  • @LauraMorgan it's just `for value in range(101)`. What you do with the resulting colors is up to you. – Mark Ransom Aug 11 '22 at 00:51