Skip to content

Instantly share code, notes, and snippets.

@ProfAndreaPollini
Created February 2, 2023 17:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ProfAndreaPollini/354d700be688a555fc3422902cbae1fc to your computer and use it in GitHub Desktop.
Save ProfAndreaPollini/354d700be688a555fc3422902cbae1fc to your computer and use it in GitHub Desktop.
GLOBAL TEMPERATURE ANOMALIES. #python data visualization
from typing import List, Tuple
from colors import hsl_to_rgb
import pygame as pg
import glm
from perlin_noise import PerlinNoise
import moviepy.editor as mp
import numpy as np
import csv
from datetime import datetime
class DataPoint:
def __init__(self, pos: glm.vec2, color) -> None:
self.angle = 0
self.alpha = 255.0
self.pos = pos
self.color = color
def update(self):
self.alpha = max(0.99 * self.alpha, 0)
def draw(self, surface):
pg.draw.circle(surface, (*self.color, int(self.alpha)),
self.pos.to_tuple(), 5)
class DataTrail:
def __init__(self) -> None:
self.trail: List[DataPoint] = []
self.MAX_ELEMENTS = 3000
def add(self, point: DataPoint):
self.trail.append(point)
if len(self.trail) > self.MAX_ELEMENTS:
self.trail.pop(0)
def update(self):
for point in self.trail:
point.update()
def draw(self, surface):
for point in self.trail:
point.draw(surface)
pg.init()
pg.font.init()
font = pg.font.SysFont("Consolas", 36)
SCREEN_SIZE = (600, 600*(16/9.0))
screen = pg.display.set_mode(SCREEN_SIZE)
point_surface = pg.surface.Surface(screen.get_size()).convert_alpha()
timer = pg.time.Clock()
center = glm.vec2(*screen.get_rect().center)
running = True
MEAN_RADIUS = 170.0
t = 0.0
data = DataTrail()
noise = PerlinNoise()
palette_img = pg.image.load("download.png").convert_alpha()
palette = []
for i in range(256):
# hsl_to_rgb(0.4 + (i/256)*30, 255, min(255, i * 5.5))
r, g, b, a = palette_img.get_at((i, 2))
palette.append((r, g, b))
temperature_data: List[Tuple[datetime, float]] = []
temperature_extrema = [10.0, -10.0]
with open('monthly_csv.csv', newline='') as csvfile:
spamreader = csv.reader(csvfile, delimiter=',', quotechar='|')
for row in spamreader:
if row[0] == "GCAG":
print(', '.join(row))
date = datetime.strptime(row[1], '%Y-%m-%d')
value = float(row[2])
temperature_data.append((date, value))
temperature_extrema[0] = min(value, temperature_extrema[0])
temperature_extrema[1] = max(value, temperature_extrema[1])
temperature_max_diff = abs(temperature_extrema[1]-temperature_extrema[0])
current_element = len(temperature_data)-1
planet = pg.image.load("planet.jpg").convert_alpha()
planet = pg.transform.rotozoom(planet, angle=0, scale=0.6)
frames = []
while running:
for event in pg.event.get():
if event.type == pg.QUIT:
running = False
year = temperature_data[current_element][0].year
screen.fill((0, 0, 0))
r = MEAN_RADIUS * (1 + temperature_data[current_element][1])
# print(f"{t=}, {noise(t/10**3)=}")
point_pos = center + glm.vec2(glm.cos(glm.radians(t*0.2))*r,
glm.sin(glm.radians(t*0.2))*r)
p = DataPoint(point_pos, palette[int(
(1.0 - abs(temperature_data[current_element][1] - temperature_extrema[0])/temperature_max_diff) * 255)])
data.add(p)
data.update()
# pg.draw.circle(screen, (255, 0, 0),
# point_pos.to_tuple(), 15)
planet_pos = planet.get_rect(center=center)
point_surface.fill((0, 0, 0))
point_surface.blit(planet, planet_pos)
title_img = font.render(
"Global Temperature Anomalies", True, (200, 200, 200))
title_center = title_img.get_rect(center=(center.x, 50))
img = font.render(
f"{year}", True, (200, 200, 200))
year_pos = img.get_rect(
center=(center).to_tuple())
# year_bg = pg.Surface(img.get_size(), color=(255, 255, 255, 128))
pg.draw.rect(point_surface, (155, 155, 155, 20),
year_pos.inflate(30, 30))
point_surface.blit(img, year_pos)
point_surface.blit(title_img, title_center)
data.draw(point_surface)
pg.draw.circle(point_surface, (250, 250, 250, 200),
center.to_tuple(), MEAN_RADIUS, width=1)
screen.blit(point_surface, (0, 0))
pg.display.update()
scaled_screen = pg.transform.rotozoom(screen, angle=0, scale=1.3)
surface_array = np.rot90(
np.fliplr(np.array(pg.surfarray.array3d(scaled_screen))))
frames.append(surface_array)
t += timer.tick(60)
current_element -= 1
if current_element < 0:
running = False
clip = mp.ImageSequenceClip(frames, fps=60)
# Salva il video
clip.write_videofile("output.mp4")
pg.quit()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment