Skip to content

Instantly share code, notes, and snippets.

@basicxman
Created September 4, 2011 18:01
Show Gist options
  • Select an option

  • Save basicxman/1193231 to your computer and use it in GitHub Desktop.

Select an option

Save basicxman/1193231 to your computer and use it in GitHub Desktop.
import glob
import string
import colorsys
import sys
from Tkinter import *
class Constellations(object):
def __init__(self):
self.named_stars = []
self.constellations = {}
def parse_constellations(self):
for file_name in glob.glob("constellations/*.txt"):
self.add_constellation_file(file_name)
def add_constellation_file(self, file_name):
star_pairs = open(file_name, "r").read().split("\n")
ss, se = 15, file_name.index(".txt")
name = file_name[ss:se]
self.constellations[name] = []
for pair in star_pairs:
t = map(self.find_star_by_name, pair.split(","))
self.constellations[name].append(t)
def add_star(self, x, y, cx, cy, magnitude, names):
if names[0] == "": return
for name in names:
self.named_stars.append((x, y, cx, cy, magnitude, name))
def sort_stars(self):
self.named_stars = sorted(self.named_stars, key=lambda star: star[5])
def binary_search(self, l, value, left = 0, right = None):
if right == None: right = len(l) - 1
if right < left:
return -1
mid = (left + right) / 2
if l[mid][5] > value:
return self.binary_search(l, value, left, mid - 1)
elif l[mid][5] < value:
return self.binary_search(l, value, mid + 1, right)
else:
return mid
def find_star_by_name(self, name):
return self.binary_search(self.named_stars, name)
def draw(self, cv):
for constellation in self.constellations:
self.draw_constellation(cv, self.constellations[constellation])
def draw_constellation(self, cv, constellation):
for pair in constellation:
if pair[0] == -1: continue
x1, y1 = self.named_stars[pair[0]][2:4]
x2, y2 = self.named_stars[pair[1]][2:4]
cv.create_line(x1, y1, x2, y2, fill = "green")
cv.pack()
class Stars(object):
def __init__(self, width, height):
self.canvas_width = width
self.canvas_height = height
self.canvas_margin = 10
self.constellations = Constellations()
self.initialize_graphics()
self.parse_file("stars.txt")
self.constellations.sort_stars()
self.constellations.parse_constellations()
self.constellations.draw(self.cv)
def initialize_graphics(self):
self.root = Tk()
self.root.title("Stars")
self.cv = Canvas(self.root, width = self.canvas_width + 50, height = self.canvas_height + 20, bg = "black")
self.cv.pack()
self.display_magnitude_legend()
def display_magnitude_legend(self):
for i in range(1, 25):
self.draw_star(i / 2.0, self.canvas_width + 15, i * (i / 3.0))
# Python can die with many fires here, such a poorly documented stdlib module (colorsys).
def convert_to_rgb(self, h, s, l):
r, g, b = map(lambda x: x * 255, colorsys.hls_to_rgb(h, s, l))
return "#%02x%02x%02x" % (r, g, b)
def magnitude_to_hsl(self, magnitude):
value = magnitude / 10.0
value = 0 if value < 0 else 1 if value > 1 else value
h, s, l = 0.55 + value / 2, value, 0.75
return (h, s, l)
def draw_star(self, magnitude, x, y):
m = magnitude * 0.45
colour = self.convert_to_rgb(*self.magnitude_to_hsl(magnitude))
self.cv.create_oval(x - m / 2, y - m / 2, x + m, y + m, fill = colour)
self.cv.pack()
def coordinate_to_pixel(self, x, y):
return self.scale(x, self.canvas_width) + self.canvas_margin, self.scale(y * -1, self.canvas_height) + self.canvas_margin
def scale(self, value, bound):
x = (value + 1) * bound # Ensure number is positive and multiply by maximum.
return x / 2.0 # Divide by range of -1 to 1.
def fill_args(self, args):
if len(args) == 6: args.append("")
elif len(args) > 7:
args[6] = " ".join(args[6:])
args = args[0:7]
return args
def parse_line(self, line):
if not line: return
x, y, z, henry, magnitude, harvard, names = self.fill_args(line.split(" "))
x, y, magnitude, names = float(x), float(y), float(magnitude), map(string.strip, names.split(";"))
cx, cy = self.coordinate_to_pixel(x, y)
self.constellations.add_star(x, y, cx, cy, magnitude, names)
self.draw_star(magnitude, cx, cy)
def parse_file(self, file_name):
lines = open(file_name, "r").read().split("\n")
return map(self.parse_line, lines)
if len(sys.argv) != 3:
star_field = Stars(800, 800)
else:
star_field = Stars(int(sys.argv[1]), int(sys.argv[2]))
star_field.root.mainloop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment