-
Notifications
You must be signed in to change notification settings - Fork 261
/
plot_ext.py
128 lines (105 loc) · 4.37 KB
/
plot_ext.py
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
"""Class wrapped around matplotlib/mintpy for polygon selection."""
############################################################
# Program is part of MintPy #
# Copyright (c) 2013, Zhang Yunjun, Heresh Fattahi #
# Author: Zhang Yunjun, Sep 2019 #
############################################################
# Recommend import:
# from mintpy.utils import plot_ext
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.path import Path
from matplotlib.widgets import PolygonSelector
from mintpy import view
################################# SelectFromCollection class begin ########################################
class SelectFromCollection:
"""Select indices from a matplotlib collection using `PolygonSelector`.
Selected pixels within the polygon is marked as True and saved in the
member variable self.mask, in the same size as input AxesImage object
with all the other pixels marked as False.
Parameters
----------
ax : :class:`~matplotlib.axes.Axes`
Axes to interact with.
collection : :class:`matplotlib.collections.Collection` subclass
Collection you want to select from.
Examples
--------
import matplotlib.pyplot as plt
from mintpy.utils import readfile, plot as pp
fig, ax = plt.subplots()
data = readfile.read('velocity.h5', datasetName='velocity')[0]
im = ax.imshow(data)
selector = pp.SelectFromCollection(ax, im)
plt.show()
selector.disconnect()
plt.figure()
plt.imshow(selector.mask)
plt.show()
"""
def __init__(self, ax, collection, alpha_other=0.3):
self.canvas = ax.figure.canvas
self.collection = collection
self.prepare_coordinates()
self.poly = PolygonSelector(ax, self.onselect)
msg = "\nSelect points in the figure by enclosing them within a polygon.\n"
msg += "Press the 'esc' key to start a new polygon.\n"
msg += "Try hold to left key to move a single vertex.\n"
msg += "After complete the selection, close the figure/window to continue.\n"
print(msg)
def prepare_coordinates(self):
imgExt = self.collection.get_extent()
self.length = int(imgExt[2] - imgExt[3])
self.width = int(imgExt[1] - imgExt[0])
yy, xx = np.mgrid[:self.length, :self.width]
self.coords = np.hstack((xx.reshape(-1, 1),
yy.reshape(-1, 1)))
def onselect(self, verts):
self.poly_path = Path(verts)
self.mask = self.poly_path.contains_points(self.coords).reshape(self.length,
self.width)
self.canvas.draw_idle()
def disconnect(self):
self.poly.disconnect_events()
self.canvas.draw_idle()
## Utility script
def get_poly_mask(fname, datasetName, print_msg=True, view_cmd=''):
"""Get mask of pixels within polygon from interactive selection
Parameters: data : 2D np.array in size of (length, width)
Returns: mask : 2D np.arrat in size of (length, width) in np.bool_ format
"""
# option 1 - Advanced plot using view.prep/plot_slice()
cmd = f'view.py {fname} '
if datasetName:
cmd += f' {datasetName} '
if view_cmd:
cmd += view_cmd
d_v, atr ,inps = view.prep_slice(cmd)
ax = plt.subplots(figsize=inps.fig_size)[1]
inps.fig_coord = 'yx' # selector works for y/x coord plot only
ax, inps, im = view.plot_slice(ax, d_v, atr, inps)[0:3]
## Option 2 - Simple plot with matplotlib
#from mintpy.utils import readfile
#data = readfile.read(fname, datasetName)[0]
#vlim = np.nanmax(np.abs(data))
#vmin, vmax = -vlim, vlim
## for dataset with non-negative values such as elevation
#if np.nanmin(data) > 0:
# vmin = np.nanmin(data)
## plot
#fig, ax = plt.subplots()
#im = ax.imshow(data, cmap='jet', vmin=vmin, vmax=vmax)
#fig.colorbar(im)
selector = SelectFromCollection(ax, im)
plt.show()
selector.disconnect()
if hasattr(selector, 'mask'):
mask = selector.mask
if print_msg:
print(f'selected polygon: {selector.poly_path}')
else:
mask = None
if print_msg:
print('no polygon selected.\n')
return mask
################################## SelectFromCollection class end #########################################