Skip to content

Commit 1b113c3

Browse files
committed
Sparse Interpolation QoL
1 parent cd52739 commit 1b113c3

File tree

2 files changed

+89
-8
lines changed

2 files changed

+89
-8
lines changed

pvdeg/geospatial.py

+43-8
Original file line numberDiff line numberDiff line change
@@ -927,14 +927,17 @@ def elevation_stochastic_downselect(
927927

928928

929929
def interpolate_analysis(
930-
result: xr.Dataset, data_var: str, method="nearest"
930+
result: xr.Dataset, data_var: str, method="nearest", resolution=100j,
931931
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
932932
"""
933933
Interpolate sparse spatial result data against DataArray coordinates.
934934
Takes DataArray instead of Dataset, index one variable of a dataset to get a dataarray.
935935
936936
Parameters:
937937
-----------
938+
resolution: complex
939+
Change the amount the input is interpolated.
940+
For more interpolation set higher (200j is more than 100j)
938941
939942
Result:
940943
-------
@@ -951,21 +954,51 @@ def interpolate_analysis(
951954
) # probably a nicer way to do this
952955

953956
grid_lat, grid_lon = np.mgrid[
954-
df["latitude"].min() : df["latitude"].max() : 100j,
955-
df["longitude"].min() : df["longitude"].max() : 100j,
957+
df["latitude"].min() : df["latitude"].max() : resolution,
958+
df["longitude"].min() : df["longitude"].max() : resolution,
956959
]
957960

958961
grid_z = griddata(data[:, 0:2], data[:, 2], xi=(grid_lat, grid_lon), method=method)
959962

960963
return grid_z, grid_lat, grid_lon
961964

962965

963-
def plot_sparse_analysis(result: xr.Dataset, data_var: str, method="nearest") -> None:
966+
# api could be updated to match that of plot_USA
967+
def plot_sparse_analysis(
968+
result: xr.Dataset,
969+
data_var: str,
970+
method="nearest",
971+
resolution:complex=100j,
972+
figsize:tuple=(10,8),
973+
) -> None:
974+
"""
975+
Plot the output of a sparse geospatial analysis using interpolation.
976+
977+
Parameters
978+
-----------
979+
result: xr.Dataset
980+
xarray dataset in memory containing coordinates['longitude', 'latitude'] and at least one datavariable.
981+
data_var: str
982+
name of datavariable to plot from result
983+
method: str
984+
interpolation method.
985+
Options: `'nearest', 'linear', 'cubic'`
986+
See [`scipy.interpolate.griddata`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.griddata.html)
987+
resolution: complex
988+
Change the amount the input is interpolated.
989+
For more interpolation set higher (200j is more than 100j)
990+
991+
Returns
992+
-------
993+
fig, ax: tuple
994+
matplotlib figure and axes of plot
995+
"""
996+
964997
grid_values, lat, lon = interpolate_analysis(
965-
result=result, data_var=data_var, method=method
998+
result=result, data_var=data_var, method=method, resolution=resolution
966999
)
9671000

968-
fig = plt.figure()
1001+
fig = plt.figure(figsize=figsize)
9691002
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.LambertConformal(), frameon=False)
9701003
ax.patch.set_visible(False)
9711004

@@ -977,7 +1010,7 @@ def plot_sparse_analysis(result: xr.Dataset, data_var: str, method="nearest") ->
9771010
origin="lower",
9781011
cmap="viridis",
9791012
transform=ccrs.PlateCarree(),
980-
) # should this be trnsposed
1013+
)
9811014

9821015
shapename = "admin_1_states_provinces_lakes"
9831016
states_shp = shpreader.natural_earth(
@@ -994,7 +1027,9 @@ def plot_sparse_analysis(result: xr.Dataset, data_var: str, method="nearest") ->
9941027
cbar = plt.colorbar(img, ax=ax, orientation="vertical", fraction=0.02, pad=0.04)
9951028
cbar.set_label("Value")
9961029

997-
plt.title("Interpolated Heatmap")
1030+
plt.title(f"Interpolated Sparse Analysis, {data_var}")
9981031
plt.xlabel("Longitude")
9991032
plt.ylabel("Latitude")
10001033
plt.show()
1034+
1035+
return fig, ax

pvdeg/utilities.py

+46
Original file line numberDiff line numberDiff line change
@@ -1262,3 +1262,49 @@ def compare_templates(
12621262
return False
12631263

12641264
return True
1265+
1266+
def merge_sparse(files: list[str])->xr.Dataset:
1267+
"""
1268+
Merge an arbitrary number of geospatial analysis results.
1269+
Creates monotonically increasing indicies.
1270+
1271+
Uses `engine='h5netcdf'` for reliability, use h5netcdf to save your results to netcdf files.
1272+
1273+
Parameters
1274+
-----------
1275+
files: list[str]
1276+
A list of strings representing filepaths to netcdf (.nc) files.
1277+
Each file must have the same coordinates, `['latitude','longitude']` and identical datavariables.
1278+
1279+
Returns
1280+
-------
1281+
merged_ds: xr.Dataset
1282+
Dataset (in memory) with `coordinates = ['latitude','longitude']` and datavariables matching files in
1283+
filepaths list.
1284+
"""
1285+
1286+
datasets = [xr.open_dataset(fp, engine='h5netcdf').compute() for fp in files]
1287+
1288+
latitudes = np.concatenate([ds.latitude.values for ds in datasets])
1289+
longitudes = np.concatenate([ds.longitude.values for ds in datasets])
1290+
unique_latitudes = np.sort(np.unique(latitudes))
1291+
unique_longitudes = np.sort(np.unique(longitudes))
1292+
1293+
data_vars = datasets[0].data_vars
1294+
1295+
merged_ds = xr.Dataset(
1296+
{var: (['latitude', 'longitude'], np.full((len(unique_latitudes), len(unique_longitudes)), np.nan)) for var in data_vars},
1297+
coords={
1298+
'latitude': unique_latitudes,
1299+
'longitude': unique_longitudes
1300+
}
1301+
)
1302+
1303+
for ds in datasets:
1304+
lat_inds = np.searchsorted(unique_latitudes, ds.latitude.values)
1305+
lon_inds = np.searchsorted(unique_longitudes, ds.longitude.values)
1306+
1307+
for var in ds.data_vars:
1308+
merged_ds[var].values[np.ix_(lat_inds, lon_inds)] = ds[var].values
1309+
1310+
return merged_ds

0 commit comments

Comments
 (0)