import requests
import pandas as pd
import os
import time
import folium
from folium.plugins import HeatMap
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from PIL import Image, ImageDraw, ImageFont
from pathlib import Path
import imageio
import shutil
Giriş
Animasyonlu haritalar, zaman içinde değişen verileri görselleştiren etkili bir yöntemdir. Örneğin, Türkiye ve çevresinde gerçekleşen depremleri animasyonlu bir harita üzerinde göstermek, deprem aktivitesinin zamanla nasıl değiştiğini ve hangi bölgelerin daha fazla risk altında olduğunu görsel olarak görmemize yardımcı olabilir.
Animasyonlu haritayı oluşturmak için kullanacağımız verilere USGS (United States Geological Survey) API ile ulaşacağız.
Kullanılacak Kütüphaneler
API ile Verilerin Çekilmesi ve Kullanılabilir Formata Dönüştürülmesi
= '2014-01-01'
start = 3
min_mag = 39.1458
lat = 34.1614
lon = 1000
max_rad_km
= f'https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime={start}&minmagnitude={min_mag}&latitude={lat}&longitude={lon}&maxradiuskm={max_rad_km}'
url = requests.get(url)
response = response.json()
data
= pd.DataFrame({
df 'Place': [feature['properties']['place'] for feature in data['features']],
'Magnitude': [feature['properties']['mag'] for feature in data['features']],
'Time': [pd.to_datetime(feature['properties']['time'], unit='ms').strftime('%Y-%m-%d') for feature in data['features']],
'Latitude': [feature['geometry']['coordinates'][1] for feature in data['features']],
'Longitude': [feature['geometry']['coordinates'][0] for feature in data['features']]
})
Yukarıdaki kodda, verilen parametrelerle USGS API’ını kullanarak deprem verilerini çekiyoruz. Başlangıç tarihini (start
) '2014-01-01'
ve minimum deprem büyüklüğünü (min_mag
) 3
olarak belirledik. Ayrıca, enlem (lat
) 39.1458
ve boylam (lon
) 34.1614
olacak şekilde Türkiye’nin koordinatlarına yakın ve maksimum 1000
kilometrelik yarıçapa (max_rad_km
) sahip bir bölgeyi sorguluyoruz. Son olarak, API’dan gelen verileri işleyerek bir DataFrame oluşturuyoruz. Bu DataFrame, depremlerin yerini (Place
), büyüklüğünü (Magnitude
), zamanını (Time
) ve enlem-boylam koordinatlarını (Latitude
-Longitude
) içeriyor.
Aylık bir seri ile çalışacağımız için tarihlerdeki (Time
sütunu) günleri 01
ile değiştiriyoruz.
'Time'] = df['Time'].str.replace(r'-\d{2}$', '-01', regex=True) df[
Haritaların Yapılması ve HTML-PNG Formatlarında Kaydedilmesi
= Options()
chrome_options '--start-fullscreen')
chrome_options.add_argument(
= df['Time'].unique()
unique_dates
unique_dates.sort()
= [39, 35]
turkey_latlon
= 5
delay
= ImageFont.load_default()
font = 36
font_size
for unique_date in unique_dates:
= df[df['Time'] == unique_date]
filtered_df = filtered_df[['Latitude', 'Longitude', 'Magnitude']]
filtered_df = folium.Map(location=turkey_latlon, zoom_start=6, tiles='cartodbdark_matter')
turkey_map =filtered_df, radius=15).add_to(turkey_map)
HeatMap(data
= f'turkey_heatmap_{unique_date}.html'
html_filename
turkey_map.save(html_filename)
= webdriver.Chrome(options=chrome_options)
browser
browser.get(os.path.abspath(html_filename))
time.sleep(delay)
= f'turkey_heatmap_{unique_date}.png'
screenshot_filename
browser.save_screenshot(screenshot_filename)
browser.quit()
= Image.open(screenshot_filename)
img = ImageDraw.Draw(img)
draw = ImageFont.truetype('arial.ttf', font_size)
font 10, img.height - 50), pd.to_datetime(unique_date).strftime('%B %Y'), font=font, fill=(255, 255, 255))
draw.text((
img.save(screenshot_filename)
os.remove(html_filename)print(f'{html_filename} loaded in the browser and screenshot {screenshot_filename} captured.')
Yukarıdaki kodda, her bir tarih döngüde kullanılacağı için tekil tarihleri unique_dates
değişkenine gönderip bu tarihleri eskiden yeniye doğru olacak şekilde sıralıyoruz. Türkiye’nin koordinatlarını tanımladığımız ve haritaların merkezi olacak değerler turkey_latlon
değişkeninde bulunuyor. Her işlemde 5
saniyelik bir bekleme süresi olacak. Bunu delay
değişkeninde tutuyoruz. Resimlerin üzerinde görünecek yazılara ait varsayılan font ve font büyüklüğü değerleri olan arial.ttf
ve 36
sırasıyla font
ve font_size
değişkenlerinde bulunuyor. Her döngüde açılacak tarayıcıların ekranı kapsayacak şekilde olmasını istediğimiz için '--start-fullscreen'
olacak şekilde ayarlama da yaptık.
Döngüde 7 kod grubu bulunmaktadır. İlk grup, tarih filtresi yapıp haritayı oluşturuyor. İkinci grup, haritayı içinde bulunduğu dizine HTML formatında kaydediyor. Üçüncü grup, HTML formatında kaydedilen dosyayı tarayıcıda açıyor ve açtıktan sonra belirlenen süre kadar bekletiyor. Dördüncü grup, ekran görüntüsü alıyor ve içinde bulunduğu dizine PNG formatında kaydediyor. Beşinci grup, açılan tarayıcıyı kapatıyor. Altıncı grup, resim üzerinde yazı işlemlerini yapıyor. Yedinci ve son grup, kaydedilen HTML dosyalarını siliyor ve ekrana bilgi veriyor.
Animasyonlu Harita Yapımı ve GIF Formatında Kaydedilmesi
Çalışmanın odak noktasını bu başlık altında göreceğiz.
= Path()
image_path = list(image_path.glob('*.png'))
images = [imageio.v3.imread(file_name) for file_name in images]
image_list 'Turkey_Earthquake.gif', image_list, fps=2)
imageio.mimwrite(= [file.unlink() for file in images]
_
'Turkey_Earthquake.gif', 'imgs/Turkey_Earthquake.gif') shutil.move(
Yukarıdaki kodda ilk olarak, Path()
fonksiyonunu çağırarak bir dosya yolu nesnesi oluşturuyor ve bunu image_path
değişkenine atıyoruz. Ardından, bu dosya yolu nesnesi üzerinde .glob()
yöntemini kullanarak tüm PNG dosyalarını alıyor ve images
listesine atıyoruz. imageio
modülünü kullanarak her bir PNG dosyasını imageio.v3.imread()
fonksiyonuyla okuyor ve bu okunan görüntüleri image_list
listesine ekliyoruz. imageio.mimwrite()
fonksiyonuyla image_list
içindeki görüntüleri kullanarak bir GIF dosyası oluşturuyoruz. Oluşturduğumuz GIF dosyasının ismini 'Turkey_Earthquake.gif'
olarak belirliyor ve saniyede 2 kare (fps=2
) hızında olacak şekilde ayarlıyoruz. Daha sonra, artık gereksiz hale gelmiş olan PNG dosyalarını tek tek sildiriyoruz. Bu işlem için bir liste dönülüyor ve her bir dosya unlink()
yöntemi kullanılarak siliniyor. Son olarak, shutil.move()
fonksiyonunu kullanarak oluşturduğumuz GIF dosyasını 'imgs/'
dizini altına taşıyoruz.
Gelecek içeriklerde görüşmek dileğiyle.