Convert number to tkinter color - python-3.x

Is there a simple way to convert a number into a tkinter color (#ffeedd).
I'm already setup to take the number and multiply it by 8 to give me a bit more color range leeway, and maybe even multiply it by 16 depending on just how much leeway I have to work with, not sure on how much leeway I will have yet... but I'm guessing I'll only be able to multiply by 8. How do I take that number and convert it over so I can use it with canvas.create_line((x,y), (x,y), fill = 'color'). I tried hex(number) but it just gives me back that color 0x0 doesn't exists... kinda figured that would happen but thought it would be worth a try.
a = 326
b = a * 8
canvas.create_line((x,y), (x,y), fill = b)

Ensure you have 3 or 6 hex digits. For instance:
frame.configure(background="#{0:06X}".format(0x808080))
The actual permitted set of color specfications is given in the GetColor
manual page.

Related

Formatting number with a bunch of zeroes

Somewhat simple problem:
I need to turn a column A, which contains numbers with up to 1 decimal (20, 142, 2.5, etc.) to a string with a specific format, namely 8 whole digits and 6 decimal digits but without the actual decimal period, like so:
1 = 00000001000000
13 = 00000013000000
125 = 00000125000000
46.5 = 00000046500000
For what it's worth, the input data from column A will never be more than 3 total digits (0.5 to 999) and the decimal will always be either none or .5.
I also need for Excel to leave the zeroes alone instead of auto-formatting as a number and removing the ones at the beginning of the string.
As a makeshift solution, I've been using =CONCATENATE("'",TEXT(A1,"00000000.000000")), then copying the returning value and "pasting as value" where I actually need it.
It works fine, but I was wondering if there was a more direct solution where I don't have to manually intervene.
Thanks in advance!
=TEXT(A1*1000000,"0000000000000") I think that's what you mean.

Restrict floats to allotted padding while parsing as string

I would like to print a series of floats with varying amounts of numbers to the left of the decimal place. I would like these numbers to exactly fill a padding with blank spaces, digits, and a decimal point.
Paraphrasing the data and code I have now
floats = [321.1234561, 21.1234561, 1.1234561, 0.123456, 0.02345, 0.0034, 0.0004567]
for number in floats:
print('{:>8.6f}'.format(number))
This outputs
321.123456
21.123456
1.123456
0.123456
0.02345
0.0034
0.000457
I am looking for a way to print the following in a for loop assuming I don't know the amount of digits that will be to the left of the decimal place and the number of digits to the left never exceeds the padding which is 8 for this example.
321.1234
21.12345
1.123456
0.123456
0.02345
0.0034
0.000457
Similar questions have been asked about printing floating points with a certain width but the width they were talking about appeared to be the precision rather than the total number of character used to print the number.
Edit:
I have added a number to the end of the list for the following reason. The use of the specifier 'g' with 7 significant figures was recommended by attdona. This prevents the padding from being exceeded for numbers greater than or equal to 1 but not for numbers less than 1 with precision greater than 6. Using {:>8.7g} instead gives
321.1234
21.12345
1.123456
0.123456
0.02345
0.0034
0.0004567
Where the only one that exceeds the padding is the newly added one.
Use the General format type specifier g:
'{:>8.7g}'.format(number)
reference: https://docs.python.org/3/library/string.html#format-specification-mini-language
Update: For small numbers this format fails to align correctly. In this case you may adopt a mixed approach, but keep in mind that very small numbers will round to zero
for number in floats:
fstr = '{:>8.7g}'.format(number)
if len(fstr) > 8:
fstr = '{:>8.6f}'.format(number)
print(fstr)
for i in floats:
print('{:>8}'.format(f'{i:{8}.{8-len(str(int(i)))-1}f}'.rstrip('0')))
321.1235
21.12346
1.123456
0.123456
0.02345
0.0034

Excel pixels not proportional to points

I've noticed that (by changing column width) that the column width measured in points is not proportional to the pixel size. For example, at 21.44 points the pixel width of a column is 200. But at 20 pixels the width becomes 1.44 points, not the expected 2.14 points.
This is very confusing as I'm trying to write a code in VBA which will divide a particular size in 'n' different columns of equal size. Can anyone explain this abnormality? How can I write a code to divide the width (since the parameters for the column width are in points)?
Thanks
So I just was trying things and stumbled across this.
Maybe the numbers are off from a "true" width. If the theory is correct, then there must exist such an offset.
(21.44 + x) = 10 (1.44 + x)
x = 0.7822
Now let's see if this offset works for other some other lengths. For 80 pixels, the length mentioned by MS Excel is 8.11 points. Thus the true length is 8.89. The true length of a column with a width 20 pixels is 1.44 + 0.7822 = 2.222. Note that 2.222 * 4 = 8.89 approx. And this works for some other numbers as well, so I guess the theory should be correct.
Thus to answer the question, add the offset 0.7822 to the observed column width that you need to divide. Then divide it by 'n'. Subtract the offset to obtain the length 'x'. Then use the command Columns(var).ColumnWidth = x for each of the n columns

My Python 3.4.2 program will only round to 15 decimal places, even when I use the round() function to tell it to round to more

I am writing a program to approximate the golden ratio to the largest amount of precision possible. It works, but when I tell it to round to more than 16 decimal places, it just doesn't go past 15. This is my code:
# Using fractions to approximate the Golden Ratio
a = 1
b = 1
while b < 1000000000000000:
g = a + b
h = g / a
print (round(h, 20))
b = a
a = g
I realize that the while loop probably isn't the best way to do this, so if there is a more efficient way, please inform me of that. But my main question is is this rounding issue fixable? Or will I just have to settle for 15 decimal places? Thank you!
float doesn't have more than about 15 actual decimal places. Rounding it to more is pointless, since they don't exist.
If you really care about precision, I believe you should be using Decimal numbers instead of integers and floats.
Regardless of the type you use, be sure that you are formatting your string the way you want, and not just using print's default.

Do all 8 bit colors exist in 24 bit color space? If so how to map?

With 8 bit color depth there are 256 colors. With 24 bit color depth there are 16,777,216 colors. Is there a direct mapping between every color in the 8 bit space to a color in the 24 bit space? I would think the answer to this question is yes, but the comments to this answer suggest the mapping is only an approximation.
What I would like to do is create a palette of 8 bit colors in the 24 bit color space by specifying a 24 bit RGB value. I figured I could do this using this (obviously broken) logic:
3 bits for red == 8 unique values of red, 0-7
3 bits for green == 8 unique values of green, 0-7
2 bits for blue == 4 unique values of blue, 0-3
255/8 = 32 for red and green increment value
255/4 = 64 for blue increment value
{
"Red": [0,31,63,95,127,159,191,223,255],
"Green": [0,31,63,95,127,159,191,223,255],
"Blue": [0,63,127,191, 255]
}
So with 9 values of red, 9 values of green, and 5 values of blue I get 405 colors which is wrong. I know I need 8 values of red and green and 4 values of blue so I just adjusted things a bit:
255/87 = 36.57142857142857 for red and green increment value
255/43 = 85 for blue increment value
So this works for blue, but now my red and green increment value is not a whole number.
Once I got the mapping figured out I was going to loop through it like this:
for(r in rgbData.get("Red")) {
for(g in rgbData.get("Green")) {
for(b in rgbData.get("Blue")) {
colors.add("rgb ${r} ${g} ${b}")
}
}
}
This may be a totally incorrect approach to do what I want, just wanted to show I have tried something :)
UPDATE:
I tried the approach #Marc B suggested but it doesn't seem right. For instance, there is no white in the map I generated (which is 255, 255, 255 using 24 bit RGB). Using his approach this makes sense to me because the highest RGB value is 224, 224, 192 as can be seen:
full red == 111
111 >> 5 == 11100000
full green == 111
111 >> 5 == 11100000
full blue == 11
11 >> 6 == 11000000
11100000 11100000 11000000 == 224, 224, 192
224, 224, 192 != white
Here is the map generated using his approach:
{
"Red": [0,32,64,96,128,160,196,224],
"Green": [0,32,64,96,128,160,196,224],
"Blue": [0,64,128,192]
}
And the palette it generates:
UPDATE 2:
After doing some more research I have realized that when "X colors" (X being some number like 256, 16,777,216, etc.) are referred to that those colors can be just about anything. There is not a predefined set of 256 colors that are "the" 256 colors, though there are (as several have already mentioned) predefined sets of 256 colors that are "the" 256 colors for a specific implementation. I was also able to find a GIMP .gpl palette file on my organizations wiki that specified the 256 colors I am concerned with, so I can just copy the values out of there.
The practical answer is probably yes. Having said that, it's really a hardware dependant thing. #Marc B is close to correct (probably close enough for most people) but the real answer is it depends, it depends on the hardware, and it wont be exact from (hardware)implementation to implementation, but it will likely be exact enough for most people.
The way to convert is to multiply each channel by the highest level you want output and divide by the highest level of input.
{
"Red": [0,36,72,109,145,182,218,255],
"Green": [0,36,72,109,145,182,218,255],
"Blue": [0,85,170,255]
}
With this method you don't need to devote an even number of bits to each channel, you can use an arbitrary number of levels for each. You can get a more even distribution, but you don't get to use all 256 colors. One common arrangement is 6/7/6 for 252 colors:
{
"Red": [0,51,102,153,204,255],
"Green": [0,42,85,127,170,212,255],
"Blue": [0,51,102,153,204,255]
}
I know this answer is probably a bit late, but it might be useful for others. If someone knows what the algorithm outlined below is called, please let me know in a comment.
I'm currently working with different display hardware and I've run into the problem of converting a channel with m bits to one with n bits, where m < n; for example: convert a 5 bit channel to an 8 bits channel. White (b11111) should map to white (b11111111) and black should map to black.
To map, for example, 5-bits b10111 to 8 bits, I pad the missing bits with the MSBs from the original data:
b10111
^^^--- we need these three MSB again later, as 8-5 = 3 missing bits
shift left 3 bits:
b10111000
and pad with MSBs:
b10111101
^^^--- the MSBs
That maps quite well (you might want to apply rounding for values that are not all 1s) and round-trips (you can convert less than 8 bits to 8 bits, convert back and the result is the same as the original value).
If the narrower channel is less than 4 bits wide (like 3), the whole value will repeat completely:
b101 -> b10110110

Resources