33import geopandas
44import matplotlib .pyplot as plt
55import datetime
6+ import requests
7+ import numpy as np
8+ from pathlib import Path
69
7- def create_map ():
10+ def fetch_grid_coordinates ():
811 """
9- Generate a world map with the current time and several fixed points .
10- In practical applications, you should fetch your real-time data here .
12+ Fetch grid coordinates from the registry file .
13+ Returns a DataFrame with latitude and longitude columns .
1114 """
12- # --- 1. Fetch your data ---
13- # This is an example. You should replace it with your own data fetching logic.
14- # For example: Fetching the latest earthquake locations from an API, your movement trajectory, etc.
15- data = {
16- 'City' : ['London' , 'New York' , 'Tokyo' , 'Sydney' ],
17- 'Latitude' : [51.5074 , 40.7128 , 35.6895 , - 33.8688 ],
18- 'Longitude' : [- 0.1278 , - 74.0060 , 139.6917 , 151.2093 ]
19- }
20- df = pd .DataFrame (data )
15+ # Fetch the registry file from the URL
16+ registry_url = "https://dl-1.tessera.wiki/v1/global_0.1_degree_representation/registry_2024.txt"
17+
18+ print ("Fetching registry file..." )
19+ response = requests .get (registry_url )
20+ response .raise_for_status ()
21+
22+ # Parse the registry content
23+ coordinates = set () # Use set to avoid duplicates
24+
25+ for line in response .text .strip ().split ('\n ' ):
26+ if line :
27+ # Extract the file path (first part before the hash)
28+ file_path = line .split ()[0 ]
29+
30+ # Only process main grid files (not _scales files)
31+ if file_path .endswith ('.npy' ) and not '_scales.npy' in file_path :
32+ # Extract grid name from path like "2024/grid_-0.05_10.05/grid_-0.05_10.05.npy"
33+ parts = file_path .split ('/' )
34+ if len (parts ) >= 2 :
35+ grid_name = parts [1 ] # e.g., "grid_-0.05_10.05"
36+
37+ if grid_name .startswith ('grid_' ):
38+ # Remove "grid_" prefix and split by underscore
39+ coords = grid_name [5 :].split ('_' )
40+ if len (coords ) == 2 :
41+ try :
42+ lon = float (coords [0 ])
43+ lat = float (coords [1 ])
44+ coordinates .add ((lat , lon ))
45+ except ValueError :
46+ continue
47+
48+ print (f"Found { len (coordinates )} unique grid points" )
49+
50+ # Convert to DataFrame
51+ coords_list = list (coordinates )
52+ df = pd .DataFrame (coords_list , columns = ['Latitude' , 'Longitude' ])
53+
54+ return df
2155
56+ def create_map ():
57+ """
58+ Generate a world map with all available grid points from the registry.
59+ """
60+ # --- 1. Fetch grid coordinates ---
61+ df = fetch_grid_coordinates ()
62+
2263 # Convert pandas DataFrame to GeoDataFrame
64+ print ("Creating GeoDataFrame..." )
2365 gdf = geopandas .GeoDataFrame (
2466 df , geometry = geopandas .points_from_xy (df .Longitude , df .Latitude )
2567 )
26- gdf .set_crs ("EPSG:4326" , inplace = True ) # Set the coordinate system to WGS84
68+ gdf .set_crs ("EPSG:4326" , inplace = True ) # Set the coordinate system to WGS84
2769
2870 # --- 2. Plot the map ---
29- # Directly load a local shapefile
30- world = geopandas .read_file ('world_map/ne_110m_admin_0_countries.shp' )
71+ # Check if world map shapefile exists
72+ world_map_path = Path ('world_map/ne_110m_admin_0_countries.shp' )
73+ if not world_map_path .exists ():
74+ print ("Warning: World map shapefile not found. Using built-in world map." )
75+ world = geopandas .read_file (geopandas .datasets .get_path ('naturalearth_lowres' ))
76+ else :
77+ world = geopandas .read_file (world_map_path )
3178
3279 # Create the plotting area
33- fig , ax = plt .subplots (1 , 1 , figsize = (15 , 10 ))
80+ print ("Creating map..." )
81+ fig , ax = plt .subplots (1 , 1 , figsize = (20 , 12 ))
3482
3583 # Plot the world map base layer
36- world .plot (ax = ax , color = 'lightgray' , edgecolor = 'black' )
84+ world .plot (ax = ax , color = 'lightgray' , edgecolor = 'black' , linewidth = 0.5 )
3785
38- # Plot your data points on the map
39- gdf .plot (ax = ax , marker = 'o' , color = 'red' , markersize = 50 , label = 'My Points ' )
86+ # Plot grid points on the map with smaller markers
87+ gdf .plot (ax = ax , marker = 'o' , color = 'red' , markersize = 2 , alpha = 0.8 , label = 'Available ' )
4088
4189 # --- 3. Customize and save the map ---
42- # Add a title with the current time
90+ # Add a title with the current time and grid count
4391 current_time_utc = datetime .datetime .now (datetime .timezone .utc ).strftime ('%Y-%m-%d %H:%M:%S UTC' )
44- ax .set_title (f'Real-time Map\n Last Updated: { current_time_utc } ' , fontdict = {'fontsize' : '16' , 'fontweight' : '3' })
92+ ax .set_title (f'GeoTessera Grid Coverage Map\n Total Grid Points: { len (df )} \n Last Updated: { current_time_utc } ' ,
93+ fontdict = {'fontsize' : '18' , 'fontweight' : 'bold' })
94+
95+ # Add legend
96+ ax .legend (loc = 'lower left' , frameon = True , fancybox = True , shadow = True , fontsize = 12 )
97+
98+ # Set axis labels
99+ ax .set_xlabel ('Longitude' , fontsize = 14 )
100+ ax .set_ylabel ('Latitude' , fontsize = 14 )
45101
46- # Hide the axes
47- ax .set_axis_off ( )
102+ # Add grid for better readability
103+ ax .grid ( True , alpha = 0.3 , linestyle = '--' )
48104
49- # Save the map as an image file, bbox_inches='tight' trims excess whitespace
50- # The filename 'map.png' is important and will be used later
51- plt .savefig ('map.png' , dpi = 150 , bbox_inches = 'tight' )
52- print ("Map generated successfully!" )
105+ # Save the map as an image file
106+ plt .tight_layout ()
107+ plt .savefig ('map.png' , dpi = 300 , bbox_inches = 'tight' )
108+ print (f"Map generated successfully with { len (df )} grid points!" )
109+
110+ # Close the plot to free memory
111+ plt .close ()
53112
54113if __name__ == '__main__' :
55114 create_map ()
0 commit comments