import holoviews as hv
import numpy as np
import zarr
from holoviews import opts
from bokeh.models import WheelZoomTool
plot
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.
'bokeh') hv.extension(
ras_plot
ras_plot (data:str, post_proc:Callable=None, n_kdim:int=None, bounds:tuple=None, level_increase=0)
plot rendered stack of ras tiles.
Type | Default | Details | |
---|---|---|---|
data | str | directory to the rendered ras pyramid | |
post_proc | Callable | None | function for the post processing, can be None, ‘intf_0’, ‘intf_seq’, ‘intf_all’ or user-defined function |
n_kdim | int | None | number of key dimensions, can only be 0 or 1 or 2, ndim of raster dataset -2 by default |
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 |
Usage:
= '../../data/rslc.zarr/'
rslc_ = zarr.open(rslc_,'r')[:] 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_plot
can also take stack of raster images. It will return DynamicMap
with keys
. Here we define a function to generate interferograms with the first SLC as reference:
def intf_0(data, xslice, yslice,i):
return np.angle(data[yslice,xslice,0]*data[yslice,xslice,i].conj())
= ras_plot(rslc,post_proc=intf_0, level_increase=0) intf_plot
We have a set of convenient predefined post_proc
functions, e.g., intf_0
, intf_seq
, intf_all
. The above code equals to:
= ras_plot(rslc,post_proc='intf_0', level_increase=0) intf_plot
Add annotations:
= ["20210802", "20210816", "20210830", "20210913", "20211011", "20211025", "20220606", "20220620",
dates "20220704", "20220718", "20220801", "20220815", "20220829", "20220912", "20220926", "20221010",
"20221024",]
= intf_plot.redim(i=hv.Dimension('i', label='Interferogram', range=(0,16), value_format=(lambda i: dates[0]+'_'+dates[i])),
intf_plot =hv.Dimension('r', label='Range'), y=hv.Dimension('az',label='Azimuth'), z=hv.Dimension('Phase',range=(-np.pi,np.pi))) x
Specify plotting options and plot:
='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
Or the intensity:
def intensity(data, xslice, yslice,i):
return np.log(np.abs(data[yslice,xslice,i])**2)
= ras_plot(rslc,post_proc=intensity)
int_plot = int_plot.redim(i=hv.Dimension('i', label='Intensity', range=(1,16), value_format=(lambda i: dates[i])),
int_plot =hv.Dimension('r', label='Range'), y=hv.Dimension('az',label='Azimuth'), z=hv.Dimension('Intensity'))
x='gray',width=600, height=600, colorbar=True,
int_plot.opts(opts.Image(cmap=True, default_tools=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
invert_yaxis=['wheel_zoom'])) active_tools
We can also plot sequential interferograms. In this case, we only plot 26 interferograms.
def intf_seq(data, xslice, yslice,i):
return np.angle(data[yslice,xslice,i]*data[yslice,xslice,i+1].conj())
= ras_plot(rslc,post_proc=intf_seq)
intf_plot # or
= ras_plot(rslc,post_proc='intf_seq')
intf_plot
= intf_plot.redim(i=hv.Dimension('i', label='Interferogram', range=(0,15), value_format=(lambda i: dates[i]+'_'+dates[i+1])),
intf_plot =hv.Dimension('r', label='Range'), y=hv.Dimension('az',label='Azimuth'), z=hv.Dimension('Phase',range=(-np.pi,np.pi)))
x='colorwheel',width=600, height=600, colorbar=True,
intf_plot.opts(opts.Image(cmap=True, default_tools=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
invert_yaxis=['wheel_zoom'])) active_tools
The n_kdim
don’t have to be data.ndim-2
. Here is an example to show all interferograms.
def intf_all(data, xslice, yslice,i,j): # we have 2 kdims here
return np.angle(data[yslice,xslice,i]*data[yslice,xslice,j].conj())
= ras_plot(rslc,post_proc=intf_all,n_kdim=2,level_increase=0)
intf_plot # or
= ras_plot(rslc,post_proc='intf_all',n_kdim=2,level_increase=0) intf_plot
Add annotations:
= intf_plot.redim(i=hv.Dimension('i', label='Reference Image', range=(0,16), value_format=(lambda i: dates[i])),
intf_plot =hv.Dimension('j', label='Secondary Image', range=(0,16), value_format=(lambda i: dates[i])),
j=hv.Dimension('r', label='Range'), y=hv.Dimension('az',label='Azimuth'), z=hv.Dimension('Phase',range=(-np.pi,np.pi))) x
Specify plotting options and plot:
='bottom')
hv.output(widget_location='colorwheel',frame_width=500, frame_height=600, 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
pc_plot
pc_plot (data:numpy.ndarray, y:numpy.ndarray, x:numpy.ndarray, ras_resolution:float=20, post_proc_pc:Callable=None, n_kdim:int=None, rtree=None, level_increase=0)
plot rendered point cloud pyramid on the fly
Type | Default | Details | |
---|---|---|---|
data | ndarray | pc dataset | |
y | ndarray | y coordinate | |
x | ndarray | x coordinate | |
ras_resolution | float | 20 | minimum resolution of rendered raster data in the pyramid |
post_proc_pc | Callable | None | function for the post processing |
n_kdim | int | None | number of key dimensions, can only be 0 or 1 or 2, ndim of point cloud dataset -1 by default |
rtree | NoneType | None | rtree, if not provide, will be automatically generated but may slow the program |
level_increase | int | 0 | amount of zoom level increase for more clear point show and faster responds time |
pc_plot
take the rendered point cloud dataset as the input and return a Holoviews DynamicMap
. When the zoom level is -1, it plot the the raw point cloud data. When the zoom level is 0 or over 0, it plot the rasterized images. Just as ras_plot
, it accept post processing functions for both point cloud data and raster data to be plot. It is the user’s duty to esure the post processing fuctions coincide with each other. It also accept n_kdim
to set number of kdims
for returned DynamicMap
.
Here is an example to plot the amplitude dispersion index:
= zarr.open('../CLI/ps/ps_can_adi.zarr/','r')[:]
ps_can_adi = zarr.open('../CLI/ps/ps_can_rslc.zarr/','r')[:]
ps_can_rslc = zarr.open('../CLI/ps/ps_can_e.zarr/','r')[:]
ps_can_x = zarr.open('../CLI/ps/ps_can_n.zarr/','r')[:] ps_can_y
= pc_plot(ps_can_adi,ps_can_y,ps_can_x,level_increase=1) adi_plot
Add annotations:
= adi_plot.redim(x=hv.Dimension('lon', label='Longitude'), y=hv.Dimension('lat',label='Latitude'),
adi_plot =hv.Dimension('adi',label='Amplitude Dispersion Index',range=(0,0.3))
z )
Specify plotting options and plot:
='fire',width=600, height=400, colorbar=True,
adi_plot.opts(opts.Image(cmap# invert_yaxis=True,
=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
default_tools=['wheel_zoom']
active_tools
),='adi', cmap='fire',width=600, height=400, colorbar=True,
opts.Points(color# invert_yaxis=True,
=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
default_tools=['wheel_zoom']
active_tools
) )
Add the optical image as the background:
*adi_plot hv.element.tiles.EsriImagery()
Note that, for displaying data over tiles, the data have to be projected to the Web Mercator Projection.
As ras_plot
, pc_plot
can also take stack of point cloud dataset. It will return DynamicMap
with keys
. Here we define a function to generate interferograms with the first SLC as reference:
def intf_0_pc(data,idx_array,i):
return np.angle(data[idx_array,0]*data[idx_array,i].conj())
= pc_plot(ps_can_rslc, ps_can_y, ps_can_x, post_proc_pc=intf_0_pc, level_increase=1)
intf_plot # or
= pc_plot(ps_can_rslc, ps_can_y, ps_can_x, post_proc_pc='intf_0', level_increase=1) intf_plot
Add annotations:
= ["20210802", "20210816", "20210830", "20210913", "20211011", "20211025", "20220606", "20220620",
dates "20220704", "20220718", "20220801", "20220815", "20220829", "20220912", "20220926", "20221010",
"20221024",]
= intf_plot.redim(i=hv.Dimension('i', label='Interferogram', range=(0,16), value_format=(lambda i: dates[0]+'_'+dates[i])),
intf_plot =hv.Dimension('lon', label='Longitude'), y=hv.Dimension('lat',label='Latitude'), z=hv.Dimension('Phase',range=(-np.pi,np.pi))) x
Specify plotting options and plot:
='bottom')
hv.output(widget_location='colorwheel',width=600, height=400, colorbar=True,
intf_plot.opts(opts.Image(cmap=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
default_tools=['wheel_zoom']
active_tools
),='Phase', cmap='colorwheel',width=600, height=400, colorbar=True,
opts.Points(color# invert_yaxis=True,
=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
default_tools=['wheel_zoom']
active_tools
) )
The n_kdim
don’t have to be data.ndim-1
. Here is an example to show all interferograms.
def intf_pc(data, idx,i,j): # we have 2 kdims here
return np.angle(data[idx,i]*data[idx,j].conj())
= pc_plot(ps_can_rslc, ps_can_y, ps_can_x, post_proc_pc=intf_pc,n_kdim=2,level_increase=0)
intf_plot # or
= pc_plot(ps_can_rslc, ps_can_y, ps_can_x, post_proc_pc='intf_all',n_kdim=2,level_increase=0) intf_plot
Add annotations:
= intf_plot.redim(i=hv.Dimension('i', label='Reference Image', range=(0,16), value_format=(lambda i: dates[i])),
intf_plot =hv.Dimension('j', label='Secondary Image', range=(0,16), value_format=(lambda i: dates[i])),
j=hv.Dimension('r', label='Range'), y=hv.Dimension('az',label='Azimuth'), z=hv.Dimension('Phase',range=(-np.pi,np.pi))) x
Specify plotting options and plot:
='bottom')
hv.output(widget_location='colorwheel',width=600, height=400, colorbar=True,
intf_plot.opts(opts.Image(cmap=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
default_tools=['wheel_zoom']
active_tools
),='Phase', cmap='colorwheel',width=600, height=400, colorbar=True,
opts.Points(color# invert_yaxis=True,
=['pan',WheelZoomTool(zoom_on_axis=False),'save','reset','hover'],
default_tools=['wheel_zoom']
active_tools
) )