{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "\n# Tricontour Smooth Delaunay\n\nDemonstrates high-resolution tricontouring of a random set of points;\na `matplotlib.tri.TriAnalyzer` is used to improve the plot quality.\n\nThe initial data points and triangular grid for this demo are:\n\n- a set of random points is instantiated, inside [-1, 1] x [-1, 1] square\n- A Delaunay triangulation of these points is then computed, of which a\n random subset of triangles is masked out by the user (based on\n *init_mask_frac* parameter). This simulates invalidated data.\n\nThe proposed generic procedure to obtain a high resolution contouring of such\na data set is the following:\n\n1. Compute an extended mask with a `matplotlib.tri.TriAnalyzer`, which will\n exclude badly shaped (flat) triangles from the border of the\n triangulation. Apply the mask to the triangulation (using set_mask).\n2. Refine and interpolate the data using a `matplotlib.tri.UniformTriRefiner`.\n3. Plot the refined data with `~.axes.Axes.tricontour`.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\nimport numpy as np\n\nfrom matplotlib.tri import TriAnalyzer, Triangulation, UniformTriRefiner\n\n\n# ----------------------------------------------------------------------------\n# Analytical test function\n# ----------------------------------------------------------------------------\ndef experiment_res(x, y):\n \"\"\"An analytic function representing experiment results.\"\"\"\n x = 2 * x\n r1 = np.sqrt((0.5 - x)**2 + (0.5 - y)**2)\n theta1 = np.arctan2(0.5 - x, 0.5 - y)\n r2 = np.sqrt((-x - 0.2)**2 + (-y - 0.2)**2)\n theta2 = np.arctan2(-x - 0.2, -y - 0.2)\n z = (4 * (np.exp((r1/10)**2) - 1) * 30 * np.cos(3 * theta1) +\n (np.exp((r2/10)**2) - 1) * 30 * np.cos(5 * theta2) +\n 2 * (x**2 + y**2))\n return (np.max(z) - z) / (np.max(z) - np.min(z))\n\n# ----------------------------------------------------------------------------\n# Generating the initial data test points and triangulation for the demo\n# ----------------------------------------------------------------------------\n# User parameters for data test points\n\n# Number of test data points, tested from 3 to 5000 for subdiv=3\nn_test = 200\n\n# Number of recursive subdivisions of the initial mesh for smooth plots.\n# Values >3 might result in a very high number of triangles for the refine\n# mesh: new triangles numbering = (4**subdiv)*ntri\nsubdiv = 3\n\n# Float > 0. adjusting the proportion of (invalid) initial triangles which will\n# be masked out. Enter 0 for no mask.\ninit_mask_frac = 0.0\n\n# Minimum circle ratio - border triangles with circle ratio below this will be\n# masked if they touch a border. Suggested value 0.01; use -1 to keep all\n# triangles.\nmin_circle_ratio = .01\n\n# Random points\nrandom_gen = np.random.RandomState(seed=19680801)\nx_test = random_gen.uniform(-1., 1., size=n_test)\ny_test = random_gen.uniform(-1., 1., size=n_test)\nz_test = experiment_res(x_test, y_test)\n\n# meshing with Delaunay triangulation\ntri = Triangulation(x_test, y_test)\nntri = tri.triangles.shape[0]\n\n# Some invalid data are masked out\nmask_init = np.zeros(ntri, dtype=bool)\nmasked_tri = random_gen.randint(0, ntri, int(ntri * init_mask_frac))\nmask_init[masked_tri] = True\ntri.set_mask(mask_init)\n\n\n# ----------------------------------------------------------------------------\n# Improving the triangulation before high-res plots: removing flat triangles\n# ----------------------------------------------------------------------------\n# masking badly shaped triangles at the border of the triangular mesh.\nmask = TriAnalyzer(tri).get_flat_tri_mask(min_circle_ratio)\ntri.set_mask(mask)\n\n# refining the data\nrefiner = UniformTriRefiner(tri)\ntri_refi, z_test_refi = refiner.refine_field(z_test, subdiv=subdiv)\n\n# analytical 'results' for comparison\nz_expected = experiment_res(tri_refi.x, tri_refi.y)\n\n# for the demo: loading the 'flat' triangles for plot\nflat_tri = Triangulation(x_test, y_test)\nflat_tri.set_mask(~mask)\n\n\n# ----------------------------------------------------------------------------\n# Now the plots\n# ----------------------------------------------------------------------------\n# User options for plots\nplot_tri = True # plot of base triangulation\nplot_masked_tri = True # plot of excessively flat excluded triangles\nplot_refi_tri = False # plot of refined triangulation\nplot_expected = False # plot of analytical function values for comparison\n\n\n# Graphical options for tricontouring\nlevels = np.arange(0., 1., 0.025)\n\nfig, ax = plt.subplots()\nax.set_aspect('equal')\nax.set_title(\"Filtering a Delaunay mesh\\n\"\n \"(application to high-resolution tricontouring)\")\n\n# 1) plot of the refined (computed) data contours:\nax.tricontour(tri_refi, z_test_refi, levels=levels, cmap='Blues',\n linewidths=[2.0, 0.5, 1.0, 0.5])\n# 2) plot of the expected (analytical) data contours (dashed):\nif plot_expected:\n ax.tricontour(tri_refi, z_expected, levels=levels, cmap='Blues',\n linestyles='--')\n# 3) plot of the fine mesh on which interpolation was done:\nif plot_refi_tri:\n ax.triplot(tri_refi, color='0.97')\n# 4) plot of the initial 'coarse' mesh:\nif plot_tri:\n ax.triplot(tri, color='0.7')\n# 4) plot of the unvalidated triangles from naive Delaunay Triangulation:\nif plot_masked_tri:\n ax.triplot(flat_tri, color='red')\n\nplt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ ".. admonition:: References\n\n The use of the following functions, methods, classes and modules is shown\n in this example:\n\n - `matplotlib.axes.Axes.tricontour` / `matplotlib.pyplot.tricontour`\n - `matplotlib.axes.Axes.tricontourf` / `matplotlib.pyplot.tricontourf`\n - `matplotlib.axes.Axes.triplot` / `matplotlib.pyplot.triplot`\n - `matplotlib.tri`\n - `matplotlib.tri.Triangulation`\n - `matplotlib.tri.TriAnalyzer`\n - `matplotlib.tri.UniformTriRefiner`\n\n" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.13.2" } }, "nbformat": 4, "nbformat_minor": 0 }