{
  "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.14.6"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}