from matplotlib import pyplot as plt
import colorcet
import toml
plot
Visualization of big data is hard.
For big raster image, ploting every pixels consumes too much time and memory and common picture format (e.g. png) do not support too big image. One common solution is to resample to a smaller image and plot it, which is the default option for common plot package (e.g. matplotlib). But it will reduce the resolution and prevent showing local features.
For big point cloud image, besides the time and memory consumming, the overlapping of rendered points is also a problem.
Here we provide the plot functions based on Holoviews and Datashader fix the problems. The point cloud is resampled to a small raster image and then plotted on the screen. The pixel size of the raster image is exactly matching the resolution of the screen to maximize the accuracy. The plot is interative and the resampling is dynamic, which means when you zoom in, a more precise raster image is automatically generated and plotted.
Note that the plotting functions here make use of dynamic updates, which require a running Jupyter server. When viewed statically (as this documentation website), the plots will not update fully when you zoom.
import holoviews as hv
import datashader as ds
import spatialpandas
import zarr
import numpy as np
from holoviews import opts
from bokeh.models import WheelZoomTool
'bokeh') hv.extension(
ras_plot
ras_plot (data:numpy.ndarray, bounds:tuple=None, level_increase=0)
plot in memory ras data.
Type | Default | Details | |
---|---|---|---|
data | ndarray | 2D numpy array to be visualized | |
bounds | tuple | None | bounding box (x0, y0, x_max, y_max) |
level_increase | int | 0 | amount of zoom level increase for more clear point show and faster responds time |
= '../Tutorials/CLI/load_data/rslc.zarr/'
rslc_ = zarr.open(rslc_,'r')[...,0:3] rslc
= ras_plot(np.angle(rslc[...,2]*rslc[...,0].conj())) intf_plot
= intf_plot.redim(x=hv.Dimension('r', label='Range'), y=hv.Dimension('az',label='Azimuth'), z=hv.Dimension('Phase',range=(-np.pi,np.pi))) intf_plot
='colorwheel',width=600, height=400, colorbar=True,
intf_plot.opts(opts.Image(cmap=True,
invert_yaxis=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],active_tools=['wheel_zoom'])) default_tools
ras_stack_plot
ras_stack_plot (data:str, bounds:tuple=None, level_increase=0)
plot rendered stack of ras tiles.
Type | Default | Details | |
---|---|---|---|
data | str | 3D numpy array, (nlines, width, nimages) | |
bounds | tuple | None | bounding box (x0, y0, x_max, y_max) |
level_increase | int | 0 | amount of zoom level increase for more clear point show and faster responds time |
= '../Tutorials/CLI/load_data/rslc.zarr/'
rslc_ = zarr.open(rslc_,'r')[:]
rslc = toml.load('../Tutorials/CLI/load_data/meta.toml')['dates'] dates_str
= ras_stack_plot(np.angle(rslc*rslc[...,[0]].conj())) intf_plot
= intf_plot.redim(i=hv.Dimension('i', label='Interferogram', range=(0,16), value_format=(lambda i: dates_str[i]+'_'+dates_str[0])),
intf_plot =hv.Dimension('r', label='Range'), y=hv.Dimension('az',label='Azimuth'), z=hv.Dimension('Phase',range=(-np.pi,np.pi))) x
='bottom')
hv.output(widget_location='colorwheel',width=600, height=400, colorbar=True,
intf_plot.opts(opts.Image(cmap=True,
invert_yaxis=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],active_tools=['wheel_zoom'])) default_tools
points
points (data:pandas.core.frame.DataFrame, kdims:list, pdim:str, prange:tuple=None, aggregator=<class 'datashader.reductions.first'>, use_hover:bool=True, vdims:list=None, google_earth:bool=False)
Interative visulization of a point cloud image.
Type | Default | Details | |
---|---|---|---|
data | DataFrame | dataset to be plot | |
kdims | list | colomn name of Mercator coordinate in dataframe | |
pdim | str | column name of data to be plotted in dataframe | |
prange | tuple | None | range of data to be plotted, it is interactively adjusted by default |
aggregator | type | first | aggregator for data rasterization |
use_hover | bool | True | use hover to show data |
vdims | list | None | column name of data showed on hover except kdims and pdim. These two are always showed. |
google_earth | bool | False | if use google earth imagery as the background |
Here we plot interferogram after DS processing:
= '../Tutorials/CLI/ds_processing/hix/ds/ds_ph.zarr/'
ds_ph_ = '../Tutorials/CLI/ds_processing/hix/ds/ds_e.zarr/'
ds_e_ = '../Tutorials/CLI/ds_processing/hix/ds/ds_n.zarr/'
ds_n_ = zarr.open(ds_ph_,'r')[:]
ds_ph = zarr.open(ds_e_,'r')[:]
ds_e = zarr.open(ds_n_,'r')[:] ds_n
# data = pd.DataFrame({'e':ds_e,'n':ds_n,'phase':np.angle(ds_ph[:,10]),'lon':ds_lon,'lat':ds_lat})
= spatialpandas.geometry.PointArray((ds_e, ds_n))
coordinates = spatialpandas.GeoDataFrame({'geometry':coordinates,'phase':np.angle(ds_ph[:,10])})
data = points(data,kdims=['e','n'],pdim='phase',prange=(-np.pi,np.pi),google_earth=True) plot
Make some options on the plot:
='colorwheel',width=600, height=400, colorbar=True, xlabel='Longitude', ylabel='Latitude'),
plot.opts(opts.Image(cmap='o',size=10,tools=['hover'])) opts.Points(marker
points_stack
points_stack (data:pandas.core.frame.DataFrame, kdims:list, pdata:pandas.core.frame.DataFrame, pdim:str, prange:tuple=None, aggregator=<class 'datashader.reductions.first'>, use_hover:bool=True, vdims:list=None, google_earth:bool=False)
Interative visulization of a stack of point cloud images.
Type | Default | Details | |
---|---|---|---|
data | DataFrame | common data in all plots | |
kdims | list | colomn name of Mercator coordinate in dataframe | |
pdata | DataFrame | data to be plotted as color | |
pdim | str | label of pdata | |
prange | tuple | None | range of pdata, it is interactively adjusted by default |
aggregator | type | first | aggregator for data rasterization |
use_hover | bool | True | use hover to show other column |
vdims | list | None | column name of data showed on hover except kdims which are always showed. |
google_earth | bool | False | if use google earth imagery as the background |
= '../Tutorials/CLI/ds_processing/hix/ds/ds_ph.zarr/'
ds_ph_ = '../Tutorials/CLI/ds_processing/hix/ds/ds_e.zarr/'
ds_e_ = '../Tutorials/CLI/ds_processing/hix/ds/ds_n.zarr/'
ds_n_ = zarr.open(ds_ph_,'r')[:]
ds_ph = zarr.open(ds_e_,'r')[:]
ds_e = zarr.open(ds_n_,'r')[:]
ds_n
= '../CLI/raw/meta.toml'
meta_file with open(meta_file,'r') as f:
= toml.load(f)
meta_data = meta_data['dates'] dates
# data = pd.DataFrame({'e':ds_e,'n':ds_n,'lon':ds_lon,'lat':ds_lat,'idx':np.arange(len(ds_e))})
= spatialpandas.geometry.PointArray((ds_e, ds_n))
coordinates = spatialpandas.GeoDataFrame({'geometry':coordinates,'idx':np.arange(len(ds_e))})
data = pd.DataFrame(np.angle(ds_ph),columns=dates) pdata
= points_stack(data,['e','n'],pdata,'phase',prange=(-np.pi,np.pi),vdims=['idx',],google_earth=True) plot_stack
='bottom',holomap='scrubber') hv.output(widget_location
='colorwheel',width=600, height=400, colorbar=True, xlabel='Longitude', ylabel='Latitude'),
plot_stack.opts(opts.Image(cmap='o',size=10)) opts.Points(marker
Plot selected images simutaneously is also supported:
0:4]].cols(2) plot_stack.layout()[dates[