17 src_idx=None, tgt_idx=None, zoom=1, quiver_kwargs={}):
18 weights = Dataset(weightsfile,
"r")
19 if 'version' in weights.__dict__:
20 if weights.version !=
"yac weight file 1.0":
21 print(
"WARNING: You are using an incompatible weight file version\n" +
22 weights.version +
" != yac weight file 1.0")
23 src_points = np.empty([2, 0])
24 num_src_fields = weights.num_src_fields
if "num_src_fields" in weights.variables
else 1
25 for src_field
in range(num_src_fields):
26 if "src_locations" in weights.variables:
27 locstr = bytes(np.array(weights[
"src_locations"][src_field, :])).decode().rstrip(
"\0")
31 src_points = np.hstack([src_points, np.stack([src_grid.clon,
33 elif locstr ==
"CORNER":
34 src_points = np.hstack([src_points, np.stack([src_grid.vlon,
36 elif locstr ==
"EDGE":
37 src_points = np.hstack([src_points, np.stack([src_grid.vlon,
40 raise f
"Unknown location string {locstr}"
41 if "dst_locations" in weights.variables:
42 locstr = bytes(np.array(weights[
"dst_location"])).decode().rstrip(
"\0")
46 tgt_points = np.stack([tgt_grid.clon, tgt_grid.clat])
47 elif locstr ==
"CORNER":
48 tgt_points = np.stack([tgt_grid.vlon, tgt_grid.vlat])
49 elif locstr ==
"EDGE":
50 tgt_points = np.stack([tgt_grid.elon, tgt_grid.elat])
52 raise f
"Unknown location string {locstr}"
54 yac_weights_format_address_offset = 1
55 src_adr = np.asarray(weights[
"src_address"])-yac_weights_format_address_offset-src_grid.idx_offset
56 tgt_adr = np.asarray(weights[
"dst_address"])-yac_weights_format_address_offset-tgt_grid.idx_offset
62 if src_idx
is not None:
63 mask *= (src_adr == (src_idx-src_grid.idx_offset))
64 if tgt_idx
is not None:
65 mask *= (tgt_adr == (tgt_idx-tgt_grid.idx_offset))
67 if src_idx
is not None or tgt_idx
is not None:
68 src_res = src_adr[mask]
69 tgt_res = tgt_adr[mask]
70 e = np.array([min(np.min(src_points[0, src_res]), np.min(tgt_points[0, tgt_res])),
71 max(np.max(src_points[0, src_res]), np.max(tgt_points[0, tgt_res])),
72 min(np.min(src_points[1, src_res]), np.min(tgt_points[1, tgt_res])),
73 max(np.max(src_points[1, src_res]), np.max(tgt_points[1, tgt_res]))])
74 c = np.array([0.5*(e[0]+e[1]), 0.5*(e[0]+e[1]),
75 0.5*(e[2]+e[3]), 0.5*(e[2]+e[3])])
76 extent = (e-c)*1.15*zoom + c
77 ax.set_extent(extent, crs=ccrs.PlateCarree())
79 extent = ax.get_extent(crs=ccrs.PlateCarree())
82 mask *= (((src_points[0, src_adr] >= extent[0]) * (src_points[0, src_adr] <= extent[1]) *
83 (src_points[1, src_adr] >= extent[2]) * (src_points[1, src_adr] <= extent[3])) +
84 ((tgt_points[0, tgt_adr] >= extent[0]) * (tgt_points[0, tgt_adr] <= extent[1]) *
85 (tgt_points[1, tgt_adr] >= extent[2]) * (tgt_points[1, tgt_adr] <= extent[3])))
87 src_adr = src_adr[mask]
88 tgt_adr = tgt_adr[mask]
90 ax_proj = ax.projection
91 src_t = ax_proj.transform_points(ccrs.PlateCarree(),
92 src_points[0, src_adr], src_points[1, src_adr])
93 tgt_t = ax_proj.transform_points(ccrs.PlateCarree(),
94 tgt_points[0, tgt_adr], tgt_points[1, tgt_adr])
97 c = weights[
"remap_matrix"][mask, 0]
99 norm = matplotlib.colors.Normalize()
100 cm = matplotlib.cm.Oranges
101 ax.quiver(src_t[:, 0], src_t[:, 1],
102 uv[:, 0], uv[:, 1], angles=
'xy', scale_units=
'xy', scale=1,
105 sm = matplotlib.cm.ScalarMappable(cmap=cm, norm=norm)
107 plt.colorbar(sm, ax=ax)
109 if src_idx
is not None:
110 ax.set_title(f
"Interpolation for source index {src_idx}\nSum of weights: {sum(c):.8f}")
111 if tgt_idx
is not None:
112 ax.set_title(f
"Interpolation for target index {tgt_idx}\nSum of weights: {sum(c):.8f}")
114 if src_idx
is not None or tgt_idx
is not None:
116 for x, y, t
in zip(src_t[:, 0] + 0.5*uv[:, 0],
117 src_t[:, 1] + 0.5*uv[:, 1], c):
118 ax.text(x, y, f
"{t:.3}",
119 horizontalalignment=
'center', verticalalignment=
'center')
121 wlines = ax.plot([src_points[0, src_adr], tgt_points[0, tgt_adr]],
122 [src_points[1, src_adr], tgt_points[1, tgt_adr]],
123 color=
'white', alpha=0.,
124 transform=ccrs.PlateCarree())
125 wcenter = np.vstack([0.5*(src_points[0, src_adr]+tgt_points[0, tgt_adr]),
126 0.5*(src_points[1, src_adr]+tgt_points[1, tgt_adr])])
127 wlabel = np.vstack([src_adr, tgt_adr, c.data])
128 annotation = ax.annotate(text=
'', xy=(0, 0), xytext=(15, 15),
129 textcoords=
'offset points',
130 bbox={
'boxstyle':
'round',
'fc':
'w'},
131 arrowprops={
'arrowstyle':
'->'},
132 transform=ccrs.PlateCarree(),
134 annotation.set_visible(
'False')
136 def motion_hover(event):
137 annotation_visible = annotation.get_visible()
138 if event.inaxes == ax:
140 for idx, wl
in enumerate(wlines):
141 if wl.contains(event)[0]:
145 annotation.xy = (wcenter[0, idx], wcenter[1, idx])
146 text_label =
'src: {} tgt: {}\nweight: {:.3f}'.format(int(wlabel[0, idx]),
149 annotation.set_text(text_label)
150 annotation.set_visible(
True)
151 fig.canvas.draw_idle()
153 if annotation_visible:
154 annotation.set_visible(
False)
155 fig.canvas.draw_idle()
157 fig.canvas.mpl_connect(
'motion_notify_event', motion_hover)
171def main(source_grid, target_grid, weights_file, center=None,
172 source_idx=None, target_idx=None, zoom=1,
173 label_src_grid=None, label_tgt_grid=None,
174 coast_res="50m", save_as=None):
175 src_grid = get_grid(source_grid)
176 if target_grid
is not None:
177 tgt_grid = get_grid(target_grid)
180 fig = plt.figure(figsize=[10, 10])
183 if source_idx
is not None:
184 center = [src_grid.clon[source_idx-src_grid.idx_offset],
185 src_grid.clat[source_idx-src_grid.idx_offset]]
186 elif target_idx
is not None:
187 center = [tgt_grid.clon[target_idx-tgt_grid.idx_offset],
188 tgt_grid.clat[target_idx-tgt_grid.idx_offset]]
190 proj = ccrs.Orthographic(*center)
191 ax = fig.add_subplot(1, 1, 1, projection=proj)
193 if weights_file
is None:
194 if source_idx
is not None:
196 ax.set_extent(extent, crs=ccrs.PlateCarree())
197 elif target_idx
is not None:
199 ax.set_extent(extent, crs=ccrs.PlateCarree())
200 if source_idx
is None and target_idx
is None:
201 ax.set_extent([center[0]-1000000*zoom, center[0]+1000000*zoom,
202 center[1]-1000000*zoom, center[1]+1000000*zoom], crs=proj)
205 ax.set_facecolor(
"#9ddbff")
207 feature = cfeature.NaturalEarthFeature(name=
'land',
212 ax.add_feature(feature, zorder=-999)
214 if weights_file
is not None:
216 source_idx, target_idx, zoom, quiver_kwargs={
"zorder": 2})
219 if src_grid
is not None:
220 src_grid.plot(ax, label=label_src_grid, plot_kwargs={
"color":
"green",
"zorder": 1})
221 if tgt_grid
is not None:
222 tgt_grid.plot(ax, label=label_tgt_grid, plot_kwargs={
"color":
"blue",
"zorder": 1})