File size: 4,624 Bytes
eb1aec4
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import PIL

def get_mask(df):
    """
        Take a Major TOM dataframe and create a mask corresponding to available cells
    """
    
    mask = np.zeros((2004,4008), dtype=np.uint8)
    row_offset = -1002
    col_offset = -2004
    
    nodata = df['nodata'].values > 0.5
    
    yy = mask.shape[0] - (np.array(df['grid_row_u']) - row_offset) - 1
    xx = np.array(df['grid_col_r']) - col_offset
    
    yy = yy[~nodata]
    xx = xx[~nodata]
    
    mask[yy, xx] = 255

    return PIL.Image.fromarray(mask)

def fig2img(fig):
    """Convert a Matplotlib figure to a PIL Image and return it"""
    import io
    buf = io.BytesIO()
    fig.savefig(buf)
    buf.seek(0)
    img = PIL.Image.open(buf)
    return img

def light_basemap():
    """
        Bright coloured contours
    """
    
    with plt.ioff():
        fig, ax = plt.subplots(figsize=(48,24), dpi=167)
    
        m = Basemap(projection='sinu', lat_0=0, lon_0=0, resolution='l', ax=ax)
        m.fillcontinents(color="#9eba9b", lake_color='#CCDDFF')
        m.drawmapboundary(fill_color="#CCDDFF")
        m.drawcountries(color="#666666", linewidth=1)
        m.drawcoastlines(color="#666666", linewidth=1)
        
        plt.gca().set_axis_off()
        plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
                    hspace = 0, wspace = 0)
        plt.margins(0,0)
        
        return fig2img(fig)

def dark_basemap():
    """
        Dark contours
    """
    
    with plt.ioff():
        fig, ax = plt.subplots(figsize=(48,24), dpi=167)
        
        m = Basemap(projection='sinu', lat_0=0, lon_0=0, resolution='l', ax=ax)
        m.fillcontinents(color="#242424", lake_color='#242424')
        m.drawmapboundary(fill_color="#242424")
        m.drawcountries(color="#000000", linewidth=1)
        m.drawcoastlines(color="#000000", linewidth=1)
        
        plt.gca().set_axis_off()
        plt.subplots_adjust(top = 1, bottom = 0, right = 1, left = 0, 
                    hspace = 0, wspace = 0)
        plt.margins(0,0)
        
        return fig2img(fig)

def get_coveragemap(input, input2=None):
    """
        Creates a complete coloured Major TOM coverage figure in the same style as in the official documentation

        Optionally, input2 can be provided and then, the map plots a map with extra colours indicating cells available only in input (green) or only input2 (blue)
    """

    if input2 is None:
        return single_coveragemap(input)
    else:
        cmap1 = single_coveragemap(input)
        cmap2 = single_coveragemap(input2)

        # arrays for mixing
        inp1_arr = np.array(cmap1)[...,:3]
        inp2_arr = np.array(cmap2)[...,:3]

        common_arr = inp1_arr*(inp1_arr.sum(-1) == inp2_arr.sum(-1))[:,:,None]
        common_arr[:,:,(1,2)] = 0
        inp1_arr[:,:,(0,2)] = 0 # Green - indicates presence of S2 only
        inp2_arr[:,:,(0,1)] = 0 # Blue - indicates presense of DEM only

        return PIL.Image.fromarray(((common_arr + inp1_arr + inp2_arr)).astype(np.uint8))
        

def single_coveragemap(input):
    """
        Creates a complete coloured Major TOM coverage figure in the same style as in the official documentation
    """

    # compute mask if df is provided
    if isinstance(input, pd.DataFrame):
        mask = get_mask(input)
    else:
        mask = input
    
    basemap = light_basemap()
    basemap_d = dark_basemap()
        
    outside_earth = np.array(basemap.convert('RGBA'))[:, :, 0] == 255
    outside_earth = PIL.Image.fromarray(outside_earth)
    
    mask = mask.resize(basemap.size, PIL.Image.NEAREST)
    
    basemap.putalpha(mask)
    
    # Mask outside of earth
    basemap.paste(outside_earth, (0,0), outside_earth)
    
    basemap_d.paste(basemap, (0,0), basemap)

    return basemap_d

if __name__ == '__main__':
    DATASET_NAME = 'Major-TOM/Core-S2L2A'
    meta_path = 'https://huggingface.co/datasets/{}/resolve/main/metadata.parquet'.format(DATASET_NAME)
    df = pd.read_parquet(meta_path)

    # This is how you make a coverage figure!
    coverage_img = get_coveragemap(df)

    coverage_img.save('coverage-example.png', format='PNG')

    # and this is how you can create an overap for 2 datasets!
    DATASET_NAME = 'Major-TOM/Core-DEM'
    meta_path = 'https://huggingface.co/datasets/{}/resolve/main/metadata.parquet'.format(DATASET_NAME)
    dem_df = pd.read_parquet(meta_path)

    coverage_img = get_coveragemap(df,dem_df)

    coverage_img.save('overlap-coverage-example.png', format='PNG')