1"""
2==========================
3Tricontour Smooth Delaunay
4==========================
5
6Demonstrates high-resolution tricontouring of a random set of points ;
7a `matplotlib.tri.TriAnalyzer` is used to improve the plot quality.
8
9The initial data points and triangular grid for this demo are:
10
11- a set of random points is instantiated, inside [-1, 1] x [-1, 1] square
12- A Delaunay triangulation of these points is then computed, of which a
13  random subset of triangles is masked out by the user (based on
14  *init_mask_frac* parameter). This simulates invalidated data.
15
16The proposed generic procedure to obtain a high resolution contouring of such
17a data set is the following:
18
191. Compute an extended mask with a `matplotlib.tri.TriAnalyzer`, which will
20   exclude badly shaped (flat) triangles from the border of the
21   triangulation. Apply the mask to the triangulation (using set_mask).
222. Refine and interpolate the data using a
23   `matplotlib.tri.UniformTriRefiner`.
243. Plot the refined data with `~.axes.Axes.tricontour`.
25
26"""
27from matplotlib.tri import Triangulation, TriAnalyzer, UniformTriRefiner
28import matplotlib.pyplot as plt
29import matplotlib.cm as cm
30import numpy as np
31
32
33#-----------------------------------------------------------------------------
34# Analytical test function
35#-----------------------------------------------------------------------------
36def experiment_res(x, y):
37    """ An analytic function representing experiment results """
38    x = 2. * x
39    r1 = np.sqrt((0.5 - x)**2 + (0.5 - y)**2)
40    theta1 = np.arctan2(0.5 - x, 0.5 - y)
41    r2 = np.sqrt((-x - 0.2)**2 + (-y - 0.2)**2)
42    theta2 = np.arctan2(-x - 0.2, -y - 0.2)
43    z = (4 * (np.exp((r1 / 10)**2) - 1) * 30. * np.cos(3 * theta1) +
44         (np.exp((r2 / 10)**2) - 1) * 30. * np.cos(5 * theta2) +
45         2 * (x**2 + y**2))
46    return (np.max(z) - z) / (np.max(z) - np.min(z))
47
48#-----------------------------------------------------------------------------
49# Generating the initial data test points and triangulation for the demo
50#-----------------------------------------------------------------------------
51# User parameters for data test points
52n_test = 200  # Number of test data points, tested from 3 to 5000 for subdiv=3
53
54subdiv = 3  # Number of recursive subdivisions of the initial mesh for smooth
55            # plots. Values >3 might result in a very high number of triangles
56            # for the refine mesh: new triangles numbering = (4**subdiv)*ntri
57
58init_mask_frac = 0.0    # Float > 0. adjusting the proportion of
59                        # (invalid) initial triangles which will be masked
60                        # out. Enter 0 for no mask.
61
62min_circle_ratio = .01  # Minimum circle ratio - border triangles with circle
63                        # ratio below this will be masked if they touch a
64                        # border. Suggested value 0.01 ; Use -1 to keep
65                        # all triangles.
66
67# Random points
68random_gen = np.random.RandomState(seed=19680801)
69x_test = random_gen.uniform(-1., 1., size=n_test)
70y_test = random_gen.uniform(-1., 1., size=n_test)
71z_test = experiment_res(x_test, y_test)
72
73# meshing with Delaunay triangulation
74tri = Triangulation(x_test, y_test)
75ntri = tri.triangles.shape[0]
76
77# Some invalid data are masked out
78mask_init = np.zeros(ntri, dtype=bool)
79masked_tri = random_gen.randint(0, ntri, int(ntri * init_mask_frac))
80mask_init[masked_tri] = True
81tri.set_mask(mask_init)
82
83
84#-----------------------------------------------------------------------------
85# Improving the triangulation before high-res plots: removing flat triangles
86#-----------------------------------------------------------------------------
87# masking badly shaped triangles at the border of the triangular mesh.
88mask = TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)
89tri.set_mask(mask)
90
91# refining the data
92refiner = UniformTriRefiner(tri)
93tri_refi, z_test_refi = refiner.refine_field(z_test, subdiv=subdiv)
94
95# analytical 'results' for comparison
96z_expected = experiment_res(tri_refi.x, tri_refi.y)
97
98# for the demo: loading the 'flat' triangles for plot
99flat_tri = Triangulation(x_test, y_test)
100flat_tri.set_mask(~mask)
101
102
103#-----------------------------------------------------------------------------
104# Now the plots
105#-----------------------------------------------------------------------------
106# User options for plots
107plot_tri = True          # plot of base triangulation
108plot_masked_tri = True   # plot of excessively flat excluded triangles
109plot_refi_tri = False    # plot of refined triangulation
110plot_expected = False    # plot of analytical function values for comparison
111
112
113# Graphical options for tricontouring
114levels = np.arange(0., 1., 0.025)
115cmap = cm.get_cmap(name='Blues', lut=None)
116
117fig, ax = plt.subplots()
118ax.set_aspect('equal')
119ax.set_title("Filtering a Delaunay mesh\n" +
120          "(application to high-resolution tricontouring)")
121
122# 1) plot of the refined (computed) data contours:
123ax.tricontour(tri_refi, z_test_refi, levels=levels, cmap=cmap,
124               linewidths=[2.0, 0.5, 1.0, 0.5])
125# 2) plot of the expected (analytical) data contours (dashed):
126if plot_expected:
127    ax.tricontour(tri_refi, z_expected, levels=levels, cmap=cmap,
128                   linestyles='--')
129# 3) plot of the fine mesh on which interpolation was done:
130if plot_refi_tri:
131    ax.triplot(tri_refi, color='0.97')
132# 4) plot of the initial 'coarse' mesh:
133if plot_tri:
134    ax.triplot(tri, color='0.7')
135# 4) plot of the unvalidated triangles from naive Delaunay Triangulation:
136if plot_masked_tri:
137    ax.triplot(flat_tri, color='red')
138
139plt.show()
140
141#############################################################################
142#
143# ------------
144#
145# References
146# """"""""""
147#
148# The use of the following functions, methods, classes and modules is shown
149# in this example:
150
151import matplotlib
152matplotlib.axes.Axes.tricontour
153matplotlib.pyplot.tricontour
154matplotlib.axes.Axes.tricontourf
155matplotlib.pyplot.tricontourf
156matplotlib.axes.Axes.triplot
157matplotlib.pyplot.triplot
158matplotlib.tri
159matplotlib.tri.Triangulation
160matplotlib.tri.TriAnalyzer
161matplotlib.tri.UniformTriRefiner
162