Reputation: 5656
For my clustering gui, I am currently using random colors for the clusters, since I won't know before hand how many clusters I will end up with.
In Python, this looks like:
import random
def randomColor():
return (random.random(),random.random(),random.random())
However, when I update things, the colors change.
So what I would favor is to have a function which has an input argument I such as
def nonrandomColor(i):
...
return color
would always return the same color for the same I, while keeping the ability to generate arbitrarily many colors.
Answer does not have to be formulated in Python, it's more the general layout I'm interested in.
Upvotes: 3
Views: 4015
Reputation: 399743
Just set the seed of the random generator to the index, this might be cheaper than storing the colors.
random.seed(i)
Note that this will make random numbers way less random than before. If that is a problem, e.g. if your application uses random numbers elsewhere, you might want to look into the caching options suggested by other answers.
Upvotes: 2
Reputation: 70314
You want to store the colors in a dictionary or a list:
colors = {} # int -> color
def nonrandomColor(i):
if i not in colors:
colors[i] = randomColor()
return colors[i]
Upvotes: 2
Reputation: 10988
If you want repeatable non colliding colors then you could use something like the function below. It sections the number into 1, 10, 100 and then uses them as the RGB parts of the color.
def color(i):
r = i % 10
g = (i//10) % 10
b = (i//100) % 10
return(r*25, g*25, b*25)
For example:
color(1) == (25,0,0)
color(10) == (0,25,0)
color(999) = (225,225,255)
Upvotes: 2
Reputation: 65853
You can use i
to seed the random number generator. So, as long as the seed remains the same, you get the same value.
>>> import random
>>> random.seed(12)
>>> random.randint(0,255), random.randint(0,255), random.randint(0,255)
(121, 168, 170)
>>> random.seed(12)
>>> random.randint(0,255), random.randint(0,255), random.randint(0,255)
(121, 168, 170)
>>> random.seed(10)
>>> random.randint(0,255), random.randint(0,255), random.randint(0,255)
(146, 109, 147)
>>> random.seed(10)
>>> random.randint(0,255), random.randint(0,255), random.randint(0,255)
(146, 109, 147)
Depending on the number of colours you're likely to generate (i.e., 10 or a million), the caching method might be better than the seed()
method.
Upvotes: 0
Reputation: 24652
One way is to use caching. Use a defaultdict
:
>>> import random
>>> def randomColor():
... return (random.random(),random.random(),random.random())
...
>>> from collections import defaultdict
>>> colors = defaultdict(randomColor)
>>> colors[3]
(0.10726172906719755, 0.97327604757295705, 0.58935794305308264)
>>> colors[1]
(0.48991106537516382, 0.77039712435566876, 0.73707003166893892)
>>> colors[3]
(0.10726172906719755, 0.97327604757295705, 0.58935794305308264)
Upvotes: 7