Browse Source

删除文件 venv

SuperHuan 5 years ago
parent
commit
bca8f8ed92
100 changed files with 0 additions and 48422 deletions
  1. 0 230
      venv/bin/Activate.ps1
  2. 0 76
      venv/bin/activate
  3. 0 37
      venv/bin/activate.csh
  4. 0 75
      venv/bin/activate.fish
  5. 0 8
      venv/bin/easy_install
  6. 0 8
      venv/bin/easy_install-3.8
  7. 0 8
      venv/bin/f2py
  8. 0 8
      venv/bin/f2py3
  9. 0 8
      venv/bin/f2py3.8
  10. 0 8
      venv/bin/pip
  11. 0 8
      venv/bin/pip3
  12. 0 8
      venv/bin/pip3.8
  13. 0 1
      venv/bin/python
  14. 0 1
      venv/bin/python3
  15. 0 1
      venv/bin/python3.8
  16. 0 3
      venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/DESCRIPTION.rst
  17. 0 1
      venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/INSTALLER
  18. 0 25
      venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/METADATA
  19. 0 9
      venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/RECORD
  20. 0 6
      venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/WHEEL
  21. 0 1
      venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/metadata.json
  22. 0 1
      venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/top_level.txt
  23. 0 558
      venv/lib/python3.8/site-packages/cycler.py
  24. 0 8
      venv/lib/python3.8/site-packages/dateutil/__init__.py
  25. 0 43
      venv/lib/python3.8/site-packages/dateutil/_common.py
  26. 0 4
      venv/lib/python3.8/site-packages/dateutil/_version.py
  27. 0 89
      venv/lib/python3.8/site-packages/dateutil/easter.py
  28. 0 61
      venv/lib/python3.8/site-packages/dateutil/parser/__init__.py
  29. 0 1609
      venv/lib/python3.8/site-packages/dateutil/parser/_parser.py
  30. 0 411
      venv/lib/python3.8/site-packages/dateutil/parser/isoparser.py
  31. 0 599
      venv/lib/python3.8/site-packages/dateutil/relativedelta.py
  32. 0 1735
      venv/lib/python3.8/site-packages/dateutil/rrule.py
  33. 0 12
      venv/lib/python3.8/site-packages/dateutil/tz/__init__.py
  34. 0 419
      venv/lib/python3.8/site-packages/dateutil/tz/_common.py
  35. 0 80
      venv/lib/python3.8/site-packages/dateutil/tz/_factories.py
  36. 0 1849
      venv/lib/python3.8/site-packages/dateutil/tz/tz.py
  37. 0 370
      venv/lib/python3.8/site-packages/dateutil/tz/win.py
  38. 0 2
      venv/lib/python3.8/site-packages/dateutil/tzwin.py
  39. 0 71
      venv/lib/python3.8/site-packages/dateutil/utils.py
  40. 0 167
      venv/lib/python3.8/site-packages/dateutil/zoneinfo/__init__.py
  41. BIN
      venv/lib/python3.8/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz
  42. 0 53
      venv/lib/python3.8/site-packages/dateutil/zoneinfo/rebuild.py
  43. 0 1
      venv/lib/python3.8/site-packages/easy-install.pth
  44. 0 5
      venv/lib/python3.8/site-packages/easy_install.py
  45. 0 1
      venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/INSTALLER
  46. 0 41
      venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/METADATA
  47. 0 6
      venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/RECORD
  48. 0 5
      venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/WHEEL
  49. 0 1
      venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/top_level.txt
  50. BIN
      venv/lib/python3.8/site-packages/kiwisolver.cpython-38-x86_64-linux-gnu.so
  51. 0 1
      venv/lib/python3.8/site-packages/matplotlib-3.2.1-py3.8-nspkg.pth
  52. 0 1
      venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/INSTALLER
  53. 0 127
      venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/METADATA
  54. 0 892
      venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/RECORD
  55. 0 5
      venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/WHEEL
  56. 0 1
      venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/namespace_packages.txt
  57. 0 3
      venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/top_level.txt
  58. BIN
      venv/lib/python3.8/site-packages/matplotlib/.libs/libpng16-cfdb1654.so.16.21.0
  59. BIN
      venv/lib/python3.8/site-packages/matplotlib/.libs/libz-a147dcb0.so.1.2.3
  60. 0 1601
      venv/lib/python3.8/site-packages/matplotlib/__init__.py
  61. 0 260
      venv/lib/python3.8/site-packages/matplotlib/_animation_data.py
  62. 0 1426
      venv/lib/python3.8/site-packages/matplotlib/_cm.py
  63. 0 1813
      venv/lib/python3.8/site-packages/matplotlib/_cm_listed.py
  64. 0 1147
      venv/lib/python3.8/site-packages/matplotlib/_color_data.py
  65. 0 726
      venv/lib/python3.8/site-packages/matplotlib/_constrained_layout.py
  66. BIN
      venv/lib/python3.8/site-packages/matplotlib/_contour.cpython-38-x86_64-linux-gnu.so
  67. BIN
      venv/lib/python3.8/site-packages/matplotlib/_image.cpython-38-x86_64-linux-gnu.so
  68. 0 711
      venv/lib/python3.8/site-packages/matplotlib/_layoutbox.py
  69. 0 2544
      venv/lib/python3.8/site-packages/matplotlib/_mathtext_data.py
  70. BIN
      venv/lib/python3.8/site-packages/matplotlib/_path.cpython-38-x86_64-linux-gnu.so
  71. BIN
      venv/lib/python3.8/site-packages/matplotlib/_png.cpython-38-x86_64-linux-gnu.so
  72. 0 129
      venv/lib/python3.8/site-packages/matplotlib/_pylab_helpers.py
  73. BIN
      venv/lib/python3.8/site-packages/matplotlib/_qhull.cpython-38-x86_64-linux-gnu.so
  74. 0 38
      venv/lib/python3.8/site-packages/matplotlib/_text_layout.py
  75. BIN
      venv/lib/python3.8/site-packages/matplotlib/_tri.cpython-38-x86_64-linux-gnu.so
  76. 0 21
      venv/lib/python3.8/site-packages/matplotlib/_version.py
  77. 0 530
      venv/lib/python3.8/site-packages/matplotlib/afm.py
  78. 0 1775
      venv/lib/python3.8/site-packages/matplotlib/animation.py
  79. 0 1633
      venv/lib/python3.8/site-packages/matplotlib/artist.py
  80. 0 2
      venv/lib/python3.8/site-packages/matplotlib/axes/__init__.py
  81. 0 8098
      venv/lib/python3.8/site-packages/matplotlib/axes/_axes.py
  82. 0 4441
      venv/lib/python3.8/site-packages/matplotlib/axes/_base.py
  83. 0 408
      venv/lib/python3.8/site-packages/matplotlib/axes/_secondary_axes.py
  84. 0 255
      venv/lib/python3.8/site-packages/matplotlib/axes/_subplots.py
  85. 0 2496
      venv/lib/python3.8/site-packages/matplotlib/axis.py
  86. 0 3421
      venv/lib/python3.8/site-packages/matplotlib/backend_bases.py
  87. 0 423
      venv/lib/python3.8/site-packages/matplotlib/backend_managers.py
  88. 0 1146
      venv/lib/python3.8/site-packages/matplotlib/backend_tools.py
  89. 0 54
      venv/lib/python3.8/site-packages/matplotlib/backends/__init__.py
  90. BIN
      venv/lib/python3.8/site-packages/matplotlib/backends/_backend_agg.cpython-38-x86_64-linux-gnu.so
  91. 0 84
      venv/lib/python3.8/site-packages/matplotlib/backends/_backend_pdf_ps.py
  92. 0 907
      venv/lib/python3.8/site-packages/matplotlib/backends/_backend_tk.py
  93. BIN
      venv/lib/python3.8/site-packages/matplotlib/backends/_tkagg.cpython-38-x86_64-linux-gnu.so
  94. 0 622
      venv/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py
  95. 0 484
      venv/lib/python3.8/site-packages/matplotlib/backends/backend_cairo.py
  96. 0 1000
      venv/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3.py
  97. 0 95
      venv/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3agg.py
  98. 0 48
      venv/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3cairo.py
  99. 0 184
      venv/lib/python3.8/site-packages/matplotlib/backends/backend_macosx.py
  100. 0 139
      venv/lib/python3.8/site-packages/matplotlib/backends/backend_mixed.py

+ 0 - 230
venv/bin/Activate.ps1

@@ -1,230 +0,0 @@
-<#
-.Synopsis
-Activate a Python virtual environment for the current Powershell session.
-
-.Description
-Pushes the python executable for a virtual environment to the front of the
-$Env:PATH environment variable and sets the prompt to signify that you are
-in a Python virtual environment. Makes use of the command line switches as
-well as the `pyvenv.cfg` file values present in the virtual environment.
-
-.Parameter VenvDir
-Path to the directory that contains the virtual environment to activate. The
-default value for this is the parent of the directory that the Activate.ps1
-script is located within.
-
-.Parameter Prompt
-The prompt prefix to display when this virtual environment is activated. By
-default, this prompt is the name of the virtual environment folder (VenvDir)
-surrounded by parentheses and followed by a single space (ie. '(.venv) ').
-
-.Example
-Activate.ps1
-Activates the Python virtual environment that contains the Activate.ps1 script.
-
-.Example
-Activate.ps1 -Verbose
-Activates the Python virtual environment that contains the Activate.ps1 script,
-and shows extra information about the activation as it executes.
-
-.Example
-Activate.ps1 -VenvDir C:\Users\MyUser\Common\.venv
-Activates the Python virtual environment located in the specified location.
-
-.Example
-Activate.ps1 -Prompt "MyPython"
-Activates the Python virtual environment that contains the Activate.ps1 script,
-and prefixes the current prompt with the specified string (surrounded in
-parentheses) while the virtual environment is active.
-
-
-#>
-Param(
-    [Parameter(Mandatory = $false)]
-    [String]
-    $VenvDir,
-    [Parameter(Mandatory = $false)]
-    [String]
-    $Prompt
-)
-
-<# Function declarations --------------------------------------------------- #>
-
-<#
-.Synopsis
-Remove all shell session elements added by the Activate script, including the
-addition of the virtual environment's Python executable from the beginning of
-the PATH variable.
-
-.Parameter NonDestructive
-If present, do not remove this function from the global namespace for the
-session.
-
-#>
-function global:deactivate ([switch]$NonDestructive) {
-    # Revert to original values
-
-    # The prior prompt:
-    if (Test-Path -Path Function:_OLD_VIRTUAL_PROMPT) {
-        Copy-Item -Path Function:_OLD_VIRTUAL_PROMPT -Destination Function:prompt
-        Remove-Item -Path Function:_OLD_VIRTUAL_PROMPT
-    }
-
-    # The prior PYTHONHOME:
-    if (Test-Path -Path Env:_OLD_VIRTUAL_PYTHONHOME) {
-        Copy-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME -Destination Env:PYTHONHOME
-        Remove-Item -Path Env:_OLD_VIRTUAL_PYTHONHOME
-    }
-
-    # The prior PATH:
-    if (Test-Path -Path Env:_OLD_VIRTUAL_PATH) {
-        Copy-Item -Path Env:_OLD_VIRTUAL_PATH -Destination Env:PATH
-        Remove-Item -Path Env:_OLD_VIRTUAL_PATH
-    }
-
-    # Just remove the VIRTUAL_ENV altogether:
-    if (Test-Path -Path Env:VIRTUAL_ENV) {
-        Remove-Item -Path env:VIRTUAL_ENV
-    }
-
-    # Just remove the _PYTHON_VENV_PROMPT_PREFIX altogether:
-    if (Get-Variable -Name "_PYTHON_VENV_PROMPT_PREFIX" -ErrorAction SilentlyContinue) {
-        Remove-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Scope Global -Force
-    }
-
-    # Leave deactivate function in the global namespace if requested:
-    if (-not $NonDestructive) {
-        Remove-Item -Path function:deactivate
-    }
-}
-
-<#
-.Description
-Get-PyVenvConfig parses the values from the pyvenv.cfg file located in the
-given folder, and returns them in a map.
-
-For each line in the pyvenv.cfg file, if that line can be parsed into exactly
-two strings separated by `=` (with any amount of whitespace surrounding the =)
-then it is considered a `key = value` line. The left hand string is the key,
-the right hand is the value.
-
-If the value starts with a `'` or a `"` then the first and last character is
-stripped from the value before being captured.
-
-.Parameter ConfigDir
-Path to the directory that contains the `pyvenv.cfg` file.
-#>
-function Get-PyVenvConfig(
-    [String]
-    $ConfigDir
-) {
-    Write-Verbose "Given ConfigDir=$ConfigDir, obtain values in pyvenv.cfg"
-
-    # Ensure the file exists, and issue a warning if it doesn't (but still allow the function to continue).
-    $pyvenvConfigPath = Join-Path -Resolve -Path $ConfigDir -ChildPath 'pyvenv.cfg' -ErrorAction Continue
-
-    # An empty map will be returned if no config file is found.
-    $pyvenvConfig = @{ }
-
-    if ($pyvenvConfigPath) {
-
-        Write-Verbose "File exists, parse `key = value` lines"
-        $pyvenvConfigContent = Get-Content -Path $pyvenvConfigPath
-
-        $pyvenvConfigContent | ForEach-Object {
-            $keyval = $PSItem -split "\s*=\s*", 2
-            if ($keyval[0] -and $keyval[1]) {
-                $val = $keyval[1]
-
-                # Remove extraneous quotations around a string value.
-                if ("'""".Contains($val.Substring(0,1))) {
-                    $val = $val.Substring(1, $val.Length - 2)
-                }
-
-                $pyvenvConfig[$keyval[0]] = $val
-                Write-Verbose "Adding Key: '$($keyval[0])'='$val'"
-            }
-        }
-    }
-    return $pyvenvConfig
-}
-
-
-<# Begin Activate script --------------------------------------------------- #>
-
-# Determine the containing directory of this script
-$VenvExecPath = Split-Path -Parent $MyInvocation.MyCommand.Definition
-$VenvExecDir = Get-Item -Path $VenvExecPath
-
-Write-Verbose "Activation script is located in path: '$VenvExecPath'"
-Write-Verbose "VenvExecDir Fullname: '$($VenvExecDir.FullName)"
-Write-Verbose "VenvExecDir Name: '$($VenvExecDir.Name)"
-
-# Set values required in priority: CmdLine, ConfigFile, Default
-# First, get the location of the virtual environment, it might not be
-# VenvExecDir if specified on the command line.
-if ($VenvDir) {
-    Write-Verbose "VenvDir given as parameter, using '$VenvDir' to determine values"
-} else {
-    Write-Verbose "VenvDir not given as a parameter, using parent directory name as VenvDir."
-    $VenvDir = $VenvExecDir.Parent.FullName.TrimEnd("\\/")
-    Write-Verbose "VenvDir=$VenvDir"
-}
-
-# Next, read the `pyvenv.cfg` file to determine any required value such
-# as `prompt`.
-$pyvenvCfg = Get-PyVenvConfig -ConfigDir $VenvDir
-
-# Next, set the prompt from the command line, or the config file, or
-# just use the name of the virtual environment folder.
-if ($Prompt) {
-    Write-Verbose "Prompt specified as argument, using '$Prompt'"
-} else {
-    Write-Verbose "Prompt not specified as argument to script, checking pyvenv.cfg value"
-    if ($pyvenvCfg -and $pyvenvCfg['prompt']) {
-        Write-Verbose "  Setting based on value in pyvenv.cfg='$($pyvenvCfg['prompt'])'"
-        $Prompt = $pyvenvCfg['prompt'];
-    }
-    else {
-        Write-Verbose "  Setting prompt based on parent's directory's name. (Is the directory name passed to venv module when creating the virutal environment)"
-        Write-Verbose "  Got leaf-name of $VenvDir='$(Split-Path -Path $venvDir -Leaf)'"
-        $Prompt = Split-Path -Path $venvDir -Leaf
-    }
-}
-
-Write-Verbose "Prompt = '$Prompt'"
-Write-Verbose "VenvDir='$VenvDir'"
-
-# Deactivate any currently active virtual environment, but leave the
-# deactivate function in place.
-deactivate -nondestructive
-
-# Now set the environment variable VIRTUAL_ENV, used by many tools to determine
-# that there is an activated venv.
-$env:VIRTUAL_ENV = $VenvDir
-
-if (-not $Env:VIRTUAL_ENV_DISABLE_PROMPT) {
-
-    Write-Verbose "Setting prompt to '$Prompt'"
-
-    # Set the prompt to include the env name
-    # Make sure _OLD_VIRTUAL_PROMPT is global
-    function global:_OLD_VIRTUAL_PROMPT { "" }
-    Copy-Item -Path function:prompt -Destination function:_OLD_VIRTUAL_PROMPT
-    New-Variable -Name _PYTHON_VENV_PROMPT_PREFIX -Description "Python virtual environment prompt prefix" -Scope Global -Option ReadOnly -Visibility Public -Value $Prompt
-
-    function global:prompt {
-        Write-Host -NoNewline -ForegroundColor Green "($_PYTHON_VENV_PROMPT_PREFIX) "
-        _OLD_VIRTUAL_PROMPT
-    }
-}
-
-# Clear PYTHONHOME
-if (Test-Path -Path Env:PYTHONHOME) {
-    Copy-Item -Path Env:PYTHONHOME -Destination Env:_OLD_VIRTUAL_PYTHONHOME
-    Remove-Item -Path Env:PYTHONHOME
-}
-
-# Add the venv to the PATH
-Copy-Item -Path Env:PATH -Destination Env:_OLD_VIRTUAL_PATH
-$Env:PATH = "$VenvExecDir$([System.IO.Path]::PathSeparator)$Env:PATH"

+ 0 - 76
venv/bin/activate

@@ -1,76 +0,0 @@
-# This file must be used with "source bin/activate" *from bash*
-# you cannot run it directly
-
-deactivate () {
-    # reset old environment variables
-    if [ -n "${_OLD_VIRTUAL_PATH:-}" ] ; then
-        PATH="${_OLD_VIRTUAL_PATH:-}"
-        export PATH
-        unset _OLD_VIRTUAL_PATH
-    fi
-    if [ -n "${_OLD_VIRTUAL_PYTHONHOME:-}" ] ; then
-        PYTHONHOME="${_OLD_VIRTUAL_PYTHONHOME:-}"
-        export PYTHONHOME
-        unset _OLD_VIRTUAL_PYTHONHOME
-    fi
-
-    # This should detect bash and zsh, which have a hash command that must
-    # be called to get it to forget past commands.  Without forgetting
-    # past commands the $PATH changes we made may not be respected
-    if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
-        hash -r
-    fi
-
-    if [ -n "${_OLD_VIRTUAL_PS1:-}" ] ; then
-        PS1="${_OLD_VIRTUAL_PS1:-}"
-        export PS1
-        unset _OLD_VIRTUAL_PS1
-    fi
-
-    unset VIRTUAL_ENV
-    if [ ! "${1:-}" = "nondestructive" ] ; then
-    # Self destruct!
-        unset -f deactivate
-    fi
-}
-
-# unset irrelevant variables
-deactivate nondestructive
-
-VIRTUAL_ENV="/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv"
-export VIRTUAL_ENV
-
-_OLD_VIRTUAL_PATH="$PATH"
-PATH="$VIRTUAL_ENV/bin:$PATH"
-export PATH
-
-# unset PYTHONHOME if set
-# this will fail if PYTHONHOME is set to the empty string (which is bad anyway)
-# could use `if (set -u; : $PYTHONHOME) ;` in bash
-if [ -n "${PYTHONHOME:-}" ] ; then
-    _OLD_VIRTUAL_PYTHONHOME="${PYTHONHOME:-}"
-    unset PYTHONHOME
-fi
-
-if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT:-}" ] ; then
-    _OLD_VIRTUAL_PS1="${PS1:-}"
-    if [ "x(venv) " != x ] ; then
-	PS1="(venv) ${PS1:-}"
-    else
-    if [ "`basename \"$VIRTUAL_ENV\"`" = "__" ] ; then
-        # special case for Aspen magic directories
-        # see http://www.zetadev.com/software/aspen/
-        PS1="[`basename \`dirname \"$VIRTUAL_ENV\"\``] $PS1"
-    else
-        PS1="(`basename \"$VIRTUAL_ENV\"`)$PS1"
-    fi
-    fi
-    export PS1
-fi
-
-# This should detect bash and zsh, which have a hash command that must
-# be called to get it to forget past commands.  Without forgetting
-# past commands the $PATH changes we made may not be respected
-if [ -n "${BASH:-}" -o -n "${ZSH_VERSION:-}" ] ; then
-    hash -r
-fi

+ 0 - 37
venv/bin/activate.csh

@@ -1,37 +0,0 @@
-# This file must be used with "source bin/activate.csh" *from csh*.
-# You cannot run it directly.
-# Created by Davide Di Blasi <davidedb@gmail.com>.
-# Ported to Python 3.3 venv by Andrew Svetlov <andrew.svetlov@gmail.com>
-
-alias deactivate 'test $?_OLD_VIRTUAL_PATH != 0 && setenv PATH "$_OLD_VIRTUAL_PATH" && unset _OLD_VIRTUAL_PATH; rehash; test $?_OLD_VIRTUAL_PROMPT != 0 && set prompt="$_OLD_VIRTUAL_PROMPT" && unset _OLD_VIRTUAL_PROMPT; unsetenv VIRTUAL_ENV; test "\!:*" != "nondestructive" && unalias deactivate'
-
-# Unset irrelevant variables.
-deactivate nondestructive
-
-setenv VIRTUAL_ENV "/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv"
-
-set _OLD_VIRTUAL_PATH="$PATH"
-setenv PATH "$VIRTUAL_ENV/bin:$PATH"
-
-
-set _OLD_VIRTUAL_PROMPT="$prompt"
-
-if (! "$?VIRTUAL_ENV_DISABLE_PROMPT") then
-    if ("venv" != "") then
-        set env_name = "venv"
-    else
-        if (`basename "VIRTUAL_ENV"` == "__") then
-            # special case for Aspen magic directories
-            # see http://www.zetadev.com/software/aspen/
-            set env_name = `basename \`dirname "$VIRTUAL_ENV"\``
-        else
-            set env_name = `basename "$VIRTUAL_ENV"`
-        endif
-    endif
-    set prompt = "[$env_name] $prompt"
-    unset env_name
-endif
-
-alias pydoc python -m pydoc
-
-rehash

+ 0 - 75
venv/bin/activate.fish

@@ -1,75 +0,0 @@
-# This file must be used with ". bin/activate.fish" *from fish* (http://fishshell.org)
-# you cannot run it directly
-
-function deactivate  -d "Exit virtualenv and return to normal shell environment"
-    # reset old environment variables
-    if test -n "$_OLD_VIRTUAL_PATH"
-        set -gx PATH $_OLD_VIRTUAL_PATH
-        set -e _OLD_VIRTUAL_PATH
-    end
-    if test -n "$_OLD_VIRTUAL_PYTHONHOME"
-        set -gx PYTHONHOME $_OLD_VIRTUAL_PYTHONHOME
-        set -e _OLD_VIRTUAL_PYTHONHOME
-    end
-
-    if test -n "$_OLD_FISH_PROMPT_OVERRIDE"
-        functions -e fish_prompt
-        set -e _OLD_FISH_PROMPT_OVERRIDE
-        functions -c _old_fish_prompt fish_prompt
-        functions -e _old_fish_prompt
-    end
-
-    set -e VIRTUAL_ENV
-    if test "$argv[1]" != "nondestructive"
-        # Self destruct!
-        functions -e deactivate
-    end
-end
-
-# unset irrelevant variables
-deactivate nondestructive
-
-set -gx VIRTUAL_ENV "/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv"
-
-set -gx _OLD_VIRTUAL_PATH $PATH
-set -gx PATH "$VIRTUAL_ENV/bin" $PATH
-
-# unset PYTHONHOME if set
-if set -q PYTHONHOME
-    set -gx _OLD_VIRTUAL_PYTHONHOME $PYTHONHOME
-    set -e PYTHONHOME
-end
-
-if test -z "$VIRTUAL_ENV_DISABLE_PROMPT"
-    # fish uses a function instead of an env var to generate the prompt.
-
-    # save the current fish_prompt function as the function _old_fish_prompt
-    functions -c fish_prompt _old_fish_prompt
-
-    # with the original prompt function renamed, we can override with our own.
-    function fish_prompt
-        # Save the return status of the last command
-        set -l old_status $status
-
-        # Prompt override?
-        if test -n "(venv) "
-            printf "%s%s" "(venv) " (set_color normal)
-        else
-            # ...Otherwise, prepend env
-            set -l _checkbase (basename "$VIRTUAL_ENV")
-            if test $_checkbase = "__"
-                # special case for Aspen magic directories
-                # see http://www.zetadev.com/software/aspen/
-                printf "%s[%s]%s " (set_color -b blue white) (basename (dirname "$VIRTUAL_ENV")) (set_color normal)
-            else
-                printf "%s(%s)%s" (set_color -b blue white) (basename "$VIRTUAL_ENV") (set_color normal)
-            end
-        end
-
-        # Restore the return status of the previous command.
-        echo "exit $old_status" | .
-        _old_fish_prompt
-    end
-
-    set -gx _OLD_FISH_PROMPT_OVERRIDE "$VIRTUAL_ENV"
-end

+ 0 - 8
venv/bin/easy_install

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from setuptools.command.easy_install import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 8
venv/bin/easy_install-3.8

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from setuptools.command.easy_install import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 8
venv/bin/f2py

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from numpy.f2py.f2py2e import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 8
venv/bin/f2py3

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from numpy.f2py.f2py2e import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 8
venv/bin/f2py3.8

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from numpy.f2py.f2py2e import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 8
venv/bin/pip

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from pip._internal.cli.main import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 8
venv/bin/pip3

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from pip._internal.cli.main import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 8
venv/bin/pip3.8

@@ -1,8 +0,0 @@
-#!/home/songzihuan/文档/PyProject/物理/弹簧加速度/venv/bin/python
-# -*- coding: utf-8 -*-
-import re
-import sys
-from pip._internal.cli.main import main
-if __name__ == '__main__':
-    sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
-    sys.exit(main())

+ 0 - 1
venv/bin/python

@@ -1 +0,0 @@
-python3.8

+ 0 - 1
venv/bin/python3

@@ -1 +0,0 @@
-python3.8

+ 0 - 1
venv/bin/python3.8

@@ -1 +0,0 @@
-/usr/bin/python3.8

+ 0 - 3
venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/DESCRIPTION.rst

@@ -1,3 +0,0 @@
-UNKNOWN
-
-

+ 0 - 1
venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/INSTALLER

@@ -1 +0,0 @@
-pip

+ 0 - 25
venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/METADATA

@@ -1,25 +0,0 @@
-Metadata-Version: 2.0
-Name: cycler
-Version: 0.10.0
-Summary: Composable style cycles
-Home-page: http://github.com/matplotlib/cycler
-Author: Thomas A Caswell
-Author-email: matplotlib-users@python.org
-License: BSD
-Keywords: cycle kwargs
-Platform: Cross platform (Linux
-Platform: Mac OSX
-Platform: Windows)
-Classifier: Development Status :: 4 - Beta
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Requires-Dist: six
-
-UNKNOWN
-
-

+ 0 - 9
venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/RECORD

@@ -1,9 +0,0 @@
-__pycache__/cycler.cpython-38.pyc,,
-cycler-0.10.0.dist-info/DESCRIPTION.rst,sha256=OCTuuN6LcWulhHS3d5rfjdsQtW22n7HENFRh6jC6ego,10
-cycler-0.10.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-cycler-0.10.0.dist-info/METADATA,sha256=aWX1pyo7D2hSDNZ2Q6Zl7DxhUQdpyu1O5uNABnvz000,722
-cycler-0.10.0.dist-info/RECORD,,
-cycler-0.10.0.dist-info/WHEEL,sha256=o2k-Qa-RMNIJmUdIc7KU6VWR_ErNRbWNlxDIpl7lm34,110
-cycler-0.10.0.dist-info/metadata.json,sha256=CCBpg-KQU-VRL1unJcHPWKQeQbB84G0j7-BeCj7YUbU,875
-cycler-0.10.0.dist-info/top_level.txt,sha256=D8BVVDdAAelLb2FOEz7lDpc6-AL21ylKPrMhtG6yzyE,7
-cycler.py,sha256=ed3G39unvVEBrBZVDwnE0FFroRNsOLkbJ_TwIT5CjCU,15959

+ 0 - 6
venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/WHEEL

@@ -1,6 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.29.0)
-Root-Is-Purelib: true
-Tag: py2-none-any
-Tag: py3-none-any
-

+ 0 - 1
venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/metadata.json

@@ -1 +0,0 @@
-{"classifiers": ["Development Status :: 4 - Beta", "Programming Language :: Python :: 2", "Programming Language :: Python :: 2.6", "Programming Language :: Python :: 2.7", "Programming Language :: Python :: 3", "Programming Language :: Python :: 3.3", "Programming Language :: Python :: 3.4", "Programming Language :: Python :: 3.5"], "extensions": {"python.details": {"contacts": [{"email": "matplotlib-users@python.org", "name": "Thomas A Caswell", "role": "author"}], "document_names": {"description": "DESCRIPTION.rst"}, "project_urls": {"Home": "http://github.com/matplotlib/cycler"}}}, "extras": [], "generator": "bdist_wheel (0.29.0)", "keywords": ["cycle", "kwargs"], "license": "BSD", "metadata_version": "2.0", "name": "cycler", "platform": "Cross platform (Linux", "run_requires": [{"requires": ["six"]}], "summary": "Composable style cycles", "version": "0.10.0"}

+ 0 - 1
venv/lib/python3.8/site-packages/cycler-0.10.0.dist-info/top_level.txt

@@ -1 +0,0 @@
-cycler

+ 0 - 558
venv/lib/python3.8/site-packages/cycler.py

@@ -1,558 +0,0 @@
-"""
-Cycler
-======
-
-Cycling through combinations of values, producing dictionaries.
-
-You can add cyclers::
-
-    from cycler import cycler
-    cc = (cycler(color=list('rgb')) +
-          cycler(linestyle=['-', '--', '-.']))
-    for d in cc:
-        print(d)
-
-Results in::
-
-    {'color': 'r', 'linestyle': '-'}
-    {'color': 'g', 'linestyle': '--'}
-    {'color': 'b', 'linestyle': '-.'}
-
-
-You can multiply cyclers::
-
-    from cycler import cycler
-    cc = (cycler(color=list('rgb')) *
-          cycler(linestyle=['-', '--', '-.']))
-    for d in cc:
-        print(d)
-
-Results in::
-
-    {'color': 'r', 'linestyle': '-'}
-    {'color': 'r', 'linestyle': '--'}
-    {'color': 'r', 'linestyle': '-.'}
-    {'color': 'g', 'linestyle': '-'}
-    {'color': 'g', 'linestyle': '--'}
-    {'color': 'g', 'linestyle': '-.'}
-    {'color': 'b', 'linestyle': '-'}
-    {'color': 'b', 'linestyle': '--'}
-    {'color': 'b', 'linestyle': '-.'}
-"""
-
-from __future__ import (absolute_import, division, print_function,
-                        unicode_literals)
-
-import six
-from itertools import product, cycle
-from six.moves import zip, reduce
-from operator import mul, add
-import copy
-
-__version__ = '0.10.0'
-
-
-def _process_keys(left, right):
-    """
-    Helper function to compose cycler keys
-
-    Parameters
-    ----------
-    left, right : iterable of dictionaries or None
-        The cyclers to be composed
-    Returns
-    -------
-    keys : set
-        The keys in the composition of the two cyclers
-    """
-    l_peek = next(iter(left)) if left is not None else {}
-    r_peek = next(iter(right)) if right is not None else {}
-    l_key = set(l_peek.keys())
-    r_key = set(r_peek.keys())
-    if l_key & r_key:
-        raise ValueError("Can not compose overlapping cycles")
-    return l_key | r_key
-
-
-class Cycler(object):
-    """
-    Composable cycles
-
-    This class has compositions methods:
-
-    ``+``
-      for 'inner' products (zip)
-
-    ``+=``
-      in-place ``+``
-
-    ``*``
-      for outer products (itertools.product) and integer multiplication
-
-    ``*=``
-      in-place ``*``
-
-    and supports basic slicing via ``[]``
-
-    Parameters
-    ----------
-    left : Cycler or None
-        The 'left' cycler
-
-    right : Cycler or None
-        The 'right' cycler
-
-    op : func or None
-        Function which composes the 'left' and 'right' cyclers.
-
-    """
-    def __call__(self):
-        return cycle(self)
-
-    def __init__(self, left, right=None, op=None):
-        """Semi-private init
-
-        Do not use this directly, use `cycler` function instead.
-        """
-        if isinstance(left, Cycler):
-            self._left = Cycler(left._left, left._right, left._op)
-        elif left is not None:
-            # Need to copy the dictionary or else that will be a residual
-            # mutable that could lead to strange errors
-            self._left = [copy.copy(v) for v in left]
-        else:
-            self._left = None
-
-        if isinstance(right, Cycler):
-            self._right = Cycler(right._left, right._right, right._op)
-        elif right is not None:
-            # Need to copy the dictionary or else that will be a residual
-            # mutable that could lead to strange errors
-            self._right = [copy.copy(v) for v in right]
-        else:
-            self._right = None
-
-        self._keys = _process_keys(self._left, self._right)
-        self._op = op
-
-    @property
-    def keys(self):
-        """
-        The keys this Cycler knows about
-        """
-        return set(self._keys)
-
-    def change_key(self, old, new):
-        """
-        Change a key in this cycler to a new name.
-        Modification is performed in-place.
-
-        Does nothing if the old key is the same as the new key.
-        Raises a ValueError if the new key is already a key.
-        Raises a KeyError if the old key isn't a key.
-
-        """
-        if old == new:
-            return
-        if new in self._keys:
-            raise ValueError("Can't replace %s with %s, %s is already a key" %
-                             (old, new, new))
-        if old not in self._keys:
-            raise KeyError("Can't replace %s with %s, %s is not a key" %
-                           (old, new, old))
-
-        self._keys.remove(old)
-        self._keys.add(new)
-
-        if self._right is not None and old in self._right.keys:
-            self._right.change_key(old, new)
-
-        # self._left should always be non-None
-        # if self._keys is non-empty.
-        elif isinstance(self._left, Cycler):
-            self._left.change_key(old, new)
-        else:
-            # It should be completely safe at this point to
-            # assume that the old key can be found in each
-            # iteration.
-            self._left = [{new: entry[old]} for entry in self._left]
-
-    def _compose(self):
-        """
-        Compose the 'left' and 'right' components of this cycle
-        with the proper operation (zip or product as of now)
-        """
-        for a, b in self._op(self._left, self._right):
-            out = dict()
-            out.update(a)
-            out.update(b)
-            yield out
-
-    @classmethod
-    def _from_iter(cls, label, itr):
-        """
-        Class method to create 'base' Cycler objects
-        that do not have a 'right' or 'op' and for which
-        the 'left' object is not another Cycler.
-
-        Parameters
-        ----------
-        label : str
-            The property key.
-
-        itr : iterable
-            Finite length iterable of the property values.
-
-        Returns
-        -------
-        cycler : Cycler
-            New 'base' `Cycler`
-        """
-        ret = cls(None)
-        ret._left = list({label: v} for v in itr)
-        ret._keys = set([label])
-        return ret
-
-    def __getitem__(self, key):
-        # TODO : maybe add numpy style fancy slicing
-        if isinstance(key, slice):
-            trans = self.by_key()
-            return reduce(add, (_cycler(k, v[key])
-                                for k, v in six.iteritems(trans)))
-        else:
-            raise ValueError("Can only use slices with Cycler.__getitem__")
-
-    def __iter__(self):
-        if self._right is None:
-            return iter(dict(l) for l in self._left)
-
-        return self._compose()
-
-    def __add__(self, other):
-        """
-        Pair-wise combine two equal length cycles (zip)
-
-        Parameters
-        ----------
-        other : Cycler
-           The second Cycler
-        """
-        if len(self) != len(other):
-            raise ValueError("Can only add equal length cycles, "
-                             "not {0} and {1}".format(len(self), len(other)))
-        return Cycler(self, other, zip)
-
-    def __mul__(self, other):
-        """
-        Outer product of two cycles (`itertools.product`) or integer
-        multiplication.
-
-        Parameters
-        ----------
-        other : Cycler or int
-           The second Cycler or integer
-        """
-        if isinstance(other, Cycler):
-            return Cycler(self, other, product)
-        elif isinstance(other, int):
-            trans = self.by_key()
-            return reduce(add, (_cycler(k, v*other)
-                                for k, v in six.iteritems(trans)))
-        else:
-            return NotImplemented
-
-    def __rmul__(self, other):
-        return self * other
-
-    def __len__(self):
-        op_dict = {zip: min, product: mul}
-        if self._right is None:
-            return len(self._left)
-        l_len = len(self._left)
-        r_len = len(self._right)
-        return op_dict[self._op](l_len, r_len)
-
-    def __iadd__(self, other):
-        """
-        In-place pair-wise combine two equal length cycles (zip)
-
-        Parameters
-        ----------
-        other : Cycler
-           The second Cycler
-        """
-        if not isinstance(other, Cycler):
-            raise TypeError("Cannot += with a non-Cycler object")
-        # True shallow copy of self is fine since this is in-place
-        old_self = copy.copy(self)
-        self._keys = _process_keys(old_self, other)
-        self._left = old_self
-        self._op = zip
-        self._right = Cycler(other._left, other._right, other._op)
-        return self
-
-    def __imul__(self, other):
-        """
-        In-place outer product of two cycles (`itertools.product`)
-
-        Parameters
-        ----------
-        other : Cycler
-           The second Cycler
-        """
-        if not isinstance(other, Cycler):
-            raise TypeError("Cannot *= with a non-Cycler object")
-        # True shallow copy of self is fine since this is in-place
-        old_self = copy.copy(self)
-        self._keys = _process_keys(old_self, other)
-        self._left = old_self
-        self._op = product
-        self._right = Cycler(other._left, other._right, other._op)
-        return self
-
-    def __eq__(self, other):
-        """
-        Check equality
-        """
-        if len(self) != len(other):
-            return False
-        if self.keys ^ other.keys:
-            return False
-
-        return all(a == b for a, b in zip(self, other))
-
-    def __repr__(self):
-        op_map = {zip: '+', product: '*'}
-        if self._right is None:
-            lab = self.keys.pop()
-            itr = list(v[lab] for v in self)
-            return "cycler({lab!r}, {itr!r})".format(lab=lab, itr=itr)
-        else:
-            op = op_map.get(self._op, '?')
-            msg = "({left!r} {op} {right!r})"
-            return msg.format(left=self._left, op=op, right=self._right)
-
-    def _repr_html_(self):
-        # an table showing the value of each key through a full cycle
-        output = "<table>"
-        sorted_keys = sorted(self.keys, key=repr)
-        for key in sorted_keys:
-            output += "<th>{key!r}</th>".format(key=key)
-        for d in iter(self):
-            output += "<tr>"
-            for k in sorted_keys:
-                output += "<td>{val!r}</td>".format(val=d[k])
-            output += "</tr>"
-        output += "</table>"
-        return output
-
-    def by_key(self):
-        """Values by key
-
-        This returns the transposed values of the cycler.  Iterating
-        over a `Cycler` yields dicts with a single value for each key,
-        this method returns a `dict` of `list` which are the values
-        for the given key.
-
-        The returned value can be used to create an equivalent `Cycler`
-        using only `+`.
-
-        Returns
-        -------
-        transpose : dict
-            dict of lists of the values for each key.
-        """
-
-        # TODO : sort out if this is a bottle neck, if there is a better way
-        # and if we care.
-
-        keys = self.keys
-        # change this to dict comprehension when drop 2.6
-        out = dict((k,  list()) for k in keys)
-
-        for d in self:
-            for k in keys:
-                out[k].append(d[k])
-        return out
-
-    # for back compatibility
-    _transpose = by_key
-
-    def simplify(self):
-        """Simplify the Cycler
-
-        Returned as a composition using only sums (no multiplications)
-
-        Returns
-        -------
-        simple : Cycler
-            An equivalent cycler using only summation"""
-        # TODO: sort out if it is worth the effort to make sure this is
-        # balanced.  Currently it is is
-        # (((a + b) + c) + d) vs
-        # ((a + b) + (c + d))
-        # I would believe that there is some performance implications
-
-        trans = self.by_key()
-        return reduce(add, (_cycler(k, v) for k, v in six.iteritems(trans)))
-
-    def concat(self, other):
-        """Concatenate this cycler and an other.
-
-        The keys must match exactly.
-
-        This returns a single Cycler which is equivalent to
-        `itertools.chain(self, other)`
-
-        Examples
-        --------
-
-        >>> num = cycler('a', range(3))
-        >>> let = cycler('a', 'abc')
-        >>> num.concat(let)
-        cycler('a', [0, 1, 2, 'a', 'b', 'c'])
-
-        Parameters
-        ----------
-        other : `Cycler`
-            The `Cycler` to concatenate to this one.
-
-        Returns
-        -------
-        ret : `Cycler`
-            The concatenated `Cycler`
-        """
-        return concat(self, other)
-
-
-def concat(left, right):
-    """Concatenate two cyclers.
-
-    The keys must match exactly.
-
-    This returns a single Cycler which is equivalent to
-    `itertools.chain(left, right)`
-
-    Examples
-    --------
-
-    >>> num = cycler('a', range(3))
-    >>> let = cycler('a', 'abc')
-    >>> num.concat(let)
-    cycler('a', [0, 1, 2, 'a', 'b', 'c'])
-
-    Parameters
-    ----------
-    left, right : `Cycler`
-        The two `Cycler` instances to concatenate
-
-    Returns
-    -------
-    ret : `Cycler`
-        The concatenated `Cycler`
-    """
-    if left.keys != right.keys:
-        msg = '\n\t'.join(["Keys do not match:",
-                           "Intersection: {both!r}",
-                           "Disjoint: {just_one!r}"]).format(
-                               both=left.keys & right.keys,
-                               just_one=left.keys ^ right.keys)
-
-        raise ValueError(msg)
-
-    _l = left.by_key()
-    _r = right.by_key()
-    return reduce(add, (_cycler(k, _l[k] + _r[k]) for k in left.keys))
-
-
-def cycler(*args, **kwargs):
-    """
-    Create a new `Cycler` object from a single positional argument,
-    a pair of positional arguments, or the combination of keyword arguments.
-
-    cycler(arg)
-    cycler(label1=itr1[, label2=iter2[, ...]])
-    cycler(label, itr)
-
-    Form 1 simply copies a given `Cycler` object.
-
-    Form 2 composes a `Cycler` as an inner product of the
-    pairs of keyword arguments. In other words, all of the
-    iterables are cycled simultaneously, as if through zip().
-
-    Form 3 creates a `Cycler` from a label and an iterable.
-    This is useful for when the label cannot be a keyword argument
-    (e.g., an integer or a name that has a space in it).
-
-    Parameters
-    ----------
-    arg : Cycler
-        Copy constructor for Cycler (does a shallow copy of iterables).
-
-    label : name
-        The property key. In the 2-arg form of the function,
-        the label can be any hashable object. In the keyword argument
-        form of the function, it must be a valid python identifier.
-
-    itr : iterable
-        Finite length iterable of the property values.
-        Can be a single-property `Cycler` that would
-        be like a key change, but as a shallow copy.
-
-    Returns
-    -------
-    cycler : Cycler
-        New `Cycler` for the given property
-
-    """
-    if args and kwargs:
-        raise TypeError("cyl() can only accept positional OR keyword "
-                        "arguments -- not both.")
-
-    if len(args) == 1:
-        if not isinstance(args[0], Cycler):
-            raise TypeError("If only one positional argument given, it must "
-                            " be a Cycler instance.")
-        return Cycler(args[0])
-    elif len(args) == 2:
-        return _cycler(*args)
-    elif len(args) > 2:
-        raise TypeError("Only a single Cycler can be accepted as the lone "
-                        "positional argument. Use keyword arguments instead.")
-
-    if kwargs:
-        return reduce(add, (_cycler(k, v) for k, v in six.iteritems(kwargs)))
-
-    raise TypeError("Must have at least a positional OR keyword arguments")
-
-
-def _cycler(label, itr):
-    """
-    Create a new `Cycler` object from a property name and
-    iterable of values.
-
-    Parameters
-    ----------
-    label : hashable
-        The property key.
-
-    itr : iterable
-        Finite length iterable of the property values.
-
-    Returns
-    -------
-    cycler : Cycler
-        New `Cycler` for the given property
-    """
-    if isinstance(itr, Cycler):
-        keys = itr.keys
-        if len(keys) != 1:
-            msg = "Can not create Cycler from a multi-property Cycler"
-            raise ValueError(msg)
-
-        lab = keys.pop()
-        # Doesn't need to be a new list because
-        # _from_iter() will be creating that new list anyway.
-        itr = (v[lab] for v in itr)
-
-    return Cycler._from_iter(label, itr)

+ 0 - 8
venv/lib/python3.8/site-packages/dateutil/__init__.py

@@ -1,8 +0,0 @@
-# -*- coding: utf-8 -*-
-try:
-    from ._version import version as __version__
-except ImportError:
-    __version__ = 'unknown'
-
-__all__ = ['easter', 'parser', 'relativedelta', 'rrule', 'tz',
-           'utils', 'zoneinfo']

+ 0 - 43
venv/lib/python3.8/site-packages/dateutil/_common.py

@@ -1,43 +0,0 @@
-"""
-Common code used in multiple modules.
-"""
-
-
-class weekday(object):
-    __slots__ = ["weekday", "n"]
-
-    def __init__(self, weekday, n=None):
-        self.weekday = weekday
-        self.n = n
-
-    def __call__(self, n):
-        if n == self.n:
-            return self
-        else:
-            return self.__class__(self.weekday, n)
-
-    def __eq__(self, other):
-        try:
-            if self.weekday != other.weekday or self.n != other.n:
-                return False
-        except AttributeError:
-            return False
-        return True
-
-    def __hash__(self):
-        return hash((
-          self.weekday,
-          self.n,
-        ))
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __repr__(self):
-        s = ("MO", "TU", "WE", "TH", "FR", "SA", "SU")[self.weekday]
-        if not self.n:
-            return s
-        else:
-            return "%s(%+d)" % (s, self.n)
-
-# vim:ts=4:sw=4:et

+ 0 - 4
venv/lib/python3.8/site-packages/dateutil/_version.py

@@ -1,4 +0,0 @@
-# coding: utf-8
-# file generated by setuptools_scm
-# don't change, don't track in version control
-version = '2.8.1'

+ 0 - 89
venv/lib/python3.8/site-packages/dateutil/easter.py

@@ -1,89 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-This module offers a generic easter computing method for any given year, using
-Western, Orthodox or Julian algorithms.
-"""
-
-import datetime
-
-__all__ = ["easter", "EASTER_JULIAN", "EASTER_ORTHODOX", "EASTER_WESTERN"]
-
-EASTER_JULIAN = 1
-EASTER_ORTHODOX = 2
-EASTER_WESTERN = 3
-
-
-def easter(year, method=EASTER_WESTERN):
-    """
-    This method was ported from the work done by GM Arts,
-    on top of the algorithm by Claus Tondering, which was
-    based in part on the algorithm of Ouding (1940), as
-    quoted in "Explanatory Supplement to the Astronomical
-    Almanac", P.  Kenneth Seidelmann, editor.
-
-    This algorithm implements three different easter
-    calculation methods:
-
-    1 - Original calculation in Julian calendar, valid in
-        dates after 326 AD
-    2 - Original method, with date converted to Gregorian
-        calendar, valid in years 1583 to 4099
-    3 - Revised method, in Gregorian calendar, valid in
-        years 1583 to 4099 as well
-
-    These methods are represented by the constants:
-
-    * ``EASTER_JULIAN   = 1``
-    * ``EASTER_ORTHODOX = 2``
-    * ``EASTER_WESTERN  = 3``
-
-    The default method is method 3.
-
-    More about the algorithm may be found at:
-
-    `GM Arts: Easter Algorithms <http://www.gmarts.org/index.php?go=415>`_
-
-    and
-
-    `The Calendar FAQ: Easter <https://www.tondering.dk/claus/cal/easter.php>`_
-
-    """
-
-    if not (1 <= method <= 3):
-        raise ValueError("invalid method")
-
-    # g - Golden year - 1
-    # c - Century
-    # h - (23 - Epact) mod 30
-    # i - Number of days from March 21 to Paschal Full Moon
-    # j - Weekday for PFM (0=Sunday, etc)
-    # p - Number of days from March 21 to Sunday on or before PFM
-    #     (-6 to 28 methods 1 & 3, to 56 for method 2)
-    # e - Extra days to add for method 2 (converting Julian
-    #     date to Gregorian date)
-
-    y = year
-    g = y % 19
-    e = 0
-    if method < 3:
-        # Old method
-        i = (19*g + 15) % 30
-        j = (y + y//4 + i) % 7
-        if method == 2:
-            # Extra dates to convert Julian to Gregorian date
-            e = 10
-            if y > 1600:
-                e = e + y//100 - 16 - (y//100 - 16)//4
-    else:
-        # New method
-        c = y//100
-        h = (c - c//4 - (8*c + 13)//25 + 19*g + 15) % 30
-        i = h - (h//28)*(1 - (h//28)*(29//(h + 1))*((21 - g)//11))
-        j = (y + y//4 + i + 2 - c + c//4) % 7
-
-    # p can be from -6 to 56 corresponding to dates 22 March to 23 May
-    # (later dates apply to method 2, although 23 May never actually occurs)
-    p = i - j + e
-    d = 1 + (p + 27 + (p + 6)//40) % 31
-    m = 3 + (p + 26)//30
-    return datetime.date(int(y), int(m), int(d))

+ 0 - 61
venv/lib/python3.8/site-packages/dateutil/parser/__init__.py

@@ -1,61 +0,0 @@
-# -*- coding: utf-8 -*-
-from ._parser import parse, parser, parserinfo, ParserError
-from ._parser import DEFAULTPARSER, DEFAULTTZPARSER
-from ._parser import UnknownTimezoneWarning
-
-from ._parser import __doc__
-
-from .isoparser import isoparser, isoparse
-
-__all__ = ['parse', 'parser', 'parserinfo',
-           'isoparse', 'isoparser',
-           'ParserError',
-           'UnknownTimezoneWarning']
-
-
-###
-# Deprecate portions of the private interface so that downstream code that
-# is improperly relying on it is given *some* notice.
-
-
-def __deprecated_private_func(f):
-    from functools import wraps
-    import warnings
-
-    msg = ('{name} is a private function and may break without warning, '
-           'it will be moved and or renamed in future versions.')
-    msg = msg.format(name=f.__name__)
-
-    @wraps(f)
-    def deprecated_func(*args, **kwargs):
-        warnings.warn(msg, DeprecationWarning)
-        return f(*args, **kwargs)
-
-    return deprecated_func
-
-def __deprecate_private_class(c):
-    import warnings
-
-    msg = ('{name} is a private class and may break without warning, '
-           'it will be moved and or renamed in future versions.')
-    msg = msg.format(name=c.__name__)
-
-    class private_class(c):
-        __doc__ = c.__doc__
-
-        def __init__(self, *args, **kwargs):
-            warnings.warn(msg, DeprecationWarning)
-            super(private_class, self).__init__(*args, **kwargs)
-
-    private_class.__name__ = c.__name__
-
-    return private_class
-
-
-from ._parser import _timelex, _resultbase
-from ._parser import _tzparser, _parsetz
-
-_timelex = __deprecate_private_class(_timelex)
-_tzparser = __deprecate_private_class(_tzparser)
-_resultbase = __deprecate_private_class(_resultbase)
-_parsetz = __deprecated_private_func(_parsetz)

+ 0 - 1609
venv/lib/python3.8/site-packages/dateutil/parser/_parser.py

@@ -1,1609 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-This module offers a generic date/time string parser which is able to parse
-most known formats to represent a date and/or time.
-
-This module attempts to be forgiving with regards to unlikely input formats,
-returning a datetime object even for dates which are ambiguous. If an element
-of a date/time stamp is omitted, the following rules are applied:
-
-- If AM or PM is left unspecified, a 24-hour clock is assumed, however, an hour
-  on a 12-hour clock (``0 <= hour <= 12``) *must* be specified if AM or PM is
-  specified.
-- If a time zone is omitted, a timezone-naive datetime is returned.
-
-If any other elements are missing, they are taken from the
-:class:`datetime.datetime` object passed to the parameter ``default``. If this
-results in a day number exceeding the valid number of days per month, the
-value falls back to the end of the month.
-
-Additional resources about date/time string formats can be found below:
-
-- `A summary of the international standard date and time notation
-  <http://www.cl.cam.ac.uk/~mgk25/iso-time.html>`_
-- `W3C Date and Time Formats <http://www.w3.org/TR/NOTE-datetime>`_
-- `Time Formats (Planetary Rings Node) <https://pds-rings.seti.org:443/tools/time_formats.html>`_
-- `CPAN ParseDate module
-  <http://search.cpan.org/~muir/Time-modules-2013.0912/lib/Time/ParseDate.pm>`_
-- `Java SimpleDateFormat Class
-  <https://docs.oracle.com/javase/6/docs/api/java/text/SimpleDateFormat.html>`_
-"""
-from __future__ import unicode_literals
-
-import datetime
-import re
-import string
-import time
-import warnings
-
-from calendar import monthrange
-from io import StringIO
-
-import six
-from six import integer_types, text_type
-
-from decimal import Decimal
-
-from warnings import warn
-
-from .. import relativedelta
-from .. import tz
-
-__all__ = ["parse", "parserinfo", "ParserError"]
-
-
-# TODO: pandas.core.tools.datetimes imports this explicitly.  Might be worth
-# making public and/or figuring out if there is something we can
-# take off their plate.
-class _timelex(object):
-    # Fractional seconds are sometimes split by a comma
-    _split_decimal = re.compile("([.,])")
-
-    def __init__(self, instream):
-        if six.PY2:
-            # In Python 2, we can't duck type properly because unicode has
-            # a 'decode' function, and we'd be double-decoding
-            if isinstance(instream, (bytes, bytearray)):
-                instream = instream.decode()
-        else:
-            if getattr(instream, 'decode', None) is not None:
-                instream = instream.decode()
-
-        if isinstance(instream, text_type):
-            instream = StringIO(instream)
-        elif getattr(instream, 'read', None) is None:
-            raise TypeError('Parser must be a string or character stream, not '
-                            '{itype}'.format(itype=instream.__class__.__name__))
-
-        self.instream = instream
-        self.charstack = []
-        self.tokenstack = []
-        self.eof = False
-
-    def get_token(self):
-        """
-        This function breaks the time string into lexical units (tokens), which
-        can be parsed by the parser. Lexical units are demarcated by changes in
-        the character set, so any continuous string of letters is considered
-        one unit, any continuous string of numbers is considered one unit.
-
-        The main complication arises from the fact that dots ('.') can be used
-        both as separators (e.g. "Sep.20.2009") or decimal points (e.g.
-        "4:30:21.447"). As such, it is necessary to read the full context of
-        any dot-separated strings before breaking it into tokens; as such, this
-        function maintains a "token stack", for when the ambiguous context
-        demands that multiple tokens be parsed at once.
-        """
-        if self.tokenstack:
-            return self.tokenstack.pop(0)
-
-        seenletters = False
-        token = None
-        state = None
-
-        while not self.eof:
-            # We only realize that we've reached the end of a token when we
-            # find a character that's not part of the current token - since
-            # that character may be part of the next token, it's stored in the
-            # charstack.
-            if self.charstack:
-                nextchar = self.charstack.pop(0)
-            else:
-                nextchar = self.instream.read(1)
-                while nextchar == '\x00':
-                    nextchar = self.instream.read(1)
-
-            if not nextchar:
-                self.eof = True
-                break
-            elif not state:
-                # First character of the token - determines if we're starting
-                # to parse a word, a number or something else.
-                token = nextchar
-                if self.isword(nextchar):
-                    state = 'a'
-                elif self.isnum(nextchar):
-                    state = '0'
-                elif self.isspace(nextchar):
-                    token = ' '
-                    break  # emit token
-                else:
-                    break  # emit token
-            elif state == 'a':
-                # If we've already started reading a word, we keep reading
-                # letters until we find something that's not part of a word.
-                seenletters = True
-                if self.isword(nextchar):
-                    token += nextchar
-                elif nextchar == '.':
-                    token += nextchar
-                    state = 'a.'
-                else:
-                    self.charstack.append(nextchar)
-                    break  # emit token
-            elif state == '0':
-                # If we've already started reading a number, we keep reading
-                # numbers until we find something that doesn't fit.
-                if self.isnum(nextchar):
-                    token += nextchar
-                elif nextchar == '.' or (nextchar == ',' and len(token) >= 2):
-                    token += nextchar
-                    state = '0.'
-                else:
-                    self.charstack.append(nextchar)
-                    break  # emit token
-            elif state == 'a.':
-                # If we've seen some letters and a dot separator, continue
-                # parsing, and the tokens will be broken up later.
-                seenletters = True
-                if nextchar == '.' or self.isword(nextchar):
-                    token += nextchar
-                elif self.isnum(nextchar) and token[-1] == '.':
-                    token += nextchar
-                    state = '0.'
-                else:
-                    self.charstack.append(nextchar)
-                    break  # emit token
-            elif state == '0.':
-                # If we've seen at least one dot separator, keep going, we'll
-                # break up the tokens later.
-                if nextchar == '.' or self.isnum(nextchar):
-                    token += nextchar
-                elif self.isword(nextchar) and token[-1] == '.':
-                    token += nextchar
-                    state = 'a.'
-                else:
-                    self.charstack.append(nextchar)
-                    break  # emit token
-
-        if (state in ('a.', '0.') and (seenletters or token.count('.') > 1 or
-                                       token[-1] in '.,')):
-            l = self._split_decimal.split(token)
-            token = l[0]
-            for tok in l[1:]:
-                if tok:
-                    self.tokenstack.append(tok)
-
-        if state == '0.' and token.count('.') == 0:
-            token = token.replace(',', '.')
-
-        return token
-
-    def __iter__(self):
-        return self
-
-    def __next__(self):
-        token = self.get_token()
-        if token is None:
-            raise StopIteration
-
-        return token
-
-    def next(self):
-        return self.__next__()  # Python 2.x support
-
-    @classmethod
-    def split(cls, s):
-        return list(cls(s))
-
-    @classmethod
-    def isword(cls, nextchar):
-        """ Whether or not the next character is part of a word """
-        return nextchar.isalpha()
-
-    @classmethod
-    def isnum(cls, nextchar):
-        """ Whether the next character is part of a number """
-        return nextchar.isdigit()
-
-    @classmethod
-    def isspace(cls, nextchar):
-        """ Whether the next character is whitespace """
-        return nextchar.isspace()
-
-
-class _resultbase(object):
-
-    def __init__(self):
-        for attr in self.__slots__:
-            setattr(self, attr, None)
-
-    def _repr(self, classname):
-        l = []
-        for attr in self.__slots__:
-            value = getattr(self, attr)
-            if value is not None:
-                l.append("%s=%s" % (attr, repr(value)))
-        return "%s(%s)" % (classname, ", ".join(l))
-
-    def __len__(self):
-        return (sum(getattr(self, attr) is not None
-                    for attr in self.__slots__))
-
-    def __repr__(self):
-        return self._repr(self.__class__.__name__)
-
-
-class parserinfo(object):
-    """
-    Class which handles what inputs are accepted. Subclass this to customize
-    the language and acceptable values for each parameter.
-
-    :param dayfirst:
-        Whether to interpret the first value in an ambiguous 3-integer date
-        (e.g. 01/05/09) as the day (``True``) or month (``False``). If
-        ``yearfirst`` is set to ``True``, this distinguishes between YDM
-        and YMD. Default is ``False``.
-
-    :param yearfirst:
-        Whether to interpret the first value in an ambiguous 3-integer date
-        (e.g. 01/05/09) as the year. If ``True``, the first number is taken
-        to be the year, otherwise the last number is taken to be the year.
-        Default is ``False``.
-    """
-
-    # m from a.m/p.m, t from ISO T separator
-    JUMP = [" ", ".", ",", ";", "-", "/", "'",
-            "at", "on", "and", "ad", "m", "t", "of",
-            "st", "nd", "rd", "th"]
-
-    WEEKDAYS = [("Mon", "Monday"),
-                ("Tue", "Tuesday"),     # TODO: "Tues"
-                ("Wed", "Wednesday"),
-                ("Thu", "Thursday"),    # TODO: "Thurs"
-                ("Fri", "Friday"),
-                ("Sat", "Saturday"),
-                ("Sun", "Sunday")]
-    MONTHS = [("Jan", "January"),
-              ("Feb", "February"),      # TODO: "Febr"
-              ("Mar", "March"),
-              ("Apr", "April"),
-              ("May", "May"),
-              ("Jun", "June"),
-              ("Jul", "July"),
-              ("Aug", "August"),
-              ("Sep", "Sept", "September"),
-              ("Oct", "October"),
-              ("Nov", "November"),
-              ("Dec", "December")]
-    HMS = [("h", "hour", "hours"),
-           ("m", "minute", "minutes"),
-           ("s", "second", "seconds")]
-    AMPM = [("am", "a"),
-            ("pm", "p")]
-    UTCZONE = ["UTC", "GMT", "Z", "z"]
-    PERTAIN = ["of"]
-    TZOFFSET = {}
-    # TODO: ERA = ["AD", "BC", "CE", "BCE", "Stardate",
-    #              "Anno Domini", "Year of Our Lord"]
-
-    def __init__(self, dayfirst=False, yearfirst=False):
-        self._jump = self._convert(self.JUMP)
-        self._weekdays = self._convert(self.WEEKDAYS)
-        self._months = self._convert(self.MONTHS)
-        self._hms = self._convert(self.HMS)
-        self._ampm = self._convert(self.AMPM)
-        self._utczone = self._convert(self.UTCZONE)
-        self._pertain = self._convert(self.PERTAIN)
-
-        self.dayfirst = dayfirst
-        self.yearfirst = yearfirst
-
-        self._year = time.localtime().tm_year
-        self._century = self._year // 100 * 100
-
-    def _convert(self, lst):
-        dct = {}
-        for i, v in enumerate(lst):
-            if isinstance(v, tuple):
-                for v in v:
-                    dct[v.lower()] = i
-            else:
-                dct[v.lower()] = i
-        return dct
-
-    def jump(self, name):
-        return name.lower() in self._jump
-
-    def weekday(self, name):
-        try:
-            return self._weekdays[name.lower()]
-        except KeyError:
-            pass
-        return None
-
-    def month(self, name):
-        try:
-            return self._months[name.lower()] + 1
-        except KeyError:
-            pass
-        return None
-
-    def hms(self, name):
-        try:
-            return self._hms[name.lower()]
-        except KeyError:
-            return None
-
-    def ampm(self, name):
-        try:
-            return self._ampm[name.lower()]
-        except KeyError:
-            return None
-
-    def pertain(self, name):
-        return name.lower() in self._pertain
-
-    def utczone(self, name):
-        return name.lower() in self._utczone
-
-    def tzoffset(self, name):
-        if name in self._utczone:
-            return 0
-
-        return self.TZOFFSET.get(name)
-
-    def convertyear(self, year, century_specified=False):
-        """
-        Converts two-digit years to year within [-50, 49]
-        range of self._year (current local time)
-        """
-
-        # Function contract is that the year is always positive
-        assert year >= 0
-
-        if year < 100 and not century_specified:
-            # assume current century to start
-            year += self._century
-
-            if year >= self._year + 50:  # if too far in future
-                year -= 100
-            elif year < self._year - 50:  # if too far in past
-                year += 100
-
-        return year
-
-    def validate(self, res):
-        # move to info
-        if res.year is not None:
-            res.year = self.convertyear(res.year, res.century_specified)
-
-        if ((res.tzoffset == 0 and not res.tzname) or
-             (res.tzname == 'Z' or res.tzname == 'z')):
-            res.tzname = "UTC"
-            res.tzoffset = 0
-        elif res.tzoffset != 0 and res.tzname and self.utczone(res.tzname):
-            res.tzoffset = 0
-        return True
-
-
-class _ymd(list):
-    def __init__(self, *args, **kwargs):
-        super(self.__class__, self).__init__(*args, **kwargs)
-        self.century_specified = False
-        self.dstridx = None
-        self.mstridx = None
-        self.ystridx = None
-
-    @property
-    def has_year(self):
-        return self.ystridx is not None
-
-    @property
-    def has_month(self):
-        return self.mstridx is not None
-
-    @property
-    def has_day(self):
-        return self.dstridx is not None
-
-    def could_be_day(self, value):
-        if self.has_day:
-            return False
-        elif not self.has_month:
-            return 1 <= value <= 31
-        elif not self.has_year:
-            # Be permissive, assume leap year
-            month = self[self.mstridx]
-            return 1 <= value <= monthrange(2000, month)[1]
-        else:
-            month = self[self.mstridx]
-            year = self[self.ystridx]
-            return 1 <= value <= monthrange(year, month)[1]
-
-    def append(self, val, label=None):
-        if hasattr(val, '__len__'):
-            if val.isdigit() and len(val) > 2:
-                self.century_specified = True
-                if label not in [None, 'Y']:  # pragma: no cover
-                    raise ValueError(label)
-                label = 'Y'
-        elif val > 100:
-            self.century_specified = True
-            if label not in [None, 'Y']:  # pragma: no cover
-                raise ValueError(label)
-            label = 'Y'
-
-        super(self.__class__, self).append(int(val))
-
-        if label == 'M':
-            if self.has_month:
-                raise ValueError('Month is already set')
-            self.mstridx = len(self) - 1
-        elif label == 'D':
-            if self.has_day:
-                raise ValueError('Day is already set')
-            self.dstridx = len(self) - 1
-        elif label == 'Y':
-            if self.has_year:
-                raise ValueError('Year is already set')
-            self.ystridx = len(self) - 1
-
-    def _resolve_from_stridxs(self, strids):
-        """
-        Try to resolve the identities of year/month/day elements using
-        ystridx, mstridx, and dstridx, if enough of these are specified.
-        """
-        if len(self) == 3 and len(strids) == 2:
-            # we can back out the remaining stridx value
-            missing = [x for x in range(3) if x not in strids.values()]
-            key = [x for x in ['y', 'm', 'd'] if x not in strids]
-            assert len(missing) == len(key) == 1
-            key = key[0]
-            val = missing[0]
-            strids[key] = val
-
-        assert len(self) == len(strids)  # otherwise this should not be called
-        out = {key: self[strids[key]] for key in strids}
-        return (out.get('y'), out.get('m'), out.get('d'))
-
-    def resolve_ymd(self, yearfirst, dayfirst):
-        len_ymd = len(self)
-        year, month, day = (None, None, None)
-
-        strids = (('y', self.ystridx),
-                  ('m', self.mstridx),
-                  ('d', self.dstridx))
-
-        strids = {key: val for key, val in strids if val is not None}
-        if (len(self) == len(strids) > 0 or
-                (len(self) == 3 and len(strids) == 2)):
-            return self._resolve_from_stridxs(strids)
-
-        mstridx = self.mstridx
-
-        if len_ymd > 3:
-            raise ValueError("More than three YMD values")
-        elif len_ymd == 1 or (mstridx is not None and len_ymd == 2):
-            # One member, or two members with a month string
-            if mstridx is not None:
-                month = self[mstridx]
-                # since mstridx is 0 or 1, self[mstridx-1] always
-                # looks up the other element
-                other = self[mstridx - 1]
-            else:
-                other = self[0]
-
-            if len_ymd > 1 or mstridx is None:
-                if other > 31:
-                    year = other
-                else:
-                    day = other
-
-        elif len_ymd == 2:
-            # Two members with numbers
-            if self[0] > 31:
-                # 99-01
-                year, month = self
-            elif self[1] > 31:
-                # 01-99
-                month, year = self
-            elif dayfirst and self[1] <= 12:
-                # 13-01
-                day, month = self
-            else:
-                # 01-13
-                month, day = self
-
-        elif len_ymd == 3:
-            # Three members
-            if mstridx == 0:
-                if self[1] > 31:
-                    # Apr-2003-25
-                    month, year, day = self
-                else:
-                    month, day, year = self
-            elif mstridx == 1:
-                if self[0] > 31 or (yearfirst and self[2] <= 31):
-                    # 99-Jan-01
-                    year, month, day = self
-                else:
-                    # 01-Jan-01
-                    # Give precedence to day-first, since
-                    # two-digit years is usually hand-written.
-                    day, month, year = self
-
-            elif mstridx == 2:
-                # WTF!?
-                if self[1] > 31:
-                    # 01-99-Jan
-                    day, year, month = self
-                else:
-                    # 99-01-Jan
-                    year, day, month = self
-
-            else:
-                if (self[0] > 31 or
-                    self.ystridx == 0 or
-                        (yearfirst and self[1] <= 12 and self[2] <= 31)):
-                    # 99-01-01
-                    if dayfirst and self[2] <= 12:
-                        year, day, month = self
-                    else:
-                        year, month, day = self
-                elif self[0] > 12 or (dayfirst and self[1] <= 12):
-                    # 13-01-01
-                    day, month, year = self
-                else:
-                    # 01-13-01
-                    month, day, year = self
-
-        return year, month, day
-
-
-class parser(object):
-    def __init__(self, info=None):
-        self.info = info or parserinfo()
-
-    def parse(self, timestr, default=None,
-              ignoretz=False, tzinfos=None, **kwargs):
-        """
-        Parse the date/time string into a :class:`datetime.datetime` object.
-
-        :param timestr:
-            Any date/time string using the supported formats.
-
-        :param default:
-            The default datetime object, if this is a datetime object and not
-            ``None``, elements specified in ``timestr`` replace elements in the
-            default object.
-
-        :param ignoretz:
-            If set ``True``, time zones in parsed strings are ignored and a
-            naive :class:`datetime.datetime` object is returned.
-
-        :param tzinfos:
-            Additional time zone names / aliases which may be present in the
-            string. This argument maps time zone names (and optionally offsets
-            from those time zones) to time zones. This parameter can be a
-            dictionary with timezone aliases mapping time zone names to time
-            zones or a function taking two parameters (``tzname`` and
-            ``tzoffset``) and returning a time zone.
-
-            The timezones to which the names are mapped can be an integer
-            offset from UTC in seconds or a :class:`tzinfo` object.
-
-            .. doctest::
-               :options: +NORMALIZE_WHITESPACE
-
-                >>> from dateutil.parser import parse
-                >>> from dateutil.tz import gettz
-                >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")}
-                >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos)
-                datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200))
-                >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos)
-                datetime.datetime(2012, 1, 19, 17, 21,
-                                  tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago'))
-
-            This parameter is ignored if ``ignoretz`` is set.
-
-        :param \\*\\*kwargs:
-            Keyword arguments as passed to ``_parse()``.
-
-        :return:
-            Returns a :class:`datetime.datetime` object or, if the
-            ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the
-            first element being a :class:`datetime.datetime` object, the second
-            a tuple containing the fuzzy tokens.
-
-        :raises ParserError:
-            Raised for invalid or unknown string format, if the provided
-            :class:`tzinfo` is not in a valid format, or if an invalid date
-            would be created.
-
-        :raises TypeError:
-            Raised for non-string or character stream input.
-
-        :raises OverflowError:
-            Raised if the parsed date exceeds the largest valid C integer on
-            your system.
-        """
-
-        if default is None:
-            default = datetime.datetime.now().replace(hour=0, minute=0,
-                                                      second=0, microsecond=0)
-
-        res, skipped_tokens = self._parse(timestr, **kwargs)
-
-        if res is None:
-            raise ParserError("Unknown string format: %s", timestr)
-
-        if len(res) == 0:
-            raise ParserError("String does not contain a date: %s", timestr)
-
-        try:
-            ret = self._build_naive(res, default)
-        except ValueError as e:
-            six.raise_from(ParserError(e.args[0] + ": %s", timestr), e)
-
-        if not ignoretz:
-            ret = self._build_tzaware(ret, res, tzinfos)
-
-        if kwargs.get('fuzzy_with_tokens', False):
-            return ret, skipped_tokens
-        else:
-            return ret
-
-    class _result(_resultbase):
-        __slots__ = ["year", "month", "day", "weekday",
-                     "hour", "minute", "second", "microsecond",
-                     "tzname", "tzoffset", "ampm","any_unused_tokens"]
-
-    def _parse(self, timestr, dayfirst=None, yearfirst=None, fuzzy=False,
-               fuzzy_with_tokens=False):
-        """
-        Private method which performs the heavy lifting of parsing, called from
-        ``parse()``, which passes on its ``kwargs`` to this function.
-
-        :param timestr:
-            The string to parse.
-
-        :param dayfirst:
-            Whether to interpret the first value in an ambiguous 3-integer date
-            (e.g. 01/05/09) as the day (``True``) or month (``False``). If
-            ``yearfirst`` is set to ``True``, this distinguishes between YDM
-            and YMD. If set to ``None``, this value is retrieved from the
-            current :class:`parserinfo` object (which itself defaults to
-            ``False``).
-
-        :param yearfirst:
-            Whether to interpret the first value in an ambiguous 3-integer date
-            (e.g. 01/05/09) as the year. If ``True``, the first number is taken
-            to be the year, otherwise the last number is taken to be the year.
-            If this is set to ``None``, the value is retrieved from the current
-            :class:`parserinfo` object (which itself defaults to ``False``).
-
-        :param fuzzy:
-            Whether to allow fuzzy parsing, allowing for string like "Today is
-            January 1, 2047 at 8:21:00AM".
-
-        :param fuzzy_with_tokens:
-            If ``True``, ``fuzzy`` is automatically set to True, and the parser
-            will return a tuple where the first element is the parsed
-            :class:`datetime.datetime` datetimestamp and the second element is
-            a tuple containing the portions of the string which were ignored:
-
-            .. doctest::
-
-                >>> from dateutil.parser import parse
-                >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True)
-                (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at '))
-
-        """
-        if fuzzy_with_tokens:
-            fuzzy = True
-
-        info = self.info
-
-        if dayfirst is None:
-            dayfirst = info.dayfirst
-
-        if yearfirst is None:
-            yearfirst = info.yearfirst
-
-        res = self._result()
-        l = _timelex.split(timestr)         # Splits the timestr into tokens
-
-        skipped_idxs = []
-
-        # year/month/day list
-        ymd = _ymd()
-
-        len_l = len(l)
-        i = 0
-        try:
-            while i < len_l:
-
-                # Check if it's a number
-                value_repr = l[i]
-                try:
-                    value = float(value_repr)
-                except ValueError:
-                    value = None
-
-                if value is not None:
-                    # Numeric token
-                    i = self._parse_numeric_token(l, i, info, ymd, res, fuzzy)
-
-                # Check weekday
-                elif info.weekday(l[i]) is not None:
-                    value = info.weekday(l[i])
-                    res.weekday = value
-
-                # Check month name
-                elif info.month(l[i]) is not None:
-                    value = info.month(l[i])
-                    ymd.append(value, 'M')
-
-                    if i + 1 < len_l:
-                        if l[i + 1] in ('-', '/'):
-                            # Jan-01[-99]
-                            sep = l[i + 1]
-                            ymd.append(l[i + 2])
-
-                            if i + 3 < len_l and l[i + 3] == sep:
-                                # Jan-01-99
-                                ymd.append(l[i + 4])
-                                i += 2
-
-                            i += 2
-
-                        elif (i + 4 < len_l and l[i + 1] == l[i + 3] == ' ' and
-                              info.pertain(l[i + 2])):
-                            # Jan of 01
-                            # In this case, 01 is clearly year
-                            if l[i + 4].isdigit():
-                                # Convert it here to become unambiguous
-                                value = int(l[i + 4])
-                                year = str(info.convertyear(value))
-                                ymd.append(year, 'Y')
-                            else:
-                                # Wrong guess
-                                pass
-                                # TODO: not hit in tests
-                            i += 4
-
-                # Check am/pm
-                elif info.ampm(l[i]) is not None:
-                    value = info.ampm(l[i])
-                    val_is_ampm = self._ampm_valid(res.hour, res.ampm, fuzzy)
-
-                    if val_is_ampm:
-                        res.hour = self._adjust_ampm(res.hour, value)
-                        res.ampm = value
-
-                    elif fuzzy:
-                        skipped_idxs.append(i)
-
-                # Check for a timezone name
-                elif self._could_be_tzname(res.hour, res.tzname, res.tzoffset, l[i]):
-                    res.tzname = l[i]
-                    res.tzoffset = info.tzoffset(res.tzname)
-
-                    # Check for something like GMT+3, or BRST+3. Notice
-                    # that it doesn't mean "I am 3 hours after GMT", but
-                    # "my time +3 is GMT". If found, we reverse the
-                    # logic so that timezone parsing code will get it
-                    # right.
-                    if i + 1 < len_l and l[i + 1] in ('+', '-'):
-                        l[i + 1] = ('+', '-')[l[i + 1] == '+']
-                        res.tzoffset = None
-                        if info.utczone(res.tzname):
-                            # With something like GMT+3, the timezone
-                            # is *not* GMT.
-                            res.tzname = None
-
-                # Check for a numbered timezone
-                elif res.hour is not None and l[i] in ('+', '-'):
-                    signal = (-1, 1)[l[i] == '+']
-                    len_li = len(l[i + 1])
-
-                    # TODO: check that l[i + 1] is integer?
-                    if len_li == 4:
-                        # -0300
-                        hour_offset = int(l[i + 1][:2])
-                        min_offset = int(l[i + 1][2:])
-                    elif i + 2 < len_l and l[i + 2] == ':':
-                        # -03:00
-                        hour_offset = int(l[i + 1])
-                        min_offset = int(l[i + 3])  # TODO: Check that l[i+3] is minute-like?
-                        i += 2
-                    elif len_li <= 2:
-                        # -[0]3
-                        hour_offset = int(l[i + 1][:2])
-                        min_offset = 0
-                    else:
-                        raise ValueError(timestr)
-
-                    res.tzoffset = signal * (hour_offset * 3600 + min_offset * 60)
-
-                    # Look for a timezone name between parenthesis
-                    if (i + 5 < len_l and
-                            info.jump(l[i + 2]) and l[i + 3] == '(' and
-                            l[i + 5] == ')' and
-                            3 <= len(l[i + 4]) and
-                            self._could_be_tzname(res.hour, res.tzname,
-                                                  None, l[i + 4])):
-                        # -0300 (BRST)
-                        res.tzname = l[i + 4]
-                        i += 4
-
-                    i += 1
-
-                # Check jumps
-                elif not (info.jump(l[i]) or fuzzy):
-                    raise ValueError(timestr)
-
-                else:
-                    skipped_idxs.append(i)
-                i += 1
-
-            # Process year/month/day
-            year, month, day = ymd.resolve_ymd(yearfirst, dayfirst)
-
-            res.century_specified = ymd.century_specified
-            res.year = year
-            res.month = month
-            res.day = day
-
-        except (IndexError, ValueError):
-            return None, None
-
-        if not info.validate(res):
-            return None, None
-
-        if fuzzy_with_tokens:
-            skipped_tokens = self._recombine_skipped(l, skipped_idxs)
-            return res, tuple(skipped_tokens)
-        else:
-            return res, None
-
-    def _parse_numeric_token(self, tokens, idx, info, ymd, res, fuzzy):
-        # Token is a number
-        value_repr = tokens[idx]
-        try:
-            value = self._to_decimal(value_repr)
-        except Exception as e:
-            six.raise_from(ValueError('Unknown numeric token'), e)
-
-        len_li = len(value_repr)
-
-        len_l = len(tokens)
-
-        if (len(ymd) == 3 and len_li in (2, 4) and
-            res.hour is None and
-            (idx + 1 >= len_l or
-             (tokens[idx + 1] != ':' and
-              info.hms(tokens[idx + 1]) is None))):
-            # 19990101T23[59]
-            s = tokens[idx]
-            res.hour = int(s[:2])
-
-            if len_li == 4:
-                res.minute = int(s[2:])
-
-        elif len_li == 6 or (len_li > 6 and tokens[idx].find('.') == 6):
-            # YYMMDD or HHMMSS[.ss]
-            s = tokens[idx]
-
-            if not ymd and '.' not in tokens[idx]:
-                ymd.append(s[:2])
-                ymd.append(s[2:4])
-                ymd.append(s[4:])
-            else:
-                # 19990101T235959[.59]
-
-                # TODO: Check if res attributes already set.
-                res.hour = int(s[:2])
-                res.minute = int(s[2:4])
-                res.second, res.microsecond = self._parsems(s[4:])
-
-        elif len_li in (8, 12, 14):
-            # YYYYMMDD
-            s = tokens[idx]
-            ymd.append(s[:4], 'Y')
-            ymd.append(s[4:6])
-            ymd.append(s[6:8])
-
-            if len_li > 8:
-                res.hour = int(s[8:10])
-                res.minute = int(s[10:12])
-
-                if len_li > 12:
-                    res.second = int(s[12:])
-
-        elif self._find_hms_idx(idx, tokens, info, allow_jump=True) is not None:
-            # HH[ ]h or MM[ ]m or SS[.ss][ ]s
-            hms_idx = self._find_hms_idx(idx, tokens, info, allow_jump=True)
-            (idx, hms) = self._parse_hms(idx, tokens, info, hms_idx)
-            if hms is not None:
-                # TODO: checking that hour/minute/second are not
-                # already set?
-                self._assign_hms(res, value_repr, hms)
-
-        elif idx + 2 < len_l and tokens[idx + 1] == ':':
-            # HH:MM[:SS[.ss]]
-            res.hour = int(value)
-            value = self._to_decimal(tokens[idx + 2])  # TODO: try/except for this?
-            (res.minute, res.second) = self._parse_min_sec(value)
-
-            if idx + 4 < len_l and tokens[idx + 3] == ':':
-                res.second, res.microsecond = self._parsems(tokens[idx + 4])
-
-                idx += 2
-
-            idx += 2
-
-        elif idx + 1 < len_l and tokens[idx + 1] in ('-', '/', '.'):
-            sep = tokens[idx + 1]
-            ymd.append(value_repr)
-
-            if idx + 2 < len_l and not info.jump(tokens[idx + 2]):
-                if tokens[idx + 2].isdigit():
-                    # 01-01[-01]
-                    ymd.append(tokens[idx + 2])
-                else:
-                    # 01-Jan[-01]
-                    value = info.month(tokens[idx + 2])
-
-                    if value is not None:
-                        ymd.append(value, 'M')
-                    else:
-                        raise ValueError()
-
-                if idx + 3 < len_l and tokens[idx + 3] == sep:
-                    # We have three members
-                    value = info.month(tokens[idx + 4])
-
-                    if value is not None:
-                        ymd.append(value, 'M')
-                    else:
-                        ymd.append(tokens[idx + 4])
-                    idx += 2
-
-                idx += 1
-            idx += 1
-
-        elif idx + 1 >= len_l or info.jump(tokens[idx + 1]):
-            if idx + 2 < len_l and info.ampm(tokens[idx + 2]) is not None:
-                # 12 am
-                hour = int(value)
-                res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 2]))
-                idx += 1
-            else:
-                # Year, month or day
-                ymd.append(value)
-            idx += 1
-
-        elif info.ampm(tokens[idx + 1]) is not None and (0 <= value < 24):
-            # 12am
-            hour = int(value)
-            res.hour = self._adjust_ampm(hour, info.ampm(tokens[idx + 1]))
-            idx += 1
-
-        elif ymd.could_be_day(value):
-            ymd.append(value)
-
-        elif not fuzzy:
-            raise ValueError()
-
-        return idx
-
-    def _find_hms_idx(self, idx, tokens, info, allow_jump):
-        len_l = len(tokens)
-
-        if idx+1 < len_l and info.hms(tokens[idx+1]) is not None:
-            # There is an "h", "m", or "s" label following this token.  We take
-            # assign the upcoming label to the current token.
-            # e.g. the "12" in 12h"
-            hms_idx = idx + 1
-
-        elif (allow_jump and idx+2 < len_l and tokens[idx+1] == ' ' and
-              info.hms(tokens[idx+2]) is not None):
-            # There is a space and then an "h", "m", or "s" label.
-            # e.g. the "12" in "12 h"
-            hms_idx = idx + 2
-
-        elif idx > 0 and info.hms(tokens[idx-1]) is not None:
-            # There is a "h", "m", or "s" preceding this token.  Since neither
-            # of the previous cases was hit, there is no label following this
-            # token, so we use the previous label.
-            # e.g. the "04" in "12h04"
-            hms_idx = idx-1
-
-        elif (1 < idx == len_l-1 and tokens[idx-1] == ' ' and
-              info.hms(tokens[idx-2]) is not None):
-            # If we are looking at the final token, we allow for a
-            # backward-looking check to skip over a space.
-            # TODO: Are we sure this is the right condition here?
-            hms_idx = idx - 2
-
-        else:
-            hms_idx = None
-
-        return hms_idx
-
-    def _assign_hms(self, res, value_repr, hms):
-        # See GH issue #427, fixing float rounding
-        value = self._to_decimal(value_repr)
-
-        if hms == 0:
-            # Hour
-            res.hour = int(value)
-            if value % 1:
-                res.minute = int(60*(value % 1))
-
-        elif hms == 1:
-            (res.minute, res.second) = self._parse_min_sec(value)
-
-        elif hms == 2:
-            (res.second, res.microsecond) = self._parsems(value_repr)
-
-    def _could_be_tzname(self, hour, tzname, tzoffset, token):
-        return (hour is not None and
-                tzname is None and
-                tzoffset is None and
-                len(token) <= 5 and
-                (all(x in string.ascii_uppercase for x in token)
-                 or token in self.info.UTCZONE))
-
-    def _ampm_valid(self, hour, ampm, fuzzy):
-        """
-        For fuzzy parsing, 'a' or 'am' (both valid English words)
-        may erroneously trigger the AM/PM flag. Deal with that
-        here.
-        """
-        val_is_ampm = True
-
-        # If there's already an AM/PM flag, this one isn't one.
-        if fuzzy and ampm is not None:
-            val_is_ampm = False
-
-        # If AM/PM is found and hour is not, raise a ValueError
-        if hour is None:
-            if fuzzy:
-                val_is_ampm = False
-            else:
-                raise ValueError('No hour specified with AM or PM flag.')
-        elif not 0 <= hour <= 12:
-            # If AM/PM is found, it's a 12 hour clock, so raise
-            # an error for invalid range
-            if fuzzy:
-                val_is_ampm = False
-            else:
-                raise ValueError('Invalid hour specified for 12-hour clock.')
-
-        return val_is_ampm
-
-    def _adjust_ampm(self, hour, ampm):
-        if hour < 12 and ampm == 1:
-            hour += 12
-        elif hour == 12 and ampm == 0:
-            hour = 0
-        return hour
-
-    def _parse_min_sec(self, value):
-        # TODO: Every usage of this function sets res.second to the return
-        # value. Are there any cases where second will be returned as None and
-        # we *don't* want to set res.second = None?
-        minute = int(value)
-        second = None
-
-        sec_remainder = value % 1
-        if sec_remainder:
-            second = int(60 * sec_remainder)
-        return (minute, second)
-
-    def _parse_hms(self, idx, tokens, info, hms_idx):
-        # TODO: Is this going to admit a lot of false-positives for when we
-        # just happen to have digits and "h", "m" or "s" characters in non-date
-        # text?  I guess hex hashes won't have that problem, but there's plenty
-        # of random junk out there.
-        if hms_idx is None:
-            hms = None
-            new_idx = idx
-        elif hms_idx > idx:
-            hms = info.hms(tokens[hms_idx])
-            new_idx = hms_idx
-        else:
-            # Looking backwards, increment one.
-            hms = info.hms(tokens[hms_idx]) + 1
-            new_idx = idx
-
-        return (new_idx, hms)
-
-    # ------------------------------------------------------------------
-    # Handling for individual tokens.  These are kept as methods instead
-    #  of functions for the sake of customizability via subclassing.
-
-    def _parsems(self, value):
-        """Parse a I[.F] seconds value into (seconds, microseconds)."""
-        if "." not in value:
-            return int(value), 0
-        else:
-            i, f = value.split(".")
-            return int(i), int(f.ljust(6, "0")[:6])
-
-    def _to_decimal(self, val):
-        try:
-            decimal_value = Decimal(val)
-            # See GH 662, edge case, infinite value should not be converted
-            #  via `_to_decimal`
-            if not decimal_value.is_finite():
-                raise ValueError("Converted decimal value is infinite or NaN")
-        except Exception as e:
-            msg = "Could not convert %s to decimal" % val
-            six.raise_from(ValueError(msg), e)
-        else:
-            return decimal_value
-
-    # ------------------------------------------------------------------
-    # Post-Parsing construction of datetime output.  These are kept as
-    #  methods instead of functions for the sake of customizability via
-    #  subclassing.
-
-    def _build_tzinfo(self, tzinfos, tzname, tzoffset):
-        if callable(tzinfos):
-            tzdata = tzinfos(tzname, tzoffset)
-        else:
-            tzdata = tzinfos.get(tzname)
-        # handle case where tzinfo is paased an options that returns None
-        # eg tzinfos = {'BRST' : None}
-        if isinstance(tzdata, datetime.tzinfo) or tzdata is None:
-            tzinfo = tzdata
-        elif isinstance(tzdata, text_type):
-            tzinfo = tz.tzstr(tzdata)
-        elif isinstance(tzdata, integer_types):
-            tzinfo = tz.tzoffset(tzname, tzdata)
-        else:
-            raise TypeError("Offset must be tzinfo subclass, tz string, "
-                            "or int offset.")
-        return tzinfo
-
-    def _build_tzaware(self, naive, res, tzinfos):
-        if (callable(tzinfos) or (tzinfos and res.tzname in tzinfos)):
-            tzinfo = self._build_tzinfo(tzinfos, res.tzname, res.tzoffset)
-            aware = naive.replace(tzinfo=tzinfo)
-            aware = self._assign_tzname(aware, res.tzname)
-
-        elif res.tzname and res.tzname in time.tzname:
-            aware = naive.replace(tzinfo=tz.tzlocal())
-
-            # Handle ambiguous local datetime
-            aware = self._assign_tzname(aware, res.tzname)
-
-            # This is mostly relevant for winter GMT zones parsed in the UK
-            if (aware.tzname() != res.tzname and
-                    res.tzname in self.info.UTCZONE):
-                aware = aware.replace(tzinfo=tz.UTC)
-
-        elif res.tzoffset == 0:
-            aware = naive.replace(tzinfo=tz.UTC)
-
-        elif res.tzoffset:
-            aware = naive.replace(tzinfo=tz.tzoffset(res.tzname, res.tzoffset))
-
-        elif not res.tzname and not res.tzoffset:
-            # i.e. no timezone information was found.
-            aware = naive
-
-        elif res.tzname:
-            # tz-like string was parsed but we don't know what to do
-            # with it
-            warnings.warn("tzname {tzname} identified but not understood.  "
-                          "Pass `tzinfos` argument in order to correctly "
-                          "return a timezone-aware datetime.  In a future "
-                          "version, this will raise an "
-                          "exception.".format(tzname=res.tzname),
-                          category=UnknownTimezoneWarning)
-            aware = naive
-
-        return aware
-
-    def _build_naive(self, res, default):
-        repl = {}
-        for attr in ("year", "month", "day", "hour",
-                     "minute", "second", "microsecond"):
-            value = getattr(res, attr)
-            if value is not None:
-                repl[attr] = value
-
-        if 'day' not in repl:
-            # If the default day exceeds the last day of the month, fall back
-            # to the end of the month.
-            cyear = default.year if res.year is None else res.year
-            cmonth = default.month if res.month is None else res.month
-            cday = default.day if res.day is None else res.day
-
-            if cday > monthrange(cyear, cmonth)[1]:
-                repl['day'] = monthrange(cyear, cmonth)[1]
-
-        naive = default.replace(**repl)
-
-        if res.weekday is not None and not res.day:
-            naive = naive + relativedelta.relativedelta(weekday=res.weekday)
-
-        return naive
-
-    def _assign_tzname(self, dt, tzname):
-        if dt.tzname() != tzname:
-            new_dt = tz.enfold(dt, fold=1)
-            if new_dt.tzname() == tzname:
-                return new_dt
-
-        return dt
-
-    def _recombine_skipped(self, tokens, skipped_idxs):
-        """
-        >>> tokens = ["foo", " ", "bar", " ", "19June2000", "baz"]
-        >>> skipped_idxs = [0, 1, 2, 5]
-        >>> _recombine_skipped(tokens, skipped_idxs)
-        ["foo bar", "baz"]
-        """
-        skipped_tokens = []
-        for i, idx in enumerate(sorted(skipped_idxs)):
-            if i > 0 and idx - 1 == skipped_idxs[i - 1]:
-                skipped_tokens[-1] = skipped_tokens[-1] + tokens[idx]
-            else:
-                skipped_tokens.append(tokens[idx])
-
-        return skipped_tokens
-
-
-DEFAULTPARSER = parser()
-
-
-def parse(timestr, parserinfo=None, **kwargs):
-    """
-
-    Parse a string in one of the supported formats, using the
-    ``parserinfo`` parameters.
-
-    :param timestr:
-        A string containing a date/time stamp.
-
-    :param parserinfo:
-        A :class:`parserinfo` object containing parameters for the parser.
-        If ``None``, the default arguments to the :class:`parserinfo`
-        constructor are used.
-
-    The ``**kwargs`` parameter takes the following keyword arguments:
-
-    :param default:
-        The default datetime object, if this is a datetime object and not
-        ``None``, elements specified in ``timestr`` replace elements in the
-        default object.
-
-    :param ignoretz:
-        If set ``True``, time zones in parsed strings are ignored and a naive
-        :class:`datetime` object is returned.
-
-    :param tzinfos:
-        Additional time zone names / aliases which may be present in the
-        string. This argument maps time zone names (and optionally offsets
-        from those time zones) to time zones. This parameter can be a
-        dictionary with timezone aliases mapping time zone names to time
-        zones or a function taking two parameters (``tzname`` and
-        ``tzoffset``) and returning a time zone.
-
-        The timezones to which the names are mapped can be an integer
-        offset from UTC in seconds or a :class:`tzinfo` object.
-
-        .. doctest::
-           :options: +NORMALIZE_WHITESPACE
-
-            >>> from dateutil.parser import parse
-            >>> from dateutil.tz import gettz
-            >>> tzinfos = {"BRST": -7200, "CST": gettz("America/Chicago")}
-            >>> parse("2012-01-19 17:21:00 BRST", tzinfos=tzinfos)
-            datetime.datetime(2012, 1, 19, 17, 21, tzinfo=tzoffset(u'BRST', -7200))
-            >>> parse("2012-01-19 17:21:00 CST", tzinfos=tzinfos)
-            datetime.datetime(2012, 1, 19, 17, 21,
-                              tzinfo=tzfile('/usr/share/zoneinfo/America/Chicago'))
-
-        This parameter is ignored if ``ignoretz`` is set.
-
-    :param dayfirst:
-        Whether to interpret the first value in an ambiguous 3-integer date
-        (e.g. 01/05/09) as the day (``True``) or month (``False``). If
-        ``yearfirst`` is set to ``True``, this distinguishes between YDM and
-        YMD. If set to ``None``, this value is retrieved from the current
-        :class:`parserinfo` object (which itself defaults to ``False``).
-
-    :param yearfirst:
-        Whether to interpret the first value in an ambiguous 3-integer date
-        (e.g. 01/05/09) as the year. If ``True``, the first number is taken to
-        be the year, otherwise the last number is taken to be the year. If
-        this is set to ``None``, the value is retrieved from the current
-        :class:`parserinfo` object (which itself defaults to ``False``).
-
-    :param fuzzy:
-        Whether to allow fuzzy parsing, allowing for string like "Today is
-        January 1, 2047 at 8:21:00AM".
-
-    :param fuzzy_with_tokens:
-        If ``True``, ``fuzzy`` is automatically set to True, and the parser
-        will return a tuple where the first element is the parsed
-        :class:`datetime.datetime` datetimestamp and the second element is
-        a tuple containing the portions of the string which were ignored:
-
-        .. doctest::
-
-            >>> from dateutil.parser import parse
-            >>> parse("Today is January 1, 2047 at 8:21:00AM", fuzzy_with_tokens=True)
-            (datetime.datetime(2047, 1, 1, 8, 21), (u'Today is ', u' ', u'at '))
-
-    :return:
-        Returns a :class:`datetime.datetime` object or, if the
-        ``fuzzy_with_tokens`` option is ``True``, returns a tuple, the
-        first element being a :class:`datetime.datetime` object, the second
-        a tuple containing the fuzzy tokens.
-
-    :raises ValueError:
-        Raised for invalid or unknown string format, if the provided
-        :class:`tzinfo` is not in a valid format, or if an invalid date
-        would be created.
-
-    :raises OverflowError:
-        Raised if the parsed date exceeds the largest valid C integer on
-        your system.
-    """
-    if parserinfo:
-        return parser(parserinfo).parse(timestr, **kwargs)
-    else:
-        return DEFAULTPARSER.parse(timestr, **kwargs)
-
-
-class _tzparser(object):
-
-    class _result(_resultbase):
-
-        __slots__ = ["stdabbr", "stdoffset", "dstabbr", "dstoffset",
-                     "start", "end"]
-
-        class _attr(_resultbase):
-            __slots__ = ["month", "week", "weekday",
-                         "yday", "jyday", "day", "time"]
-
-        def __repr__(self):
-            return self._repr("")
-
-        def __init__(self):
-            _resultbase.__init__(self)
-            self.start = self._attr()
-            self.end = self._attr()
-
-    def parse(self, tzstr):
-        res = self._result()
-        l = [x for x in re.split(r'([,:.]|[a-zA-Z]+|[0-9]+)',tzstr) if x]
-        used_idxs = list()
-        try:
-
-            len_l = len(l)
-
-            i = 0
-            while i < len_l:
-                # BRST+3[BRDT[+2]]
-                j = i
-                while j < len_l and not [x for x in l[j]
-                                         if x in "0123456789:,-+"]:
-                    j += 1
-                if j != i:
-                    if not res.stdabbr:
-                        offattr = "stdoffset"
-                        res.stdabbr = "".join(l[i:j])
-                    else:
-                        offattr = "dstoffset"
-                        res.dstabbr = "".join(l[i:j])
-
-                    for ii in range(j):
-                        used_idxs.append(ii)
-                    i = j
-                    if (i < len_l and (l[i] in ('+', '-') or l[i][0] in
-                                       "0123456789")):
-                        if l[i] in ('+', '-'):
-                            # Yes, that's right.  See the TZ variable
-                            # documentation.
-                            signal = (1, -1)[l[i] == '+']
-                            used_idxs.append(i)
-                            i += 1
-                        else:
-                            signal = -1
-                        len_li = len(l[i])
-                        if len_li == 4:
-                            # -0300
-                            setattr(res, offattr, (int(l[i][:2]) * 3600 +
-                                                   int(l[i][2:]) * 60) * signal)
-                        elif i + 1 < len_l and l[i + 1] == ':':
-                            # -03:00
-                            setattr(res, offattr,
-                                    (int(l[i]) * 3600 +
-                                     int(l[i + 2]) * 60) * signal)
-                            used_idxs.append(i)
-                            i += 2
-                        elif len_li <= 2:
-                            # -[0]3
-                            setattr(res, offattr,
-                                    int(l[i][:2]) * 3600 * signal)
-                        else:
-                            return None
-                        used_idxs.append(i)
-                        i += 1
-                    if res.dstabbr:
-                        break
-                else:
-                    break
-
-
-            if i < len_l:
-                for j in range(i, len_l):
-                    if l[j] == ';':
-                        l[j] = ','
-
-                assert l[i] == ','
-
-                i += 1
-
-            if i >= len_l:
-                pass
-            elif (8 <= l.count(',') <= 9 and
-                  not [y for x in l[i:] if x != ','
-                       for y in x if y not in "0123456789+-"]):
-                # GMT0BST,3,0,30,3600,10,0,26,7200[,3600]
-                for x in (res.start, res.end):
-                    x.month = int(l[i])
-                    used_idxs.append(i)
-                    i += 2
-                    if l[i] == '-':
-                        value = int(l[i + 1]) * -1
-                        used_idxs.append(i)
-                        i += 1
-                    else:
-                        value = int(l[i])
-                    used_idxs.append(i)
-                    i += 2
-                    if value:
-                        x.week = value
-                        x.weekday = (int(l[i]) - 1) % 7
-                    else:
-                        x.day = int(l[i])
-                    used_idxs.append(i)
-                    i += 2
-                    x.time = int(l[i])
-                    used_idxs.append(i)
-                    i += 2
-                if i < len_l:
-                    if l[i] in ('-', '+'):
-                        signal = (-1, 1)[l[i] == "+"]
-                        used_idxs.append(i)
-                        i += 1
-                    else:
-                        signal = 1
-                    used_idxs.append(i)
-                    res.dstoffset = (res.stdoffset + int(l[i]) * signal)
-
-                # This was a made-up format that is not in normal use
-                warn(('Parsed time zone "%s"' % tzstr) +
-                     'is in a non-standard dateutil-specific format, which ' +
-                     'is now deprecated; support for parsing this format ' +
-                     'will be removed in future versions. It is recommended ' +
-                     'that you switch to a standard format like the GNU ' +
-                     'TZ variable format.', tz.DeprecatedTzFormatWarning)
-            elif (l.count(',') == 2 and l[i:].count('/') <= 2 and
-                  not [y for x in l[i:] if x not in (',', '/', 'J', 'M',
-                                                     '.', '-', ':')
-                       for y in x if y not in "0123456789"]):
-                for x in (res.start, res.end):
-                    if l[i] == 'J':
-                        # non-leap year day (1 based)
-                        used_idxs.append(i)
-                        i += 1
-                        x.jyday = int(l[i])
-                    elif l[i] == 'M':
-                        # month[-.]week[-.]weekday
-                        used_idxs.append(i)
-                        i += 1
-                        x.month = int(l[i])
-                        used_idxs.append(i)
-                        i += 1
-                        assert l[i] in ('-', '.')
-                        used_idxs.append(i)
-                        i += 1
-                        x.week = int(l[i])
-                        if x.week == 5:
-                            x.week = -1
-                        used_idxs.append(i)
-                        i += 1
-                        assert l[i] in ('-', '.')
-                        used_idxs.append(i)
-                        i += 1
-                        x.weekday = (int(l[i]) - 1) % 7
-                    else:
-                        # year day (zero based)
-                        x.yday = int(l[i]) + 1
-
-                    used_idxs.append(i)
-                    i += 1
-
-                    if i < len_l and l[i] == '/':
-                        used_idxs.append(i)
-                        i += 1
-                        # start time
-                        len_li = len(l[i])
-                        if len_li == 4:
-                            # -0300
-                            x.time = (int(l[i][:2]) * 3600 +
-                                      int(l[i][2:]) * 60)
-                        elif i + 1 < len_l and l[i + 1] == ':':
-                            # -03:00
-                            x.time = int(l[i]) * 3600 + int(l[i + 2]) * 60
-                            used_idxs.append(i)
-                            i += 2
-                            if i + 1 < len_l and l[i + 1] == ':':
-                                used_idxs.append(i)
-                                i += 2
-                                x.time += int(l[i])
-                        elif len_li <= 2:
-                            # -[0]3
-                            x.time = (int(l[i][:2]) * 3600)
-                        else:
-                            return None
-                        used_idxs.append(i)
-                        i += 1
-
-                    assert i == len_l or l[i] == ','
-
-                    i += 1
-
-                assert i >= len_l
-
-        except (IndexError, ValueError, AssertionError):
-            return None
-
-        unused_idxs = set(range(len_l)).difference(used_idxs)
-        res.any_unused_tokens = not {l[n] for n in unused_idxs}.issubset({",",":"})
-        return res
-
-
-DEFAULTTZPARSER = _tzparser()
-
-
-def _parsetz(tzstr):
-    return DEFAULTTZPARSER.parse(tzstr)
-
-
-class ParserError(ValueError):
-    """Error class for representing failure to parse a datetime string."""
-    def __str__(self):
-        try:
-            return self.args[0] % self.args[1:]
-        except (TypeError, IndexError):
-            return super(ParserError, self).__str__()
-
-        def __repr__(self):
-            return "%s(%s)" % (self.__class__.__name__, str(self))
-
-
-class UnknownTimezoneWarning(RuntimeWarning):
-    """Raised when the parser finds a timezone it cannot parse into a tzinfo"""
-# vim:ts=4:sw=4:et

+ 0 - 411
venv/lib/python3.8/site-packages/dateutil/parser/isoparser.py

@@ -1,411 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-This module offers a parser for ISO-8601 strings
-
-It is intended to support all valid date, time and datetime formats per the
-ISO-8601 specification.
-
-..versionadded:: 2.7.0
-"""
-from datetime import datetime, timedelta, time, date
-import calendar
-from dateutil import tz
-
-from functools import wraps
-
-import re
-import six
-
-__all__ = ["isoparse", "isoparser"]
-
-
-def _takes_ascii(f):
-    @wraps(f)
-    def func(self, str_in, *args, **kwargs):
-        # If it's a stream, read the whole thing
-        str_in = getattr(str_in, 'read', lambda: str_in)()
-
-        # If it's unicode, turn it into bytes, since ISO-8601 only covers ASCII
-        if isinstance(str_in, six.text_type):
-            # ASCII is the same in UTF-8
-            try:
-                str_in = str_in.encode('ascii')
-            except UnicodeEncodeError as e:
-                msg = 'ISO-8601 strings should contain only ASCII characters'
-                six.raise_from(ValueError(msg), e)
-
-        return f(self, str_in, *args, **kwargs)
-
-    return func
-
-
-class isoparser(object):
-    def __init__(self, sep=None):
-        """
-        :param sep:
-            A single character that separates date and time portions. If
-            ``None``, the parser will accept any single character.
-            For strict ISO-8601 adherence, pass ``'T'``.
-        """
-        if sep is not None:
-            if (len(sep) != 1 or ord(sep) >= 128 or sep in '0123456789'):
-                raise ValueError('Separator must be a single, non-numeric ' +
-                                 'ASCII character')
-
-            sep = sep.encode('ascii')
-
-        self._sep = sep
-
-    @_takes_ascii
-    def isoparse(self, dt_str):
-        """
-        Parse an ISO-8601 datetime string into a :class:`datetime.datetime`.
-
-        An ISO-8601 datetime string consists of a date portion, followed
-        optionally by a time portion - the date and time portions are separated
-        by a single character separator, which is ``T`` in the official
-        standard. Incomplete date formats (such as ``YYYY-MM``) may *not* be
-        combined with a time portion.
-
-        Supported date formats are:
-
-        Common:
-
-        - ``YYYY``
-        - ``YYYY-MM`` or ``YYYYMM``
-        - ``YYYY-MM-DD`` or ``YYYYMMDD``
-
-        Uncommon:
-
-        - ``YYYY-Www`` or ``YYYYWww`` - ISO week (day defaults to 0)
-        - ``YYYY-Www-D`` or ``YYYYWwwD`` - ISO week and day
-
-        The ISO week and day numbering follows the same logic as
-        :func:`datetime.date.isocalendar`.
-
-        Supported time formats are:
-
-        - ``hh``
-        - ``hh:mm`` or ``hhmm``
-        - ``hh:mm:ss`` or ``hhmmss``
-        - ``hh:mm:ss.ssssss`` (Up to 6 sub-second digits)
-
-        Midnight is a special case for `hh`, as the standard supports both
-        00:00 and 24:00 as a representation. The decimal separator can be
-        either a dot or a comma.
-
-
-        .. caution::
-
-            Support for fractional components other than seconds is part of the
-            ISO-8601 standard, but is not currently implemented in this parser.
-
-        Supported time zone offset formats are:
-
-        - `Z` (UTC)
-        - `±HH:MM`
-        - `±HHMM`
-        - `±HH`
-
-        Offsets will be represented as :class:`dateutil.tz.tzoffset` objects,
-        with the exception of UTC, which will be represented as
-        :class:`dateutil.tz.tzutc`. Time zone offsets equivalent to UTC (such
-        as `+00:00`) will also be represented as :class:`dateutil.tz.tzutc`.
-
-        :param dt_str:
-            A string or stream containing only an ISO-8601 datetime string
-
-        :return:
-            Returns a :class:`datetime.datetime` representing the string.
-            Unspecified components default to their lowest value.
-
-        .. warning::
-
-            As of version 2.7.0, the strictness of the parser should not be
-            considered a stable part of the contract. Any valid ISO-8601 string
-            that parses correctly with the default settings will continue to
-            parse correctly in future versions, but invalid strings that
-            currently fail (e.g. ``2017-01-01T00:00+00:00:00``) are not
-            guaranteed to continue failing in future versions if they encode
-            a valid date.
-
-        .. versionadded:: 2.7.0
-        """
-        components, pos = self._parse_isodate(dt_str)
-
-        if len(dt_str) > pos:
-            if self._sep is None or dt_str[pos:pos + 1] == self._sep:
-                components += self._parse_isotime(dt_str[pos + 1:])
-            else:
-                raise ValueError('String contains unknown ISO components')
-
-        if len(components) > 3 and components[3] == 24:
-            components[3] = 0
-            return datetime(*components) + timedelta(days=1)
-
-        return datetime(*components)
-
-    @_takes_ascii
-    def parse_isodate(self, datestr):
-        """
-        Parse the date portion of an ISO string.
-
-        :param datestr:
-            The string portion of an ISO string, without a separator
-
-        :return:
-            Returns a :class:`datetime.date` object
-        """
-        components, pos = self._parse_isodate(datestr)
-        if pos < len(datestr):
-            raise ValueError('String contains unknown ISO ' +
-                             'components: {}'.format(datestr))
-        return date(*components)
-
-    @_takes_ascii
-    def parse_isotime(self, timestr):
-        """
-        Parse the time portion of an ISO string.
-
-        :param timestr:
-            The time portion of an ISO string, without a separator
-
-        :return:
-            Returns a :class:`datetime.time` object
-        """
-        components = self._parse_isotime(timestr)
-        if components[0] == 24:
-            components[0] = 0
-        return time(*components)
-
-    @_takes_ascii
-    def parse_tzstr(self, tzstr, zero_as_utc=True):
-        """
-        Parse a valid ISO time zone string.
-
-        See :func:`isoparser.isoparse` for details on supported formats.
-
-        :param tzstr:
-            A string representing an ISO time zone offset
-
-        :param zero_as_utc:
-            Whether to return :class:`dateutil.tz.tzutc` for zero-offset zones
-
-        :return:
-            Returns :class:`dateutil.tz.tzoffset` for offsets and
-            :class:`dateutil.tz.tzutc` for ``Z`` and (if ``zero_as_utc`` is
-            specified) offsets equivalent to UTC.
-        """
-        return self._parse_tzstr(tzstr, zero_as_utc=zero_as_utc)
-
-    # Constants
-    _DATE_SEP = b'-'
-    _TIME_SEP = b':'
-    _FRACTION_REGEX = re.compile(b'[\\.,]([0-9]+)')
-
-    def _parse_isodate(self, dt_str):
-        try:
-            return self._parse_isodate_common(dt_str)
-        except ValueError:
-            return self._parse_isodate_uncommon(dt_str)
-
-    def _parse_isodate_common(self, dt_str):
-        len_str = len(dt_str)
-        components = [1, 1, 1]
-
-        if len_str < 4:
-            raise ValueError('ISO string too short')
-
-        # Year
-        components[0] = int(dt_str[0:4])
-        pos = 4
-        if pos >= len_str:
-            return components, pos
-
-        has_sep = dt_str[pos:pos + 1] == self._DATE_SEP
-        if has_sep:
-            pos += 1
-
-        # Month
-        if len_str - pos < 2:
-            raise ValueError('Invalid common month')
-
-        components[1] = int(dt_str[pos:pos + 2])
-        pos += 2
-
-        if pos >= len_str:
-            if has_sep:
-                return components, pos
-            else:
-                raise ValueError('Invalid ISO format')
-
-        if has_sep:
-            if dt_str[pos:pos + 1] != self._DATE_SEP:
-                raise ValueError('Invalid separator in ISO string')
-            pos += 1
-
-        # Day
-        if len_str - pos < 2:
-            raise ValueError('Invalid common day')
-        components[2] = int(dt_str[pos:pos + 2])
-        return components, pos + 2
-
-    def _parse_isodate_uncommon(self, dt_str):
-        if len(dt_str) < 4:
-            raise ValueError('ISO string too short')
-
-        # All ISO formats start with the year
-        year = int(dt_str[0:4])
-
-        has_sep = dt_str[4:5] == self._DATE_SEP
-
-        pos = 4 + has_sep       # Skip '-' if it's there
-        if dt_str[pos:pos + 1] == b'W':
-            # YYYY-?Www-?D?
-            pos += 1
-            weekno = int(dt_str[pos:pos + 2])
-            pos += 2
-
-            dayno = 1
-            if len(dt_str) > pos:
-                if (dt_str[pos:pos + 1] == self._DATE_SEP) != has_sep:
-                    raise ValueError('Inconsistent use of dash separator')
-
-                pos += has_sep
-
-                dayno = int(dt_str[pos:pos + 1])
-                pos += 1
-
-            base_date = self._calculate_weekdate(year, weekno, dayno)
-        else:
-            # YYYYDDD or YYYY-DDD
-            if len(dt_str) - pos < 3:
-                raise ValueError('Invalid ordinal day')
-
-            ordinal_day = int(dt_str[pos:pos + 3])
-            pos += 3
-
-            if ordinal_day < 1 or ordinal_day > (365 + calendar.isleap(year)):
-                raise ValueError('Invalid ordinal day' +
-                                 ' {} for year {}'.format(ordinal_day, year))
-
-            base_date = date(year, 1, 1) + timedelta(days=ordinal_day - 1)
-
-        components = [base_date.year, base_date.month, base_date.day]
-        return components, pos
-
-    def _calculate_weekdate(self, year, week, day):
-        """
-        Calculate the day of corresponding to the ISO year-week-day calendar.
-
-        This function is effectively the inverse of
-        :func:`datetime.date.isocalendar`.
-
-        :param year:
-            The year in the ISO calendar
-
-        :param week:
-            The week in the ISO calendar - range is [1, 53]
-
-        :param day:
-            The day in the ISO calendar - range is [1 (MON), 7 (SUN)]
-
-        :return:
-            Returns a :class:`datetime.date`
-        """
-        if not 0 < week < 54:
-            raise ValueError('Invalid week: {}'.format(week))
-
-        if not 0 < day < 8:     # Range is 1-7
-            raise ValueError('Invalid weekday: {}'.format(day))
-
-        # Get week 1 for the specific year:
-        jan_4 = date(year, 1, 4)   # Week 1 always has January 4th in it
-        week_1 = jan_4 - timedelta(days=jan_4.isocalendar()[2] - 1)
-
-        # Now add the specific number of weeks and days to get what we want
-        week_offset = (week - 1) * 7 + (day - 1)
-        return week_1 + timedelta(days=week_offset)
-
-    def _parse_isotime(self, timestr):
-        len_str = len(timestr)
-        components = [0, 0, 0, 0, None]
-        pos = 0
-        comp = -1
-
-        if len(timestr) < 2:
-            raise ValueError('ISO time too short')
-
-        has_sep = len_str >= 3 and timestr[2:3] == self._TIME_SEP
-
-        while pos < len_str and comp < 5:
-            comp += 1
-
-            if timestr[pos:pos + 1] in b'-+Zz':
-                # Detect time zone boundary
-                components[-1] = self._parse_tzstr(timestr[pos:])
-                pos = len_str
-                break
-
-            if comp < 3:
-                # Hour, minute, second
-                components[comp] = int(timestr[pos:pos + 2])
-                pos += 2
-                if (has_sep and pos < len_str and
-                        timestr[pos:pos + 1] == self._TIME_SEP):
-                    pos += 1
-
-            if comp == 3:
-                # Fraction of a second
-                frac = self._FRACTION_REGEX.match(timestr[pos:])
-                if not frac:
-                    continue
-
-                us_str = frac.group(1)[:6]  # Truncate to microseconds
-                components[comp] = int(us_str) * 10**(6 - len(us_str))
-                pos += len(frac.group())
-
-        if pos < len_str:
-            raise ValueError('Unused components in ISO string')
-
-        if components[0] == 24:
-            # Standard supports 00:00 and 24:00 as representations of midnight
-            if any(component != 0 for component in components[1:4]):
-                raise ValueError('Hour may only be 24 at 24:00:00.000')
-
-        return components
-
-    def _parse_tzstr(self, tzstr, zero_as_utc=True):
-        if tzstr == b'Z' or tzstr == b'z':
-            return tz.UTC
-
-        if len(tzstr) not in {3, 5, 6}:
-            raise ValueError('Time zone offset must be 1, 3, 5 or 6 characters')
-
-        if tzstr[0:1] == b'-':
-            mult = -1
-        elif tzstr[0:1] == b'+':
-            mult = 1
-        else:
-            raise ValueError('Time zone offset requires sign')
-
-        hours = int(tzstr[1:3])
-        if len(tzstr) == 3:
-            minutes = 0
-        else:
-            minutes = int(tzstr[(4 if tzstr[3:4] == self._TIME_SEP else 3):])
-
-        if zero_as_utc and hours == 0 and minutes == 0:
-            return tz.UTC
-        else:
-            if minutes > 59:
-                raise ValueError('Invalid minutes in time zone offset')
-
-            if hours > 23:
-                raise ValueError('Invalid hours in time zone offset')
-
-            return tz.tzoffset(None, mult * (hours * 60 + minutes) * 60)
-
-
-DEFAULT_ISOPARSER = isoparser()
-isoparse = DEFAULT_ISOPARSER.isoparse

+ 0 - 599
venv/lib/python3.8/site-packages/dateutil/relativedelta.py

@@ -1,599 +0,0 @@
-# -*- coding: utf-8 -*-
-import datetime
-import calendar
-
-import operator
-from math import copysign
-
-from six import integer_types
-from warnings import warn
-
-from ._common import weekday
-
-MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7))
-
-__all__ = ["relativedelta", "MO", "TU", "WE", "TH", "FR", "SA", "SU"]
-
-
-class relativedelta(object):
-    """
-    The relativedelta type is designed to be applied to an existing datetime and
-    can replace specific components of that datetime, or represents an interval
-    of time.
-
-    It is based on the specification of the excellent work done by M.-A. Lemburg
-    in his
-    `mx.DateTime <https://www.egenix.com/products/python/mxBase/mxDateTime/>`_ extension.
-    However, notice that this type does *NOT* implement the same algorithm as
-    his work. Do *NOT* expect it to behave like mx.DateTime's counterpart.
-
-    There are two different ways to build a relativedelta instance. The
-    first one is passing it two date/datetime classes::
-
-        relativedelta(datetime1, datetime2)
-
-    The second one is passing it any number of the following keyword arguments::
-
-        relativedelta(arg1=x,arg2=y,arg3=z...)
-
-        year, month, day, hour, minute, second, microsecond:
-            Absolute information (argument is singular); adding or subtracting a
-            relativedelta with absolute information does not perform an arithmetic
-            operation, but rather REPLACES the corresponding value in the
-            original datetime with the value(s) in relativedelta.
-
-        years, months, weeks, days, hours, minutes, seconds, microseconds:
-            Relative information, may be negative (argument is plural); adding
-            or subtracting a relativedelta with relative information performs
-            the corresponding arithmetic operation on the original datetime value
-            with the information in the relativedelta.
-
-        weekday: 
-            One of the weekday instances (MO, TU, etc) available in the
-            relativedelta module. These instances may receive a parameter N,
-            specifying the Nth weekday, which could be positive or negative
-            (like MO(+1) or MO(-2)). Not specifying it is the same as specifying
-            +1. You can also use an integer, where 0=MO. This argument is always
-            relative e.g. if the calculated date is already Monday, using MO(1)
-            or MO(-1) won't change the day. To effectively make it absolute, use
-            it in combination with the day argument (e.g. day=1, MO(1) for first
-            Monday of the month).
-
-        leapdays:
-            Will add given days to the date found, if year is a leap
-            year, and the date found is post 28 of february.
-
-        yearday, nlyearday:
-            Set the yearday or the non-leap year day (jump leap days).
-            These are converted to day/month/leapdays information.
-
-    There are relative and absolute forms of the keyword
-    arguments. The plural is relative, and the singular is
-    absolute. For each argument in the order below, the absolute form
-    is applied first (by setting each attribute to that value) and
-    then the relative form (by adding the value to the attribute).
-
-    The order of attributes considered when this relativedelta is
-    added to a datetime is:
-
-    1. Year
-    2. Month
-    3. Day
-    4. Hours
-    5. Minutes
-    6. Seconds
-    7. Microseconds
-
-    Finally, weekday is applied, using the rule described above.
-
-    For example
-
-    >>> from datetime import datetime
-    >>> from dateutil.relativedelta import relativedelta, MO
-    >>> dt = datetime(2018, 4, 9, 13, 37, 0)
-    >>> delta = relativedelta(hours=25, day=1, weekday=MO(1))
-    >>> dt + delta
-    datetime.datetime(2018, 4, 2, 14, 37)
-
-    First, the day is set to 1 (the first of the month), then 25 hours
-    are added, to get to the 2nd day and 14th hour, finally the
-    weekday is applied, but since the 2nd is already a Monday there is
-    no effect.
-
-    """
-
-    def __init__(self, dt1=None, dt2=None,
-                 years=0, months=0, days=0, leapdays=0, weeks=0,
-                 hours=0, minutes=0, seconds=0, microseconds=0,
-                 year=None, month=None, day=None, weekday=None,
-                 yearday=None, nlyearday=None,
-                 hour=None, minute=None, second=None, microsecond=None):
-
-        if dt1 and dt2:
-            # datetime is a subclass of date. So both must be date
-            if not (isinstance(dt1, datetime.date) and
-                    isinstance(dt2, datetime.date)):
-                raise TypeError("relativedelta only diffs datetime/date")
-
-            # We allow two dates, or two datetimes, so we coerce them to be
-            # of the same type
-            if (isinstance(dt1, datetime.datetime) !=
-                    isinstance(dt2, datetime.datetime)):
-                if not isinstance(dt1, datetime.datetime):
-                    dt1 = datetime.datetime.fromordinal(dt1.toordinal())
-                elif not isinstance(dt2, datetime.datetime):
-                    dt2 = datetime.datetime.fromordinal(dt2.toordinal())
-
-            self.years = 0
-            self.months = 0
-            self.days = 0
-            self.leapdays = 0
-            self.hours = 0
-            self.minutes = 0
-            self.seconds = 0
-            self.microseconds = 0
-            self.year = None
-            self.month = None
-            self.day = None
-            self.weekday = None
-            self.hour = None
-            self.minute = None
-            self.second = None
-            self.microsecond = None
-            self._has_time = 0
-
-            # Get year / month delta between the two
-            months = (dt1.year - dt2.year) * 12 + (dt1.month - dt2.month)
-            self._set_months(months)
-
-            # Remove the year/month delta so the timedelta is just well-defined
-            # time units (seconds, days and microseconds)
-            dtm = self.__radd__(dt2)
-
-            # If we've overshot our target, make an adjustment
-            if dt1 < dt2:
-                compare = operator.gt
-                increment = 1
-            else:
-                compare = operator.lt
-                increment = -1
-
-            while compare(dt1, dtm):
-                months += increment
-                self._set_months(months)
-                dtm = self.__radd__(dt2)
-
-            # Get the timedelta between the "months-adjusted" date and dt1
-            delta = dt1 - dtm
-            self.seconds = delta.seconds + delta.days * 86400
-            self.microseconds = delta.microseconds
-        else:
-            # Check for non-integer values in integer-only quantities
-            if any(x is not None and x != int(x) for x in (years, months)):
-                raise ValueError("Non-integer years and months are "
-                                 "ambiguous and not currently supported.")
-
-            # Relative information
-            self.years = int(years)
-            self.months = int(months)
-            self.days = days + weeks * 7
-            self.leapdays = leapdays
-            self.hours = hours
-            self.minutes = minutes
-            self.seconds = seconds
-            self.microseconds = microseconds
-
-            # Absolute information
-            self.year = year
-            self.month = month
-            self.day = day
-            self.hour = hour
-            self.minute = minute
-            self.second = second
-            self.microsecond = microsecond
-
-            if any(x is not None and int(x) != x
-                   for x in (year, month, day, hour,
-                             minute, second, microsecond)):
-                # For now we'll deprecate floats - later it'll be an error.
-                warn("Non-integer value passed as absolute information. " +
-                     "This is not a well-defined condition and will raise " +
-                     "errors in future versions.", DeprecationWarning)
-
-            if isinstance(weekday, integer_types):
-                self.weekday = weekdays[weekday]
-            else:
-                self.weekday = weekday
-
-            yday = 0
-            if nlyearday:
-                yday = nlyearday
-            elif yearday:
-                yday = yearday
-                if yearday > 59:
-                    self.leapdays = -1
-            if yday:
-                ydayidx = [31, 59, 90, 120, 151, 181, 212,
-                           243, 273, 304, 334, 366]
-                for idx, ydays in enumerate(ydayidx):
-                    if yday <= ydays:
-                        self.month = idx+1
-                        if idx == 0:
-                            self.day = yday
-                        else:
-                            self.day = yday-ydayidx[idx-1]
-                        break
-                else:
-                    raise ValueError("invalid year day (%d)" % yday)
-
-        self._fix()
-
-    def _fix(self):
-        if abs(self.microseconds) > 999999:
-            s = _sign(self.microseconds)
-            div, mod = divmod(self.microseconds * s, 1000000)
-            self.microseconds = mod * s
-            self.seconds += div * s
-        if abs(self.seconds) > 59:
-            s = _sign(self.seconds)
-            div, mod = divmod(self.seconds * s, 60)
-            self.seconds = mod * s
-            self.minutes += div * s
-        if abs(self.minutes) > 59:
-            s = _sign(self.minutes)
-            div, mod = divmod(self.minutes * s, 60)
-            self.minutes = mod * s
-            self.hours += div * s
-        if abs(self.hours) > 23:
-            s = _sign(self.hours)
-            div, mod = divmod(self.hours * s, 24)
-            self.hours = mod * s
-            self.days += div * s
-        if abs(self.months) > 11:
-            s = _sign(self.months)
-            div, mod = divmod(self.months * s, 12)
-            self.months = mod * s
-            self.years += div * s
-        if (self.hours or self.minutes or self.seconds or self.microseconds
-                or self.hour is not None or self.minute is not None or
-                self.second is not None or self.microsecond is not None):
-            self._has_time = 1
-        else:
-            self._has_time = 0
-
-    @property
-    def weeks(self):
-        return int(self.days / 7.0)
-
-    @weeks.setter
-    def weeks(self, value):
-        self.days = self.days - (self.weeks * 7) + value * 7
-
-    def _set_months(self, months):
-        self.months = months
-        if abs(self.months) > 11:
-            s = _sign(self.months)
-            div, mod = divmod(self.months * s, 12)
-            self.months = mod * s
-            self.years = div * s
-        else:
-            self.years = 0
-
-    def normalized(self):
-        """
-        Return a version of this object represented entirely using integer
-        values for the relative attributes.
-
-        >>> relativedelta(days=1.5, hours=2).normalized()
-        relativedelta(days=+1, hours=+14)
-
-        :return:
-            Returns a :class:`dateutil.relativedelta.relativedelta` object.
-        """
-        # Cascade remainders down (rounding each to roughly nearest microsecond)
-        days = int(self.days)
-
-        hours_f = round(self.hours + 24 * (self.days - days), 11)
-        hours = int(hours_f)
-
-        minutes_f = round(self.minutes + 60 * (hours_f - hours), 10)
-        minutes = int(minutes_f)
-
-        seconds_f = round(self.seconds + 60 * (minutes_f - minutes), 8)
-        seconds = int(seconds_f)
-
-        microseconds = round(self.microseconds + 1e6 * (seconds_f - seconds))
-
-        # Constructor carries overflow back up with call to _fix()
-        return self.__class__(years=self.years, months=self.months,
-                              days=days, hours=hours, minutes=minutes,
-                              seconds=seconds, microseconds=microseconds,
-                              leapdays=self.leapdays, year=self.year,
-                              month=self.month, day=self.day,
-                              weekday=self.weekday, hour=self.hour,
-                              minute=self.minute, second=self.second,
-                              microsecond=self.microsecond)
-
-    def __add__(self, other):
-        if isinstance(other, relativedelta):
-            return self.__class__(years=other.years + self.years,
-                                 months=other.months + self.months,
-                                 days=other.days + self.days,
-                                 hours=other.hours + self.hours,
-                                 minutes=other.minutes + self.minutes,
-                                 seconds=other.seconds + self.seconds,
-                                 microseconds=(other.microseconds +
-                                               self.microseconds),
-                                 leapdays=other.leapdays or self.leapdays,
-                                 year=(other.year if other.year is not None
-                                       else self.year),
-                                 month=(other.month if other.month is not None
-                                        else self.month),
-                                 day=(other.day if other.day is not None
-                                      else self.day),
-                                 weekday=(other.weekday if other.weekday is not None
-                                          else self.weekday),
-                                 hour=(other.hour if other.hour is not None
-                                       else self.hour),
-                                 minute=(other.minute if other.minute is not None
-                                         else self.minute),
-                                 second=(other.second if other.second is not None
-                                         else self.second),
-                                 microsecond=(other.microsecond if other.microsecond
-                                              is not None else
-                                              self.microsecond))
-        if isinstance(other, datetime.timedelta):
-            return self.__class__(years=self.years,
-                                  months=self.months,
-                                  days=self.days + other.days,
-                                  hours=self.hours,
-                                  minutes=self.minutes,
-                                  seconds=self.seconds + other.seconds,
-                                  microseconds=self.microseconds + other.microseconds,
-                                  leapdays=self.leapdays,
-                                  year=self.year,
-                                  month=self.month,
-                                  day=self.day,
-                                  weekday=self.weekday,
-                                  hour=self.hour,
-                                  minute=self.minute,
-                                  second=self.second,
-                                  microsecond=self.microsecond)
-        if not isinstance(other, datetime.date):
-            return NotImplemented
-        elif self._has_time and not isinstance(other, datetime.datetime):
-            other = datetime.datetime.fromordinal(other.toordinal())
-        year = (self.year or other.year)+self.years
-        month = self.month or other.month
-        if self.months:
-            assert 1 <= abs(self.months) <= 12
-            month += self.months
-            if month > 12:
-                year += 1
-                month -= 12
-            elif month < 1:
-                year -= 1
-                month += 12
-        day = min(calendar.monthrange(year, month)[1],
-                  self.day or other.day)
-        repl = {"year": year, "month": month, "day": day}
-        for attr in ["hour", "minute", "second", "microsecond"]:
-            value = getattr(self, attr)
-            if value is not None:
-                repl[attr] = value
-        days = self.days
-        if self.leapdays and month > 2 and calendar.isleap(year):
-            days += self.leapdays
-        ret = (other.replace(**repl)
-               + datetime.timedelta(days=days,
-                                    hours=self.hours,
-                                    minutes=self.minutes,
-                                    seconds=self.seconds,
-                                    microseconds=self.microseconds))
-        if self.weekday:
-            weekday, nth = self.weekday.weekday, self.weekday.n or 1
-            jumpdays = (abs(nth) - 1) * 7
-            if nth > 0:
-                jumpdays += (7 - ret.weekday() + weekday) % 7
-            else:
-                jumpdays += (ret.weekday() - weekday) % 7
-                jumpdays *= -1
-            ret += datetime.timedelta(days=jumpdays)
-        return ret
-
-    def __radd__(self, other):
-        return self.__add__(other)
-
-    def __rsub__(self, other):
-        return self.__neg__().__radd__(other)
-
-    def __sub__(self, other):
-        if not isinstance(other, relativedelta):
-            return NotImplemented   # In case the other object defines __rsub__
-        return self.__class__(years=self.years - other.years,
-                             months=self.months - other.months,
-                             days=self.days - other.days,
-                             hours=self.hours - other.hours,
-                             minutes=self.minutes - other.minutes,
-                             seconds=self.seconds - other.seconds,
-                             microseconds=self.microseconds - other.microseconds,
-                             leapdays=self.leapdays or other.leapdays,
-                             year=(self.year if self.year is not None
-                                   else other.year),
-                             month=(self.month if self.month is not None else
-                                    other.month),
-                             day=(self.day if self.day is not None else
-                                  other.day),
-                             weekday=(self.weekday if self.weekday is not None else
-                                      other.weekday),
-                             hour=(self.hour if self.hour is not None else
-                                   other.hour),
-                             minute=(self.minute if self.minute is not None else
-                                     other.minute),
-                             second=(self.second if self.second is not None else
-                                     other.second),
-                             microsecond=(self.microsecond if self.microsecond
-                                          is not None else
-                                          other.microsecond))
-
-    def __abs__(self):
-        return self.__class__(years=abs(self.years),
-                              months=abs(self.months),
-                              days=abs(self.days),
-                              hours=abs(self.hours),
-                              minutes=abs(self.minutes),
-                              seconds=abs(self.seconds),
-                              microseconds=abs(self.microseconds),
-                              leapdays=self.leapdays,
-                              year=self.year,
-                              month=self.month,
-                              day=self.day,
-                              weekday=self.weekday,
-                              hour=self.hour,
-                              minute=self.minute,
-                              second=self.second,
-                              microsecond=self.microsecond)
-
-    def __neg__(self):
-        return self.__class__(years=-self.years,
-                             months=-self.months,
-                             days=-self.days,
-                             hours=-self.hours,
-                             minutes=-self.minutes,
-                             seconds=-self.seconds,
-                             microseconds=-self.microseconds,
-                             leapdays=self.leapdays,
-                             year=self.year,
-                             month=self.month,
-                             day=self.day,
-                             weekday=self.weekday,
-                             hour=self.hour,
-                             minute=self.minute,
-                             second=self.second,
-                             microsecond=self.microsecond)
-
-    def __bool__(self):
-        return not (not self.years and
-                    not self.months and
-                    not self.days and
-                    not self.hours and
-                    not self.minutes and
-                    not self.seconds and
-                    not self.microseconds and
-                    not self.leapdays and
-                    self.year is None and
-                    self.month is None and
-                    self.day is None and
-                    self.weekday is None and
-                    self.hour is None and
-                    self.minute is None and
-                    self.second is None and
-                    self.microsecond is None)
-    # Compatibility with Python 2.x
-    __nonzero__ = __bool__
-
-    def __mul__(self, other):
-        try:
-            f = float(other)
-        except TypeError:
-            return NotImplemented
-
-        return self.__class__(years=int(self.years * f),
-                             months=int(self.months * f),
-                             days=int(self.days * f),
-                             hours=int(self.hours * f),
-                             minutes=int(self.minutes * f),
-                             seconds=int(self.seconds * f),
-                             microseconds=int(self.microseconds * f),
-                             leapdays=self.leapdays,
-                             year=self.year,
-                             month=self.month,
-                             day=self.day,
-                             weekday=self.weekday,
-                             hour=self.hour,
-                             minute=self.minute,
-                             second=self.second,
-                             microsecond=self.microsecond)
-
-    __rmul__ = __mul__
-
-    def __eq__(self, other):
-        if not isinstance(other, relativedelta):
-            return NotImplemented
-        if self.weekday or other.weekday:
-            if not self.weekday or not other.weekday:
-                return False
-            if self.weekday.weekday != other.weekday.weekday:
-                return False
-            n1, n2 = self.weekday.n, other.weekday.n
-            if n1 != n2 and not ((not n1 or n1 == 1) and (not n2 or n2 == 1)):
-                return False
-        return (self.years == other.years and
-                self.months == other.months and
-                self.days == other.days and
-                self.hours == other.hours and
-                self.minutes == other.minutes and
-                self.seconds == other.seconds and
-                self.microseconds == other.microseconds and
-                self.leapdays == other.leapdays and
-                self.year == other.year and
-                self.month == other.month and
-                self.day == other.day and
-                self.hour == other.hour and
-                self.minute == other.minute and
-                self.second == other.second and
-                self.microsecond == other.microsecond)
-
-    def __hash__(self):
-        return hash((
-            self.weekday,
-            self.years,
-            self.months,
-            self.days,
-            self.hours,
-            self.minutes,
-            self.seconds,
-            self.microseconds,
-            self.leapdays,
-            self.year,
-            self.month,
-            self.day,
-            self.hour,
-            self.minute,
-            self.second,
-            self.microsecond,
-        ))
-
-    def __ne__(self, other):
-        return not self.__eq__(other)
-
-    def __div__(self, other):
-        try:
-            reciprocal = 1 / float(other)
-        except TypeError:
-            return NotImplemented
-
-        return self.__mul__(reciprocal)
-
-    __truediv__ = __div__
-
-    def __repr__(self):
-        l = []
-        for attr in ["years", "months", "days", "leapdays",
-                     "hours", "minutes", "seconds", "microseconds"]:
-            value = getattr(self, attr)
-            if value:
-                l.append("{attr}={value:+g}".format(attr=attr, value=value))
-        for attr in ["year", "month", "day", "weekday",
-                     "hour", "minute", "second", "microsecond"]:
-            value = getattr(self, attr)
-            if value is not None:
-                l.append("{attr}={value}".format(attr=attr, value=repr(value)))
-        return "{classname}({attrs})".format(classname=self.__class__.__name__,
-                                             attrs=", ".join(l))
-
-
-def _sign(x):
-    return int(copysign(1, x))
-
-# vim:ts=4:sw=4:et

+ 0 - 1735
venv/lib/python3.8/site-packages/dateutil/rrule.py

@@ -1,1735 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-The rrule module offers a small, complete, and very fast, implementation of
-the recurrence rules documented in the
-`iCalendar RFC <https://tools.ietf.org/html/rfc5545>`_,
-including support for caching of results.
-"""
-import itertools
-import datetime
-import calendar
-import re
-import sys
-
-try:
-    from math import gcd
-except ImportError:
-    from fractions import gcd
-
-from six import advance_iterator, integer_types
-from six.moves import _thread, range
-import heapq
-
-from ._common import weekday as weekdaybase
-
-# For warning about deprecation of until and count
-from warnings import warn
-
-__all__ = ["rrule", "rruleset", "rrulestr",
-           "YEARLY", "MONTHLY", "WEEKLY", "DAILY",
-           "HOURLY", "MINUTELY", "SECONDLY",
-           "MO", "TU", "WE", "TH", "FR", "SA", "SU"]
-
-# Every mask is 7 days longer to handle cross-year weekly periods.
-M366MASK = tuple([1]*31+[2]*29+[3]*31+[4]*30+[5]*31+[6]*30 +
-                 [7]*31+[8]*31+[9]*30+[10]*31+[11]*30+[12]*31+[1]*7)
-M365MASK = list(M366MASK)
-M29, M30, M31 = list(range(1, 30)), list(range(1, 31)), list(range(1, 32))
-MDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7])
-MDAY365MASK = list(MDAY366MASK)
-M29, M30, M31 = list(range(-29, 0)), list(range(-30, 0)), list(range(-31, 0))
-NMDAY366MASK = tuple(M31+M29+M31+M30+M31+M30+M31+M31+M30+M31+M30+M31+M31[:7])
-NMDAY365MASK = list(NMDAY366MASK)
-M366RANGE = (0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366)
-M365RANGE = (0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365)
-WDAYMASK = [0, 1, 2, 3, 4, 5, 6]*55
-del M29, M30, M31, M365MASK[59], MDAY365MASK[59], NMDAY365MASK[31]
-MDAY365MASK = tuple(MDAY365MASK)
-M365MASK = tuple(M365MASK)
-
-FREQNAMES = ['YEARLY', 'MONTHLY', 'WEEKLY', 'DAILY', 'HOURLY', 'MINUTELY', 'SECONDLY']
-
-(YEARLY,
- MONTHLY,
- WEEKLY,
- DAILY,
- HOURLY,
- MINUTELY,
- SECONDLY) = list(range(7))
-
-# Imported on demand.
-easter = None
-parser = None
-
-
-class weekday(weekdaybase):
-    """
-    This version of weekday does not allow n = 0.
-    """
-    def __init__(self, wkday, n=None):
-        if n == 0:
-            raise ValueError("Can't create weekday with n==0")
-
-        super(weekday, self).__init__(wkday, n)
-
-
-MO, TU, WE, TH, FR, SA, SU = weekdays = tuple(weekday(x) for x in range(7))
-
-
-def _invalidates_cache(f):
-    """
-    Decorator for rruleset methods which may invalidate the
-    cached length.
-    """
-    def inner_func(self, *args, **kwargs):
-        rv = f(self, *args, **kwargs)
-        self._invalidate_cache()
-        return rv
-
-    return inner_func
-
-
-class rrulebase(object):
-    def __init__(self, cache=False):
-        if cache:
-            self._cache = []
-            self._cache_lock = _thread.allocate_lock()
-            self._invalidate_cache()
-        else:
-            self._cache = None
-            self._cache_complete = False
-            self._len = None
-
-    def __iter__(self):
-        if self._cache_complete:
-            return iter(self._cache)
-        elif self._cache is None:
-            return self._iter()
-        else:
-            return self._iter_cached()
-
-    def _invalidate_cache(self):
-        if self._cache is not None:
-            self._cache = []
-            self._cache_complete = False
-            self._cache_gen = self._iter()
-
-            if self._cache_lock.locked():
-                self._cache_lock.release()
-
-        self._len = None
-
-    def _iter_cached(self):
-        i = 0
-        gen = self._cache_gen
-        cache = self._cache
-        acquire = self._cache_lock.acquire
-        release = self._cache_lock.release
-        while gen:
-            if i == len(cache):
-                acquire()
-                if self._cache_complete:
-                    break
-                try:
-                    for j in range(10):
-                        cache.append(advance_iterator(gen))
-                except StopIteration:
-                    self._cache_gen = gen = None
-                    self._cache_complete = True
-                    break
-                release()
-            yield cache[i]
-            i += 1
-        while i < self._len:
-            yield cache[i]
-            i += 1
-
-    def __getitem__(self, item):
-        if self._cache_complete:
-            return self._cache[item]
-        elif isinstance(item, slice):
-            if item.step and item.step < 0:
-                return list(iter(self))[item]
-            else:
-                return list(itertools.islice(self,
-                                             item.start or 0,
-                                             item.stop or sys.maxsize,
-                                             item.step or 1))
-        elif item >= 0:
-            gen = iter(self)
-            try:
-                for i in range(item+1):
-                    res = advance_iterator(gen)
-            except StopIteration:
-                raise IndexError
-            return res
-        else:
-            return list(iter(self))[item]
-
-    def __contains__(self, item):
-        if self._cache_complete:
-            return item in self._cache
-        else:
-            for i in self:
-                if i == item:
-                    return True
-                elif i > item:
-                    return False
-        return False
-
-    # __len__() introduces a large performance penalty.
-    def count(self):
-        """ Returns the number of recurrences in this set. It will have go
-            trough the whole recurrence, if this hasn't been done before. """
-        if self._len is None:
-            for x in self:
-                pass
-        return self._len
-
-    def before(self, dt, inc=False):
-        """ Returns the last recurrence before the given datetime instance. The
-            inc keyword defines what happens if dt is an occurrence. With
-            inc=True, if dt itself is an occurrence, it will be returned. """
-        if self._cache_complete:
-            gen = self._cache
-        else:
-            gen = self
-        last = None
-        if inc:
-            for i in gen:
-                if i > dt:
-                    break
-                last = i
-        else:
-            for i in gen:
-                if i >= dt:
-                    break
-                last = i
-        return last
-
-    def after(self, dt, inc=False):
-        """ Returns the first recurrence after the given datetime instance. The
-            inc keyword defines what happens if dt is an occurrence. With
-            inc=True, if dt itself is an occurrence, it will be returned.  """
-        if self._cache_complete:
-            gen = self._cache
-        else:
-            gen = self
-        if inc:
-            for i in gen:
-                if i >= dt:
-                    return i
-        else:
-            for i in gen:
-                if i > dt:
-                    return i
-        return None
-
-    def xafter(self, dt, count=None, inc=False):
-        """
-        Generator which yields up to `count` recurrences after the given
-        datetime instance, equivalent to `after`.
-
-        :param dt:
-            The datetime at which to start generating recurrences.
-
-        :param count:
-            The maximum number of recurrences to generate. If `None` (default),
-            dates are generated until the recurrence rule is exhausted.
-
-        :param inc:
-            If `dt` is an instance of the rule and `inc` is `True`, it is
-            included in the output.
-
-        :yields: Yields a sequence of `datetime` objects.
-        """
-
-        if self._cache_complete:
-            gen = self._cache
-        else:
-            gen = self
-
-        # Select the comparison function
-        if inc:
-            comp = lambda dc, dtc: dc >= dtc
-        else:
-            comp = lambda dc, dtc: dc > dtc
-
-        # Generate dates
-        n = 0
-        for d in gen:
-            if comp(d, dt):
-                if count is not None:
-                    n += 1
-                    if n > count:
-                        break
-
-                yield d
-
-    def between(self, after, before, inc=False, count=1):
-        """ Returns all the occurrences of the rrule between after and before.
-        The inc keyword defines what happens if after and/or before are
-        themselves occurrences. With inc=True, they will be included in the
-        list, if they are found in the recurrence set. """
-        if self._cache_complete:
-            gen = self._cache
-        else:
-            gen = self
-        started = False
-        l = []
-        if inc:
-            for i in gen:
-                if i > before:
-                    break
-                elif not started:
-                    if i >= after:
-                        started = True
-                        l.append(i)
-                else:
-                    l.append(i)
-        else:
-            for i in gen:
-                if i >= before:
-                    break
-                elif not started:
-                    if i > after:
-                        started = True
-                        l.append(i)
-                else:
-                    l.append(i)
-        return l
-
-
-class rrule(rrulebase):
-    """
-    That's the base of the rrule operation. It accepts all the keywords
-    defined in the RFC as its constructor parameters (except byday,
-    which was renamed to byweekday) and more. The constructor prototype is::
-
-            rrule(freq)
-
-    Where freq must be one of YEARLY, MONTHLY, WEEKLY, DAILY, HOURLY, MINUTELY,
-    or SECONDLY.
-
-    .. note::
-        Per RFC section 3.3.10, recurrence instances falling on invalid dates
-        and times are ignored rather than coerced:
-
-            Recurrence rules may generate recurrence instances with an invalid
-            date (e.g., February 30) or nonexistent local time (e.g., 1:30 AM
-            on a day where the local time is moved forward by an hour at 1:00
-            AM).  Such recurrence instances MUST be ignored and MUST NOT be
-            counted as part of the recurrence set.
-
-        This can lead to possibly surprising behavior when, for example, the
-        start date occurs at the end of the month:
-
-        >>> from dateutil.rrule import rrule, MONTHLY
-        >>> from datetime import datetime
-        >>> start_date = datetime(2014, 12, 31)
-        >>> list(rrule(freq=MONTHLY, count=4, dtstart=start_date))
-        ... # doctest: +NORMALIZE_WHITESPACE
-        [datetime.datetime(2014, 12, 31, 0, 0),
-         datetime.datetime(2015, 1, 31, 0, 0),
-         datetime.datetime(2015, 3, 31, 0, 0),
-         datetime.datetime(2015, 5, 31, 0, 0)]
-
-    Additionally, it supports the following keyword arguments:
-
-    :param dtstart:
-        The recurrence start. Besides being the base for the recurrence,
-        missing parameters in the final recurrence instances will also be
-        extracted from this date. If not given, datetime.now() will be used
-        instead.
-    :param interval:
-        The interval between each freq iteration. For example, when using
-        YEARLY, an interval of 2 means once every two years, but with HOURLY,
-        it means once every two hours. The default interval is 1.
-    :param wkst:
-        The week start day. Must be one of the MO, TU, WE constants, or an
-        integer, specifying the first day of the week. This will affect
-        recurrences based on weekly periods. The default week start is got
-        from calendar.firstweekday(), and may be modified by
-        calendar.setfirstweekday().
-    :param count:
-        If given, this determines how many occurrences will be generated.
-
-        .. note::
-            As of version 2.5.0, the use of the keyword ``until`` in conjunction
-            with ``count`` is deprecated, to make sure ``dateutil`` is fully
-            compliant with `RFC-5545 Sec. 3.3.10 <https://tools.ietf.org/
-            html/rfc5545#section-3.3.10>`_. Therefore, ``until`` and ``count``
-            **must not** occur in the same call to ``rrule``.
-    :param until:
-        If given, this must be a datetime instance specifying the upper-bound
-        limit of the recurrence. The last recurrence in the rule is the greatest
-        datetime that is less than or equal to the value specified in the
-        ``until`` parameter.
-
-        .. note::
-            As of version 2.5.0, the use of the keyword ``until`` in conjunction
-            with ``count`` is deprecated, to make sure ``dateutil`` is fully
-            compliant with `RFC-5545 Sec. 3.3.10 <https://tools.ietf.org/
-            html/rfc5545#section-3.3.10>`_. Therefore, ``until`` and ``count``
-            **must not** occur in the same call to ``rrule``.
-    :param bysetpos:
-        If given, it must be either an integer, or a sequence of integers,
-        positive or negative. Each given integer will specify an occurrence
-        number, corresponding to the nth occurrence of the rule inside the
-        frequency period. For example, a bysetpos of -1 if combined with a
-        MONTHLY frequency, and a byweekday of (MO, TU, WE, TH, FR), will
-        result in the last work day of every month.
-    :param bymonth:
-        If given, it must be either an integer, or a sequence of integers,
-        meaning the months to apply the recurrence to.
-    :param bymonthday:
-        If given, it must be either an integer, or a sequence of integers,
-        meaning the month days to apply the recurrence to.
-    :param byyearday:
-        If given, it must be either an integer, or a sequence of integers,
-        meaning the year days to apply the recurrence to.
-    :param byeaster:
-        If given, it must be either an integer, or a sequence of integers,
-        positive or negative. Each integer will define an offset from the
-        Easter Sunday. Passing the offset 0 to byeaster will yield the Easter
-        Sunday itself. This is an extension to the RFC specification.
-    :param byweekno:
-        If given, it must be either an integer, or a sequence of integers,
-        meaning the week numbers to apply the recurrence to. Week numbers
-        have the meaning described in ISO8601, that is, the first week of
-        the year is that containing at least four days of the new year.
-    :param byweekday:
-        If given, it must be either an integer (0 == MO), a sequence of
-        integers, one of the weekday constants (MO, TU, etc), or a sequence
-        of these constants. When given, these variables will define the
-        weekdays where the recurrence will be applied. It's also possible to
-        use an argument n for the weekday instances, which will mean the nth
-        occurrence of this weekday in the period. For example, with MONTHLY,
-        or with YEARLY and BYMONTH, using FR(+1) in byweekday will specify the
-        first friday of the month where the recurrence happens. Notice that in
-        the RFC documentation, this is specified as BYDAY, but was renamed to
-        avoid the ambiguity of that keyword.
-    :param byhour:
-        If given, it must be either an integer, or a sequence of integers,
-        meaning the hours to apply the recurrence to.
-    :param byminute:
-        If given, it must be either an integer, or a sequence of integers,
-        meaning the minutes to apply the recurrence to.
-    :param bysecond:
-        If given, it must be either an integer, or a sequence of integers,
-        meaning the seconds to apply the recurrence to.
-    :param cache:
-        If given, it must be a boolean value specifying to enable or disable
-        caching of results. If you will use the same rrule instance multiple
-        times, enabling caching will improve the performance considerably.
-     """
-    def __init__(self, freq, dtstart=None,
-                 interval=1, wkst=None, count=None, until=None, bysetpos=None,
-                 bymonth=None, bymonthday=None, byyearday=None, byeaster=None,
-                 byweekno=None, byweekday=None,
-                 byhour=None, byminute=None, bysecond=None,
-                 cache=False):
-        super(rrule, self).__init__(cache)
-        global easter
-        if not dtstart:
-            if until and until.tzinfo:
-                dtstart = datetime.datetime.now(tz=until.tzinfo).replace(microsecond=0)
-            else:
-                dtstart = datetime.datetime.now().replace(microsecond=0)
-        elif not isinstance(dtstart, datetime.datetime):
-            dtstart = datetime.datetime.fromordinal(dtstart.toordinal())
-        else:
-            dtstart = dtstart.replace(microsecond=0)
-        self._dtstart = dtstart
-        self._tzinfo = dtstart.tzinfo
-        self._freq = freq
-        self._interval = interval
-        self._count = count
-
-        # Cache the original byxxx rules, if they are provided, as the _byxxx
-        # attributes do not necessarily map to the inputs, and this can be
-        # a problem in generating the strings. Only store things if they've
-        # been supplied (the string retrieval will just use .get())
-        self._original_rule = {}
-
-        if until and not isinstance(until, datetime.datetime):
-            until = datetime.datetime.fromordinal(until.toordinal())
-        self._until = until
-
-        if self._dtstart and self._until:
-            if (self._dtstart.tzinfo is not None) != (self._until.tzinfo is not None):
-                # According to RFC5545 Section 3.3.10:
-                # https://tools.ietf.org/html/rfc5545#section-3.3.10
-                #
-                # > If the "DTSTART" property is specified as a date with UTC
-                # > time or a date with local time and time zone reference,
-                # > then the UNTIL rule part MUST be specified as a date with
-                # > UTC time.
-                raise ValueError(
-                    'RRULE UNTIL values must be specified in UTC when DTSTART '
-                    'is timezone-aware'
-                )
-
-        if count is not None and until:
-            warn("Using both 'count' and 'until' is inconsistent with RFC 5545"
-                 " and has been deprecated in dateutil. Future versions will "
-                 "raise an error.", DeprecationWarning)
-
-        if wkst is None:
-            self._wkst = calendar.firstweekday()
-        elif isinstance(wkst, integer_types):
-            self._wkst = wkst
-        else:
-            self._wkst = wkst.weekday
-
-        if bysetpos is None:
-            self._bysetpos = None
-        elif isinstance(bysetpos, integer_types):
-            if bysetpos == 0 or not (-366 <= bysetpos <= 366):
-                raise ValueError("bysetpos must be between 1 and 366, "
-                                 "or between -366 and -1")
-            self._bysetpos = (bysetpos,)
-        else:
-            self._bysetpos = tuple(bysetpos)
-            for pos in self._bysetpos:
-                if pos == 0 or not (-366 <= pos <= 366):
-                    raise ValueError("bysetpos must be between 1 and 366, "
-                                     "or between -366 and -1")
-
-        if self._bysetpos:
-            self._original_rule['bysetpos'] = self._bysetpos
-
-        if (byweekno is None and byyearday is None and bymonthday is None and
-                byweekday is None and byeaster is None):
-            if freq == YEARLY:
-                if bymonth is None:
-                    bymonth = dtstart.month
-                    self._original_rule['bymonth'] = None
-                bymonthday = dtstart.day
-                self._original_rule['bymonthday'] = None
-            elif freq == MONTHLY:
-                bymonthday = dtstart.day
-                self._original_rule['bymonthday'] = None
-            elif freq == WEEKLY:
-                byweekday = dtstart.weekday()
-                self._original_rule['byweekday'] = None
-
-        # bymonth
-        if bymonth is None:
-            self._bymonth = None
-        else:
-            if isinstance(bymonth, integer_types):
-                bymonth = (bymonth,)
-
-            self._bymonth = tuple(sorted(set(bymonth)))
-
-            if 'bymonth' not in self._original_rule:
-                self._original_rule['bymonth'] = self._bymonth
-
-        # byyearday
-        if byyearday is None:
-            self._byyearday = None
-        else:
-            if isinstance(byyearday, integer_types):
-                byyearday = (byyearday,)
-
-            self._byyearday = tuple(sorted(set(byyearday)))
-            self._original_rule['byyearday'] = self._byyearday
-
-        # byeaster
-        if byeaster is not None:
-            if not easter:
-                from dateutil import easter
-            if isinstance(byeaster, integer_types):
-                self._byeaster = (byeaster,)
-            else:
-                self._byeaster = tuple(sorted(byeaster))
-
-            self._original_rule['byeaster'] = self._byeaster
-        else:
-            self._byeaster = None
-
-        # bymonthday
-        if bymonthday is None:
-            self._bymonthday = ()
-            self._bynmonthday = ()
-        else:
-            if isinstance(bymonthday, integer_types):
-                bymonthday = (bymonthday,)
-
-            bymonthday = set(bymonthday)            # Ensure it's unique
-
-            self._bymonthday = tuple(sorted(x for x in bymonthday if x > 0))
-            self._bynmonthday = tuple(sorted(x for x in bymonthday if x < 0))
-
-            # Storing positive numbers first, then negative numbers
-            if 'bymonthday' not in self._original_rule:
-                self._original_rule['bymonthday'] = tuple(
-                    itertools.chain(self._bymonthday, self._bynmonthday))
-
-        # byweekno
-        if byweekno is None:
-            self._byweekno = None
-        else:
-            if isinstance(byweekno, integer_types):
-                byweekno = (byweekno,)
-
-            self._byweekno = tuple(sorted(set(byweekno)))
-
-            self._original_rule['byweekno'] = self._byweekno
-
-        # byweekday / bynweekday
-        if byweekday is None:
-            self._byweekday = None
-            self._bynweekday = None
-        else:
-            # If it's one of the valid non-sequence types, convert to a
-            # single-element sequence before the iterator that builds the
-            # byweekday set.
-            if isinstance(byweekday, integer_types) or hasattr(byweekday, "n"):
-                byweekday = (byweekday,)
-
-            self._byweekday = set()
-            self._bynweekday = set()
-            for wday in byweekday:
-                if isinstance(wday, integer_types):
-                    self._byweekday.add(wday)
-                elif not wday.n or freq > MONTHLY:
-                    self._byweekday.add(wday.weekday)
-                else:
-                    self._bynweekday.add((wday.weekday, wday.n))
-
-            if not self._byweekday:
-                self._byweekday = None
-            elif not self._bynweekday:
-                self._bynweekday = None
-
-            if self._byweekday is not None:
-                self._byweekday = tuple(sorted(self._byweekday))
-                orig_byweekday = [weekday(x) for x in self._byweekday]
-            else:
-                orig_byweekday = ()
-
-            if self._bynweekday is not None:
-                self._bynweekday = tuple(sorted(self._bynweekday))
-                orig_bynweekday = [weekday(*x) for x in self._bynweekday]
-            else:
-                orig_bynweekday = ()
-
-            if 'byweekday' not in self._original_rule:
-                self._original_rule['byweekday'] = tuple(itertools.chain(
-                    orig_byweekday, orig_bynweekday))
-
-        # byhour
-        if byhour is None:
-            if freq < HOURLY:
-                self._byhour = {dtstart.hour}
-            else:
-                self._byhour = None
-        else:
-            if isinstance(byhour, integer_types):
-                byhour = (byhour,)
-
-            if freq == HOURLY:
-                self._byhour = self.__construct_byset(start=dtstart.hour,
-                                                      byxxx=byhour,
-                                                      base=24)
-            else:
-                self._byhour = set(byhour)
-
-            self._byhour = tuple(sorted(self._byhour))
-            self._original_rule['byhour'] = self._byhour
-
-        # byminute
-        if byminute is None:
-            if freq < MINUTELY:
-                self._byminute = {dtstart.minute}
-            else:
-                self._byminute = None
-        else:
-            if isinstance(byminute, integer_types):
-                byminute = (byminute,)
-
-            if freq == MINUTELY:
-                self._byminute = self.__construct_byset(start=dtstart.minute,
-                                                        byxxx=byminute,
-                                                        base=60)
-            else:
-                self._byminute = set(byminute)
-
-            self._byminute = tuple(sorted(self._byminute))
-            self._original_rule['byminute'] = self._byminute
-
-        # bysecond
-        if bysecond is None:
-            if freq < SECONDLY:
-                self._bysecond = ((dtstart.second,))
-            else:
-                self._bysecond = None
-        else:
-            if isinstance(bysecond, integer_types):
-                bysecond = (bysecond,)
-
-            self._bysecond = set(bysecond)
-
-            if freq == SECONDLY:
-                self._bysecond = self.__construct_byset(start=dtstart.second,
-                                                        byxxx=bysecond,
-                                                        base=60)
-            else:
-                self._bysecond = set(bysecond)
-
-            self._bysecond = tuple(sorted(self._bysecond))
-            self._original_rule['bysecond'] = self._bysecond
-
-        if self._freq >= HOURLY:
-            self._timeset = None
-        else:
-            self._timeset = []
-            for hour in self._byhour:
-                for minute in self._byminute:
-                    for second in self._bysecond:
-                        self._timeset.append(
-                            datetime.time(hour, minute, second,
-                                          tzinfo=self._tzinfo))
-            self._timeset.sort()
-            self._timeset = tuple(self._timeset)
-
-    def __str__(self):
-        """
-        Output a string that would generate this RRULE if passed to rrulestr.
-        This is mostly compatible with RFC5545, except for the
-        dateutil-specific extension BYEASTER.
-        """
-
-        output = []
-        h, m, s = [None] * 3
-        if self._dtstart:
-            output.append(self._dtstart.strftime('DTSTART:%Y%m%dT%H%M%S'))
-            h, m, s = self._dtstart.timetuple()[3:6]
-
-        parts = ['FREQ=' + FREQNAMES[self._freq]]
-        if self._interval != 1:
-            parts.append('INTERVAL=' + str(self._interval))
-
-        if self._wkst:
-            parts.append('WKST=' + repr(weekday(self._wkst))[0:2])
-
-        if self._count is not None:
-            parts.append('COUNT=' + str(self._count))
-
-        if self._until:
-            parts.append(self._until.strftime('UNTIL=%Y%m%dT%H%M%S'))
-
-        if self._original_rule.get('byweekday') is not None:
-            # The str() method on weekday objects doesn't generate
-            # RFC5545-compliant strings, so we should modify that.
-            original_rule = dict(self._original_rule)
-            wday_strings = []
-            for wday in original_rule['byweekday']:
-                if wday.n:
-                    wday_strings.append('{n:+d}{wday}'.format(
-                        n=wday.n,
-                        wday=repr(wday)[0:2]))
-                else:
-                    wday_strings.append(repr(wday))
-
-            original_rule['byweekday'] = wday_strings
-        else:
-            original_rule = self._original_rule
-
-        partfmt = '{name}={vals}'
-        for name, key in [('BYSETPOS', 'bysetpos'),
-                          ('BYMONTH', 'bymonth'),
-                          ('BYMONTHDAY', 'bymonthday'),
-                          ('BYYEARDAY', 'byyearday'),
-                          ('BYWEEKNO', 'byweekno'),
-                          ('BYDAY', 'byweekday'),
-                          ('BYHOUR', 'byhour'),
-                          ('BYMINUTE', 'byminute'),
-                          ('BYSECOND', 'bysecond'),
-                          ('BYEASTER', 'byeaster')]:
-            value = original_rule.get(key)
-            if value:
-                parts.append(partfmt.format(name=name, vals=(','.join(str(v)
-                                                             for v in value))))
-
-        output.append('RRULE:' + ';'.join(parts))
-        return '\n'.join(output)
-
-    def replace(self, **kwargs):
-        """Return new rrule with same attributes except for those attributes given new
-           values by whichever keyword arguments are specified."""
-        new_kwargs = {"interval": self._interval,
-                      "count": self._count,
-                      "dtstart": self._dtstart,
-                      "freq": self._freq,
-                      "until": self._until,
-                      "wkst": self._wkst,
-                      "cache": False if self._cache is None else True }
-        new_kwargs.update(self._original_rule)
-        new_kwargs.update(kwargs)
-        return rrule(**new_kwargs)
-
-    def _iter(self):
-        year, month, day, hour, minute, second, weekday, yearday, _ = \
-            self._dtstart.timetuple()
-
-        # Some local variables to speed things up a bit
-        freq = self._freq
-        interval = self._interval
-        wkst = self._wkst
-        until = self._until
-        bymonth = self._bymonth
-        byweekno = self._byweekno
-        byyearday = self._byyearday
-        byweekday = self._byweekday
-        byeaster = self._byeaster
-        bymonthday = self._bymonthday
-        bynmonthday = self._bynmonthday
-        bysetpos = self._bysetpos
-        byhour = self._byhour
-        byminute = self._byminute
-        bysecond = self._bysecond
-
-        ii = _iterinfo(self)
-        ii.rebuild(year, month)
-
-        getdayset = {YEARLY: ii.ydayset,
-                     MONTHLY: ii.mdayset,
-                     WEEKLY: ii.wdayset,
-                     DAILY: ii.ddayset,
-                     HOURLY: ii.ddayset,
-                     MINUTELY: ii.ddayset,
-                     SECONDLY: ii.ddayset}[freq]
-
-        if freq < HOURLY:
-            timeset = self._timeset
-        else:
-            gettimeset = {HOURLY: ii.htimeset,
-                          MINUTELY: ii.mtimeset,
-                          SECONDLY: ii.stimeset}[freq]
-            if ((freq >= HOURLY and
-                 self._byhour and hour not in self._byhour) or
-                (freq >= MINUTELY and
-                 self._byminute and minute not in self._byminute) or
-                (freq >= SECONDLY and
-                 self._bysecond and second not in self._bysecond)):
-                timeset = ()
-            else:
-                timeset = gettimeset(hour, minute, second)
-
-        total = 0
-        count = self._count
-        while True:
-            # Get dayset with the right frequency
-            dayset, start, end = getdayset(year, month, day)
-
-            # Do the "hard" work ;-)
-            filtered = False
-            for i in dayset[start:end]:
-                if ((bymonth and ii.mmask[i] not in bymonth) or
-                    (byweekno and not ii.wnomask[i]) or
-                    (byweekday and ii.wdaymask[i] not in byweekday) or
-                    (ii.nwdaymask and not ii.nwdaymask[i]) or
-                    (byeaster and not ii.eastermask[i]) or
-                    ((bymonthday or bynmonthday) and
-                     ii.mdaymask[i] not in bymonthday and
-                     ii.nmdaymask[i] not in bynmonthday) or
-                    (byyearday and
-                     ((i < ii.yearlen and i+1 not in byyearday and
-                       -ii.yearlen+i not in byyearday) or
-                      (i >= ii.yearlen and i+1-ii.yearlen not in byyearday and
-                       -ii.nextyearlen+i-ii.yearlen not in byyearday)))):
-                    dayset[i] = None
-                    filtered = True
-
-            # Output results
-            if bysetpos and timeset:
-                poslist = []
-                for pos in bysetpos:
-                    if pos < 0:
-                        daypos, timepos = divmod(pos, len(timeset))
-                    else:
-                        daypos, timepos = divmod(pos-1, len(timeset))
-                    try:
-                        i = [x for x in dayset[start:end]
-                             if x is not None][daypos]
-                        time = timeset[timepos]
-                    except IndexError:
-                        pass
-                    else:
-                        date = datetime.date.fromordinal(ii.yearordinal+i)
-                        res = datetime.datetime.combine(date, time)
-                        if res not in poslist:
-                            poslist.append(res)
-                poslist.sort()
-                for res in poslist:
-                    if until and res > until:
-                        self._len = total
-                        return
-                    elif res >= self._dtstart:
-                        if count is not None:
-                            count -= 1
-                            if count < 0:
-                                self._len = total
-                                return
-                        total += 1
-                        yield res
-            else:
-                for i in dayset[start:end]:
-                    if i is not None:
-                        date = datetime.date.fromordinal(ii.yearordinal + i)
-                        for time in timeset:
-                            res = datetime.datetime.combine(date, time)
-                            if until and res > until:
-                                self._len = total
-                                return
-                            elif res >= self._dtstart:
-                                if count is not None:
-                                    count -= 1
-                                    if count < 0:
-                                        self._len = total
-                                        return
-
-                                total += 1
-                                yield res
-
-            # Handle frequency and interval
-            fixday = False
-            if freq == YEARLY:
-                year += interval
-                if year > datetime.MAXYEAR:
-                    self._len = total
-                    return
-                ii.rebuild(year, month)
-            elif freq == MONTHLY:
-                month += interval
-                if month > 12:
-                    div, mod = divmod(month, 12)
-                    month = mod
-                    year += div
-                    if month == 0:
-                        month = 12
-                        year -= 1
-                    if year > datetime.MAXYEAR:
-                        self._len = total
-                        return
-                ii.rebuild(year, month)
-            elif freq == WEEKLY:
-                if wkst > weekday:
-                    day += -(weekday+1+(6-wkst))+self._interval*7
-                else:
-                    day += -(weekday-wkst)+self._interval*7
-                weekday = wkst
-                fixday = True
-            elif freq == DAILY:
-                day += interval
-                fixday = True
-            elif freq == HOURLY:
-                if filtered:
-                    # Jump to one iteration before next day
-                    hour += ((23-hour)//interval)*interval
-
-                if byhour:
-                    ndays, hour = self.__mod_distance(value=hour,
-                                                      byxxx=self._byhour,
-                                                      base=24)
-                else:
-                    ndays, hour = divmod(hour+interval, 24)
-
-                if ndays:
-                    day += ndays
-                    fixday = True
-
-                timeset = gettimeset(hour, minute, second)
-            elif freq == MINUTELY:
-                if filtered:
-                    # Jump to one iteration before next day
-                    minute += ((1439-(hour*60+minute))//interval)*interval
-
-                valid = False
-                rep_rate = (24*60)
-                for j in range(rep_rate // gcd(interval, rep_rate)):
-                    if byminute:
-                        nhours, minute = \
-                            self.__mod_distance(value=minute,
-                                                byxxx=self._byminute,
-                                                base=60)
-                    else:
-                        nhours, minute = divmod(minute+interval, 60)
-
-                    div, hour = divmod(hour+nhours, 24)
-                    if div:
-                        day += div
-                        fixday = True
-                        filtered = False
-
-                    if not byhour or hour in byhour:
-                        valid = True
-                        break
-
-                if not valid:
-                    raise ValueError('Invalid combination of interval and ' +
-                                     'byhour resulting in empty rule.')
-
-                timeset = gettimeset(hour, minute, second)
-            elif freq == SECONDLY:
-                if filtered:
-                    # Jump to one iteration before next day
-                    second += (((86399 - (hour * 3600 + minute * 60 + second))
-                                // interval) * interval)
-
-                rep_rate = (24 * 3600)
-                valid = False
-                for j in range(0, rep_rate // gcd(interval, rep_rate)):
-                    if bysecond:
-                        nminutes, second = \
-                            self.__mod_distance(value=second,
-                                                byxxx=self._bysecond,
-                                                base=60)
-                    else:
-                        nminutes, second = divmod(second+interval, 60)
-
-                    div, minute = divmod(minute+nminutes, 60)
-                    if div:
-                        hour += div
-                        div, hour = divmod(hour, 24)
-                        if div:
-                            day += div
-                            fixday = True
-
-                    if ((not byhour or hour in byhour) and
-                            (not byminute or minute in byminute) and
-                            (not bysecond or second in bysecond)):
-                        valid = True
-                        break
-
-                if not valid:
-                    raise ValueError('Invalid combination of interval, ' +
-                                     'byhour and byminute resulting in empty' +
-                                     ' rule.')
-
-                timeset = gettimeset(hour, minute, second)
-
-            if fixday and day > 28:
-                daysinmonth = calendar.monthrange(year, month)[1]
-                if day > daysinmonth:
-                    while day > daysinmonth:
-                        day -= daysinmonth
-                        month += 1
-                        if month == 13:
-                            month = 1
-                            year += 1
-                            if year > datetime.MAXYEAR:
-                                self._len = total
-                                return
-                        daysinmonth = calendar.monthrange(year, month)[1]
-                    ii.rebuild(year, month)
-
-    def __construct_byset(self, start, byxxx, base):
-        """
-        If a `BYXXX` sequence is passed to the constructor at the same level as
-        `FREQ` (e.g. `FREQ=HOURLY,BYHOUR={2,4,7},INTERVAL=3`), there are some
-        specifications which cannot be reached given some starting conditions.
-
-        This occurs whenever the interval is not coprime with the base of a
-        given unit and the difference between the starting position and the
-        ending position is not coprime with the greatest common denominator
-        between the interval and the base. For example, with a FREQ of hourly
-        starting at 17:00 and an interval of 4, the only valid values for
-        BYHOUR would be {21, 1, 5, 9, 13, 17}, because 4 and 24 are not
-        coprime.
-
-        :param start:
-            Specifies the starting position.
-        :param byxxx:
-            An iterable containing the list of allowed values.
-        :param base:
-            The largest allowable value for the specified frequency (e.g.
-            24 hours, 60 minutes).
-
-        This does not preserve the type of the iterable, returning a set, since
-        the values should be unique and the order is irrelevant, this will
-        speed up later lookups.
-
-        In the event of an empty set, raises a :exception:`ValueError`, as this
-        results in an empty rrule.
-        """
-
-        cset = set()
-
-        # Support a single byxxx value.
-        if isinstance(byxxx, integer_types):
-            byxxx = (byxxx, )
-
-        for num in byxxx:
-            i_gcd = gcd(self._interval, base)
-            # Use divmod rather than % because we need to wrap negative nums.
-            if i_gcd == 1 or divmod(num - start, i_gcd)[1] == 0:
-                cset.add(num)
-
-        if len(cset) == 0:
-            raise ValueError("Invalid rrule byxxx generates an empty set.")
-
-        return cset
-
-    def __mod_distance(self, value, byxxx, base):
-        """
-        Calculates the next value in a sequence where the `FREQ` parameter is
-        specified along with a `BYXXX` parameter at the same "level"
-        (e.g. `HOURLY` specified with `BYHOUR`).
-
-        :param value:
-            The old value of the component.
-        :param byxxx:
-            The `BYXXX` set, which should have been generated by
-            `rrule._construct_byset`, or something else which checks that a
-            valid rule is present.
-        :param base:
-            The largest allowable value for the specified frequency (e.g.
-            24 hours, 60 minutes).
-
-        If a valid value is not found after `base` iterations (the maximum
-        number before the sequence would start to repeat), this raises a
-        :exception:`ValueError`, as no valid values were found.
-
-        This returns a tuple of `divmod(n*interval, base)`, where `n` is the
-        smallest number of `interval` repetitions until the next specified
-        value in `byxxx` is found.
-        """
-        accumulator = 0
-        for ii in range(1, base + 1):
-            # Using divmod() over % to account for negative intervals
-            div, value = divmod(value + self._interval, base)
-            accumulator += div
-            if value in byxxx:
-                return (accumulator, value)
-
-
-class _iterinfo(object):
-    __slots__ = ["rrule", "lastyear", "lastmonth",
-                 "yearlen", "nextyearlen", "yearordinal", "yearweekday",
-                 "mmask", "mrange", "mdaymask", "nmdaymask",
-                 "wdaymask", "wnomask", "nwdaymask", "eastermask"]
-
-    def __init__(self, rrule):
-        for attr in self.__slots__:
-            setattr(self, attr, None)
-        self.rrule = rrule
-
-    def rebuild(self, year, month):
-        # Every mask is 7 days longer to handle cross-year weekly periods.
-        rr = self.rrule
-        if year != self.lastyear:
-            self.yearlen = 365 + calendar.isleap(year)
-            self.nextyearlen = 365 + calendar.isleap(year + 1)
-            firstyday = datetime.date(year, 1, 1)
-            self.yearordinal = firstyday.toordinal()
-            self.yearweekday = firstyday.weekday()
-
-            wday = datetime.date(year, 1, 1).weekday()
-            if self.yearlen == 365:
-                self.mmask = M365MASK
-                self.mdaymask = MDAY365MASK
-                self.nmdaymask = NMDAY365MASK
-                self.wdaymask = WDAYMASK[wday:]
-                self.mrange = M365RANGE
-            else:
-                self.mmask = M366MASK
-                self.mdaymask = MDAY366MASK
-                self.nmdaymask = NMDAY366MASK
-                self.wdaymask = WDAYMASK[wday:]
-                self.mrange = M366RANGE
-
-            if not rr._byweekno:
-                self.wnomask = None
-            else:
-                self.wnomask = [0]*(self.yearlen+7)
-                # no1wkst = firstwkst = self.wdaymask.index(rr._wkst)
-                no1wkst = firstwkst = (7-self.yearweekday+rr._wkst) % 7
-                if no1wkst >= 4:
-                    no1wkst = 0
-                    # Number of days in the year, plus the days we got
-                    # from last year.
-                    wyearlen = self.yearlen+(self.yearweekday-rr._wkst) % 7
-                else:
-                    # Number of days in the year, minus the days we
-                    # left in last year.
-                    wyearlen = self.yearlen-no1wkst
-                div, mod = divmod(wyearlen, 7)
-                numweeks = div+mod//4
-                for n in rr._byweekno:
-                    if n < 0:
-                        n += numweeks+1
-                    if not (0 < n <= numweeks):
-                        continue
-                    if n > 1:
-                        i = no1wkst+(n-1)*7
-                        if no1wkst != firstwkst:
-                            i -= 7-firstwkst
-                    else:
-                        i = no1wkst
-                    for j in range(7):
-                        self.wnomask[i] = 1
-                        i += 1
-                        if self.wdaymask[i] == rr._wkst:
-                            break
-                if 1 in rr._byweekno:
-                    # Check week number 1 of next year as well
-                    # TODO: Check -numweeks for next year.
-                    i = no1wkst+numweeks*7
-                    if no1wkst != firstwkst:
-                        i -= 7-firstwkst
-                    if i < self.yearlen:
-                        # If week starts in next year, we
-                        # don't care about it.
-                        for j in range(7):
-                            self.wnomask[i] = 1
-                            i += 1
-                            if self.wdaymask[i] == rr._wkst:
-                                break
-                if no1wkst:
-                    # Check last week number of last year as
-                    # well. If no1wkst is 0, either the year
-                    # started on week start, or week number 1
-                    # got days from last year, so there are no
-                    # days from last year's last week number in
-                    # this year.
-                    if -1 not in rr._byweekno:
-                        lyearweekday = datetime.date(year-1, 1, 1).weekday()
-                        lno1wkst = (7-lyearweekday+rr._wkst) % 7
-                        lyearlen = 365+calendar.isleap(year-1)
-                        if lno1wkst >= 4:
-                            lno1wkst = 0
-                            lnumweeks = 52+(lyearlen +
-                                            (lyearweekday-rr._wkst) % 7) % 7//4
-                        else:
-                            lnumweeks = 52+(self.yearlen-no1wkst) % 7//4
-                    else:
-                        lnumweeks = -1
-                    if lnumweeks in rr._byweekno:
-                        for i in range(no1wkst):
-                            self.wnomask[i] = 1
-
-        if (rr._bynweekday and (month != self.lastmonth or
-                                year != self.lastyear)):
-            ranges = []
-            if rr._freq == YEARLY:
-                if rr._bymonth:
-                    for month in rr._bymonth:
-                        ranges.append(self.mrange[month-1:month+1])
-                else:
-                    ranges = [(0, self.yearlen)]
-            elif rr._freq == MONTHLY:
-                ranges = [self.mrange[month-1:month+1]]
-            if ranges:
-                # Weekly frequency won't get here, so we may not
-                # care about cross-year weekly periods.
-                self.nwdaymask = [0]*self.yearlen
-                for first, last in ranges:
-                    last -= 1
-                    for wday, n in rr._bynweekday:
-                        if n < 0:
-                            i = last+(n+1)*7
-                            i -= (self.wdaymask[i]-wday) % 7
-                        else:
-                            i = first+(n-1)*7
-                            i += (7-self.wdaymask[i]+wday) % 7
-                        if first <= i <= last:
-                            self.nwdaymask[i] = 1
-
-        if rr._byeaster:
-            self.eastermask = [0]*(self.yearlen+7)
-            eyday = easter.easter(year).toordinal()-self.yearordinal
-            for offset in rr._byeaster:
-                self.eastermask[eyday+offset] = 1
-
-        self.lastyear = year
-        self.lastmonth = month
-
-    def ydayset(self, year, month, day):
-        return list(range(self.yearlen)), 0, self.yearlen
-
-    def mdayset(self, year, month, day):
-        dset = [None]*self.yearlen
-        start, end = self.mrange[month-1:month+1]
-        for i in range(start, end):
-            dset[i] = i
-        return dset, start, end
-
-    def wdayset(self, year, month, day):
-        # We need to handle cross-year weeks here.
-        dset = [None]*(self.yearlen+7)
-        i = datetime.date(year, month, day).toordinal()-self.yearordinal
-        start = i
-        for j in range(7):
-            dset[i] = i
-            i += 1
-            # if (not (0 <= i < self.yearlen) or
-            #    self.wdaymask[i] == self.rrule._wkst):
-            # This will cross the year boundary, if necessary.
-            if self.wdaymask[i] == self.rrule._wkst:
-                break
-        return dset, start, i
-
-    def ddayset(self, year, month, day):
-        dset = [None] * self.yearlen
-        i = datetime.date(year, month, day).toordinal() - self.yearordinal
-        dset[i] = i
-        return dset, i, i + 1
-
-    def htimeset(self, hour, minute, second):
-        tset = []
-        rr = self.rrule
-        for minute in rr._byminute:
-            for second in rr._bysecond:
-                tset.append(datetime.time(hour, minute, second,
-                                          tzinfo=rr._tzinfo))
-        tset.sort()
-        return tset
-
-    def mtimeset(self, hour, minute, second):
-        tset = []
-        rr = self.rrule
-        for second in rr._bysecond:
-            tset.append(datetime.time(hour, minute, second, tzinfo=rr._tzinfo))
-        tset.sort()
-        return tset
-
-    def stimeset(self, hour, minute, second):
-        return (datetime.time(hour, minute, second,
-                tzinfo=self.rrule._tzinfo),)
-
-
-class rruleset(rrulebase):
-    """ The rruleset type allows more complex recurrence setups, mixing
-    multiple rules, dates, exclusion rules, and exclusion dates. The type
-    constructor takes the following keyword arguments:
-
-    :param cache: If True, caching of results will be enabled, improving
-                  performance of multiple queries considerably. """
-
-    class _genitem(object):
-        def __init__(self, genlist, gen):
-            try:
-                self.dt = advance_iterator(gen)
-                genlist.append(self)
-            except StopIteration:
-                pass
-            self.genlist = genlist
-            self.gen = gen
-
-        def __next__(self):
-            try:
-                self.dt = advance_iterator(self.gen)
-            except StopIteration:
-                if self.genlist[0] is self:
-                    heapq.heappop(self.genlist)
-                else:
-                    self.genlist.remove(self)
-                    heapq.heapify(self.genlist)
-
-        next = __next__
-
-        def __lt__(self, other):
-            return self.dt < other.dt
-
-        def __gt__(self, other):
-            return self.dt > other.dt
-
-        def __eq__(self, other):
-            return self.dt == other.dt
-
-        def __ne__(self, other):
-            return self.dt != other.dt
-
-    def __init__(self, cache=False):
-        super(rruleset, self).__init__(cache)
-        self._rrule = []
-        self._rdate = []
-        self._exrule = []
-        self._exdate = []
-
-    @_invalidates_cache
-    def rrule(self, rrule):
-        """ Include the given :py:class:`rrule` instance in the recurrence set
-            generation. """
-        self._rrule.append(rrule)
-
-    @_invalidates_cache
-    def rdate(self, rdate):
-        """ Include the given :py:class:`datetime` instance in the recurrence
-            set generation. """
-        self._rdate.append(rdate)
-
-    @_invalidates_cache
-    def exrule(self, exrule):
-        """ Include the given rrule instance in the recurrence set exclusion
-            list. Dates which are part of the given recurrence rules will not
-            be generated, even if some inclusive rrule or rdate matches them.
-        """
-        self._exrule.append(exrule)
-
-    @_invalidates_cache
-    def exdate(self, exdate):
-        """ Include the given datetime instance in the recurrence set
-            exclusion list. Dates included that way will not be generated,
-            even if some inclusive rrule or rdate matches them. """
-        self._exdate.append(exdate)
-
-    def _iter(self):
-        rlist = []
-        self._rdate.sort()
-        self._genitem(rlist, iter(self._rdate))
-        for gen in [iter(x) for x in self._rrule]:
-            self._genitem(rlist, gen)
-        exlist = []
-        self._exdate.sort()
-        self._genitem(exlist, iter(self._exdate))
-        for gen in [iter(x) for x in self._exrule]:
-            self._genitem(exlist, gen)
-        lastdt = None
-        total = 0
-        heapq.heapify(rlist)
-        heapq.heapify(exlist)
-        while rlist:
-            ritem = rlist[0]
-            if not lastdt or lastdt != ritem.dt:
-                while exlist and exlist[0] < ritem:
-                    exitem = exlist[0]
-                    advance_iterator(exitem)
-                    if exlist and exlist[0] is exitem:
-                        heapq.heapreplace(exlist, exitem)
-                if not exlist or ritem != exlist[0]:
-                    total += 1
-                    yield ritem.dt
-                lastdt = ritem.dt
-            advance_iterator(ritem)
-            if rlist and rlist[0] is ritem:
-                heapq.heapreplace(rlist, ritem)
-        self._len = total
-
-
-
-
-class _rrulestr(object):
-    """ Parses a string representation of a recurrence rule or set of
-    recurrence rules.
-
-    :param s:
-        Required, a string defining one or more recurrence rules.
-
-    :param dtstart:
-        If given, used as the default recurrence start if not specified in the
-        rule string.
-
-    :param cache:
-        If set ``True`` caching of results will be enabled, improving
-        performance of multiple queries considerably.
-
-    :param unfold:
-        If set ``True`` indicates that a rule string is split over more
-        than one line and should be joined before processing.
-
-    :param forceset:
-        If set ``True`` forces a :class:`dateutil.rrule.rruleset` to
-        be returned.
-
-    :param compatible:
-        If set ``True`` forces ``unfold`` and ``forceset`` to be ``True``.
-
-    :param ignoretz:
-        If set ``True``, time zones in parsed strings are ignored and a naive
-        :class:`datetime.datetime` object is returned.
-
-    :param tzids:
-        If given, a callable or mapping used to retrieve a
-        :class:`datetime.tzinfo` from a string representation.
-        Defaults to :func:`dateutil.tz.gettz`.
-
-    :param tzinfos:
-        Additional time zone names / aliases which may be present in a string
-        representation.  See :func:`dateutil.parser.parse` for more
-        information.
-
-    :return:
-        Returns a :class:`dateutil.rrule.rruleset` or
-        :class:`dateutil.rrule.rrule`
-    """
-
-    _freq_map = {"YEARLY": YEARLY,
-                 "MONTHLY": MONTHLY,
-                 "WEEKLY": WEEKLY,
-                 "DAILY": DAILY,
-                 "HOURLY": HOURLY,
-                 "MINUTELY": MINUTELY,
-                 "SECONDLY": SECONDLY}
-
-    _weekday_map = {"MO": 0, "TU": 1, "WE": 2, "TH": 3,
-                    "FR": 4, "SA": 5, "SU": 6}
-
-    def _handle_int(self, rrkwargs, name, value, **kwargs):
-        rrkwargs[name.lower()] = int(value)
-
-    def _handle_int_list(self, rrkwargs, name, value, **kwargs):
-        rrkwargs[name.lower()] = [int(x) for x in value.split(',')]
-
-    _handle_INTERVAL = _handle_int
-    _handle_COUNT = _handle_int
-    _handle_BYSETPOS = _handle_int_list
-    _handle_BYMONTH = _handle_int_list
-    _handle_BYMONTHDAY = _handle_int_list
-    _handle_BYYEARDAY = _handle_int_list
-    _handle_BYEASTER = _handle_int_list
-    _handle_BYWEEKNO = _handle_int_list
-    _handle_BYHOUR = _handle_int_list
-    _handle_BYMINUTE = _handle_int_list
-    _handle_BYSECOND = _handle_int_list
-
-    def _handle_FREQ(self, rrkwargs, name, value, **kwargs):
-        rrkwargs["freq"] = self._freq_map[value]
-
-    def _handle_UNTIL(self, rrkwargs, name, value, **kwargs):
-        global parser
-        if not parser:
-            from dateutil import parser
-        try:
-            rrkwargs["until"] = parser.parse(value,
-                                             ignoretz=kwargs.get("ignoretz"),
-                                             tzinfos=kwargs.get("tzinfos"))
-        except ValueError:
-            raise ValueError("invalid until date")
-
-    def _handle_WKST(self, rrkwargs, name, value, **kwargs):
-        rrkwargs["wkst"] = self._weekday_map[value]
-
-    def _handle_BYWEEKDAY(self, rrkwargs, name, value, **kwargs):
-        """
-        Two ways to specify this: +1MO or MO(+1)
-        """
-        l = []
-        for wday in value.split(','):
-            if '(' in wday:
-                # If it's of the form TH(+1), etc.
-                splt = wday.split('(')
-                w = splt[0]
-                n = int(splt[1][:-1])
-            elif len(wday):
-                # If it's of the form +1MO
-                for i in range(len(wday)):
-                    if wday[i] not in '+-0123456789':
-                        break
-                n = wday[:i] or None
-                w = wday[i:]
-                if n:
-                    n = int(n)
-            else:
-                raise ValueError("Invalid (empty) BYDAY specification.")
-
-            l.append(weekdays[self._weekday_map[w]](n))
-        rrkwargs["byweekday"] = l
-
-    _handle_BYDAY = _handle_BYWEEKDAY
-
-    def _parse_rfc_rrule(self, line,
-                         dtstart=None,
-                         cache=False,
-                         ignoretz=False,
-                         tzinfos=None):
-        if line.find(':') != -1:
-            name, value = line.split(':')
-            if name != "RRULE":
-                raise ValueError("unknown parameter name")
-        else:
-            value = line
-        rrkwargs = {}
-        for pair in value.split(';'):
-            name, value = pair.split('=')
-            name = name.upper()
-            value = value.upper()
-            try:
-                getattr(self, "_handle_"+name)(rrkwargs, name, value,
-                                               ignoretz=ignoretz,
-                                               tzinfos=tzinfos)
-            except AttributeError:
-                raise ValueError("unknown parameter '%s'" % name)
-            except (KeyError, ValueError):
-                raise ValueError("invalid '%s': %s" % (name, value))
-        return rrule(dtstart=dtstart, cache=cache, **rrkwargs)
-
-    def _parse_date_value(self, date_value, parms, rule_tzids,
-                          ignoretz, tzids, tzinfos):
-        global parser
-        if not parser:
-            from dateutil import parser
-
-        datevals = []
-        value_found = False
-        TZID = None
-
-        for parm in parms:
-            if parm.startswith("TZID="):
-                try:
-                    tzkey = rule_tzids[parm.split('TZID=')[-1]]
-                except KeyError:
-                    continue
-                if tzids is None:
-                    from . import tz
-                    tzlookup = tz.gettz
-                elif callable(tzids):
-                    tzlookup = tzids
-                else:
-                    tzlookup = getattr(tzids, 'get', None)
-                    if tzlookup is None:
-                        msg = ('tzids must be a callable, mapping, or None, '
-                               'not %s' % tzids)
-                        raise ValueError(msg)
-
-                TZID = tzlookup(tzkey)
-                continue
-
-            # RFC 5445 3.8.2.4: The VALUE parameter is optional, but may be found
-            # only once.
-            if parm not in {"VALUE=DATE-TIME", "VALUE=DATE"}:
-                raise ValueError("unsupported parm: " + parm)
-            else:
-                if value_found:
-                    msg = ("Duplicate value parameter found in: " + parm)
-                    raise ValueError(msg)
-                value_found = True
-
-        for datestr in date_value.split(','):
-            date = parser.parse(datestr, ignoretz=ignoretz, tzinfos=tzinfos)
-            if TZID is not None:
-                if date.tzinfo is None:
-                    date = date.replace(tzinfo=TZID)
-                else:
-                    raise ValueError('DTSTART/EXDATE specifies multiple timezone')
-            datevals.append(date)
-
-        return datevals
-
-    def _parse_rfc(self, s,
-                   dtstart=None,
-                   cache=False,
-                   unfold=False,
-                   forceset=False,
-                   compatible=False,
-                   ignoretz=False,
-                   tzids=None,
-                   tzinfos=None):
-        global parser
-        if compatible:
-            forceset = True
-            unfold = True
-
-        TZID_NAMES = dict(map(
-            lambda x: (x.upper(), x),
-            re.findall('TZID=(?P<name>[^:]+):', s)
-        ))
-        s = s.upper()
-        if not s.strip():
-            raise ValueError("empty string")
-        if unfold:
-            lines = s.splitlines()
-            i = 0
-            while i < len(lines):
-                line = lines[i].rstrip()
-                if not line:
-                    del lines[i]
-                elif i > 0 and line[0] == " ":
-                    lines[i-1] += line[1:]
-                    del lines[i]
-                else:
-                    i += 1
-        else:
-            lines = s.split()
-        if (not forceset and len(lines) == 1 and (s.find(':') == -1 or
-                                                  s.startswith('RRULE:'))):
-            return self._parse_rfc_rrule(lines[0], cache=cache,
-                                         dtstart=dtstart, ignoretz=ignoretz,
-                                         tzinfos=tzinfos)
-        else:
-            rrulevals = []
-            rdatevals = []
-            exrulevals = []
-            exdatevals = []
-            for line in lines:
-                if not line:
-                    continue
-                if line.find(':') == -1:
-                    name = "RRULE"
-                    value = line
-                else:
-                    name, value = line.split(':', 1)
-                parms = name.split(';')
-                if not parms:
-                    raise ValueError("empty property name")
-                name = parms[0]
-                parms = parms[1:]
-                if name == "RRULE":
-                    for parm in parms:
-                        raise ValueError("unsupported RRULE parm: "+parm)
-                    rrulevals.append(value)
-                elif name == "RDATE":
-                    for parm in parms:
-                        if parm != "VALUE=DATE-TIME":
-                            raise ValueError("unsupported RDATE parm: "+parm)
-                    rdatevals.append(value)
-                elif name == "EXRULE":
-                    for parm in parms:
-                        raise ValueError("unsupported EXRULE parm: "+parm)
-                    exrulevals.append(value)
-                elif name == "EXDATE":
-                    exdatevals.extend(
-                        self._parse_date_value(value, parms,
-                                               TZID_NAMES, ignoretz,
-                                               tzids, tzinfos)
-                    )
-                elif name == "DTSTART":
-                    dtvals = self._parse_date_value(value, parms, TZID_NAMES,
-                                                    ignoretz, tzids, tzinfos)
-                    if len(dtvals) != 1:
-                        raise ValueError("Multiple DTSTART values specified:" +
-                                         value)
-                    dtstart = dtvals[0]
-                else:
-                    raise ValueError("unsupported property: "+name)
-            if (forceset or len(rrulevals) > 1 or rdatevals
-                    or exrulevals or exdatevals):
-                if not parser and (rdatevals or exdatevals):
-                    from dateutil import parser
-                rset = rruleset(cache=cache)
-                for value in rrulevals:
-                    rset.rrule(self._parse_rfc_rrule(value, dtstart=dtstart,
-                                                     ignoretz=ignoretz,
-                                                     tzinfos=tzinfos))
-                for value in rdatevals:
-                    for datestr in value.split(','):
-                        rset.rdate(parser.parse(datestr,
-                                                ignoretz=ignoretz,
-                                                tzinfos=tzinfos))
-                for value in exrulevals:
-                    rset.exrule(self._parse_rfc_rrule(value, dtstart=dtstart,
-                                                      ignoretz=ignoretz,
-                                                      tzinfos=tzinfos))
-                for value in exdatevals:
-                    rset.exdate(value)
-                if compatible and dtstart:
-                    rset.rdate(dtstart)
-                return rset
-            else:
-                return self._parse_rfc_rrule(rrulevals[0],
-                                             dtstart=dtstart,
-                                             cache=cache,
-                                             ignoretz=ignoretz,
-                                             tzinfos=tzinfos)
-
-    def __call__(self, s, **kwargs):
-        return self._parse_rfc(s, **kwargs)
-
-
-rrulestr = _rrulestr()
-
-# vim:ts=4:sw=4:et

+ 0 - 12
venv/lib/python3.8/site-packages/dateutil/tz/__init__.py

@@ -1,12 +0,0 @@
-# -*- coding: utf-8 -*-
-from .tz import *
-from .tz import __doc__
-
-__all__ = ["tzutc", "tzoffset", "tzlocal", "tzfile", "tzrange",
-           "tzstr", "tzical", "tzwin", "tzwinlocal", "gettz",
-           "enfold", "datetime_ambiguous", "datetime_exists",
-           "resolve_imaginary", "UTC", "DeprecatedTzFormatWarning"]
-
-
-class DeprecatedTzFormatWarning(Warning):
-    """Warning raised when time zones are parsed from deprecated formats."""

+ 0 - 419
venv/lib/python3.8/site-packages/dateutil/tz/_common.py

@@ -1,419 +0,0 @@
-from six import PY2
-
-from functools import wraps
-
-from datetime import datetime, timedelta, tzinfo
-
-
-ZERO = timedelta(0)
-
-__all__ = ['tzname_in_python2', 'enfold']
-
-
-def tzname_in_python2(namefunc):
-    """Change unicode output into bytestrings in Python 2
-
-    tzname() API changed in Python 3. It used to return bytes, but was changed
-    to unicode strings
-    """
-    if PY2:
-        @wraps(namefunc)
-        def adjust_encoding(*args, **kwargs):
-            name = namefunc(*args, **kwargs)
-            if name is not None:
-                name = name.encode()
-
-            return name
-
-        return adjust_encoding
-    else:
-        return namefunc
-
-
-# The following is adapted from Alexander Belopolsky's tz library
-# https://github.com/abalkin/tz
-if hasattr(datetime, 'fold'):
-    # This is the pre-python 3.6 fold situation
-    def enfold(dt, fold=1):
-        """
-        Provides a unified interface for assigning the ``fold`` attribute to
-        datetimes both before and after the implementation of PEP-495.
-
-        :param fold:
-            The value for the ``fold`` attribute in the returned datetime. This
-            should be either 0 or 1.
-
-        :return:
-            Returns an object for which ``getattr(dt, 'fold', 0)`` returns
-            ``fold`` for all versions of Python. In versions prior to
-            Python 3.6, this is a ``_DatetimeWithFold`` object, which is a
-            subclass of :py:class:`datetime.datetime` with the ``fold``
-            attribute added, if ``fold`` is 1.
-
-        .. versionadded:: 2.6.0
-        """
-        return dt.replace(fold=fold)
-
-else:
-    class _DatetimeWithFold(datetime):
-        """
-        This is a class designed to provide a PEP 495-compliant interface for
-        Python versions before 3.6. It is used only for dates in a fold, so
-        the ``fold`` attribute is fixed at ``1``.
-
-        .. versionadded:: 2.6.0
-        """
-        __slots__ = ()
-
-        def replace(self, *args, **kwargs):
-            """
-            Return a datetime with the same attributes, except for those
-            attributes given new values by whichever keyword arguments are
-            specified. Note that tzinfo=None can be specified to create a naive
-            datetime from an aware datetime with no conversion of date and time
-            data.
-
-            This is reimplemented in ``_DatetimeWithFold`` because pypy3 will
-            return a ``datetime.datetime`` even if ``fold`` is unchanged.
-            """
-            argnames = (
-                'year', 'month', 'day', 'hour', 'minute', 'second',
-                'microsecond', 'tzinfo'
-            )
-
-            for arg, argname in zip(args, argnames):
-                if argname in kwargs:
-                    raise TypeError('Duplicate argument: {}'.format(argname))
-
-                kwargs[argname] = arg
-
-            for argname in argnames:
-                if argname not in kwargs:
-                    kwargs[argname] = getattr(self, argname)
-
-            dt_class = self.__class__ if kwargs.get('fold', 1) else datetime
-
-            return dt_class(**kwargs)
-
-        @property
-        def fold(self):
-            return 1
-
-    def enfold(dt, fold=1):
-        """
-        Provides a unified interface for assigning the ``fold`` attribute to
-        datetimes both before and after the implementation of PEP-495.
-
-        :param fold:
-            The value for the ``fold`` attribute in the returned datetime. This
-            should be either 0 or 1.
-
-        :return:
-            Returns an object for which ``getattr(dt, 'fold', 0)`` returns
-            ``fold`` for all versions of Python. In versions prior to
-            Python 3.6, this is a ``_DatetimeWithFold`` object, which is a
-            subclass of :py:class:`datetime.datetime` with the ``fold``
-            attribute added, if ``fold`` is 1.
-
-        .. versionadded:: 2.6.0
-        """
-        if getattr(dt, 'fold', 0) == fold:
-            return dt
-
-        args = dt.timetuple()[:6]
-        args += (dt.microsecond, dt.tzinfo)
-
-        if fold:
-            return _DatetimeWithFold(*args)
-        else:
-            return datetime(*args)
-
-
-def _validate_fromutc_inputs(f):
-    """
-    The CPython version of ``fromutc`` checks that the input is a ``datetime``
-    object and that ``self`` is attached as its ``tzinfo``.
-    """
-    @wraps(f)
-    def fromutc(self, dt):
-        if not isinstance(dt, datetime):
-            raise TypeError("fromutc() requires a datetime argument")
-        if dt.tzinfo is not self:
-            raise ValueError("dt.tzinfo is not self")
-
-        return f(self, dt)
-
-    return fromutc
-
-
-class _tzinfo(tzinfo):
-    """
-    Base class for all ``dateutil`` ``tzinfo`` objects.
-    """
-
-    def is_ambiguous(self, dt):
-        """
-        Whether or not the "wall time" of a given datetime is ambiguous in this
-        zone.
-
-        :param dt:
-            A :py:class:`datetime.datetime`, naive or time zone aware.
-
-
-        :return:
-            Returns ``True`` if ambiguous, ``False`` otherwise.
-
-        .. versionadded:: 2.6.0
-        """
-
-        dt = dt.replace(tzinfo=self)
-
-        wall_0 = enfold(dt, fold=0)
-        wall_1 = enfold(dt, fold=1)
-
-        same_offset = wall_0.utcoffset() == wall_1.utcoffset()
-        same_dt = wall_0.replace(tzinfo=None) == wall_1.replace(tzinfo=None)
-
-        return same_dt and not same_offset
-
-    def _fold_status(self, dt_utc, dt_wall):
-        """
-        Determine the fold status of a "wall" datetime, given a representation
-        of the same datetime as a (naive) UTC datetime. This is calculated based
-        on the assumption that ``dt.utcoffset() - dt.dst()`` is constant for all
-        datetimes, and that this offset is the actual number of hours separating
-        ``dt_utc`` and ``dt_wall``.
-
-        :param dt_utc:
-            Representation of the datetime as UTC
-
-        :param dt_wall:
-            Representation of the datetime as "wall time". This parameter must
-            either have a `fold` attribute or have a fold-naive
-            :class:`datetime.tzinfo` attached, otherwise the calculation may
-            fail.
-        """
-        if self.is_ambiguous(dt_wall):
-            delta_wall = dt_wall - dt_utc
-            _fold = int(delta_wall == (dt_utc.utcoffset() - dt_utc.dst()))
-        else:
-            _fold = 0
-
-        return _fold
-
-    def _fold(self, dt):
-        return getattr(dt, 'fold', 0)
-
-    def _fromutc(self, dt):
-        """
-        Given a timezone-aware datetime in a given timezone, calculates a
-        timezone-aware datetime in a new timezone.
-
-        Since this is the one time that we *know* we have an unambiguous
-        datetime object, we take this opportunity to determine whether the
-        datetime is ambiguous and in a "fold" state (e.g. if it's the first
-        occurrence, chronologically, of the ambiguous datetime).
-
-        :param dt:
-            A timezone-aware :class:`datetime.datetime` object.
-        """
-
-        # Re-implement the algorithm from Python's datetime.py
-        dtoff = dt.utcoffset()
-        if dtoff is None:
-            raise ValueError("fromutc() requires a non-None utcoffset() "
-                             "result")
-
-        # The original datetime.py code assumes that `dst()` defaults to
-        # zero during ambiguous times. PEP 495 inverts this presumption, so
-        # for pre-PEP 495 versions of python, we need to tweak the algorithm.
-        dtdst = dt.dst()
-        if dtdst is None:
-            raise ValueError("fromutc() requires a non-None dst() result")
-        delta = dtoff - dtdst
-
-        dt += delta
-        # Set fold=1 so we can default to being in the fold for
-        # ambiguous dates.
-        dtdst = enfold(dt, fold=1).dst()
-        if dtdst is None:
-            raise ValueError("fromutc(): dt.dst gave inconsistent "
-                             "results; cannot convert")
-        return dt + dtdst
-
-    @_validate_fromutc_inputs
-    def fromutc(self, dt):
-        """
-        Given a timezone-aware datetime in a given timezone, calculates a
-        timezone-aware datetime in a new timezone.
-
-        Since this is the one time that we *know* we have an unambiguous
-        datetime object, we take this opportunity to determine whether the
-        datetime is ambiguous and in a "fold" state (e.g. if it's the first
-        occurrence, chronologically, of the ambiguous datetime).
-
-        :param dt:
-            A timezone-aware :class:`datetime.datetime` object.
-        """
-        dt_wall = self._fromutc(dt)
-
-        # Calculate the fold status given the two datetimes.
-        _fold = self._fold_status(dt, dt_wall)
-
-        # Set the default fold value for ambiguous dates
-        return enfold(dt_wall, fold=_fold)
-
-
-class tzrangebase(_tzinfo):
-    """
-    This is an abstract base class for time zones represented by an annual
-    transition into and out of DST. Child classes should implement the following
-    methods:
-
-        * ``__init__(self, *args, **kwargs)``
-        * ``transitions(self, year)`` - this is expected to return a tuple of
-          datetimes representing the DST on and off transitions in standard
-          time.
-
-    A fully initialized ``tzrangebase`` subclass should also provide the
-    following attributes:
-        * ``hasdst``: Boolean whether or not the zone uses DST.
-        * ``_dst_offset`` / ``_std_offset``: :class:`datetime.timedelta` objects
-          representing the respective UTC offsets.
-        * ``_dst_abbr`` / ``_std_abbr``: Strings representing the timezone short
-          abbreviations in DST and STD, respectively.
-        * ``_hasdst``: Whether or not the zone has DST.
-
-    .. versionadded:: 2.6.0
-    """
-    def __init__(self):
-        raise NotImplementedError('tzrangebase is an abstract base class')
-
-    def utcoffset(self, dt):
-        isdst = self._isdst(dt)
-
-        if isdst is None:
-            return None
-        elif isdst:
-            return self._dst_offset
-        else:
-            return self._std_offset
-
-    def dst(self, dt):
-        isdst = self._isdst(dt)
-
-        if isdst is None:
-            return None
-        elif isdst:
-            return self._dst_base_offset
-        else:
-            return ZERO
-
-    @tzname_in_python2
-    def tzname(self, dt):
-        if self._isdst(dt):
-            return self._dst_abbr
-        else:
-            return self._std_abbr
-
-    def fromutc(self, dt):
-        """ Given a datetime in UTC, return local time """
-        if not isinstance(dt, datetime):
-            raise TypeError("fromutc() requires a datetime argument")
-
-        if dt.tzinfo is not self:
-            raise ValueError("dt.tzinfo is not self")
-
-        # Get transitions - if there are none, fixed offset
-        transitions = self.transitions(dt.year)
-        if transitions is None:
-            return dt + self.utcoffset(dt)
-
-        # Get the transition times in UTC
-        dston, dstoff = transitions
-
-        dston -= self._std_offset
-        dstoff -= self._std_offset
-
-        utc_transitions = (dston, dstoff)
-        dt_utc = dt.replace(tzinfo=None)
-
-        isdst = self._naive_isdst(dt_utc, utc_transitions)
-
-        if isdst:
-            dt_wall = dt + self._dst_offset
-        else:
-            dt_wall = dt + self._std_offset
-
-        _fold = int(not isdst and self.is_ambiguous(dt_wall))
-
-        return enfold(dt_wall, fold=_fold)
-
-    def is_ambiguous(self, dt):
-        """
-        Whether or not the "wall time" of a given datetime is ambiguous in this
-        zone.
-
-        :param dt:
-            A :py:class:`datetime.datetime`, naive or time zone aware.
-
-
-        :return:
-            Returns ``True`` if ambiguous, ``False`` otherwise.
-
-        .. versionadded:: 2.6.0
-        """
-        if not self.hasdst:
-            return False
-
-        start, end = self.transitions(dt.year)
-
-        dt = dt.replace(tzinfo=None)
-        return (end <= dt < end + self._dst_base_offset)
-
-    def _isdst(self, dt):
-        if not self.hasdst:
-            return False
-        elif dt is None:
-            return None
-
-        transitions = self.transitions(dt.year)
-
-        if transitions is None:
-            return False
-
-        dt = dt.replace(tzinfo=None)
-
-        isdst = self._naive_isdst(dt, transitions)
-
-        # Handle ambiguous dates
-        if not isdst and self.is_ambiguous(dt):
-            return not self._fold(dt)
-        else:
-            return isdst
-
-    def _naive_isdst(self, dt, transitions):
-        dston, dstoff = transitions
-
-        dt = dt.replace(tzinfo=None)
-
-        if dston < dstoff:
-            isdst = dston <= dt < dstoff
-        else:
-            isdst = not dstoff <= dt < dston
-
-        return isdst
-
-    @property
-    def _dst_base_offset(self):
-        return self._dst_offset - self._std_offset
-
-    __hash__ = None
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __repr__(self):
-        return "%s(...)" % self.__class__.__name__
-
-    __reduce__ = object.__reduce__

+ 0 - 80
venv/lib/python3.8/site-packages/dateutil/tz/_factories.py

@@ -1,80 +0,0 @@
-from datetime import timedelta
-import weakref
-from collections import OrderedDict
-
-from six.moves import _thread
-
-
-class _TzSingleton(type):
-    def __init__(cls, *args, **kwargs):
-        cls.__instance = None
-        super(_TzSingleton, cls).__init__(*args, **kwargs)
-
-    def __call__(cls):
-        if cls.__instance is None:
-            cls.__instance = super(_TzSingleton, cls).__call__()
-        return cls.__instance
-
-
-class _TzFactory(type):
-    def instance(cls, *args, **kwargs):
-        """Alternate constructor that returns a fresh instance"""
-        return type.__call__(cls, *args, **kwargs)
-
-
-class _TzOffsetFactory(_TzFactory):
-    def __init__(cls, *args, **kwargs):
-        cls.__instances = weakref.WeakValueDictionary()
-        cls.__strong_cache = OrderedDict()
-        cls.__strong_cache_size = 8
-
-        cls._cache_lock = _thread.allocate_lock()
-
-    def __call__(cls, name, offset):
-        if isinstance(offset, timedelta):
-            key = (name, offset.total_seconds())
-        else:
-            key = (name, offset)
-
-        instance = cls.__instances.get(key, None)
-        if instance is None:
-            instance = cls.__instances.setdefault(key,
-                                                  cls.instance(name, offset))
-
-        # This lock may not be necessary in Python 3. See GH issue #901
-        with cls._cache_lock:
-            cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance)
-
-            # Remove an item if the strong cache is overpopulated
-            if len(cls.__strong_cache) > cls.__strong_cache_size:
-                cls.__strong_cache.popitem(last=False)
-
-        return instance
-
-
-class _TzStrFactory(_TzFactory):
-    def __init__(cls, *args, **kwargs):
-        cls.__instances = weakref.WeakValueDictionary()
-        cls.__strong_cache = OrderedDict()
-        cls.__strong_cache_size = 8
-
-        cls.__cache_lock = _thread.allocate_lock()
-
-    def __call__(cls, s, posix_offset=False):
-        key = (s, posix_offset)
-        instance = cls.__instances.get(key, None)
-
-        if instance is None:
-            instance = cls.__instances.setdefault(key,
-                cls.instance(s, posix_offset))
-
-        # This lock may not be necessary in Python 3. See GH issue #901
-        with cls.__cache_lock:
-            cls.__strong_cache[key] = cls.__strong_cache.pop(key, instance)
-
-            # Remove an item if the strong cache is overpopulated
-            if len(cls.__strong_cache) > cls.__strong_cache_size:
-                cls.__strong_cache.popitem(last=False)
-
-        return instance
-

+ 0 - 1849
venv/lib/python3.8/site-packages/dateutil/tz/tz.py

@@ -1,1849 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-This module offers timezone implementations subclassing the abstract
-:py:class:`datetime.tzinfo` type. There are classes to handle tzfile format
-files (usually are in :file:`/etc/localtime`, :file:`/usr/share/zoneinfo`,
-etc), TZ environment string (in all known formats), given ranges (with help
-from relative deltas), local machine timezone, fixed offset timezone, and UTC
-timezone.
-"""
-import datetime
-import struct
-import time
-import sys
-import os
-import bisect
-import weakref
-from collections import OrderedDict
-
-import six
-from six import string_types
-from six.moves import _thread
-from ._common import tzname_in_python2, _tzinfo
-from ._common import tzrangebase, enfold
-from ._common import _validate_fromutc_inputs
-
-from ._factories import _TzSingleton, _TzOffsetFactory
-from ._factories import _TzStrFactory
-try:
-    from .win import tzwin, tzwinlocal
-except ImportError:
-    tzwin = tzwinlocal = None
-
-# For warning about rounding tzinfo
-from warnings import warn
-
-ZERO = datetime.timedelta(0)
-EPOCH = datetime.datetime.utcfromtimestamp(0)
-EPOCHORDINAL = EPOCH.toordinal()
-
-
-@six.add_metaclass(_TzSingleton)
-class tzutc(datetime.tzinfo):
-    """
-    This is a tzinfo object that represents the UTC time zone.
-
-    **Examples:**
-
-    .. doctest::
-
-        >>> from datetime import *
-        >>> from dateutil.tz import *
-
-        >>> datetime.now()
-        datetime.datetime(2003, 9, 27, 9, 40, 1, 521290)
-
-        >>> datetime.now(tzutc())
-        datetime.datetime(2003, 9, 27, 12, 40, 12, 156379, tzinfo=tzutc())
-
-        >>> datetime.now(tzutc()).tzname()
-        'UTC'
-
-    .. versionchanged:: 2.7.0
-        ``tzutc()`` is now a singleton, so the result of ``tzutc()`` will
-        always return the same object.
-
-        .. doctest::
-
-            >>> from dateutil.tz import tzutc, UTC
-            >>> tzutc() is tzutc()
-            True
-            >>> tzutc() is UTC
-            True
-    """
-    def utcoffset(self, dt):
-        return ZERO
-
-    def dst(self, dt):
-        return ZERO
-
-    @tzname_in_python2
-    def tzname(self, dt):
-        return "UTC"
-
-    def is_ambiguous(self, dt):
-        """
-        Whether or not the "wall time" of a given datetime is ambiguous in this
-        zone.
-
-        :param dt:
-            A :py:class:`datetime.datetime`, naive or time zone aware.
-
-
-        :return:
-            Returns ``True`` if ambiguous, ``False`` otherwise.
-
-        .. versionadded:: 2.6.0
-        """
-        return False
-
-    @_validate_fromutc_inputs
-    def fromutc(self, dt):
-        """
-        Fast track version of fromutc() returns the original ``dt`` object for
-        any valid :py:class:`datetime.datetime` object.
-        """
-        return dt
-
-    def __eq__(self, other):
-        if not isinstance(other, (tzutc, tzoffset)):
-            return NotImplemented
-
-        return (isinstance(other, tzutc) or
-                (isinstance(other, tzoffset) and other._offset == ZERO))
-
-    __hash__ = None
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __repr__(self):
-        return "%s()" % self.__class__.__name__
-
-    __reduce__ = object.__reduce__
-
-
-#: Convenience constant providing a :class:`tzutc()` instance
-#:
-#: .. versionadded:: 2.7.0
-UTC = tzutc()
-
-
-@six.add_metaclass(_TzOffsetFactory)
-class tzoffset(datetime.tzinfo):
-    """
-    A simple class for representing a fixed offset from UTC.
-
-    :param name:
-        The timezone name, to be returned when ``tzname()`` is called.
-    :param offset:
-        The time zone offset in seconds, or (since version 2.6.0, represented
-        as a :py:class:`datetime.timedelta` object).
-    """
-    def __init__(self, name, offset):
-        self._name = name
-
-        try:
-            # Allow a timedelta
-            offset = offset.total_seconds()
-        except (TypeError, AttributeError):
-            pass
-
-        self._offset = datetime.timedelta(seconds=_get_supported_offset(offset))
-
-    def utcoffset(self, dt):
-        return self._offset
-
-    def dst(self, dt):
-        return ZERO
-
-    @tzname_in_python2
-    def tzname(self, dt):
-        return self._name
-
-    @_validate_fromutc_inputs
-    def fromutc(self, dt):
-        return dt + self._offset
-
-    def is_ambiguous(self, dt):
-        """
-        Whether or not the "wall time" of a given datetime is ambiguous in this
-        zone.
-
-        :param dt:
-            A :py:class:`datetime.datetime`, naive or time zone aware.
-        :return:
-            Returns ``True`` if ambiguous, ``False`` otherwise.
-
-        .. versionadded:: 2.6.0
-        """
-        return False
-
-    def __eq__(self, other):
-        if not isinstance(other, tzoffset):
-            return NotImplemented
-
-        return self._offset == other._offset
-
-    __hash__ = None
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __repr__(self):
-        return "%s(%s, %s)" % (self.__class__.__name__,
-                               repr(self._name),
-                               int(self._offset.total_seconds()))
-
-    __reduce__ = object.__reduce__
-
-
-class tzlocal(_tzinfo):
-    """
-    A :class:`tzinfo` subclass built around the ``time`` timezone functions.
-    """
-    def __init__(self):
-        super(tzlocal, self).__init__()
-
-        self._std_offset = datetime.timedelta(seconds=-time.timezone)
-        if time.daylight:
-            self._dst_offset = datetime.timedelta(seconds=-time.altzone)
-        else:
-            self._dst_offset = self._std_offset
-
-        self._dst_saved = self._dst_offset - self._std_offset
-        self._hasdst = bool(self._dst_saved)
-        self._tznames = tuple(time.tzname)
-
-    def utcoffset(self, dt):
-        if dt is None and self._hasdst:
-            return None
-
-        if self._isdst(dt):
-            return self._dst_offset
-        else:
-            return self._std_offset
-
-    def dst(self, dt):
-        if dt is None and self._hasdst:
-            return None
-
-        if self._isdst(dt):
-            return self._dst_offset - self._std_offset
-        else:
-            return ZERO
-
-    @tzname_in_python2
-    def tzname(self, dt):
-        return self._tznames[self._isdst(dt)]
-
-    def is_ambiguous(self, dt):
-        """
-        Whether or not the "wall time" of a given datetime is ambiguous in this
-        zone.
-
-        :param dt:
-            A :py:class:`datetime.datetime`, naive or time zone aware.
-
-
-        :return:
-            Returns ``True`` if ambiguous, ``False`` otherwise.
-
-        .. versionadded:: 2.6.0
-        """
-        naive_dst = self._naive_is_dst(dt)
-        return (not naive_dst and
-                (naive_dst != self._naive_is_dst(dt - self._dst_saved)))
-
-    def _naive_is_dst(self, dt):
-        timestamp = _datetime_to_timestamp(dt)
-        return time.localtime(timestamp + time.timezone).tm_isdst
-
-    def _isdst(self, dt, fold_naive=True):
-        # We can't use mktime here. It is unstable when deciding if
-        # the hour near to a change is DST or not.
-        #
-        # timestamp = time.mktime((dt.year, dt.month, dt.day, dt.hour,
-        #                         dt.minute, dt.second, dt.weekday(), 0, -1))
-        # return time.localtime(timestamp).tm_isdst
-        #
-        # The code above yields the following result:
-        #
-        # >>> import tz, datetime
-        # >>> t = tz.tzlocal()
-        # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname()
-        # 'BRDT'
-        # >>> datetime.datetime(2003,2,16,0,tzinfo=t).tzname()
-        # 'BRST'
-        # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname()
-        # 'BRST'
-        # >>> datetime.datetime(2003,2,15,22,tzinfo=t).tzname()
-        # 'BRDT'
-        # >>> datetime.datetime(2003,2,15,23,tzinfo=t).tzname()
-        # 'BRDT'
-        #
-        # Here is a more stable implementation:
-        #
-        if not self._hasdst:
-            return False
-
-        # Check for ambiguous times:
-        dstval = self._naive_is_dst(dt)
-        fold = getattr(dt, 'fold', None)
-
-        if self.is_ambiguous(dt):
-            if fold is not None:
-                return not self._fold(dt)
-            else:
-                return True
-
-        return dstval
-
-    def __eq__(self, other):
-        if isinstance(other, tzlocal):
-            return (self._std_offset == other._std_offset and
-                    self._dst_offset == other._dst_offset)
-        elif isinstance(other, tzutc):
-            return (not self._hasdst and
-                    self._tznames[0] in {'UTC', 'GMT'} and
-                    self._std_offset == ZERO)
-        elif isinstance(other, tzoffset):
-            return (not self._hasdst and
-                    self._tznames[0] == other._name and
-                    self._std_offset == other._offset)
-        else:
-            return NotImplemented
-
-    __hash__ = None
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __repr__(self):
-        return "%s()" % self.__class__.__name__
-
-    __reduce__ = object.__reduce__
-
-
-class _ttinfo(object):
-    __slots__ = ["offset", "delta", "isdst", "abbr",
-                 "isstd", "isgmt", "dstoffset"]
-
-    def __init__(self):
-        for attr in self.__slots__:
-            setattr(self, attr, None)
-
-    def __repr__(self):
-        l = []
-        for attr in self.__slots__:
-            value = getattr(self, attr)
-            if value is not None:
-                l.append("%s=%s" % (attr, repr(value)))
-        return "%s(%s)" % (self.__class__.__name__, ", ".join(l))
-
-    def __eq__(self, other):
-        if not isinstance(other, _ttinfo):
-            return NotImplemented
-
-        return (self.offset == other.offset and
-                self.delta == other.delta and
-                self.isdst == other.isdst and
-                self.abbr == other.abbr and
-                self.isstd == other.isstd and
-                self.isgmt == other.isgmt and
-                self.dstoffset == other.dstoffset)
-
-    __hash__ = None
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __getstate__(self):
-        state = {}
-        for name in self.__slots__:
-            state[name] = getattr(self, name, None)
-        return state
-
-    def __setstate__(self, state):
-        for name in self.__slots__:
-            if name in state:
-                setattr(self, name, state[name])
-
-
-class _tzfile(object):
-    """
-    Lightweight class for holding the relevant transition and time zone
-    information read from binary tzfiles.
-    """
-    attrs = ['trans_list', 'trans_list_utc', 'trans_idx', 'ttinfo_list',
-             'ttinfo_std', 'ttinfo_dst', 'ttinfo_before', 'ttinfo_first']
-
-    def __init__(self, **kwargs):
-        for attr in self.attrs:
-            setattr(self, attr, kwargs.get(attr, None))
-
-
-class tzfile(_tzinfo):
-    """
-    This is a ``tzinfo`` subclass that allows one to use the ``tzfile(5)``
-    format timezone files to extract current and historical zone information.
-
-    :param fileobj:
-        This can be an opened file stream or a file name that the time zone
-        information can be read from.
-
-    :param filename:
-        This is an optional parameter specifying the source of the time zone
-        information in the event that ``fileobj`` is a file object. If omitted
-        and ``fileobj`` is a file stream, this parameter will be set either to
-        ``fileobj``'s ``name`` attribute or to ``repr(fileobj)``.
-
-    See `Sources for Time Zone and Daylight Saving Time Data
-    <https://data.iana.org/time-zones/tz-link.html>`_ for more information.
-    Time zone files can be compiled from the `IANA Time Zone database files
-    <https://www.iana.org/time-zones>`_ with the `zic time zone compiler
-    <https://www.freebsd.org/cgi/man.cgi?query=zic&sektion=8>`_
-
-    .. note::
-
-        Only construct a ``tzfile`` directly if you have a specific timezone
-        file on disk that you want to read into a Python ``tzinfo`` object.
-        If you want to get a ``tzfile`` representing a specific IANA zone,
-        (e.g. ``'America/New_York'``), you should call
-        :func:`dateutil.tz.gettz` with the zone identifier.
-
-
-    **Examples:**
-
-    Using the US Eastern time zone as an example, we can see that a ``tzfile``
-    provides time zone information for the standard Daylight Saving offsets:
-
-    .. testsetup:: tzfile
-
-        from dateutil.tz import gettz
-        from datetime import datetime
-
-    .. doctest:: tzfile
-
-        >>> NYC = gettz('America/New_York')
-        >>> NYC
-        tzfile('/usr/share/zoneinfo/America/New_York')
-
-        >>> print(datetime(2016, 1, 3, tzinfo=NYC))     # EST
-        2016-01-03 00:00:00-05:00
-
-        >>> print(datetime(2016, 7, 7, tzinfo=NYC))     # EDT
-        2016-07-07 00:00:00-04:00
-
-
-    The ``tzfile`` structure contains a fully history of the time zone,
-    so historical dates will also have the right offsets. For example, before
-    the adoption of the UTC standards, New York used local solar  mean time:
-
-    .. doctest:: tzfile
-
-       >>> print(datetime(1901, 4, 12, tzinfo=NYC))    # LMT
-       1901-04-12 00:00:00-04:56
-
-    And during World War II, New York was on "Eastern War Time", which was a
-    state of permanent daylight saving time:
-
-    .. doctest:: tzfile
-
-        >>> print(datetime(1944, 2, 7, tzinfo=NYC))    # EWT
-        1944-02-07 00:00:00-04:00
-
-    """
-
-    def __init__(self, fileobj, filename=None):
-        super(tzfile, self).__init__()
-
-        file_opened_here = False
-        if isinstance(fileobj, string_types):
-            self._filename = fileobj
-            fileobj = open(fileobj, 'rb')
-            file_opened_here = True
-        elif filename is not None:
-            self._filename = filename
-        elif hasattr(fileobj, "name"):
-            self._filename = fileobj.name
-        else:
-            self._filename = repr(fileobj)
-
-        if fileobj is not None:
-            if not file_opened_here:
-                fileobj = _nullcontext(fileobj)
-
-            with fileobj as file_stream:
-                tzobj = self._read_tzfile(file_stream)
-
-            self._set_tzdata(tzobj)
-
-    def _set_tzdata(self, tzobj):
-        """ Set the time zone data of this object from a _tzfile object """
-        # Copy the relevant attributes over as private attributes
-        for attr in _tzfile.attrs:
-            setattr(self, '_' + attr, getattr(tzobj, attr))
-
-    def _read_tzfile(self, fileobj):
-        out = _tzfile()
-
-        # From tzfile(5):
-        #
-        # The time zone information files used by tzset(3)
-        # begin with the magic characters "TZif" to identify
-        # them as time zone information files, followed by
-        # sixteen bytes reserved for future use, followed by
-        # six four-byte values of type long, written in a
-        # ``standard'' byte order (the high-order  byte
-        # of the value is written first).
-        if fileobj.read(4).decode() != "TZif":
-            raise ValueError("magic not found")
-
-        fileobj.read(16)
-
-        (
-            # The number of UTC/local indicators stored in the file.
-            ttisgmtcnt,
-
-            # The number of standard/wall indicators stored in the file.
-            ttisstdcnt,
-
-            # The number of leap seconds for which data is
-            # stored in the file.
-            leapcnt,
-
-            # The number of "transition times" for which data
-            # is stored in the file.
-            timecnt,
-
-            # The number of "local time types" for which data
-            # is stored in the file (must not be zero).
-            typecnt,
-
-            # The  number  of  characters  of "time zone
-            # abbreviation strings" stored in the file.
-            charcnt,
-
-        ) = struct.unpack(">6l", fileobj.read(24))
-
-        # The above header is followed by tzh_timecnt four-byte
-        # values  of  type long,  sorted  in ascending order.
-        # These values are written in ``standard'' byte order.
-        # Each is used as a transition time (as  returned  by
-        # time(2)) at which the rules for computing local time
-        # change.
-
-        if timecnt:
-            out.trans_list_utc = list(struct.unpack(">%dl" % timecnt,
-                                                    fileobj.read(timecnt*4)))
-        else:
-            out.trans_list_utc = []
-
-        # Next come tzh_timecnt one-byte values of type unsigned
-        # char; each one tells which of the different types of
-        # ``local time'' types described in the file is associated
-        # with the same-indexed transition time. These values
-        # serve as indices into an array of ttinfo structures that
-        # appears next in the file.
-
-        if timecnt:
-            out.trans_idx = struct.unpack(">%dB" % timecnt,
-                                          fileobj.read(timecnt))
-        else:
-            out.trans_idx = []
-
-        # Each ttinfo structure is written as a four-byte value
-        # for tt_gmtoff  of  type long,  in  a  standard  byte
-        # order, followed  by a one-byte value for tt_isdst
-        # and a one-byte  value  for  tt_abbrind.   In  each
-        # structure, tt_gmtoff  gives  the  number  of
-        # seconds to be added to UTC, tt_isdst tells whether
-        # tm_isdst should be set by  localtime(3),  and
-        # tt_abbrind serves  as an index into the array of
-        # time zone abbreviation characters that follow the
-        # ttinfo structure(s) in the file.
-
-        ttinfo = []
-
-        for i in range(typecnt):
-            ttinfo.append(struct.unpack(">lbb", fileobj.read(6)))
-
-        abbr = fileobj.read(charcnt).decode()
-
-        # Then there are tzh_leapcnt pairs of four-byte
-        # values, written in  standard byte  order;  the
-        # first  value  of  each pair gives the time (as
-        # returned by time(2)) at which a leap second
-        # occurs;  the  second  gives the  total  number of
-        # leap seconds to be applied after the given time.
-        # The pairs of values are sorted in ascending order
-        # by time.
-
-        # Not used, for now (but seek for correct file position)
-        if leapcnt:
-            fileobj.seek(leapcnt * 8, os.SEEK_CUR)
-
-        # Then there are tzh_ttisstdcnt standard/wall
-        # indicators, each stored as a one-byte value;
-        # they tell whether the transition times associated
-        # with local time types were specified as standard
-        # time or wall clock time, and are used when
-        # a time zone file is used in handling POSIX-style
-        # time zone environment variables.
-
-        if ttisstdcnt:
-            isstd = struct.unpack(">%db" % ttisstdcnt,
-                                  fileobj.read(ttisstdcnt))
-
-        # Finally, there are tzh_ttisgmtcnt UTC/local
-        # indicators, each stored as a one-byte value;
-        # they tell whether the transition times associated
-        # with local time types were specified as UTC or
-        # local time, and are used when a time zone file
-        # is used in handling POSIX-style time zone envi-
-        # ronment variables.
-
-        if ttisgmtcnt:
-            isgmt = struct.unpack(">%db" % ttisgmtcnt,
-                                  fileobj.read(ttisgmtcnt))
-
-        # Build ttinfo list
-        out.ttinfo_list = []
-        for i in range(typecnt):
-            gmtoff, isdst, abbrind = ttinfo[i]
-            gmtoff = _get_supported_offset(gmtoff)
-            tti = _ttinfo()
-            tti.offset = gmtoff
-            tti.dstoffset = datetime.timedelta(0)
-            tti.delta = datetime.timedelta(seconds=gmtoff)
-            tti.isdst = isdst
-            tti.abbr = abbr[abbrind:abbr.find('\x00', abbrind)]
-            tti.isstd = (ttisstdcnt > i and isstd[i] != 0)
-            tti.isgmt = (ttisgmtcnt > i and isgmt[i] != 0)
-            out.ttinfo_list.append(tti)
-
-        # Replace ttinfo indexes for ttinfo objects.
-        out.trans_idx = [out.ttinfo_list[idx] for idx in out.trans_idx]
-
-        # Set standard, dst, and before ttinfos. before will be
-        # used when a given time is before any transitions,
-        # and will be set to the first non-dst ttinfo, or to
-        # the first dst, if all of them are dst.
-        out.ttinfo_std = None
-        out.ttinfo_dst = None
-        out.ttinfo_before = None
-        if out.ttinfo_list:
-            if not out.trans_list_utc:
-                out.ttinfo_std = out.ttinfo_first = out.ttinfo_list[0]
-            else:
-                for i in range(timecnt-1, -1, -1):
-                    tti = out.trans_idx[i]
-                    if not out.ttinfo_std and not tti.isdst:
-                        out.ttinfo_std = tti
-                    elif not out.ttinfo_dst and tti.isdst:
-                        out.ttinfo_dst = tti
-
-                    if out.ttinfo_std and out.ttinfo_dst:
-                        break
-                else:
-                    if out.ttinfo_dst and not out.ttinfo_std:
-                        out.ttinfo_std = out.ttinfo_dst
-
-                for tti in out.ttinfo_list:
-                    if not tti.isdst:
-                        out.ttinfo_before = tti
-                        break
-                else:
-                    out.ttinfo_before = out.ttinfo_list[0]
-
-        # Now fix transition times to become relative to wall time.
-        #
-        # I'm not sure about this. In my tests, the tz source file
-        # is setup to wall time, and in the binary file isstd and
-        # isgmt are off, so it should be in wall time. OTOH, it's
-        # always in gmt time. Let me know if you have comments
-        # about this.
-        lastdst = None
-        lastoffset = None
-        lastdstoffset = None
-        lastbaseoffset = None
-        out.trans_list = []
-
-        for i, tti in enumerate(out.trans_idx):
-            offset = tti.offset
-            dstoffset = 0
-
-            if lastdst is not None:
-                if tti.isdst:
-                    if not lastdst:
-                        dstoffset = offset - lastoffset
-
-                    if not dstoffset and lastdstoffset:
-                        dstoffset = lastdstoffset
-
-                    tti.dstoffset = datetime.timedelta(seconds=dstoffset)
-                    lastdstoffset = dstoffset
-
-            # If a time zone changes its base offset during a DST transition,
-            # then you need to adjust by the previous base offset to get the
-            # transition time in local time. Otherwise you use the current
-            # base offset. Ideally, I would have some mathematical proof of
-            # why this is true, but I haven't really thought about it enough.
-            baseoffset = offset - dstoffset
-            adjustment = baseoffset
-            if (lastbaseoffset is not None and baseoffset != lastbaseoffset
-                    and tti.isdst != lastdst):
-                # The base DST has changed
-                adjustment = lastbaseoffset
-
-            lastdst = tti.isdst
-            lastoffset = offset
-            lastbaseoffset = baseoffset
-
-            out.trans_list.append(out.trans_list_utc[i] + adjustment)
-
-        out.trans_idx = tuple(out.trans_idx)
-        out.trans_list = tuple(out.trans_list)
-        out.trans_list_utc = tuple(out.trans_list_utc)
-
-        return out
-
-    def _find_last_transition(self, dt, in_utc=False):
-        # If there's no list, there are no transitions to find
-        if not self._trans_list:
-            return None
-
-        timestamp = _datetime_to_timestamp(dt)
-
-        # Find where the timestamp fits in the transition list - if the
-        # timestamp is a transition time, it's part of the "after" period.
-        trans_list = self._trans_list_utc if in_utc else self._trans_list
-        idx = bisect.bisect_right(trans_list, timestamp)
-
-        # We want to know when the previous transition was, so subtract off 1
-        return idx - 1
-
-    def _get_ttinfo(self, idx):
-        # For no list or after the last transition, default to _ttinfo_std
-        if idx is None or (idx + 1) >= len(self._trans_list):
-            return self._ttinfo_std
-
-        # If there is a list and the time is before it, return _ttinfo_before
-        if idx < 0:
-            return self._ttinfo_before
-
-        return self._trans_idx[idx]
-
-    def _find_ttinfo(self, dt):
-        idx = self._resolve_ambiguous_time(dt)
-
-        return self._get_ttinfo(idx)
-
-    def fromutc(self, dt):
-        """
-        The ``tzfile`` implementation of :py:func:`datetime.tzinfo.fromutc`.
-
-        :param dt:
-            A :py:class:`datetime.datetime` object.
-
-        :raises TypeError:
-            Raised if ``dt`` is not a :py:class:`datetime.datetime` object.
-
-        :raises ValueError:
-            Raised if this is called with a ``dt`` which does not have this
-            ``tzinfo`` attached.
-
-        :return:
-            Returns a :py:class:`datetime.datetime` object representing the
-            wall time in ``self``'s time zone.
-        """
-        # These isinstance checks are in datetime.tzinfo, so we'll preserve
-        # them, even if we don't care about duck typing.
-        if not isinstance(dt, datetime.datetime):
-            raise TypeError("fromutc() requires a datetime argument")
-
-        if dt.tzinfo is not self:
-            raise ValueError("dt.tzinfo is not self")
-
-        # First treat UTC as wall time and get the transition we're in.
-        idx = self._find_last_transition(dt, in_utc=True)
-        tti = self._get_ttinfo(idx)
-
-        dt_out = dt + datetime.timedelta(seconds=tti.offset)
-
-        fold = self.is_ambiguous(dt_out, idx=idx)
-
-        return enfold(dt_out, fold=int(fold))
-
-    def is_ambiguous(self, dt, idx=None):
-        """
-        Whether or not the "wall time" of a given datetime is ambiguous in this
-        zone.
-
-        :param dt:
-            A :py:class:`datetime.datetime`, naive or time zone aware.
-
-
-        :return:
-            Returns ``True`` if ambiguous, ``False`` otherwise.
-
-        .. versionadded:: 2.6.0
-        """
-        if idx is None:
-            idx = self._find_last_transition(dt)
-
-        # Calculate the difference in offsets from current to previous
-        timestamp = _datetime_to_timestamp(dt)
-        tti = self._get_ttinfo(idx)
-
-        if idx is None or idx <= 0:
-            return False
-
-        od = self._get_ttinfo(idx - 1).offset - tti.offset
-        tt = self._trans_list[idx]          # Transition time
-
-        return timestamp < tt + od
-
-    def _resolve_ambiguous_time(self, dt):
-        idx = self._find_last_transition(dt)
-
-        # If we have no transitions, return the index
-        _fold = self._fold(dt)
-        if idx is None or idx == 0:
-            return idx
-
-        # If it's ambiguous and we're in a fold, shift to a different index.
-        idx_offset = int(not _fold and self.is_ambiguous(dt, idx))
-
-        return idx - idx_offset
-
-    def utcoffset(self, dt):
-        if dt is None:
-            return None
-
-        if not self._ttinfo_std:
-            return ZERO
-
-        return self._find_ttinfo(dt).delta
-
-    def dst(self, dt):
-        if dt is None:
-            return None
-
-        if not self._ttinfo_dst:
-            return ZERO
-
-        tti = self._find_ttinfo(dt)
-
-        if not tti.isdst:
-            return ZERO
-
-        # The documentation says that utcoffset()-dst() must
-        # be constant for every dt.
-        return tti.dstoffset
-
-    @tzname_in_python2
-    def tzname(self, dt):
-        if not self._ttinfo_std or dt is None:
-            return None
-        return self._find_ttinfo(dt).abbr
-
-    def __eq__(self, other):
-        if not isinstance(other, tzfile):
-            return NotImplemented
-        return (self._trans_list == other._trans_list and
-                self._trans_idx == other._trans_idx and
-                self._ttinfo_list == other._ttinfo_list)
-
-    __hash__ = None
-
-    def __ne__(self, other):
-        return not (self == other)
-
-    def __repr__(self):
-        return "%s(%s)" % (self.__class__.__name__, repr(self._filename))
-
-    def __reduce__(self):
-        return self.__reduce_ex__(None)
-
-    def __reduce_ex__(self, protocol):
-        return (self.__class__, (None, self._filename), self.__dict__)
-
-
-class tzrange(tzrangebase):
-    """
-    The ``tzrange`` object is a time zone specified by a set of offsets and
-    abbreviations, equivalent to the way the ``TZ`` variable can be specified
-    in POSIX-like systems, but using Python delta objects to specify DST
-    start, end and offsets.
-
-    :param stdabbr:
-        The abbreviation for standard time (e.g. ``'EST'``).
-
-    :param stdoffset:
-        An integer or :class:`datetime.timedelta` object or equivalent
-        specifying the base offset from UTC.
-
-        If unspecified, +00:00 is used.
-
-    :param dstabbr:
-        The abbreviation for DST / "Summer" time (e.g. ``'EDT'``).
-
-        If specified, with no other DST information, DST is assumed to occur
-        and the default behavior or ``dstoffset``, ``start`` and ``end`` is
-        used. If unspecified and no other DST information is specified, it
-        is assumed that this zone has no DST.
-
-        If this is unspecified and other DST information is *is* specified,
-        DST occurs in the zone but the time zone abbreviation is left
-        unchanged.
-
-    :param dstoffset:
-        A an integer or :class:`datetime.timedelta` object or equivalent
-        specifying the UTC offset during DST. If unspecified and any other DST
-        information is specified, it is assumed to be the STD offset +1 hour.
-
-    :param start:
-        A :class:`relativedelta.relativedelta` object or equivalent specifying
-        the time and time of year that daylight savings time starts. To
-        specify, for example, that DST starts at 2AM on the 2nd Sunday in
-        March, pass:
-
-            ``relativedelta(hours=2, month=3, day=1, weekday=SU(+2))``
-
-        If unspecified and any other DST information is specified, the default
-        value is 2 AM on the first Sunday in April.
-
-    :param end:
-        A :class:`relativedelta.relativedelta` object or equivalent
-        representing the time and time of year that daylight savings time
-        ends, with the same specification method as in ``start``. One note is
-        that this should point to the first time in the *standard* zone, so if
-        a transition occurs at 2AM in the DST zone and the clocks are set back
-        1 hour to 1AM, set the ``hours`` parameter to +1.
-
-
-    **Examples:**
-
-    .. testsetup:: tzrange
-
-        from dateutil.tz import tzrange, tzstr
-
-    .. doctest:: tzrange
-
-        >>> tzstr('EST5EDT') == tzrange("EST", -18000, "EDT")
-        True
-
-        >>> from dateutil.relativedelta import *
-        >>> range1 = tzrange("EST", -18000, "EDT")
-        >>> range2 = tzrange("EST", -18000, "EDT", -14400,
-        ...                  relativedelta(hours=+2, month=4, day=1,
-        ...                                weekday=SU(+1)),
-        ...                  relativedelta(hours=+1, month=10, day=31,
-        ...                                weekday=SU(-1)))
-        >>> tzstr('EST5EDT') == range1 == range2
-        True
-
-    """
-    def __init__(self, stdabbr, stdoffset=None,
-                 dstabbr=None, dstoffset=None,
-                 start=None, end=None):
-
-        global relativedelta
-        from dateutil import relativedelta
-
-        self._std_abbr = stdabbr
-        self._dst_abbr = dstabbr
-
-        try:
-            stdoffset = stdoffset.total_seconds()
-        except (TypeError, AttributeError):
-            pass
-
-        try:
-            dstoffset = dstoffset.total_seconds()
-        except (TypeError, AttributeError):
-            pass
-
-        if stdoffset is not None:
-            self._std_offset = datetime.timedelta(seconds=stdoffset)
-        else:
-            self._std_offset = ZERO
-
-        if dstoffset is not None:
-            self._dst_offset = datetime.timedelta(seconds=dstoffset)
-        elif dstabbr and stdoffset is not None:
-            self._dst_offset = self._std_offset + datetime.timedelta(hours=+1)
-        else:
-            self._dst_offset = ZERO
-
-        if dstabbr and start is None:
-            self._start_delta = relativedelta.relativedelta(
-                hours=+2, month=4, day=1, weekday=relativedelta.SU(+1))
-        else:
-            self._start_delta = start
-
-        if dstabbr and end is None:
-            self._end_delta = relativedelta.relativedelta(
-                hours=+1, month=10, day=31, weekday=relativedelta.SU(-1))
-        else:
-            self._end_delta = end
-
-        self._dst_base_offset_ = self._dst_offset - self._std_offset
-        self.hasdst = bool(self._start_delta)
-
-    def transitions(self, year):
-        """
-        For a given year, get the DST on and off transition times, expressed
-        always on the standard time side. For zones with no transitions, this
-        function returns ``None``.
-
-        :param year:
-            The year whose transitions you would like to query.
-
-        :return:
-            Returns a :class:`tuple` of :class:`datetime.datetime` objects,
-            ``(dston, dstoff)`` for zones with an annual DST transition, or
-            ``None`` for fixed offset zones.
-        """
-        if not self.hasdst:
-            return None
-
-        base_year = datetime.datetime(year, 1, 1)
-
-        start = base_year + self._start_delta
-        end = base_year + self._end_delta
-
-        return (start, end)
-
-    def __eq__(self, other):
-        if not isinstance(other, tzrange):
-            return NotImplemented
-
-        return (self._std_abbr == other._std_abbr and
-                self._dst_abbr == other._dst_abbr and
-                self._std_offset == other._std_offset and
-                self._dst_offset == other._dst_offset and
-                self._start_delta == other._start_delta and
-                self._end_delta == other._end_delta)
-
-    @property
-    def _dst_base_offset(self):
-        return self._dst_base_offset_
-
-
-@six.add_metaclass(_TzStrFactory)
-class tzstr(tzrange):
-    """
-    ``tzstr`` objects are time zone objects specified by a time-zone string as
-    it would be passed to a ``TZ`` variable on POSIX-style systems (see
-    the `GNU C Library: TZ Variable`_ for more details).
-
-    There is one notable exception, which is that POSIX-style time zones use an
-    inverted offset format, so normally ``GMT+3`` would be parsed as an offset
-    3 hours *behind* GMT. The ``tzstr`` time zone object will parse this as an
-    offset 3 hours *ahead* of GMT. If you would like to maintain the POSIX
-    behavior, pass a ``True`` value to ``posix_offset``.
-
-    The :class:`tzrange` object provides the same functionality, but is
-    specified using :class:`relativedelta.relativedelta` objects. rather than
-    strings.
-
-    :param s:
-        A time zone string in ``TZ`` variable format. This can be a
-        :class:`bytes` (2.x: :class:`str`), :class:`str` (2.x:
-        :class:`unicode`) or a stream emitting unicode characters
-        (e.g. :class:`StringIO`).
-
-    :param posix_offset:
-        Optional. If set to ``True``, interpret strings such as ``GMT+3`` or
-        ``UTC+3`` as being 3 hours *behind* UTC rather than ahead, per the
-        POSIX standard.
-
-    .. caution::
-
-        Prior to version 2.7.0, this function also supported time zones
-        in the format:
-
-            * ``EST5EDT,4,0,6,7200,10,0,26,7200,3600``
-            * ``EST5EDT,4,1,0,7200,10,-1,0,7200,3600``
-
-        This format is non-standard and has been deprecated; this function
-        will raise a :class:`DeprecatedTZFormatWarning` until
-        support is removed in a future version.
-
-    .. _`GNU C Library: TZ Variable`:
-        https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
-    """
-    def __init__(self, s, posix_offset=False):
-        global parser
-        from dateutil.parser import _parser as parser
-
-        self._s = s
-
-        res = parser._parsetz(s)
-        if res is None or res.any_unused_tokens:
-            raise ValueError("unknown string format")
-
-        # Here we break the compatibility with the TZ variable handling.
-        # GMT-3 actually *means* the timezone -3.
-        if res.stdabbr in ("GMT", "UTC") and not posix_offset:
-            res.stdoffset *= -1
-
-        # We must initialize it first, since _delta() needs
-        # _std_offset and _dst_offset set. Use False in start/end
-        # to avoid building it two times.
-        tzrange.__init__(self, res.stdabbr, res.stdoffset,
-                         res.dstabbr, res.dstoffset,
-                         start=False, end=False)
-
-        if not res.dstabbr:
-            self._start_delta = None
-            self._end_delta = None
-        else:
-            self._start_delta = self._delta(res.start)
-            if self._start_delta:
-                self._end_delta = self._delta(res.end, isend=1)
-
-        self.hasdst = bool(self._start_delta)
-
-    def _delta(self, x, isend=0):
-        from dateutil import relativedelta
-        kwargs = {}
-        if x.month is not None:
-            kwargs["month"] = x.month
-            if x.weekday is not None:
-                kwargs["weekday"] = relativedelta.weekday(x.weekday, x.week)
-                if x.week > 0:
-                    kwargs["day"] = 1
-                else:
-                    kwargs["day"] = 31
-            elif x.day:
-                kwargs["day"] = x.day
-        elif x.yday is not None:
-            kwargs["yearday"] = x.yday
-        elif x.jyday is not None:
-            kwargs["nlyearday"] = x.jyday
-        if not kwargs:
-            # Default is to start on first sunday of april, and end
-            # on last sunday of october.
-            if not isend:
-                kwargs["month"] = 4
-                kwargs["day"] = 1
-                kwargs["weekday"] = relativedelta.SU(+1)
-            else:
-                kwargs["month"] = 10
-                kwargs["day"] = 31
-                kwargs["weekday"] = relativedelta.SU(-1)
-        if x.time is not None:
-            kwargs["seconds"] = x.time
-        else:
-            # Default is 2AM.
-            kwargs["seconds"] = 7200
-        if isend:
-            # Convert to standard time, to follow the documented way
-            # of working with the extra hour. See the documentation
-            # of the tzinfo class.
-            delta = self._dst_offset - self._std_offset
-            kwargs["seconds"] -= delta.seconds + delta.days * 86400
-        return relativedelta.relativedelta(**kwargs)
-
-    def __repr__(self):
-        return "%s(%s)" % (self.__class__.__name__, repr(self._s))
-
-
-class _tzicalvtzcomp(object):
-    def __init__(self, tzoffsetfrom, tzoffsetto, isdst,
-                 tzname=None, rrule=None):
-        self.tzoffsetfrom = datetime.timedelta(seconds=tzoffsetfrom)
-        self.tzoffsetto = datetime.timedelta(seconds=tzoffsetto)
-        self.tzoffsetdiff = self.tzoffsetto - self.tzoffsetfrom
-        self.isdst = isdst
-        self.tzname = tzname
-        self.rrule = rrule
-
-
-class _tzicalvtz(_tzinfo):
-    def __init__(self, tzid, comps=[]):
-        super(_tzicalvtz, self).__init__()
-
-        self._tzid = tzid
-        self._comps = comps
-        self._cachedate = []
-        self._cachecomp = []
-        self._cache_lock = _thread.allocate_lock()
-
-    def _find_comp(self, dt):
-        if len(self._comps) == 1:
-            return self._comps[0]
-
-        dt = dt.replace(tzinfo=None)
-
-        try:
-            with self._cache_lock:
-                return self._cachecomp[self._cachedate.index(
-                    (dt, self._fold(dt)))]
-        except ValueError:
-            pass
-
-        lastcompdt = None
-        lastcomp = None
-
-        for comp in self._comps:
-            compdt = self._find_compdt(comp, dt)
-
-            if compdt and (not lastcompdt or lastcompdt < compdt):
-                lastcompdt = compdt
-                lastcomp = comp
-
-        if not lastcomp:
-            # RFC says nothing about what to do when a given
-            # time is before the first onset date. We'll look for the
-            # first standard component, or the first component, if
-            # none is found.
-            for comp in self._comps:
-                if not comp.isdst:
-                    lastcomp = comp
-                    break
-            else:
-                lastcomp = comp[0]
-
-        with self._cache_lock:
-            self._cachedate.insert(0, (dt, self._fold(dt)))
-            self._cachecomp.insert(0, lastcomp)
-
-            if len(self._cachedate) > 10:
-                self._cachedate.pop()
-                self._cachecomp.pop()
-
-        return lastcomp
-
-    def _find_compdt(self, comp, dt):
-        if comp.tzoffsetdiff < ZERO and self._fold(dt):
-            dt -= comp.tzoffsetdiff
-
-        compdt = comp.rrule.before(dt, inc=True)
-
-        return compdt
-
-    def utcoffset(self, dt):
-        if dt is None:
-            return None
-
-        return self._find_comp(dt).tzoffsetto
-
-    def dst(self, dt):
-        comp = self._find_comp(dt)
-        if comp.isdst:
-            return comp.tzoffsetdiff
-        else:
-            return ZERO
-
-    @tzname_in_python2
-    def tzname(self, dt):
-        return self._find_comp(dt).tzname
-
-    def __repr__(self):
-        return "<tzicalvtz %s>" % repr(self._tzid)
-
-    __reduce__ = object.__reduce__
-
-
-class tzical(object):
-    """
-    This object is designed to parse an iCalendar-style ``VTIMEZONE`` structure
-    as set out in `RFC 5545`_ Section 4.6.5 into one or more `tzinfo` objects.
-
-    :param `fileobj`:
-        A file or stream in iCalendar format, which should be UTF-8 encoded
-        with CRLF endings.
-
-    .. _`RFC 5545`: https://tools.ietf.org/html/rfc5545
-    """
-    def __init__(self, fileobj):
-        global rrule
-        from dateutil import rrule
-
-        if isinstance(fileobj, string_types):
-            self._s = fileobj
-            # ical should be encoded in UTF-8 with CRLF
-            fileobj = open(fileobj, 'r')
-        else:
-            self._s = getattr(fileobj, 'name', repr(fileobj))
-            fileobj = _nullcontext(fileobj)
-
-        self._vtz = {}
-
-        with fileobj as fobj:
-            self._parse_rfc(fobj.read())
-
-    def keys(self):
-        """
-        Retrieves the available time zones as a list.
-        """
-        return list(self._vtz.keys())
-
-    def get(self, tzid=None):
-        """
-        Retrieve a :py:class:`datetime.tzinfo` object by its ``tzid``.
-
-        :param tzid:
-            If there is exactly one time zone available, omitting ``tzid``
-            or passing :py:const:`None` value returns it. Otherwise a valid
-            key (which can be retrieved from :func:`keys`) is required.
-
-        :raises ValueError:
-            Raised if ``tzid`` is not specified but there are either more
-            or fewer than 1 zone defined.
-
-        :returns:
-            Returns either a :py:class:`datetime.tzinfo` object representing
-            the relevant time zone or :py:const:`None` if the ``tzid`` was
-            not found.
-        """
-        if tzid is None:
-            if len(self._vtz) == 0:
-                raise ValueError("no timezones defined")
-            elif len(self._vtz) > 1:
-                raise ValueError("more than one timezone available")
-            tzid = next(iter(self._vtz))
-
-        return self._vtz.get(tzid)
-
-    def _parse_offset(self, s):
-        s = s.strip()
-        if not s:
-            raise ValueError("empty offset")
-        if s[0] in ('+', '-'):
-            signal = (-1, +1)[s[0] == '+']
-            s = s[1:]
-        else:
-            signal = +1
-        if len(s) == 4:
-            return (int(s[:2]) * 3600 + int(s[2:]) * 60) * signal
-        elif len(s) == 6:
-            return (int(s[:2]) * 3600 + int(s[2:4]) * 60 + int(s[4:])) * signal
-        else:
-            raise ValueError("invalid offset: " + s)
-
-    def _parse_rfc(self, s):
-        lines = s.splitlines()
-        if not lines:
-            raise ValueError("empty string")
-
-        # Unfold
-        i = 0
-        while i < len(lines):
-            line = lines[i].rstrip()
-            if not line:
-                del lines[i]
-            elif i > 0 and line[0] == " ":
-                lines[i-1] += line[1:]
-                del lines[i]
-            else:
-                i += 1
-
-        tzid = None
-        comps = []
-        invtz = False
-        comptype = None
-        for line in lines:
-            if not line:
-                continue
-            name, value = line.split(':', 1)
-            parms = name.split(';')
-            if not parms:
-                raise ValueError("empty property name")
-            name = parms[0].upper()
-            parms = parms[1:]
-            if invtz:
-                if name == "BEGIN":
-                    if value in ("STANDARD", "DAYLIGHT"):
-                        # Process component
-                        pass
-                    else:
-                        raise ValueError("unknown component: "+value)
-                    comptype = value
-                    founddtstart = False
-                    tzoffsetfrom = None
-                    tzoffsetto = None
-                    rrulelines = []
-                    tzname = None
-                elif name == "END":
-                    if value == "VTIMEZONE":
-                        if comptype:
-                            raise ValueError("component not closed: "+comptype)
-                        if not tzid:
-                            raise ValueError("mandatory TZID not found")
-                        if not comps:
-                            raise ValueError(
-                                "at least one component is needed")
-                        # Process vtimezone
-                        self._vtz[tzid] = _tzicalvtz(tzid, comps)
-                        invtz = False
-                    elif value == comptype:
-                        if not founddtstart:
-                            raise ValueError("mandatory DTSTART not found")
-                        if tzoffsetfrom is None:
-                            raise ValueError(
-                                "mandatory TZOFFSETFROM not found")
-                        if tzoffsetto is None:
-                            raise ValueError(
-                                "mandatory TZOFFSETFROM not found")
-                        # Process component
-                        rr = None
-                        if rrulelines:
-                            rr = rrule.rrulestr("\n".join(rrulelines),
-                                                compatible=True,
-                                                ignoretz=True,
-                                                cache=True)
-                        comp = _tzicalvtzcomp(tzoffsetfrom, tzoffsetto,
-                                              (comptype == "DAYLIGHT"),
-                                              tzname, rr)
-                        comps.append(comp)
-                        comptype = None
-                    else:
-                        raise ValueError("invalid component end: "+value)
-                elif comptype:
-                    if name == "DTSTART":
-                        # DTSTART in VTIMEZONE takes a subset of valid RRULE
-                        # values under RFC 5545.
-                        for parm in parms:
-                            if parm != 'VALUE=DATE-TIME':
-                                msg = ('Unsupported DTSTART param in ' +
-                                       'VTIMEZONE: ' + parm)
-                                raise ValueError(msg)
-                        rrulelines.append(line)
-                        founddtstart = True
-                    elif name in ("RRULE", "RDATE", "EXRULE", "EXDATE"):
-                        rrulelines.append(line)
-                    elif name == "TZOFFSETFROM":
-                        if parms:
-                            raise ValueError(
-                                "unsupported %s parm: %s " % (name, parms[0]))
-                        tzoffsetfrom = self._parse_offset(value)
-                    elif name == "TZOFFSETTO":
-                        if parms:
-                            raise ValueError(
-                                "unsupported TZOFFSETTO parm: "+parms[0])
-                        tzoffsetto = self._parse_offset(value)
-                    elif name == "TZNAME":
-                        if parms:
-                            raise ValueError(
-                                "unsupported TZNAME parm: "+parms[0])
-                        tzname = value
-                    elif name == "COMMENT":
-                        pass
-                    else:
-                        raise ValueError("unsupported property: "+name)
-                else:
-                    if name == "TZID":
-                        if parms:
-                            raise ValueError(
-                                "unsupported TZID parm: "+parms[0])
-                        tzid = value
-                    elif name in ("TZURL", "LAST-MODIFIED", "COMMENT"):
-                        pass
-                    else:
-                        raise ValueError("unsupported property: "+name)
-            elif name == "BEGIN" and value == "VTIMEZONE":
-                tzid = None
-                comps = []
-                invtz = True
-
-    def __repr__(self):
-        return "%s(%s)" % (self.__class__.__name__, repr(self._s))
-
-
-if sys.platform != "win32":
-    TZFILES = ["/etc/localtime", "localtime"]
-    TZPATHS = ["/usr/share/zoneinfo",
-               "/usr/lib/zoneinfo",
-               "/usr/share/lib/zoneinfo",
-               "/etc/zoneinfo"]
-else:
-    TZFILES = []
-    TZPATHS = []
-
-
-def __get_gettz():
-    tzlocal_classes = (tzlocal,)
-    if tzwinlocal is not None:
-        tzlocal_classes += (tzwinlocal,)
-
-    class GettzFunc(object):
-        """
-        Retrieve a time zone object from a string representation
-
-        This function is intended to retrieve the :py:class:`tzinfo` subclass
-        that best represents the time zone that would be used if a POSIX
-        `TZ variable`_ were set to the same value.
-
-        If no argument or an empty string is passed to ``gettz``, local time
-        is returned:
-
-        .. code-block:: python3
-
-            >>> gettz()
-            tzfile('/etc/localtime')
-
-        This function is also the preferred way to map IANA tz database keys
-        to :class:`tzfile` objects:
-
-        .. code-block:: python3
-
-            >>> gettz('Pacific/Kiritimati')
-            tzfile('/usr/share/zoneinfo/Pacific/Kiritimati')
-
-        On Windows, the standard is extended to include the Windows-specific
-        zone names provided by the operating system:
-
-        .. code-block:: python3
-
-            >>> gettz('Egypt Standard Time')
-            tzwin('Egypt Standard Time')
-
-        Passing a GNU ``TZ`` style string time zone specification returns a
-        :class:`tzstr` object:
-
-        .. code-block:: python3
-
-            >>> gettz('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3')
-            tzstr('AEST-10AEDT-11,M10.1.0/2,M4.1.0/3')
-
-        :param name:
-            A time zone name (IANA, or, on Windows, Windows keys), location of
-            a ``tzfile(5)`` zoneinfo file or ``TZ`` variable style time zone
-            specifier. An empty string, no argument or ``None`` is interpreted
-            as local time.
-
-        :return:
-            Returns an instance of one of ``dateutil``'s :py:class:`tzinfo`
-            subclasses.
-
-        .. versionchanged:: 2.7.0
-
-            After version 2.7.0, any two calls to ``gettz`` using the same
-            input strings will return the same object:
-
-            .. code-block:: python3
-
-                >>> tz.gettz('America/Chicago') is tz.gettz('America/Chicago')
-                True
-
-            In addition to improving performance, this ensures that
-            `"same zone" semantics`_ are used for datetimes in the same zone.
-
-
-        .. _`TZ variable`:
-            https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
-
-        .. _`"same zone" semantics`:
-            https://blog.ganssle.io/articles/2018/02/aware-datetime-arithmetic.html
-        """
-        def __init__(self):
-
-            self.__instances = weakref.WeakValueDictionary()
-            self.__strong_cache_size = 8
-            self.__strong_cache = OrderedDict()
-            self._cache_lock = _thread.allocate_lock()
-
-        def __call__(self, name=None):
-            with self._cache_lock:
-                rv = self.__instances.get(name, None)
-
-                if rv is None:
-                    rv = self.nocache(name=name)
-                    if not (name is None
-                            or isinstance(rv, tzlocal_classes)
-                            or rv is None):
-                        # tzlocal is slightly more complicated than the other
-                        # time zone providers because it depends on environment
-                        # at construction time, so don't cache that.
-                        #
-                        # We also cannot store weak references to None, so we
-                        # will also not store that.
-                        self.__instances[name] = rv
-                    else:
-                        # No need for strong caching, return immediately
-                        return rv
-
-                self.__strong_cache[name] = self.__strong_cache.pop(name, rv)
-
-                if len(self.__strong_cache) > self.__strong_cache_size:
-                    self.__strong_cache.popitem(last=False)
-
-            return rv
-
-        def set_cache_size(self, size):
-            with self._cache_lock:
-                self.__strong_cache_size = size
-                while len(self.__strong_cache) > size:
-                    self.__strong_cache.popitem(last=False)
-
-        def cache_clear(self):
-            with self._cache_lock:
-                self.__instances = weakref.WeakValueDictionary()
-                self.__strong_cache.clear()
-
-        @staticmethod
-        def nocache(name=None):
-            """A non-cached version of gettz"""
-            tz = None
-            if not name:
-                try:
-                    name = os.environ["TZ"]
-                except KeyError:
-                    pass
-            if name is None or name == ":":
-                for filepath in TZFILES:
-                    if not os.path.isabs(filepath):
-                        filename = filepath
-                        for path in TZPATHS:
-                            filepath = os.path.join(path, filename)
-                            if os.path.isfile(filepath):
-                                break
-                        else:
-                            continue
-                    if os.path.isfile(filepath):
-                        try:
-                            tz = tzfile(filepath)
-                            break
-                        except (IOError, OSError, ValueError):
-                            pass
-                else:
-                    tz = tzlocal()
-            else:
-                try:
-                    if name.startswith(":"):
-                        name = name[1:]
-                except TypeError as e:
-                    if isinstance(name, bytes):
-                        new_msg = "gettz argument should be str, not bytes"
-                        six.raise_from(TypeError(new_msg), e)
-                    else:
-                        raise
-                if os.path.isabs(name):
-                    if os.path.isfile(name):
-                        tz = tzfile(name)
-                    else:
-                        tz = None
-                else:
-                    for path in TZPATHS:
-                        filepath = os.path.join(path, name)
-                        if not os.path.isfile(filepath):
-                            filepath = filepath.replace(' ', '_')
-                            if not os.path.isfile(filepath):
-                                continue
-                        try:
-                            tz = tzfile(filepath)
-                            break
-                        except (IOError, OSError, ValueError):
-                            pass
-                    else:
-                        tz = None
-                        if tzwin is not None:
-                            try:
-                                tz = tzwin(name)
-                            except (WindowsError, UnicodeEncodeError):
-                                # UnicodeEncodeError is for Python 2.7 compat
-                                tz = None
-
-                        if not tz:
-                            from dateutil.zoneinfo import get_zonefile_instance
-                            tz = get_zonefile_instance().get(name)
-
-                        if not tz:
-                            for c in name:
-                                # name is not a tzstr unless it has at least
-                                # one offset. For short values of "name", an
-                                # explicit for loop seems to be the fastest way
-                                # To determine if a string contains a digit
-                                if c in "0123456789":
-                                    try:
-                                        tz = tzstr(name)
-                                    except ValueError:
-                                        pass
-                                    break
-                            else:
-                                if name in ("GMT", "UTC"):
-                                    tz = UTC
-                                elif name in time.tzname:
-                                    tz = tzlocal()
-            return tz
-
-    return GettzFunc()
-
-
-gettz = __get_gettz()
-del __get_gettz
-
-
-def datetime_exists(dt, tz=None):
-    """
-    Given a datetime and a time zone, determine whether or not a given datetime
-    would fall in a gap.
-
-    :param dt:
-        A :class:`datetime.datetime` (whose time zone will be ignored if ``tz``
-        is provided.)
-
-    :param tz:
-        A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If
-        ``None`` or not provided, the datetime's own time zone will be used.
-
-    :return:
-        Returns a boolean value whether or not the "wall time" exists in
-        ``tz``.
-
-    .. versionadded:: 2.7.0
-    """
-    if tz is None:
-        if dt.tzinfo is None:
-            raise ValueError('Datetime is naive and no time zone provided.')
-        tz = dt.tzinfo
-
-    dt = dt.replace(tzinfo=None)
-
-    # This is essentially a test of whether or not the datetime can survive
-    # a round trip to UTC.
-    dt_rt = dt.replace(tzinfo=tz).astimezone(UTC).astimezone(tz)
-    dt_rt = dt_rt.replace(tzinfo=None)
-
-    return dt == dt_rt
-
-
-def datetime_ambiguous(dt, tz=None):
-    """
-    Given a datetime and a time zone, determine whether or not a given datetime
-    is ambiguous (i.e if there are two times differentiated only by their DST
-    status).
-
-    :param dt:
-        A :class:`datetime.datetime` (whose time zone will be ignored if ``tz``
-        is provided.)
-
-    :param tz:
-        A :class:`datetime.tzinfo` with support for the ``fold`` attribute. If
-        ``None`` or not provided, the datetime's own time zone will be used.
-
-    :return:
-        Returns a boolean value whether or not the "wall time" is ambiguous in
-        ``tz``.
-
-    .. versionadded:: 2.6.0
-    """
-    if tz is None:
-        if dt.tzinfo is None:
-            raise ValueError('Datetime is naive and no time zone provided.')
-
-        tz = dt.tzinfo
-
-    # If a time zone defines its own "is_ambiguous" function, we'll use that.
-    is_ambiguous_fn = getattr(tz, 'is_ambiguous', None)
-    if is_ambiguous_fn is not None:
-        try:
-            return tz.is_ambiguous(dt)
-        except Exception:
-            pass
-
-    # If it doesn't come out and tell us it's ambiguous, we'll just check if
-    # the fold attribute has any effect on this particular date and time.
-    dt = dt.replace(tzinfo=tz)
-    wall_0 = enfold(dt, fold=0)
-    wall_1 = enfold(dt, fold=1)
-
-    same_offset = wall_0.utcoffset() == wall_1.utcoffset()
-    same_dst = wall_0.dst() == wall_1.dst()
-
-    return not (same_offset and same_dst)
-
-
-def resolve_imaginary(dt):
-    """
-    Given a datetime that may be imaginary, return an existing datetime.
-
-    This function assumes that an imaginary datetime represents what the
-    wall time would be in a zone had the offset transition not occurred, so
-    it will always fall forward by the transition's change in offset.
-
-    .. doctest::
-
-        >>> from dateutil import tz
-        >>> from datetime import datetime
-        >>> NYC = tz.gettz('America/New_York')
-        >>> print(tz.resolve_imaginary(datetime(2017, 3, 12, 2, 30, tzinfo=NYC)))
-        2017-03-12 03:30:00-04:00
-
-        >>> KIR = tz.gettz('Pacific/Kiritimati')
-        >>> print(tz.resolve_imaginary(datetime(1995, 1, 1, 12, 30, tzinfo=KIR)))
-        1995-01-02 12:30:00+14:00
-
-    As a note, :func:`datetime.astimezone` is guaranteed to produce a valid,
-    existing datetime, so a round-trip to and from UTC is sufficient to get
-    an extant datetime, however, this generally "falls back" to an earlier time
-    rather than falling forward to the STD side (though no guarantees are made
-    about this behavior).
-
-    :param dt:
-        A :class:`datetime.datetime` which may or may not exist.
-
-    :return:
-        Returns an existing :class:`datetime.datetime`. If ``dt`` was not
-        imaginary, the datetime returned is guaranteed to be the same object
-        passed to the function.
-
-    .. versionadded:: 2.7.0
-    """
-    if dt.tzinfo is not None and not datetime_exists(dt):
-
-        curr_offset = (dt + datetime.timedelta(hours=24)).utcoffset()
-        old_offset = (dt - datetime.timedelta(hours=24)).utcoffset()
-
-        dt += curr_offset - old_offset
-
-    return dt
-
-
-def _datetime_to_timestamp(dt):
-    """
-    Convert a :class:`datetime.datetime` object to an epoch timestamp in
-    seconds since January 1, 1970, ignoring the time zone.
-    """
-    return (dt.replace(tzinfo=None) - EPOCH).total_seconds()
-
-
-if sys.version_info >= (3, 6):
-    def _get_supported_offset(second_offset):
-        return second_offset
-else:
-    def _get_supported_offset(second_offset):
-        # For python pre-3.6, round to full-minutes if that's not the case.
-        # Python's datetime doesn't accept sub-minute timezones. Check
-        # http://python.org/sf/1447945 or https://bugs.python.org/issue5288
-        # for some information.
-        old_offset = second_offset
-        calculated_offset = 60 * ((second_offset + 30) // 60)
-        return calculated_offset
-
-
-try:
-    # Python 3.7 feature
-    from contextlib import nullcontext as _nullcontext
-except ImportError:
-    class _nullcontext(object):
-        """
-        Class for wrapping contexts so that they are passed through in a
-        with statement.
-        """
-        def __init__(self, context):
-            self.context = context
-
-        def __enter__(self):
-            return self.context
-
-        def __exit__(*args, **kwargs):
-            pass
-
-# vim:ts=4:sw=4:et

+ 0 - 370
venv/lib/python3.8/site-packages/dateutil/tz/win.py

@@ -1,370 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-This module provides an interface to the native time zone data on Windows,
-including :py:class:`datetime.tzinfo` implementations.
-
-Attempting to import this module on a non-Windows platform will raise an
-:py:obj:`ImportError`.
-"""
-# This code was originally contributed by Jeffrey Harris.
-import datetime
-import struct
-
-from six.moves import winreg
-from six import text_type
-
-try:
-    import ctypes
-    from ctypes import wintypes
-except ValueError:
-    # ValueError is raised on non-Windows systems for some horrible reason.
-    raise ImportError("Running tzwin on non-Windows system")
-
-from ._common import tzrangebase
-
-__all__ = ["tzwin", "tzwinlocal", "tzres"]
-
-ONEWEEK = datetime.timedelta(7)
-
-TZKEYNAMENT = r"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
-TZKEYNAME9X = r"SOFTWARE\Microsoft\Windows\CurrentVersion\Time Zones"
-TZLOCALKEYNAME = r"SYSTEM\CurrentControlSet\Control\TimeZoneInformation"
-
-
-def _settzkeyname():
-    handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
-    try:
-        winreg.OpenKey(handle, TZKEYNAMENT).Close()
-        TZKEYNAME = TZKEYNAMENT
-    except WindowsError:
-        TZKEYNAME = TZKEYNAME9X
-    handle.Close()
-    return TZKEYNAME
-
-
-TZKEYNAME = _settzkeyname()
-
-
-class tzres(object):
-    """
-    Class for accessing ``tzres.dll``, which contains timezone name related
-    resources.
-
-    .. versionadded:: 2.5.0
-    """
-    p_wchar = ctypes.POINTER(wintypes.WCHAR)        # Pointer to a wide char
-
-    def __init__(self, tzres_loc='tzres.dll'):
-        # Load the user32 DLL so we can load strings from tzres
-        user32 = ctypes.WinDLL('user32')
-
-        # Specify the LoadStringW function
-        user32.LoadStringW.argtypes = (wintypes.HINSTANCE,
-                                       wintypes.UINT,
-                                       wintypes.LPWSTR,
-                                       ctypes.c_int)
-
-        self.LoadStringW = user32.LoadStringW
-        self._tzres = ctypes.WinDLL(tzres_loc)
-        self.tzres_loc = tzres_loc
-
-    def load_name(self, offset):
-        """
-        Load a timezone name from a DLL offset (integer).
-
-        >>> from dateutil.tzwin import tzres
-        >>> tzr = tzres()
-        >>> print(tzr.load_name(112))
-        'Eastern Standard Time'
-
-        :param offset:
-            A positive integer value referring to a string from the tzres dll.
-
-        .. note::
-
-            Offsets found in the registry are generally of the form
-            ``@tzres.dll,-114``. The offset in this case is 114, not -114.
-
-        """
-        resource = self.p_wchar()
-        lpBuffer = ctypes.cast(ctypes.byref(resource), wintypes.LPWSTR)
-        nchar = self.LoadStringW(self._tzres._handle, offset, lpBuffer, 0)
-        return resource[:nchar]
-
-    def name_from_string(self, tzname_str):
-        """
-        Parse strings as returned from the Windows registry into the time zone
-        name as defined in the registry.
-
-        >>> from dateutil.tzwin import tzres
-        >>> tzr = tzres()
-        >>> print(tzr.name_from_string('@tzres.dll,-251'))
-        'Dateline Daylight Time'
-        >>> print(tzr.name_from_string('Eastern Standard Time'))
-        'Eastern Standard Time'
-
-        :param tzname_str:
-            A timezone name string as returned from a Windows registry key.
-
-        :return:
-            Returns the localized timezone string from tzres.dll if the string
-            is of the form `@tzres.dll,-offset`, else returns the input string.
-        """
-        if not tzname_str.startswith('@'):
-            return tzname_str
-
-        name_splt = tzname_str.split(',-')
-        try:
-            offset = int(name_splt[1])
-        except:
-            raise ValueError("Malformed timezone string.")
-
-        return self.load_name(offset)
-
-
-class tzwinbase(tzrangebase):
-    """tzinfo class based on win32's timezones available in the registry."""
-    def __init__(self):
-        raise NotImplementedError('tzwinbase is an abstract base class')
-
-    def __eq__(self, other):
-        # Compare on all relevant dimensions, including name.
-        if not isinstance(other, tzwinbase):
-            return NotImplemented
-
-        return  (self._std_offset == other._std_offset and
-                 self._dst_offset == other._dst_offset and
-                 self._stddayofweek == other._stddayofweek and
-                 self._dstdayofweek == other._dstdayofweek and
-                 self._stdweeknumber == other._stdweeknumber and
-                 self._dstweeknumber == other._dstweeknumber and
-                 self._stdhour == other._stdhour and
-                 self._dsthour == other._dsthour and
-                 self._stdminute == other._stdminute and
-                 self._dstminute == other._dstminute and
-                 self._std_abbr == other._std_abbr and
-                 self._dst_abbr == other._dst_abbr)
-
-    @staticmethod
-    def list():
-        """Return a list of all time zones known to the system."""
-        with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle:
-            with winreg.OpenKey(handle, TZKEYNAME) as tzkey:
-                result = [winreg.EnumKey(tzkey, i)
-                          for i in range(winreg.QueryInfoKey(tzkey)[0])]
-        return result
-
-    def display(self):
-        """
-        Return the display name of the time zone.
-        """
-        return self._display
-
-    def transitions(self, year):
-        """
-        For a given year, get the DST on and off transition times, expressed
-        always on the standard time side. For zones with no transitions, this
-        function returns ``None``.
-
-        :param year:
-            The year whose transitions you would like to query.
-
-        :return:
-            Returns a :class:`tuple` of :class:`datetime.datetime` objects,
-            ``(dston, dstoff)`` for zones with an annual DST transition, or
-            ``None`` for fixed offset zones.
-        """
-
-        if not self.hasdst:
-            return None
-
-        dston = picknthweekday(year, self._dstmonth, self._dstdayofweek,
-                               self._dsthour, self._dstminute,
-                               self._dstweeknumber)
-
-        dstoff = picknthweekday(year, self._stdmonth, self._stddayofweek,
-                                self._stdhour, self._stdminute,
-                                self._stdweeknumber)
-
-        # Ambiguous dates default to the STD side
-        dstoff -= self._dst_base_offset
-
-        return dston, dstoff
-
-    def _get_hasdst(self):
-        return self._dstmonth != 0
-
-    @property
-    def _dst_base_offset(self):
-        return self._dst_base_offset_
-
-
-class tzwin(tzwinbase):
-    """
-    Time zone object created from the zone info in the Windows registry
-
-    These are similar to :py:class:`dateutil.tz.tzrange` objects in that
-    the time zone data is provided in the format of a single offset rule
-    for either 0 or 2 time zone transitions per year.
-
-    :param: name
-        The name of a Windows time zone key, e.g. "Eastern Standard Time".
-        The full list of keys can be retrieved with :func:`tzwin.list`.
-    """
-
-    def __init__(self, name):
-        self._name = name
-
-        with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle:
-            tzkeyname = text_type("{kn}\\{name}").format(kn=TZKEYNAME, name=name)
-            with winreg.OpenKey(handle, tzkeyname) as tzkey:
-                keydict = valuestodict(tzkey)
-
-        self._std_abbr = keydict["Std"]
-        self._dst_abbr = keydict["Dlt"]
-
-        self._display = keydict["Display"]
-
-        # See http://ww_winreg.jsiinc.com/SUBA/tip0300/rh0398.htm
-        tup = struct.unpack("=3l16h", keydict["TZI"])
-        stdoffset = -tup[0]-tup[1]          # Bias + StandardBias * -1
-        dstoffset = stdoffset-tup[2]        # + DaylightBias * -1
-        self._std_offset = datetime.timedelta(minutes=stdoffset)
-        self._dst_offset = datetime.timedelta(minutes=dstoffset)
-
-        # for the meaning see the win32 TIME_ZONE_INFORMATION structure docs
-        # http://msdn.microsoft.com/en-us/library/windows/desktop/ms725481(v=vs.85).aspx
-        (self._stdmonth,
-         self._stddayofweek,   # Sunday = 0
-         self._stdweeknumber,  # Last = 5
-         self._stdhour,
-         self._stdminute) = tup[4:9]
-
-        (self._dstmonth,
-         self._dstdayofweek,   # Sunday = 0
-         self._dstweeknumber,  # Last = 5
-         self._dsthour,
-         self._dstminute) = tup[12:17]
-
-        self._dst_base_offset_ = self._dst_offset - self._std_offset
-        self.hasdst = self._get_hasdst()
-
-    def __repr__(self):
-        return "tzwin(%s)" % repr(self._name)
-
-    def __reduce__(self):
-        return (self.__class__, (self._name,))
-
-
-class tzwinlocal(tzwinbase):
-    """
-    Class representing the local time zone information in the Windows registry
-
-    While :class:`dateutil.tz.tzlocal` makes system calls (via the :mod:`time`
-    module) to retrieve time zone information, ``tzwinlocal`` retrieves the
-    rules directly from the Windows registry and creates an object like
-    :class:`dateutil.tz.tzwin`.
-
-    Because Windows does not have an equivalent of :func:`time.tzset`, on
-    Windows, :class:`dateutil.tz.tzlocal` instances will always reflect the
-    time zone settings *at the time that the process was started*, meaning
-    changes to the machine's time zone settings during the run of a program
-    on Windows will **not** be reflected by :class:`dateutil.tz.tzlocal`.
-    Because ``tzwinlocal`` reads the registry directly, it is unaffected by
-    this issue.
-    """
-    def __init__(self):
-        with winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE) as handle:
-            with winreg.OpenKey(handle, TZLOCALKEYNAME) as tzlocalkey:
-                keydict = valuestodict(tzlocalkey)
-
-            self._std_abbr = keydict["StandardName"]
-            self._dst_abbr = keydict["DaylightName"]
-
-            try:
-                tzkeyname = text_type('{kn}\\{sn}').format(kn=TZKEYNAME,
-                                                          sn=self._std_abbr)
-                with winreg.OpenKey(handle, tzkeyname) as tzkey:
-                    _keydict = valuestodict(tzkey)
-                    self._display = _keydict["Display"]
-            except OSError:
-                self._display = None
-
-        stdoffset = -keydict["Bias"]-keydict["StandardBias"]
-        dstoffset = stdoffset-keydict["DaylightBias"]
-
-        self._std_offset = datetime.timedelta(minutes=stdoffset)
-        self._dst_offset = datetime.timedelta(minutes=dstoffset)
-
-        # For reasons unclear, in this particular key, the day of week has been
-        # moved to the END of the SYSTEMTIME structure.
-        tup = struct.unpack("=8h", keydict["StandardStart"])
-
-        (self._stdmonth,
-         self._stdweeknumber,  # Last = 5
-         self._stdhour,
-         self._stdminute) = tup[1:5]
-
-        self._stddayofweek = tup[7]
-
-        tup = struct.unpack("=8h", keydict["DaylightStart"])
-
-        (self._dstmonth,
-         self._dstweeknumber,  # Last = 5
-         self._dsthour,
-         self._dstminute) = tup[1:5]
-
-        self._dstdayofweek = tup[7]
-
-        self._dst_base_offset_ = self._dst_offset - self._std_offset
-        self.hasdst = self._get_hasdst()
-
-    def __repr__(self):
-        return "tzwinlocal()"
-
-    def __str__(self):
-        # str will return the standard name, not the daylight name.
-        return "tzwinlocal(%s)" % repr(self._std_abbr)
-
-    def __reduce__(self):
-        return (self.__class__, ())
-
-
-def picknthweekday(year, month, dayofweek, hour, minute, whichweek):
-    """ dayofweek == 0 means Sunday, whichweek 5 means last instance """
-    first = datetime.datetime(year, month, 1, hour, minute)
-
-    # This will work if dayofweek is ISO weekday (1-7) or Microsoft-style (0-6),
-    # Because 7 % 7 = 0
-    weekdayone = first.replace(day=((dayofweek - first.isoweekday()) % 7) + 1)
-    wd = weekdayone + ((whichweek - 1) * ONEWEEK)
-    if (wd.month != month):
-        wd -= ONEWEEK
-
-    return wd
-
-
-def valuestodict(key):
-    """Convert a registry key's values to a dictionary."""
-    dout = {}
-    size = winreg.QueryInfoKey(key)[1]
-    tz_res = None
-
-    for i in range(size):
-        key_name, value, dtype = winreg.EnumValue(key, i)
-        if dtype == winreg.REG_DWORD or dtype == winreg.REG_DWORD_LITTLE_ENDIAN:
-            # If it's a DWORD (32-bit integer), it's stored as unsigned - convert
-            # that to a proper signed integer
-            if value & (1 << 31):
-                value = value - (1 << 32)
-        elif dtype == winreg.REG_SZ:
-            # If it's a reference to the tzres DLL, load the actual string
-            if value.startswith('@tzres'):
-                tz_res = tz_res or tzres()
-                value = tz_res.name_from_string(value)
-
-            value = value.rstrip('\x00')    # Remove trailing nulls
-
-        dout[key_name] = value
-
-    return dout

+ 0 - 2
venv/lib/python3.8/site-packages/dateutil/tzwin.py

@@ -1,2 +0,0 @@
-# tzwin has moved to dateutil.tz.win
-from .tz.win import *

+ 0 - 71
venv/lib/python3.8/site-packages/dateutil/utils.py

@@ -1,71 +0,0 @@
-# -*- coding: utf-8 -*-
-"""
-This module offers general convenience and utility functions for dealing with
-datetimes.
-
-.. versionadded:: 2.7.0
-"""
-from __future__ import unicode_literals
-
-from datetime import datetime, time
-
-
-def today(tzinfo=None):
-    """
-    Returns a :py:class:`datetime` representing the current day at midnight
-
-    :param tzinfo:
-        The time zone to attach (also used to determine the current day).
-
-    :return:
-        A :py:class:`datetime.datetime` object representing the current day
-        at midnight.
-    """
-
-    dt = datetime.now(tzinfo)
-    return datetime.combine(dt.date(), time(0, tzinfo=tzinfo))
-
-
-def default_tzinfo(dt, tzinfo):
-    """
-    Sets the ``tzinfo`` parameter on naive datetimes only
-
-    This is useful for example when you are provided a datetime that may have
-    either an implicit or explicit time zone, such as when parsing a time zone
-    string.
-
-    .. doctest::
-
-        >>> from dateutil.tz import tzoffset
-        >>> from dateutil.parser import parse
-        >>> from dateutil.utils import default_tzinfo
-        >>> dflt_tz = tzoffset("EST", -18000)
-        >>> print(default_tzinfo(parse('2014-01-01 12:30 UTC'), dflt_tz))
-        2014-01-01 12:30:00+00:00
-        >>> print(default_tzinfo(parse('2014-01-01 12:30'), dflt_tz))
-        2014-01-01 12:30:00-05:00
-
-    :param dt:
-        The datetime on which to replace the time zone
-
-    :param tzinfo:
-        The :py:class:`datetime.tzinfo` subclass instance to assign to
-        ``dt`` if (and only if) it is naive.
-
-    :return:
-        Returns an aware :py:class:`datetime.datetime`.
-    """
-    if dt.tzinfo is not None:
-        return dt
-    else:
-        return dt.replace(tzinfo=tzinfo)
-
-
-def within_delta(dt1, dt2, delta):
-    """
-    Useful for comparing two datetimes that may a negilible difference
-    to be considered equal.
-    """
-    delta = abs(delta)
-    difference = dt1 - dt2
-    return -delta <= difference <= delta

+ 0 - 167
venv/lib/python3.8/site-packages/dateutil/zoneinfo/__init__.py

@@ -1,167 +0,0 @@
-# -*- coding: utf-8 -*-
-import warnings
-import json
-
-from tarfile import TarFile
-from pkgutil import get_data
-from io import BytesIO
-
-from dateutil.tz import tzfile as _tzfile
-
-__all__ = ["get_zonefile_instance", "gettz", "gettz_db_metadata"]
-
-ZONEFILENAME = "dateutil-zoneinfo.tar.gz"
-METADATA_FN = 'METADATA'
-
-
-class tzfile(_tzfile):
-    def __reduce__(self):
-        return (gettz, (self._filename,))
-
-
-def getzoneinfofile_stream():
-    try:
-        return BytesIO(get_data(__name__, ZONEFILENAME))
-    except IOError as e:  # TODO  switch to FileNotFoundError?
-        warnings.warn("I/O error({0}): {1}".format(e.errno, e.strerror))
-        return None
-
-
-class ZoneInfoFile(object):
-    def __init__(self, zonefile_stream=None):
-        if zonefile_stream is not None:
-            with TarFile.open(fileobj=zonefile_stream) as tf:
-                self.zones = {zf.name: tzfile(tf.extractfile(zf), filename=zf.name)
-                              for zf in tf.getmembers()
-                              if zf.isfile() and zf.name != METADATA_FN}
-                # deal with links: They'll point to their parent object. Less
-                # waste of memory
-                links = {zl.name: self.zones[zl.linkname]
-                         for zl in tf.getmembers() if
-                         zl.islnk() or zl.issym()}
-                self.zones.update(links)
-                try:
-                    metadata_json = tf.extractfile(tf.getmember(METADATA_FN))
-                    metadata_str = metadata_json.read().decode('UTF-8')
-                    self.metadata = json.loads(metadata_str)
-                except KeyError:
-                    # no metadata in tar file
-                    self.metadata = None
-        else:
-            self.zones = {}
-            self.metadata = None
-
-    def get(self, name, default=None):
-        """
-        Wrapper for :func:`ZoneInfoFile.zones.get`. This is a convenience method
-        for retrieving zones from the zone dictionary.
-
-        :param name:
-            The name of the zone to retrieve. (Generally IANA zone names)
-
-        :param default:
-            The value to return in the event of a missing key.
-
-        .. versionadded:: 2.6.0
-
-        """
-        return self.zones.get(name, default)
-
-
-# The current API has gettz as a module function, although in fact it taps into
-# a stateful class. So as a workaround for now, without changing the API, we
-# will create a new "global" class instance the first time a user requests a
-# timezone. Ugly, but adheres to the api.
-#
-# TODO: Remove after deprecation period.
-_CLASS_ZONE_INSTANCE = []
-
-
-def get_zonefile_instance(new_instance=False):
-    """
-    This is a convenience function which provides a :class:`ZoneInfoFile`
-    instance using the data provided by the ``dateutil`` package. By default, it
-    caches a single instance of the ZoneInfoFile object and returns that.
-
-    :param new_instance:
-        If ``True``, a new instance of :class:`ZoneInfoFile` is instantiated and
-        used as the cached instance for the next call. Otherwise, new instances
-        are created only as necessary.
-
-    :return:
-        Returns a :class:`ZoneInfoFile` object.
-
-    .. versionadded:: 2.6
-    """
-    if new_instance:
-        zif = None
-    else:
-        zif = getattr(get_zonefile_instance, '_cached_instance', None)
-
-    if zif is None:
-        zif = ZoneInfoFile(getzoneinfofile_stream())
-
-        get_zonefile_instance._cached_instance = zif
-
-    return zif
-
-
-def gettz(name):
-    """
-    This retrieves a time zone from the local zoneinfo tarball that is packaged
-    with dateutil.
-
-    :param name:
-        An IANA-style time zone name, as found in the zoneinfo file.
-
-    :return:
-        Returns a :class:`dateutil.tz.tzfile` time zone object.
-
-    .. warning::
-        It is generally inadvisable to use this function, and it is only
-        provided for API compatibility with earlier versions. This is *not*
-        equivalent to ``dateutil.tz.gettz()``, which selects an appropriate
-        time zone based on the inputs, favoring system zoneinfo. This is ONLY
-        for accessing the dateutil-specific zoneinfo (which may be out of
-        date compared to the system zoneinfo).
-
-    .. deprecated:: 2.6
-        If you need to use a specific zoneinfofile over the system zoneinfo,
-        instantiate a :class:`dateutil.zoneinfo.ZoneInfoFile` object and call
-        :func:`dateutil.zoneinfo.ZoneInfoFile.get(name)` instead.
-
-        Use :func:`get_zonefile_instance` to retrieve an instance of the
-        dateutil-provided zoneinfo.
-    """
-    warnings.warn("zoneinfo.gettz() will be removed in future versions, "
-                  "to use the dateutil-provided zoneinfo files, instantiate a "
-                  "ZoneInfoFile object and use ZoneInfoFile.zones.get() "
-                  "instead. See the documentation for details.",
-                  DeprecationWarning)
-
-    if len(_CLASS_ZONE_INSTANCE) == 0:
-        _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream()))
-    return _CLASS_ZONE_INSTANCE[0].zones.get(name)
-
-
-def gettz_db_metadata():
-    """ Get the zonefile metadata
-
-    See `zonefile_metadata`_
-
-    :returns:
-        A dictionary with the database metadata
-
-    .. deprecated:: 2.6
-        See deprecation warning in :func:`zoneinfo.gettz`. To get metadata,
-        query the attribute ``zoneinfo.ZoneInfoFile.metadata``.
-    """
-    warnings.warn("zoneinfo.gettz_db_metadata() will be removed in future "
-                  "versions, to use the dateutil-provided zoneinfo files, "
-                  "ZoneInfoFile object and query the 'metadata' attribute "
-                  "instead. See the documentation for details.",
-                  DeprecationWarning)
-
-    if len(_CLASS_ZONE_INSTANCE) == 0:
-        _CLASS_ZONE_INSTANCE.append(ZoneInfoFile(getzoneinfofile_stream()))
-    return _CLASS_ZONE_INSTANCE[0].metadata

BIN
venv/lib/python3.8/site-packages/dateutil/zoneinfo/dateutil-zoneinfo.tar.gz


+ 0 - 53
venv/lib/python3.8/site-packages/dateutil/zoneinfo/rebuild.py

@@ -1,53 +0,0 @@
-import logging
-import os
-import tempfile
-import shutil
-import json
-from subprocess import check_call
-from tarfile import TarFile
-
-from dateutil.zoneinfo import METADATA_FN, ZONEFILENAME
-
-
-def rebuild(filename, tag=None, format="gz", zonegroups=[], metadata=None):
-    """Rebuild the internal timezone info in dateutil/zoneinfo/zoneinfo*tar*
-
-    filename is the timezone tarball from ``ftp.iana.org/tz``.
-
-    """
-    tmpdir = tempfile.mkdtemp()
-    zonedir = os.path.join(tmpdir, "zoneinfo")
-    moduledir = os.path.dirname(__file__)
-    try:
-        with TarFile.open(filename) as tf:
-            for name in zonegroups:
-                tf.extract(name, tmpdir)
-            filepaths = [os.path.join(tmpdir, n) for n in zonegroups]
-            try:
-                check_call(["zic", "-d", zonedir] + filepaths)
-            except OSError as e:
-                _print_on_nosuchfile(e)
-                raise
-        # write metadata file
-        with open(os.path.join(zonedir, METADATA_FN), 'w') as f:
-            json.dump(metadata, f, indent=4, sort_keys=True)
-        target = os.path.join(moduledir, ZONEFILENAME)
-        with TarFile.open(target, "w:%s" % format) as tf:
-            for entry in os.listdir(zonedir):
-                entrypath = os.path.join(zonedir, entry)
-                tf.add(entrypath, entry)
-    finally:
-        shutil.rmtree(tmpdir)
-
-
-def _print_on_nosuchfile(e):
-    """Print helpful troubleshooting message
-
-    e is an exception raised by subprocess.check_call()
-
-    """
-    if e.errno == 2:
-        logging.error(
-            "Could not find zic. Perhaps you need to install "
-            "libc-bin or some other package that provides it, "
-            "or it's not in your PATH?")

+ 0 - 1
venv/lib/python3.8/site-packages/easy-install.pth

@@ -1 +0,0 @@
-./pygame-1.9.6-py3.8-linux-x86_64.egg

+ 0 - 5
venv/lib/python3.8/site-packages/easy_install.py

@@ -1,5 +0,0 @@
-"""Run the EasyInstall command"""
-
-if __name__ == '__main__':
-    from setuptools.command.easy_install import main
-    main()

+ 0 - 1
venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/INSTALLER

@@ -1 +0,0 @@
-pip

+ 0 - 41
venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/METADATA

@@ -1,41 +0,0 @@
-Metadata-Version: 2.1
-Name: kiwisolver
-Version: 1.2.0
-Summary: A fast implementation of the Cassowary constraint solver
-Home-page: https://github.com/nucleic/kiwi
-Author: The Nucleic Development Team
-Author-email: sccolbert@gmail.com
-License: BSD
-Platform: UNKNOWN
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: Implementation :: CPython
-Requires-Python: >=3.6
-
-Welcome to Kiwi
-===============
-
-.. image:: https://travis-ci.org/nucleic/kiwi.svg?branch=master
-    :target: https://travis-ci.org/nucleic/kiwi
-.. image:: https://codecov.io/gh/nucleic/kiwi/branch/master/graph/badge.svg
-  :target: https://codecov.io/gh/nucleic/kiwi
-.. image:: https://readthedocs.org/projects/kiwisolver/badge/?version=latest
-    :target: https://kiwisolver.readthedocs.io/en/latest/?badge=latest
-    :alt: Documentation Status
-
-Kiwi is an efficient C++ implementation of the Cassowary constraint solving
-algorithm. Kiwi is an implementation of the algorithm based on the seminal
-Cassowary paper. It is *not* a refactoring of the original C++ solver. Kiwi
-has been designed from the ground up to be lightweight and fast. Kiwi ranges
-from 10x to 500x faster than the original Cassowary solver with typical use
-cases gaining a 40x improvement. Memory savings are consistently > 5x.
-
-In addition to the C++ solver, Kiwi ships with hand-rolled Python bindings.
-
-The version 1.1.0 of the Python bindings will be the last one to support
-Python 2, moving forward support will be limited to Python 3.5+.
-
-

+ 0 - 6
venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/RECORD

@@ -1,6 +0,0 @@
-kiwisolver-1.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-kiwisolver-1.2.0.dist-info/METADATA,sha256=GJrhSqJ37gKKWd9lqPultG3mcP013xKeHLD7QyF5z4M,1718
-kiwisolver-1.2.0.dist-info/RECORD,,
-kiwisolver-1.2.0.dist-info/WHEEL,sha256=VEyGcIFAmk_1KbI6gaZGw_mMiT-pdGweASQLX-DzYaY,108
-kiwisolver-1.2.0.dist-info/top_level.txt,sha256=xqwWj7oSHlpIjcw2QMJb8puTFPdjDBO78AZp9gjTh9c,11
-kiwisolver.cpython-38-x86_64-linux-gnu.so,sha256=M6rlCMjCLuAQQkwvZn0yHSInz15TxuUvZwzjN9Oscr4,254056

+ 0 - 5
venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/WHEEL

@@ -1,5 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.31.1)
-Root-Is-Purelib: false
-Tag: cp38-cp38-manylinux1_x86_64
-

+ 0 - 1
venv/lib/python3.8/site-packages/kiwisolver-1.2.0.dist-info/top_level.txt

@@ -1 +0,0 @@
-kiwisolver

BIN
venv/lib/python3.8/site-packages/kiwisolver.cpython-38-x86_64-linux-gnu.so


+ 0 - 1
venv/lib/python3.8/site-packages/matplotlib-3.2.1-py3.8-nspkg.pth

@@ -1 +0,0 @@
-import sys, types, os;has_mfs = sys.version_info > (3, 5);p = os.path.join(sys._getframe(1).f_locals['sitedir'], *('mpl_toolkits',));importlib = has_mfs and __import__('importlib.util');has_mfs and __import__('importlib.machinery');m = has_mfs and sys.modules.setdefault('mpl_toolkits', importlib.util.module_from_spec(importlib.machinery.PathFinder.find_spec('mpl_toolkits', [os.path.dirname(p)])));m = m or sys.modules.setdefault('mpl_toolkits', types.ModuleType('mpl_toolkits'));mp = (m or []) and m.__dict__.setdefault('__path__',[]);(p not in mp) and mp.append(p)

+ 0 - 1
venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/INSTALLER

@@ -1 +0,0 @@
-pip

+ 0 - 127
venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/METADATA

@@ -1,127 +0,0 @@
-Metadata-Version: 2.1
-Name: matplotlib
-Version: 3.2.1
-Summary: Python plotting package
-Home-page: https://matplotlib.org
-Author: John D. Hunter, Michael Droettboom
-Author-email: matplotlib-users@python.org
-License: PSF
-Download-URL: https://matplotlib.org/users/installing.html
-Project-URL: Documentation, https://matplotlib.org
-Project-URL: Source Code, https://github.com/matplotlib/matplotlib
-Project-URL: Bug Tracker, https://github.com/matplotlib/matplotlib/issues
-Project-URL: Forum, https://discourse.matplotlib.org/
-Project-URL: Donate, https://numfocus.org/donate-to-matplotlib
-Platform: any
-Classifier: Development Status :: 5 - Production/Stable
-Classifier: Framework :: Matplotlib
-Classifier: Intended Audience :: Science/Research
-Classifier: Intended Audience :: Education
-Classifier: License :: OSI Approved :: Python Software Foundation License
-Classifier: Programming Language :: Python
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Topic :: Scientific/Engineering :: Visualization
-Requires-Python: >=3.6
-Description-Content-Type: text/x-rst
-Requires-Dist: cycler (>=0.10)
-Requires-Dist: kiwisolver (>=1.0.1)
-Requires-Dist: numpy (>=1.11)
-Requires-Dist: pyparsing (!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1)
-Requires-Dist: python-dateutil (>=2.1)
-
-|Travis|_ |AzurePipelines|_ |AppVeyor|_ |Codecov|_ |LGTM|_ |PyPi|_ |Gitter|_ |NUMFocus|_ |GitTutorial|_
-
-
-.. |Travis| image:: https://travis-ci.org/matplotlib/matplotlib.svg?branch=master
-.. _Travis: https://travis-ci.org/matplotlib/matplotlib
-
-.. |AzurePipelines| image:: https://dev.azure.com/matplotlib/matplotlib/_apis/build/status/matplotlib.matplotlib?branchName=master
-.. _AzurePipelines: https://dev.azure.com/matplotlib/matplotlib/_build/latest?definitionId=1&branchName=master
-
-.. |AppVeyor| image:: https://ci.appveyor.com/api/projects/status/github/matplotlib/matplotlib?branch=master&svg=true
-.. _AppVeyor: https://ci.appveyor.com/project/matplotlib/matplotlib
-
-.. |Codecov| image:: https://codecov.io/github/matplotlib/matplotlib/badge.svg?branch=master&service=github
-.. _Codecov: https://codecov.io/github/matplotlib/matplotlib?branch=master
-
-.. |LGTM| image:: https://img.shields.io/lgtm/grade/python/g/matplotlib/matplotlib.svg?logo=lgtm&logoWidth=18
-.. _LGTM: https://lgtm.com/projects/g/matplotlib/matplotlib
-
-.. |PyPi| image:: https://badge.fury.io/py/matplotlib.svg
-.. _PyPi: https://badge.fury.io/py/matplotlib
-
-.. |Gitter| image:: https://badges.gitter.im/matplotlib/matplotlib.png
-.. _Gitter: https://gitter.im/matplotlib/matplotlib
-
-.. |NUMFocus| image:: https://img.shields.io/badge/powered%20by-NumFOCUS-orange.svg?style=flat&colorA=E1523D&colorB=007D8A
-.. _NUMFocus: https://www.numfocus.org
-
-.. |GitTutorial| image:: https://img.shields.io/badge/PR-Welcome-%23FF8300.svg?
-.. _GitTutorial: https://git-scm.com/book/en/v2/GitHub-Contributing-to-a-Project
-
-.. image:: https://matplotlib.org/_static/logo2.svg
-
-
-Matplotlib is a comprehensive library for creating static, animated, and interactive visualizations in Python.
-
-Check out our `home page <https://matplotlib.org/>`_ for more information.
-
-.. image:: https://matplotlib.org/_static/readme_preview.png
-
-Matplotlib produces publication-quality figures in a variety of hardcopy formats
-and interactive environments across platforms. Matplotlib can be used in Python scripts,
-the Python and IPython shell, web application servers, and various
-graphical user interface toolkits.
-
-
-Install
-=======
-
-For installation instructions and requirements, see `INSTALL.rst <INSTALL.rst>`_  or the
-`install <https://matplotlib.org/users/installing.html>`_ documentation.
-
-Test
-====
-
-After installation, launch the test suite::
-
-  python -m pytest
-
-Read the `testing guide <https://matplotlib.org/devel/testing.html>`_ for more information and alternatives.
-
-Contribute
-==========
-You've discovered a bug or something else you want to change - excellent!
-
-You've worked out a way to fix it – even better!
-
-You want to tell us about it – best of all!
-
-Start at the `contributing guide <https://matplotlib.org/devdocs/devel/contributing.html>`_!
-
-Contact
-=======
-
-`Discourse <https://discourse.matplotlib.org/>`_ is the discussion forum for general questions and discussions and our recommended starting point.
-
-Our active mailing lists (which are mirrored on Discourse) are:
-
-* `Users <https://mail.python.org/mailman/listinfo/matplotlib-users>`_ mailing list: matplotlib-users@python.org
-* `Announcement  <https://mail.python.org/mailman/listinfo/matplotlib-announce>`_ mailing list: matplotlib-announce@python.org
-* `Development <https://mail.python.org/mailman/listinfo/matplotlib-devel>`_ mailing list: matplotlib-devel@python.org
-
-Gitter_ is for coordinating development and asking questions directly related
-to contributing to matplotlib.
-
-
-Citing Matplotlib
-=================
-If Matplotlib contributes to a project that leads to publication, please
-acknowledge this by citing Matplotlib.
-
-`A ready-made citation entry <https://matplotlib.org/citing.html>`_ is available.
-
-

+ 0 - 892
venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/RECORD

@@ -1,892 +0,0 @@
-__pycache__/pylab.cpython-38.pyc,,
-matplotlib-3.2.1-py3.8-nspkg.pth,sha256=FgO_3ug071EXEKT8mgOPBUhyrswPtPCYjOpUCyau7UU,569
-matplotlib-3.2.1.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
-matplotlib-3.2.1.dist-info/METADATA,sha256=F1oGQTHWb-ltDWNhlYUpDR9UvF5wAQ7l9pyVaRKk_1M,5170
-matplotlib-3.2.1.dist-info/RECORD,,
-matplotlib-3.2.1.dist-info/WHEEL,sha256=VEyGcIFAmk_1KbI6gaZGw_mMiT-pdGweASQLX-DzYaY,108
-matplotlib-3.2.1.dist-info/namespace_packages.txt,sha256=A2PHFg9NKYOU4pEQ1h97U0Qd-rB-65W34XqC-56ZN9g,13
-matplotlib-3.2.1.dist-info/top_level.txt,sha256=9tEw2ni8DdgX8CceoYHqSH1s50vrJ9SDfgtLIG8e3Y4,30
-matplotlib/.libs/libpng16-cfdb1654.so.16.21.0,sha256=Fo8LBDWTuCclLkpSng_KP5pI7wcQtuXA9opT1FFkXl0,275648
-matplotlib/.libs/libz-a147dcb0.so.1.2.3,sha256=VwXH3AM7bnoa793tKDw_H0pW-VZos08-FEtM_g_VWVM,87848
-matplotlib/__init__.py,sha256=FLEIOOmlbJDBzqg4aq8W6w0wSpQF9tVwGu0VW8EwqsA,54615
-matplotlib/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/__pycache__/_animation_data.cpython-38.pyc,,
-matplotlib/__pycache__/_cm.cpython-38.pyc,,
-matplotlib/__pycache__/_cm_listed.cpython-38.pyc,,
-matplotlib/__pycache__/_color_data.cpython-38.pyc,,
-matplotlib/__pycache__/_constrained_layout.cpython-38.pyc,,
-matplotlib/__pycache__/_layoutbox.cpython-38.pyc,,
-matplotlib/__pycache__/_mathtext_data.cpython-38.pyc,,
-matplotlib/__pycache__/_pylab_helpers.cpython-38.pyc,,
-matplotlib/__pycache__/_text_layout.cpython-38.pyc,,
-matplotlib/__pycache__/_version.cpython-38.pyc,,
-matplotlib/__pycache__/afm.cpython-38.pyc,,
-matplotlib/__pycache__/animation.cpython-38.pyc,,
-matplotlib/__pycache__/artist.cpython-38.pyc,,
-matplotlib/__pycache__/axis.cpython-38.pyc,,
-matplotlib/__pycache__/backend_bases.cpython-38.pyc,,
-matplotlib/__pycache__/backend_managers.cpython-38.pyc,,
-matplotlib/__pycache__/backend_tools.cpython-38.pyc,,
-matplotlib/__pycache__/bezier.cpython-38.pyc,,
-matplotlib/__pycache__/blocking_input.cpython-38.pyc,,
-matplotlib/__pycache__/category.cpython-38.pyc,,
-matplotlib/__pycache__/cm.cpython-38.pyc,,
-matplotlib/__pycache__/collections.cpython-38.pyc,,
-matplotlib/__pycache__/colorbar.cpython-38.pyc,,
-matplotlib/__pycache__/colors.cpython-38.pyc,,
-matplotlib/__pycache__/container.cpython-38.pyc,,
-matplotlib/__pycache__/contour.cpython-38.pyc,,
-matplotlib/__pycache__/dates.cpython-38.pyc,,
-matplotlib/__pycache__/docstring.cpython-38.pyc,,
-matplotlib/__pycache__/dviread.cpython-38.pyc,,
-matplotlib/__pycache__/figure.cpython-38.pyc,,
-matplotlib/__pycache__/font_manager.cpython-38.pyc,,
-matplotlib/__pycache__/fontconfig_pattern.cpython-38.pyc,,
-matplotlib/__pycache__/gridspec.cpython-38.pyc,,
-matplotlib/__pycache__/hatch.cpython-38.pyc,,
-matplotlib/__pycache__/image.cpython-38.pyc,,
-matplotlib/__pycache__/legend.cpython-38.pyc,,
-matplotlib/__pycache__/legend_handler.cpython-38.pyc,,
-matplotlib/__pycache__/lines.cpython-38.pyc,,
-matplotlib/__pycache__/markers.cpython-38.pyc,,
-matplotlib/__pycache__/mathtext.cpython-38.pyc,,
-matplotlib/__pycache__/mlab.cpython-38.pyc,,
-matplotlib/__pycache__/offsetbox.cpython-38.pyc,,
-matplotlib/__pycache__/patches.cpython-38.pyc,,
-matplotlib/__pycache__/path.cpython-38.pyc,,
-matplotlib/__pycache__/patheffects.cpython-38.pyc,,
-matplotlib/__pycache__/pylab.cpython-38.pyc,,
-matplotlib/__pycache__/pyplot.cpython-38.pyc,,
-matplotlib/__pycache__/quiver.cpython-38.pyc,,
-matplotlib/__pycache__/rcsetup.cpython-38.pyc,,
-matplotlib/__pycache__/sankey.cpython-38.pyc,,
-matplotlib/__pycache__/scale.cpython-38.pyc,,
-matplotlib/__pycache__/spines.cpython-38.pyc,,
-matplotlib/__pycache__/stackplot.cpython-38.pyc,,
-matplotlib/__pycache__/streamplot.cpython-38.pyc,,
-matplotlib/__pycache__/table.cpython-38.pyc,,
-matplotlib/__pycache__/texmanager.cpython-38.pyc,,
-matplotlib/__pycache__/text.cpython-38.pyc,,
-matplotlib/__pycache__/textpath.cpython-38.pyc,,
-matplotlib/__pycache__/ticker.cpython-38.pyc,,
-matplotlib/__pycache__/tight_bbox.cpython-38.pyc,,
-matplotlib/__pycache__/tight_layout.cpython-38.pyc,,
-matplotlib/__pycache__/transforms.cpython-38.pyc,,
-matplotlib/__pycache__/type1font.cpython-38.pyc,,
-matplotlib/__pycache__/units.cpython-38.pyc,,
-matplotlib/__pycache__/widgets.cpython-38.pyc,,
-matplotlib/_animation_data.py,sha256=yClmMx6K-y6pjG3FdHancRyRhyneFuBEbQZ_lhezVys,7499
-matplotlib/_cm.py,sha256=nZCQdTWsPc5aJ-n08l2g293Wwg0kSWIgcfStzv9Dtxg,66643
-matplotlib/_cm_listed.py,sha256=9aMZ1uoTkxeDKlXfUNmY99HEtAXsW_JcSpwYaBs0kHs,98165
-matplotlib/_color_data.py,sha256=K2HSKblmuh-X_1ZZ9TcXcP7iKHaGC4mC_ScWqX_tdXE,34947
-matplotlib/_constrained_layout.py,sha256=eafuhM2rw5SL_ilqf0ImxQwtmFX_pR_boeKUrjTHvB0,29678
-matplotlib/_contour.cpython-38-x86_64-linux-gnu.so,sha256=J8lraYcOxIbZ6hAIyK0zvSYKyRunSzUdFyZSmcqF004,95144
-matplotlib/_image.cpython-38-x86_64-linux-gnu.so,sha256=jiNef3vzvaDg8wpvmd-fASybETFlxpgOlQiSYzofU_Q,239232
-matplotlib/_layoutbox.py,sha256=LG5KEmNm5apZa1putqzafEpX9w4lLwkoOPxg4owiO2Y,23872
-matplotlib/_mathtext_data.py,sha256=CmKFRW6mXCJqgZSQaiNOSG_VUn9WiSx5Hrg-4qKIn14,89371
-matplotlib/_path.cpython-38-x86_64-linux-gnu.so,sha256=Eb0DMGN_CF3SuY27zCnwjyranrGxg60lR8UYHuj6nSQ,190216
-matplotlib/_png.cpython-38-x86_64-linux-gnu.so,sha256=wL4br11noZizM-qrCC6H39HHmIFJkNibGmttbjh7Jdo,35552
-matplotlib/_pylab_helpers.py,sha256=RscVbvWEk6QyznzVvX-lSHkWCUOo9Lik7D7j4xelQJ4,3445
-matplotlib/_qhull.cpython-38-x86_64-linux-gnu.so,sha256=byRIOIOe-V5tqwnMCI7i-3lhqlNAC6VC6MP78x-7EpM,382672
-matplotlib/_text_layout.py,sha256=88DxzfAOPzpRjpu0OwLaRl6eOVJ5Var8ZxrDyhAQ7C8,1036
-matplotlib/_tri.cpython-38-x86_64-linux-gnu.so,sha256=7wzrMnAFHdKA3-9Eg3A-3x8E-_jDdkm4bJRZdHxiFBk,125960
-matplotlib/_version.py,sha256=etxeX_ByADCJBN53WhU2IEezakT1gixcO41qmDlMwfY,471
-matplotlib/afm.py,sha256=Y2FmLqutIXI__QiAbMNpFclleQrpGf1xsqBgjyCZir0,16642
-matplotlib/animation.py,sha256=N0HzAqLF1fscM2OIkER3gv4zsqUXWpxA8BmE_3Jqi5k,68066
-matplotlib/artist.py,sha256=2Qd4EUb9n4FAizD1fdb48diR7yRivgwvY8JESg4r4mE,53229
-matplotlib/axes/__init__.py,sha256=npQuBvs_xEBEGUP2-BBZzCrelsAQYgB1U96kSZTSWIs,46
-matplotlib/axes/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/axes/__pycache__/_axes.cpython-38.pyc,,
-matplotlib/axes/__pycache__/_base.cpython-38.pyc,,
-matplotlib/axes/__pycache__/_secondary_axes.cpython-38.pyc,,
-matplotlib/axes/__pycache__/_subplots.cpython-38.pyc,,
-matplotlib/axes/_axes.py,sha256=dSaGhVBB00lKf1AF9mCsaFcleTU8qKlSkVNP2ET_CPU,312519
-matplotlib/axes/_base.py,sha256=x89D4ElapqkI9lQ0oTAwTGcKPm-m-J26Fg-A0R3Ys1M,159726
-matplotlib/axes/_secondary_axes.py,sha256=plMlrvrznuuBSRakuznyCyr_ZNnSiuc_3J-YD3Hg8e8,14352
-matplotlib/axes/_subplots.py,sha256=rkT6vCCbCTItY_oAmlT-1rSPOoIerjScJC91I2YLTp0,10203
-matplotlib/axis.py,sha256=50zN9IvoaYGqq8t8zUiaaTtcUJeNjxdAnmXioRlfNWc,90049
-matplotlib/backend_bases.py,sha256=vNzjru0RDGIlzyeT9vjmWv8ktEFaax0C7W1tXz1qR_w,117888
-matplotlib/backend_managers.py,sha256=HuHOXPFjVF1R6ttBLxlucsLcEsWlRXtbm_wr1OJer2Q,12819
-matplotlib/backend_tools.py,sha256=zVBxfyPoQx0_lQe1Su0o-zTycOQt-zKWTp3HEY-jTxI,36252
-matplotlib/backends/__init__.py,sha256=cKAeiC5g0Up9svoxT24paOcnKc4tb5cbfbF-AWxXLUE,1722
-matplotlib/backends/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/backends/__pycache__/_backend_pdf_ps.cpython-38.pyc,,
-matplotlib/backends/__pycache__/_backend_tk.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_agg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_cairo.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_gtk3.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_gtk3agg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_gtk3cairo.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_macosx.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_mixed.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_nbagg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_pdf.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_pgf.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_ps.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_qt4.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_qt4agg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_qt4cairo.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_qt5.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_qt5agg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_qt5cairo.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_svg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_template.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_tkagg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_tkcairo.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_webagg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_webagg_core.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_wx.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_wxagg.cpython-38.pyc,,
-matplotlib/backends/__pycache__/backend_wxcairo.cpython-38.pyc,,
-matplotlib/backends/__pycache__/qt_compat.cpython-38.pyc,,
-matplotlib/backends/_backend_agg.cpython-38-x86_64-linux-gnu.so,sha256=UvDwI9RPPoFGH_PODmYP6DqcgeGCiqEoloxbDWaY51Y,358224
-matplotlib/backends/_backend_pdf_ps.py,sha256=T8x_NWAo9_Wvnpw6HnsneRI9AyAxcp80TDe-z2eosbM,2709
-matplotlib/backends/_backend_tk.py,sha256=k1eZjNeVC0rDMEKlOqevga-PFTERv9mcwUn_d_LZUyo,32021
-matplotlib/backends/_tkagg.cpython-38-x86_64-linux-gnu.so,sha256=r_YnlqbmC6XT7-Mm6AdmjNWa0mBoQLJd9xmbZow6HI0,27192
-matplotlib/backends/backend_agg.py,sha256=bjt43QEsQ-AeEeWXSBwRcbJsuDU7Dex-JsdbApekXzA,22347
-matplotlib/backends/backend_cairo.py,sha256=zJAQ5_OkKchNrItE8jN9CriAw4aQ0PP3qKqfINu3CSc,16562
-matplotlib/backends/backend_gtk3.py,sha256=ED_iXiCIXQlMJmh8YlJJcPkCxnm9Wly7kSod0UogtRc,33832
-matplotlib/backends/backend_gtk3agg.py,sha256=iKLBQ48c9Vh4krSxYeSDbHZ4G9wXoezk2VTIgNR4BWw,3072
-matplotlib/backends/backend_gtk3cairo.py,sha256=TDQUuYq5KCPvAU-MY2wBxpx2zAn9vOO_ieeE_7fdtS4,1591
-matplotlib/backends/backend_macosx.py,sha256=fALNUVEkZrqRrMHe5G_wy5i7FODvXXIum7RU2PXOiG4,5829
-matplotlib/backends/backend_mixed.py,sha256=R3-Z5AW7anq31csMjylsY4pSehsAsBLrxFD5YhZkZ6w,5280
-matplotlib/backends/backend_nbagg.py,sha256=xAv_OZfz6NtMrbAXWqwX9GCgTEsb5e5FpyAMHSIE-j4,8902
-matplotlib/backends/backend_pdf.py,sha256=sq_dTpmyOkYrtWdHQGKanZxRezXFmfeZNCMcObJR95A,96197
-matplotlib/backends/backend_pgf.py,sha256=R34xfvJyVm0k4IgjCHPU0bKeP02zJ0_Pr0hV6yaCVv8,43431
-matplotlib/backends/backend_ps.py,sha256=MWZmgx9nrlp9_u50gp_JZE2bEt2E3ixZxPqT9Wk5BqY,50575
-matplotlib/backends/backend_qt4.py,sha256=H9AsG4NAF27LdGUJDi1n5RwJhK1lI43sa9VXtUgW3K8,397
-matplotlib/backends/backend_qt4agg.py,sha256=BXMTBYmqyT_uvEpgSMWts5m2q1YK0vhPeybt0ZMVd0I,292
-matplotlib/backends/backend_qt4cairo.py,sha256=cvXKhk8CZvceDiEl9OXmumjJ6dZ3k0u93xy8w8i24gQ,229
-matplotlib/backends/backend_qt5.py,sha256=BjGTvVXytXhqRPpYNzoWaO03ULCfKdF3xG78e9nr0Sc,39256
-matplotlib/backends/backend_qt5agg.py,sha256=sF1oFyKNmOAdCGUChUbrKfmFmNo8QuD2SzuQQl4U0Mg,3560
-matplotlib/backends/backend_qt5cairo.py,sha256=YzXN1Ckr6JLS2r50LPxeypajdWccXaHoXC5QZ4VWrEY,1892
-matplotlib/backends/backend_svg.py,sha256=KGdJMf-cXIW82s0MC9-wOsmtEeo8P3np_uK06z2FGkI,43552
-matplotlib/backends/backend_template.py,sha256=SVPx4bl2n0eKgEolfJH7ljJnqlak0XhFE6Zr3yr6GU4,8407
-matplotlib/backends/backend_tkagg.py,sha256=WMslLWYmtxlmAaBH4tx4HjmRDWMKiSV91KHF9yeMRng,676
-matplotlib/backends/backend_tkcairo.py,sha256=dVCh7ZD_2OR0DBQ0N3icD8cDV1SeEzCsRja446wWhPw,1069
-matplotlib/backends/backend_webagg.py,sha256=NtP1VSSXQNvB_EBQi14No7flt1C64VwekiTG58tt7LU,10794
-matplotlib/backends/backend_webagg_core.py,sha256=u026hAuD_dwL0a2D7g--jzBr_KFS5UqJdFZDvIdlmII,17558
-matplotlib/backends/backend_wx.py,sha256=O606ybHYiOFCxpnhpZ_TYaHdULG53YuAZQDq70xjoms,66672
-matplotlib/backends/backend_wxagg.py,sha256=Jhb24f2W6e5yCqSi4F971hor_I8Epf_WMfutq3VoTYI,3027
-matplotlib/backends/backend_wxcairo.py,sha256=VC5TyJaX8TPLSgHv5ckAreoGrY_KiNRMQjVInMLlcFk,1843
-matplotlib/backends/qt_compat.py,sha256=Me6QS6xk4ASjOdBhr7RxvIp4Frzbdmu7mIXRO5uJlwU,6551
-matplotlib/backends/qt_editor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-matplotlib/backends/qt_editor/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/backends/qt_editor/__pycache__/_formlayout.cpython-38.pyc,,
-matplotlib/backends/qt_editor/__pycache__/figureoptions.cpython-38.pyc,,
-matplotlib/backends/qt_editor/__pycache__/formlayout.cpython-38.pyc,,
-matplotlib/backends/qt_editor/__pycache__/formsubplottool.cpython-38.pyc,,
-matplotlib/backends/qt_editor/_formlayout.py,sha256=aHC33AfwtVjly7sPjLTFrVABZqAD2RAloR6KCEAUv5A,20592
-matplotlib/backends/qt_editor/figureoptions.py,sha256=YySx6A_wZSACMEHbXYkoQ6wR0_6PPwON2c6YwejUeVs,9481
-matplotlib/backends/qt_editor/formlayout.py,sha256=ERfmFwpvhl168PWNTJ0SFhQmPuSrmjzFNOe_puUCoSE,177
-matplotlib/backends/qt_editor/formsubplottool.py,sha256=HiiXkwCotra_hI9JU208KOs8Q9JuGH1uAW3mV5l3Evg,1934
-matplotlib/backends/web_backend/all_figures.html,sha256=m20aQIhuI4GBdrgZg_j02zSVjAcTRUufPOMSe4i7ayc,1525
-matplotlib/backends/web_backend/css/boilerplate.css,sha256=qui16QXRnQFNJDbcMasfH6KtN9hLjv8883U9cJmsVCE,2310
-matplotlib/backends/web_backend/css/fbm.css,sha256=Us0osu_rK8EUAdp_GXrh89tN_hUNCN-r7N1T1NvmmwI,1473
-matplotlib/backends/web_backend/css/page.css,sha256=Djf6ZNMFaM6_hVaizSkDFoqk-jn81qgduwles4AroGk,1599
-matplotlib/backends/web_backend/ipython_inline_figure.html,sha256=mzi-yWg4fcO6PdtTBCfiNuvcv04T53lcRQi-8hphwuE,1305
-matplotlib/backends/web_backend/jquery-ui-1.12.1/AUTHORS.txt,sha256=W2Lh1mbGo3Owc0oXX9U1-TFVSZYaC72KvSRrrRp3UII,12660
-matplotlib/backends/web_backend/jquery-ui-1.12.1/LICENSE.txt,sha256=3jP7aViA0LB2FdS4b3jNQ3lpBpWa3l_f73CWiCeg23g,1817
-matplotlib/backends/web_backend/jquery-ui-1.12.1/external/jquery/jquery.js,sha256=Qw82-bXyGq6MydymqBxNPYTaUXXq7c8v3CwiYwLLNXU,293430
-matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_444444_256x240.png,sha256=6vfH7idHJ13abFPnMaENsaexX0-7RuG2nWuyBWvJ_YE,7006
-matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_555555_256x240.png,sha256=XQQFHf2dLXQDVUBPmKaD0ewP6y_KfXblM8Gm5c6S3S4,7074
-matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_777620_256x240.png,sha256=nb5KDQP-7W9l6yVgoKi0ukJkVF7o_THBdjo7IZ0DKNY,4676
-matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_777777_256x240.png,sha256=51snIR4W_PlHFRaAAbtwVco3bUb5KBELo9CCUjJFLlo,7013
-matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_cc0000_256x240.png,sha256=AokVddQ1jp7d4-QtlAV_jp-CqdZDdvce6GzvFJ0wU34,4632
-matplotlib/backends/web_backend/jquery-ui-1.12.1/images/ui-icons_ffffff_256x240.png,sha256=trBt7vK5JMw4NdY_SIPUeIJzSjPnGyEtkXpozt47jp0,6313
-matplotlib/backends/web_backend/jquery-ui-1.12.1/index.html,sha256=5g7_MLZlkh92FXWOR0q02My8knssXq20DXz-BkiYiP4,32588
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.css,sha256=p6xU9YulB7E2Ic62_PX-h59ayb3PBJ0WFTEQxq0EjHw,37326
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.js,sha256=T0Vest3yCU7pafRw9r-settMBX6JkKN06dqBnpQ8d30,520714
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.min.css,sha256=rByPlHULObEjJ6XQxW_flG2r-22R5dKiAoef-aXWfik,32076
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.min.js,sha256=KM512VNnjElC30ehFwehXjx1YCHPiQkOPmqnrWtpccM,253669
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.structure.css,sha256=E1uqV-d412nbSI-oqDMIQsTSttP-FS7Bxwc7mQdQYOo,18705
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.structure.min.css,sha256=rxais37anKUnpL5QzSYte-JnIsmkGmLG-ZhKSkZkwVM,15548
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.theme.css,sha256=mEMD30TTg-vIEGUmHHgcgSOgm0FBfLipyQ97Jr0TTH8,18671
-matplotlib/backends/web_backend/jquery-ui-1.12.1/jquery-ui.theme.min.css,sha256=AjyoyaRtnGVTywKH_Isxxu5PXI0s4CcE0BzPAX83Ppc,13849
-matplotlib/backends/web_backend/jquery-ui-1.12.1/package.json,sha256=kjEW8xMYuqRSwEE58KqTDNLgkx_6YL7tb1M9vlMK98w,1847
-matplotlib/backends/web_backend/js/mpl.js,sha256=xrBOaet7K2P2iq7wgIexceDdc9T_WFb4TPJXDX55JuU,16991
-matplotlib/backends/web_backend/js/mpl_tornado.js,sha256=lSxC7-yqF1GYY-6SheaHanx6SujMdcG7Vx2_3qbi-9Q,272
-matplotlib/backends/web_backend/js/nbagg_mpl.js,sha256=nqIF0zFBQGpOo5Tmq2uRkyFJDeali66PWQDSYySgpnQ,7428
-matplotlib/backends/web_backend/nbagg_uat.ipynb,sha256=y1N8hQzBJ05rJ2hZla2_Mw6tOUfNP1UHKo636W1e098,15933
-matplotlib/backends/web_backend/single_figure.html,sha256=-iFrlIsaY1rOK9bNiDxcX8fdc0WP7DXXq-MEuLYfOvM,1216
-matplotlib/bezier.py,sha256=Fqb2gqRnmS2wYjEZVFcdSngRxh5g_hFnxX82RFpimec,17271
-matplotlib/blocking_input.py,sha256=soMcLeXT2mKxkH5fyQqYEOP_Dd-TUjoA1_L7imb2B2Q,11105
-matplotlib/category.py,sha256=_iJbNlZzi3kqPtz_bhEBCj8q6RsBp5Urd3yNS81dOQg,7131
-matplotlib/cbook/__init__.py,sha256=k7_Gdpbg26mrQlfQJr3eTnRGvXInhfuEjWeBrY5-IlY,70426
-matplotlib/cbook/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/cbook/__pycache__/deprecation.cpython-38.pyc,,
-matplotlib/cbook/deprecation.py,sha256=E8xSJYv-br0VswU-LNQFTU0VlurdH6v2rNOMCvOfs2I,15080
-matplotlib/cm.py,sha256=qo1ZhJvKa7dCfALcj1X6rsy7R60pbJht7zK6pi_9EcA,12623
-matplotlib/collections.py,sha256=n_Mru2nfEhqvAGHAD3g_JhWAoxvtK5MjYFLfztvSK3s,74328
-matplotlib/colorbar.py,sha256=gaI17iRKX4NntEaLROYsg4q1fXUboda2L0w7PUaWSKg,63074
-matplotlib/colors.py,sha256=auWiOGPMdI5twHSoVVI0AyEe7O9LJfn3fKetp_8yMzA,75537
-matplotlib/compat/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-matplotlib/compat/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/container.py,sha256=yAq9s8ylaQxkt2N-qTSnBdF7zQZ5_-g96XgKzlySaLI,4302
-matplotlib/contour.py,sha256=p8PJvj7N7wd-yA94NP7cz230VHmYG3rkSsdYSoTP4hE,68387
-matplotlib/dates.py,sha256=hGrXqJ-O1ahP2yCYK0HjFWJu0jt-EDke1S33VZ2uOe0,66867
-matplotlib/docstring.py,sha256=TuDl6xhQwCISvIV5_rPKvT85V1k1IA5HVSyK-JMY9k4,3970
-matplotlib/dviread.py,sha256=sO5Mq6CkNYqgu5S3oMcDc6Gqh1YhD36VoRWH9PbbIJw,39009
-matplotlib/figure.py,sha256=yQsOCdFl3HHez8H3Y6xylSKAAEZzy-Hl-b1-BSJ3r8k,100886
-matplotlib/font_manager.py,sha256=OZ2BAmPgFrO4VjeBA-DKGM0H0I5T4ev5gtAdirbXwR0,45282
-matplotlib/fontconfig_pattern.py,sha256=El7xTXT3EnEESVONX9bKz_Yvaq4lLQp3KIYBgNbAguI,6719
-matplotlib/ft2font.cpython-38-x86_64-linux-gnu.so,sha256=8ZalFUIbDG4e1r_hh9jOu1kktn6flWEH2TZHa4Xol_A,919008
-matplotlib/gridspec.py,sha256=k_YO0Enho4Ztxi9-rv-ZgSXs-rrqKq1TdeOGwOzJwQI,25046
-matplotlib/hatch.py,sha256=6AcnVeBs4d_Uv_FWQoU48v28iW5F7oKI_RKkv68L_WM,6971
-matplotlib/image.py,sha256=0FR_I8bEV0XfM6kYyAS8j965LCbtapgnpxDWLrEV390,62787
-matplotlib/legend.py,sha256=QBSq0VyGWFsTB7QFGx8bpmUR-MLw9xJPrhMcJSlpVtU,48268
-matplotlib/legend_handler.py,sha256=hDMDvDJepK6UUyTJCkGQcAMVgLYW7eD16hQoQNVGQFY,26428
-matplotlib/lines.py,sha256=8u3vEQXb_ceOivl4zyL5MIDuVDlxgZwOsH9xf37OIYo,51362
-matplotlib/markers.py,sha256=Xpuq9O1t7OB3DBK2nZa4IbPjqV0ROGY9mxXW_NUKDKk,32533
-matplotlib/mathtext.py,sha256=udfWXa-87xV1Mhve65rO0jf5On3DAQwJ-FgD6BSojhM,120491
-matplotlib/mlab.py,sha256=1V0nvAkZF5RJbsIAp3AfTgzim2wRQCql0FCq7HvLknI,49040
-matplotlib/mpl-data/fonts/afm/cmex10.afm,sha256=blR3ERmrVBV5XKkAnDCj4NMeYVgzH7cXtJ3u59u9GuE,12070
-matplotlib/mpl-data/fonts/afm/cmmi10.afm,sha256=5qwEOpedEo76bDUahyuuF1q0cD84tRrX-VQ4p3MlfBo,10416
-matplotlib/mpl-data/fonts/afm/cmr10.afm,sha256=WDvgC_D3UkGJg9u-J0U6RaT02lF4oz3lQxHtg1r3lYw,10101
-matplotlib/mpl-data/fonts/afm/cmsy10.afm,sha256=AbmzvCVWBceHRfmRfeJ9E6xzOQTFLk0U1zDfpf3_MaM,8295
-matplotlib/mpl-data/fonts/afm/cmtt10.afm,sha256=4ji7_mTpeWMa93o_UHBWPKCnqsBfhJJNllat1lJArP4,6501
-matplotlib/mpl-data/fonts/afm/pagd8a.afm,sha256=jjFrigwkTpYLqa26cpzZvKQNBo-PuF4bmDVqaM4pMWw,17183
-matplotlib/mpl-data/fonts/afm/pagdo8a.afm,sha256=sgNQdeYyx8J-itGw9h31y95aMBiTCRvmNSPTXwwS7xg,17255
-matplotlib/mpl-data/fonts/afm/pagk8a.afm,sha256=ZUtfHPloNqcvGMHMxaKDSlshhOcjwheUx143RwpGdIU,17241
-matplotlib/mpl-data/fonts/afm/pagko8a.afm,sha256=Yj1wBg6Jsqqz1KBfhRoJ3ACR-CMQol8Fj_ZM5NZ1gDk,17346
-matplotlib/mpl-data/fonts/afm/pbkd8a.afm,sha256=Zl5o6J_di9Y5j2EpHtjew-_sfg7-WoeVmO9PzOYSTUc,15157
-matplotlib/mpl-data/fonts/afm/pbkdi8a.afm,sha256=JAOno930iTyfZILMf11vWtiaTgrJcPpP6FRTRhEMMD4,15278
-matplotlib/mpl-data/fonts/afm/pbkl8a.afm,sha256=UJqJjOJ6xQDgDBLX157mKpohIJFVmHM-N6x2-DiGv14,15000
-matplotlib/mpl-data/fonts/afm/pbkli8a.afm,sha256=AWislZ2hDbs0ox_qOWREugsbS8_8lpL48LPMR40qpi0,15181
-matplotlib/mpl-data/fonts/afm/pcrb8a.afm,sha256=6j1TS2Uc7DWSc-8l42TGDc1u0Fg8JspeWfxFayjUwi8,15352
-matplotlib/mpl-data/fonts/afm/pcrbo8a.afm,sha256=smg3mjl9QaBDtQIt06ko5GvaxLsO9QtTvYANuE5hfG0,15422
-matplotlib/mpl-data/fonts/afm/pcrr8a.afm,sha256=7nxFr0Ehz4E5KG_zSE5SZOhxRH8MyfnCbw-7x5wu7tw,15339
-matplotlib/mpl-data/fonts/afm/pcrro8a.afm,sha256=NKEz7XtdFkh9cA8MvY-S3UOZlV2Y_J3tMEWFFxj7QSg,15443
-matplotlib/mpl-data/fonts/afm/phvb8a.afm,sha256=NAx4M4HjL7vANCJbc-tk04Vkol-T0oaXeQ3T2h-XUvM,17155
-matplotlib/mpl-data/fonts/afm/phvb8an.afm,sha256=8e_myD-AQkNF7q9XNLb2m76_lX2TUr3a5wog_LIE1sk,17086
-matplotlib/mpl-data/fonts/afm/phvbo8a.afm,sha256=8fkBRmJ-SWY2YrBg8fFyjJyrJp8daQ6JPO6LvhM8xPI,17230
-matplotlib/mpl-data/fonts/afm/phvbo8an.afm,sha256=aeVRvV4r15BBvxuRJ0MG8ZHuH2HViuIiCYkvuapmkmM,17195
-matplotlib/mpl-data/fonts/afm/phvl8a.afm,sha256=IyMYM-bgl-gI6rG0EuZZ2OLzlxJfGeSh8xqsh0t-eJQ,15627
-matplotlib/mpl-data/fonts/afm/phvlo8a.afm,sha256=s12C-eNnIDHJ_UVbuiprjxBjCiHIbS3Y8ORTC-qTpuI,15729
-matplotlib/mpl-data/fonts/afm/phvr8a.afm,sha256=Kt8KaRidts89EBIK29X2JomDUEDxvroeaJz_RNTi6r4,17839
-matplotlib/mpl-data/fonts/afm/phvr8an.afm,sha256=lL5fAHTRwODl-sB5mH7IfsD1tnnea4yRUK-_Ca2bQHM,17781
-matplotlib/mpl-data/fonts/afm/phvro8a.afm,sha256=3KqK3eejiR4hIFBUynuSX_4lMdE2V2T58xOF8lX-fwc,17919
-matplotlib/mpl-data/fonts/afm/phvro8an.afm,sha256=Vx9rRf3YfasMY7tz-njSxz67xHKk-fNkN7yBi0X2IP0,17877
-matplotlib/mpl-data/fonts/afm/pncb8a.afm,sha256=aoXepTcDQtQa_mspflMJkEFKefzXHoyjz6ioJVI0YNc,16028
-matplotlib/mpl-data/fonts/afm/pncbi8a.afm,sha256=pCWW1MYgy0EmvwaYsaYJaAI_LfrsKmDANHu7Pk0RaiU,17496
-matplotlib/mpl-data/fonts/afm/pncr8a.afm,sha256=0CIB2BLe9r-6_Wl5ObRTTf98UOrezmGQ8ZOuBX5kLks,16665
-matplotlib/mpl-data/fonts/afm/pncri8a.afm,sha256=5R-pLZOnaHNG8pjV6MP3Ai-d2OTQYR_cYCb5zQhzfSU,16920
-matplotlib/mpl-data/fonts/afm/pplb8a.afm,sha256=3EzUbNnXr5Ft5eFLY00W9oWu59rHORgDXUuJaOoKN58,15662
-matplotlib/mpl-data/fonts/afm/pplbi8a.afm,sha256=X_9tVspvrcMer3OS8qvdwjFFqpAXYZneyCL2NHA902g,15810
-matplotlib/mpl-data/fonts/afm/pplr8a.afm,sha256=ijMb497FDJ9nVdVMb21F7W3-cu9sb_9nF0oriFpSn8k,15752
-matplotlib/mpl-data/fonts/afm/pplri8a.afm,sha256=8KITbarcUUMi_hdoRLLmNHtlqs0TtOSKqtPFft7X5nY,15733
-matplotlib/mpl-data/fonts/afm/psyr.afm,sha256=Iyt8ajE4B2Tm34oBj2pKtctIf9kPfq05suQefq8p3Ro,9644
-matplotlib/mpl-data/fonts/afm/ptmb8a.afm,sha256=bL1fA1NC4_nW14Zrnxz4nHlXJb4dzELJPvodqKnYeMg,17983
-matplotlib/mpl-data/fonts/afm/ptmbi8a.afm,sha256=-_Ui6XlKaFTHEnkoS_-1GtIr5VtGa3gFQ2ezLOYHs08,18070
-matplotlib/mpl-data/fonts/afm/ptmr8a.afm,sha256=IEcsWcmzJyjCwkgsw4o6hIMmzlyXUglJat9s1PZNnEU,17942
-matplotlib/mpl-data/fonts/afm/ptmri8a.afm,sha256=49fQMg5fIGguZ7rgc_2styMK55Pv5bPTs7wCzqpcGpk,18068
-matplotlib/mpl-data/fonts/afm/putb8a.afm,sha256=qMaHTdpkrNL-m4DWhjpxJCSmgYkCv1qIzLlFfM0rl40,21532
-matplotlib/mpl-data/fonts/afm/putbi8a.afm,sha256=g7AVJyiTxeMpNk_1cSfmYgM09uNUfPlZyWGv3D1vcAk,21931
-matplotlib/mpl-data/fonts/afm/putr8a.afm,sha256=XYmNC5GQgSVAZKTIYdYeNksE6znNm9GF_0SmQlriqx0,22148
-matplotlib/mpl-data/fonts/afm/putri8a.afm,sha256=i7fVe-iLyLtQxCfAa4IxdxH-ufcHmMk7hbCGG5TxAY4,21891
-matplotlib/mpl-data/fonts/afm/pzcmi8a.afm,sha256=wyuoIWEZOcoXrSl1tPzLkEahik7kGi91JJj-tkFRG4A,16250
-matplotlib/mpl-data/fonts/afm/pzdr.afm,sha256=MyjLAnzKYRdQBfof1W3k_hf30MvqOkqL__G22mQ5xww,9467
-matplotlib/mpl-data/fonts/pdfcorefonts/Courier-Bold.afm,sha256=sIDDI-B82VZ3C0mI_mHFITCZ7PVn37AIYMv1CrHX4sE,15333
-matplotlib/mpl-data/fonts/pdfcorefonts/Courier-BoldOblique.afm,sha256=zg61QobD3YU9UBfCXmvmhBNaFKno-xj8sY0b2RpgfLw,15399
-matplotlib/mpl-data/fonts/pdfcorefonts/Courier-Oblique.afm,sha256=vRQm5j1sTUN4hicT1PcVZ9P9DTTUHhEzfPXqUUzVZhE,15441
-matplotlib/mpl-data/fonts/pdfcorefonts/Courier.afm,sha256=Mdcq2teZEBJrIqVXnsnhee7oZnTs6-P8_292kWGTrw4,15335
-matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-Bold.afm,sha256=i2l4gcjuYXoXf28uK7yIVwuf0rnw6J7PwPVQeHj5iPw,69269
-matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-BoldOblique.afm,sha256=Um5O6qK11DXLt8uj_0IoWkc84TKqHK3bObSKUswQqvY,69365
-matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica-Oblique.afm,sha256=hVYDg2b52kqtbVeCzmiv25bW1yYdpkZS-LXlGREN2Rs,74392
-matplotlib/mpl-data/fonts/pdfcorefonts/Helvetica.afm,sha256=23cvKDD7bQAJB3kdjSahJSTZaUOppznlIO6FXGslyW8,74292
-matplotlib/mpl-data/fonts/pdfcorefonts/Symbol.afm,sha256=P5UaoXr4y0qh4SiMa5uqijDT6ZDr2-jPmj1ayry593E,9740
-matplotlib/mpl-data/fonts/pdfcorefonts/Times-Bold.afm,sha256=cQTmr2LFPwKQE_sGQageMcmFicjye16mKJslsJLHQyE,64251
-matplotlib/mpl-data/fonts/pdfcorefonts/Times-BoldItalic.afm,sha256=pzWOdycm6RqocBWgAVY5Jq0z3Fp7LuqWgLNMx4q6OFw,59642
-matplotlib/mpl-data/fonts/pdfcorefonts/Times-Italic.afm,sha256=bK5puSMpGT_YUILwyJrXoxjfj7XJOdfv5TQ_iKsJRzw,66328
-matplotlib/mpl-data/fonts/pdfcorefonts/Times-Roman.afm,sha256=hhNrUnpazuDDKD1WpraPxqPWCYLrO7D7bMVOg-zI13o,60460
-matplotlib/mpl-data/fonts/pdfcorefonts/ZapfDingbats.afm,sha256=ZuOmt9GcKofjdOq8kqhPhtAIhOwkL2rTJTmZxAjFakA,9527
-matplotlib/mpl-data/fonts/pdfcorefonts/readme.txt,sha256=MRv8ppSITYYAb7lt5EOw9DWWNZIblfxsFhu5TQE7cpI,828
-matplotlib/mpl-data/fonts/ttf/DejaVuSans-Bold.ttf,sha256=sYS4njwQdfIva3FXW2_CDUlys8_TsjMiym_Vltyu8Wc,704128
-matplotlib/mpl-data/fonts/ttf/DejaVuSans-BoldOblique.ttf,sha256=bt8CgxYBhq9FHL7nHnuEXy5Mq_Jku5ks5mjIPCVGXm8,641720
-matplotlib/mpl-data/fonts/ttf/DejaVuSans-Oblique.ttf,sha256=zN90s1DxH9PdV3TeUOXmNGoaXaH1t9X7g1kGZel6UhM,633840
-matplotlib/mpl-data/fonts/ttf/DejaVuSans.ttf,sha256=P99pyr8GBJ6nCgC1kZNA4s4ebQKwzDxLRPtoAb0eDSI,756072
-matplotlib/mpl-data/fonts/ttf/DejaVuSansDisplay.ttf,sha256=ggmdz7paqGjN_CdFGYlSX-MpL3N_s8ngMozpzvWWUvY,25712
-matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Bold.ttf,sha256=uq2ppRcv4giGJRr_BDP8OEYZEtXa8HKH577lZiCo2pY,331536
-matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-BoldOblique.ttf,sha256=ppCBwVx2yCfgonpaf1x0thNchDSZlVSV_6jCDTqYKIs,253116
-matplotlib/mpl-data/fonts/ttf/DejaVuSansMono-Oblique.ttf,sha256=KAUoE_enCfyJ9S0ZLcmV708P3Fw9e3OknWhJsZFtDNA,251472
-matplotlib/mpl-data/fonts/ttf/DejaVuSansMono.ttf,sha256=YC7Ia4lIz82VZIL-ZPlMNshndwFJ7y95HUYT9EO87LM,340240
-matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Bold.ttf,sha256=w3U_Lta8Zz8VhG3EWt2-s7nIcvMvsY_VOiHxvvHtdnY,355692
-matplotlib/mpl-data/fonts/ttf/DejaVuSerif-BoldItalic.ttf,sha256=2T7-x6nS6CZ2jRou6VuVhw4V4pWZqE80hK8d4c7C4YE,347064
-matplotlib/mpl-data/fonts/ttf/DejaVuSerif-Italic.ttf,sha256=PnmU-8VPoQzjNSpC1Uj63X2crbacsRCbydlg9trFfwQ,345612
-matplotlib/mpl-data/fonts/ttf/DejaVuSerif.ttf,sha256=EHJElW6ZYrnpb6zNxVGCXgrgiYrhNzcTPhuSGi_TX_o,379740
-matplotlib/mpl-data/fonts/ttf/DejaVuSerifDisplay.ttf,sha256=KRTzLkfHd8J75Wd6-ufbTeefnkXeb8kJfZlJwjwU99U,14300
-matplotlib/mpl-data/fonts/ttf/LICENSE_DEJAVU,sha256=11k43sCY8G8Kw8AIUwZdlPAgvhw8Yu8dwpdboVtNmw4,4816
-matplotlib/mpl-data/fonts/ttf/LICENSE_STIX,sha256=cxFOZdp1AxNhXR6XxCzf5iJpNcu-APm-geOHhD-s0h8,5475
-matplotlib/mpl-data/fonts/ttf/STIXGeneral.ttf,sha256=FnN4Ax4t3cYhbWeBnJJg6aBv_ExHjk4jy5im_USxg8I,448228
-matplotlib/mpl-data/fonts/ttf/STIXGeneralBol.ttf,sha256=6FM9xwg_o0a9oZM9YOpKg7Z9CUW86vGzVB-CtKDixqA,237360
-matplotlib/mpl-data/fonts/ttf/STIXGeneralBolIta.ttf,sha256=mHiP1LpI37sr0CbA4gokeosGxzcoeWKLemuw1bsJc2w,181152
-matplotlib/mpl-data/fonts/ttf/STIXGeneralItalic.ttf,sha256=bPyzM9IrfDxiO9_UAXTxTIXD1nMcphZsHtyAFA6uhSc,175040
-matplotlib/mpl-data/fonts/ttf/STIXNonUni.ttf,sha256=Ulb34CEzWsSFTRgPDovxmJZOwvyCAXYnbhaqvGU3u1c,59108
-matplotlib/mpl-data/fonts/ttf/STIXNonUniBol.ttf,sha256=XRBqW3jR_8MBdFU0ObhiV7-kXwiBIMs7QVClHcT5tgs,30512
-matplotlib/mpl-data/fonts/ttf/STIXNonUniBolIta.ttf,sha256=pb22DnbDf2yQqizotc3wBDqFGC_g27YcCGJivH9-Le8,41272
-matplotlib/mpl-data/fonts/ttf/STIXNonUniIta.ttf,sha256=BMr9pWiBv2YIZdq04X4c3CgL6NPLUPrl64aV1N4w9Ug,46752
-matplotlib/mpl-data/fonts/ttf/STIXSizFiveSymReg.ttf,sha256=wYuH1gYUpCuusqItRH5kf9p_s6mUD-9X3L5RvRtKSxs,13656
-matplotlib/mpl-data/fonts/ttf/STIXSizFourSymBol.ttf,sha256=yNdvjUoSmsZCULmD7SVq9HabndG9P4dPhboL1JpAf0s,12228
-matplotlib/mpl-data/fonts/ttf/STIXSizFourSymReg.ttf,sha256=-9xVMYL4_1rcO8FiCKrCfR4PaSmKtA42ddLGqwtei1w,15972
-matplotlib/mpl-data/fonts/ttf/STIXSizOneSymBol.ttf,sha256=cYexyo8rZcdqMlpa9fNF5a2IoXLUTZuIvh0JD1Qp0i4,12556
-matplotlib/mpl-data/fonts/ttf/STIXSizOneSymReg.ttf,sha256=0lbHzpndzJmO8S42mlkhsz5NbvJLQCaH5Mcc7QZRDzc,19760
-matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymBol.ttf,sha256=3eBc-VtYbhQU3BnxiypfO6eAzEu8BdDvtIJSFbkS2oY,12192
-matplotlib/mpl-data/fonts/ttf/STIXSizThreeSymReg.ttf,sha256=XFSKCptbESM8uxHtUFSAV2cybwxhSjd8dWVByq6f3w0,15836
-matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymBol.ttf,sha256=MUCYHrA0ZqFiSE_PjIGlJZgMuv79aUgQqE7Dtu3kuo0,12116
-matplotlib/mpl-data/fonts/ttf/STIXSizTwoSymReg.ttf,sha256=_sdxDuEwBDtADpu9CyIXQxV7sIqA2TZVBCUiUjq5UCk,15704
-matplotlib/mpl-data/fonts/ttf/cmb10.ttf,sha256=B0SXtQxD6ldZcYFZH5iT04_BKofpUQT1ZX_CSB9hojo,25680
-matplotlib/mpl-data/fonts/ttf/cmex10.ttf,sha256=ryjwwXByOsd2pxv6WVrKCemNFa5cPVTOGa_VYZyWqQU,21092
-matplotlib/mpl-data/fonts/ttf/cmmi10.ttf,sha256=MJKWW4gR_WpnZXmWZIRRgfwd0TMLk3-RWAjEhdMWI00,32560
-matplotlib/mpl-data/fonts/ttf/cmr10.ttf,sha256=Tdl2GwWMAJ25shRfVe5mF9CTwnPdPWxbPkP_YRD6m_Y,26348
-matplotlib/mpl-data/fonts/ttf/cmss10.ttf,sha256=ffkag9BbLkcexjjLC0NaNgo8eSsJ_EKn2mfpHy55EVo,20376
-matplotlib/mpl-data/fonts/ttf/cmsy10.ttf,sha256=uyJu2TLz8QDNDlL15JEu5VO0G2nnv9uNOFTbDrZgUjI,29396
-matplotlib/mpl-data/fonts/ttf/cmtt10.ttf,sha256=YhHwmuk1mZka_alwwkZp2tGnfiU9kVYk-_IS9wLwcdc,28136
-matplotlib/mpl-data/images/back.gif,sha256=sdkxFRAh-Mgs44DTvruO5OxcI3Av9CS1g5MqMA_DDkQ,608
-matplotlib/mpl-data/images/back.pdf,sha256=ZR7CJo_dAeCM-KlaGvskgtHQyRtrPIolc8REOmcoqJk,1623
-matplotlib/mpl-data/images/back.png,sha256=E4dGf4Gnz1xJ1v2tMygHV0YNQgShreDeVApaMb-74mU,380
-matplotlib/mpl-data/images/back.svg,sha256=yRdMiKsa-awUm2x_JE_rEV20rNTa7FInbFBEoMo-6ik,1512
-matplotlib/mpl-data/images/back_large.gif,sha256=tqCtecrxNrPuDCUj7FGs8UXWftljKcwgp5cSBBhXwiQ,799
-matplotlib/mpl-data/images/back_large.png,sha256=9A6hUSQeszhYONE4ZuH3kvOItM0JfDVu6tkfromCbsQ,620
-matplotlib/mpl-data/images/filesave.gif,sha256=wAyNwOPd9c-EIPwcUAlqHSfLmxq167nhDVppOWPy9UA,723
-matplotlib/mpl-data/images/filesave.pdf,sha256=P1EPPV2g50WTt8UaX-6kFoTZM1xVqo6S2H6FJ6Zd1ec,1734
-matplotlib/mpl-data/images/filesave.png,sha256=b7ctucrM_F2mG-DycTedG_a_y4pHkx3F-zM7l18GLhk,458
-matplotlib/mpl-data/images/filesave.svg,sha256=oxPVbLS9Pzelz71C1GCJWB34DZ0sx_pUVPRHBrCZrGs,2029
-matplotlib/mpl-data/images/filesave_large.gif,sha256=IXrenlwu3wwO8WTRvxHt_q62NF6ZWyqk3jZhm6GE-G8,1498
-matplotlib/mpl-data/images/filesave_large.png,sha256=LNbRD5KZ3Kf7nbp-stx_a1_6XfGBSWUfDdpgmnzoRvk,720
-matplotlib/mpl-data/images/forward.gif,sha256=VNL9R-dECOX7wUAYPtU_DWn5hwi3SwLR17DhmBvUIxE,590
-matplotlib/mpl-data/images/forward.pdf,sha256=KIqIL4YId43LkcOxV_TT5uvz1SP8k5iUNUeJmAElMV8,1630
-matplotlib/mpl-data/images/forward.png,sha256=pKbLepgGiGeyY2TCBl8svjvm7Z4CS3iysFxcq4GR-wk,357
-matplotlib/mpl-data/images/forward.svg,sha256=NnQDOenfjsn-o0aJMUfErrP320Zcx9XHZkLh0cjMHsk,1531
-matplotlib/mpl-data/images/forward_large.gif,sha256=H6Jbcc7qJwHJAE294YqI5Bm-5irofX40cKRvYdrG_Ig,786
-matplotlib/mpl-data/images/forward_large.png,sha256=36h7m7DZDHql6kkdpNPckyi2LKCe_xhhyavWARz_2kQ,593
-matplotlib/mpl-data/images/hand.gif,sha256=3lRfmAqQU7A2t1YXXsB9IbwzK7FaRh-IZO84D5-xCrw,1267
-matplotlib/mpl-data/images/hand.pdf,sha256=hspwkNY915KPD7AMWnVQs7LFPOtlcj0VUiLu76dMabQ,4172
-matplotlib/mpl-data/images/hand.png,sha256=2cchRETGKa0hYNKUxnJABwkyYXEBPqJy_VqSPlT0W2Q,979
-matplotlib/mpl-data/images/hand.svg,sha256=tsVIES_nINrAbH4FqdsCGOx0SVE37vcofSYBhnnaOP0,4888
-matplotlib/mpl-data/images/hand_large.gif,sha256=H5IHmVTvOqHQb9FZ_7g7AlPt9gv-zRq0L5_Q9B7OuvU,973
-matplotlib/mpl-data/images/help.pdf,sha256=CeE978IMi0YWznWKjIT1R8IrP4KhZ0S7usPUvreSgcA,1813
-matplotlib/mpl-data/images/help.png,sha256=s4pQrqaQ0py8I7vc9hv3BI3DO_tky-7YBMpaHuBDCBY,472
-matplotlib/mpl-data/images/help.ppm,sha256=mVPvgwcddzCM-nGZd8Lnl_CorzDkRIXQE17b7qo8vlU,1741
-matplotlib/mpl-data/images/help.svg,sha256=KXabvQhqIWen_t2SvZuddFYa3S0iI3W8cAKm3s1fI8Q,1870
-matplotlib/mpl-data/images/help_large.png,sha256=1IwEyWfGRgnoCWM-r9CJHEogTJVD5n1c8LXTK4AJ4RE,747
-matplotlib/mpl-data/images/help_large.ppm,sha256=MiCSKp1Su88FXOi9MTtkQDA2srwbX3w5navi6cneAi4,6925
-matplotlib/mpl-data/images/home.gif,sha256=NKuFM7tTtFngdfsOpJ4AxYTL8PYS5GWKAoiJjBMwLlU,666
-matplotlib/mpl-data/images/home.pdf,sha256=e0e0pI-XRtPmvUCW2VTKL1DeYu1pvPmUUeRSgEbWmik,1737
-matplotlib/mpl-data/images/home.png,sha256=IcFdAAUa6_A0qt8IO3I8p4rpXpQgAlJ8ndBECCh7C1w,468
-matplotlib/mpl-data/images/home.svg,sha256=n_AosjJVXET3McymFuHgXbUr5vMLdXK2PDgghX8Cch4,1891
-matplotlib/mpl-data/images/home_large.gif,sha256=k86PJCgED46sCFkOlUYHA0s5U7OjRsc517bpAtU2JSw,1422
-matplotlib/mpl-data/images/home_large.png,sha256=uxS2O3tWOHh1iau7CaVV4ermIJaZ007ibm5Z3i8kXYg,790
-matplotlib/mpl-data/images/matplotlib.pdf,sha256=BkSUf-2xoij-eXfpV2t7y1JFKG1zD1gtV6aAg3Xi_wE,22852
-matplotlib/mpl-data/images/matplotlib.png,sha256=w8KLRYVa-voUZXa41hgJauQuoois23f3NFfdc72pUYY,1283
-matplotlib/mpl-data/images/matplotlib.svg,sha256=QiTIcqlQwGaVPtHsEk-vtmJk1wxwZSvijhqBe_b9VCI,62087
-matplotlib/mpl-data/images/matplotlib_128.ppm,sha256=IHPRWXpLFRq3Vb7UjiCkFrN_N86lSPcfrEGunST08d8,49167
-matplotlib/mpl-data/images/matplotlib_large.png,sha256=ElRoue9grUqkZXJngk-nvh4GKfpvJ4gE69WryjCbX5U,3088
-matplotlib/mpl-data/images/move.gif,sha256=FN52MptH4FZiwmV2rQgYCO2FvO3m5LtqYv8jk6Xbeyk,679
-matplotlib/mpl-data/images/move.pdf,sha256=CXk3PGK9WL5t-5J-G2X5Tl-nb6lcErTBS5oUj2St6aU,1867
-matplotlib/mpl-data/images/move.png,sha256=TmjR41IzSzxGbhiUcV64X0zx2BjrxbWH3cSKvnG2vzc,481
-matplotlib/mpl-data/images/move.svg,sha256=_ZKpcwGD6DMTkZlbyj0nQbT8Ygt5vslEZ0OqXaXGd4E,2509
-matplotlib/mpl-data/images/move_large.gif,sha256=RMIAr-G9OOY7vWC04oN6qv5TAHJxhQGhLsw_bNsvWbg,951
-matplotlib/mpl-data/images/move_large.png,sha256=Skjz2nW_RTA5s_0g88gdq2hrVbm6DOcfYW4Fu42Fn9U,767
-matplotlib/mpl-data/images/qt4_editor_options.pdf,sha256=2qu6GVyBrJvVHxychQoJUiXPYxBylbH2j90QnytXs_w,1568
-matplotlib/mpl-data/images/qt4_editor_options.png,sha256=EryQjQ5hh2dwmIxtzCFiMN1U6Tnd11p1CDfgH5ZHjNM,380
-matplotlib/mpl-data/images/qt4_editor_options.svg,sha256=E00YoX7u4NrxMHm_L1TM8PDJ88bX5qRdCrO-Uj59CEA,1244
-matplotlib/mpl-data/images/qt4_editor_options_large.png,sha256=-Pd-9Vh5aIr3PZa8O6Ge_BLo41kiEnpmkdDj8a11JkY,619
-matplotlib/mpl-data/images/subplots.gif,sha256=QfhmUdcrko08-WtrzCJUjrVFDTvUZCJEXpARNtzEwkg,691
-matplotlib/mpl-data/images/subplots.pdf,sha256=Q0syPMI5EvtgM-CE-YXKOkL9eFUAZnj_X2Ihoj6R4p4,1714
-matplotlib/mpl-data/images/subplots.png,sha256=MUfCItq3_yzb9yRieGOglpn0Y74h8IA7m5i70B63iRc,445
-matplotlib/mpl-data/images/subplots.svg,sha256=8acBogXIr9OWGn1iD6mUkgahdFZgDybww385zLCLoIs,2130
-matplotlib/mpl-data/images/subplots_large.gif,sha256=Ff3ERmtVAaGP9i1QGUNnIIKac6LGuSW2Qf4DrockZSI,1350
-matplotlib/mpl-data/images/subplots_large.png,sha256=Edu9SwVMQEXJZ5ogU5cyW7VLcwXJdhdf-EtxxmxdkIs,662
-matplotlib/mpl-data/images/zoom_to_rect.gif,sha256=mTX6h9fh2W9zmvUYqeibK0TZ7qIMKOB1nAXMpD_jDys,696
-matplotlib/mpl-data/images/zoom_to_rect.pdf,sha256=SEvPc24gfZRpl-dHv7nx8KkxPyU66Kq4zgQTvGFm9KA,1609
-matplotlib/mpl-data/images/zoom_to_rect.png,sha256=aNz3QZBrIgxu9E-fFfaQweCVNitGuDUFoC27e5NU2L4,530
-matplotlib/mpl-data/images/zoom_to_rect.svg,sha256=1vRxr3cl8QTwTuRlQzD1jxu0fXZofTJ2PMgG97E7Bco,1479
-matplotlib/mpl-data/images/zoom_to_rect_large.gif,sha256=nx5LUpTAH6ZynM3ZfZDS-wR87jbMUsUnyQ27NGkV0_c,1456
-matplotlib/mpl-data/images/zoom_to_rect_large.png,sha256=V6pkxmm6VwFExdg_PEJWdK37HB7k3cE_corLa7RbUMk,1016
-matplotlib/mpl-data/matplotlibrc,sha256=ZDuS3NjqmSy4_oIXNk9mMNcD74ExJ9clpz6fbgSVMCk,40282
-matplotlib/mpl-data/sample_data/Minduka_Present_Blue_Pack.png,sha256=XnKGiCanpDKalQ5anvo5NZSAeDP7fyflzQAaivuc0IE,13634
-matplotlib/mpl-data/sample_data/None_vs_nearest-pdf.png,sha256=5CPvcG3SDNfOXx39CMKHCNS9JKZ-fmOUwIfpppNXsQ0,106228
-matplotlib/mpl-data/sample_data/README.txt,sha256=ABz19VBKfGewdY39QInG9Qccgn1MTYV3bT5Ph7TCy2Y,128
-matplotlib/mpl-data/sample_data/aapl.npz,sha256=GssVYka_EccteiXbNRJJ5GsuqU7G8F597qX7srYXZsw,107503
-matplotlib/mpl-data/sample_data/ada.png,sha256=X1hjJK1_1Nc8DN-EEhey3G7Sq8jBwQDKNSl4cCAE0uY,308313
-matplotlib/mpl-data/sample_data/axes_grid/bivariate_normal.npy,sha256=DpWZ9udAh6ospYqneEa27D6EkRgORFwHosacZXVu98U,1880
-matplotlib/mpl-data/sample_data/ct.raw.gz,sha256=LDvvgH-mycRQF2D29-w5MW94ZI0opvwKUoFI8euNpMk,256159
-matplotlib/mpl-data/sample_data/data_x_x2_x3.csv,sha256=A0SU3buOUGhT-NI_6LQ6p70fFSIU3iLFdgzvzrKR6SE,132
-matplotlib/mpl-data/sample_data/demodata.csv,sha256=MRybziqnyrqMCH9qG7Mr6BwcohIhftVG5dejXV2AX2M,659
-matplotlib/mpl-data/sample_data/eeg.dat,sha256=KGVjFt8ABKz7p6XZirNfcxSTOpGGNuyA8JYErRKLRBc,25600
-matplotlib/mpl-data/sample_data/embedding_in_wx3.xrc,sha256=cUqVw5vDHNSZoaO4J0ebZUf5SrJP36775abs7R9Bclg,2186
-matplotlib/mpl-data/sample_data/goog.npz,sha256=QAkXzzDmtmT3sNqT18dFhg06qQCNqLfxYNLdEuajGLE,22845
-matplotlib/mpl-data/sample_data/grace_hopper.jpg,sha256=qMptc0dlcDsJcoq0f-WfRz2Trjln_CTHwCiMPHrbcTA,61306
-matplotlib/mpl-data/sample_data/grace_hopper.png,sha256=MCf0ju2kpC40srQ0xw4HEyOoKhLL4khP3jHfU9_dR7s,628280
-matplotlib/mpl-data/sample_data/jacksboro_fault_dem.npz,sha256=1JP1CjPoKkQgSUxU0fyhU50Xe9wnqxkLxf5ukvYvtjc,174061
-matplotlib/mpl-data/sample_data/logo2.png,sha256=ITxkJUsan2oqXgJDy6DJvwJ4aHviKeWGnxPkTjXUt7A,33541
-matplotlib/mpl-data/sample_data/membrane.dat,sha256=q3lbQpIBpbtXXGNw1eFwkN_PwxdDGqk4L46IE2b0M1c,48000
-matplotlib/mpl-data/sample_data/msft.csv,sha256=GArKb0O3DgKZRsKdJf6lX3rMSf-PCekIiBoLNdgF7Mk,3211
-matplotlib/mpl-data/sample_data/percent_bachelors_degrees_women_usa.csv,sha256=TzoqamsV_N3d3lW7SKmj14zZVX4FOOg9jJcsC5U9pbA,5681
-matplotlib/mpl-data/sample_data/s1045.ima.gz,sha256=MrQk1k9it-ccsk0p_VOTitVmTWCAVaZ6srKvQ2n4uJ4,33229
-matplotlib/mpl-data/sample_data/topobathy.npz,sha256=AkTgMpFwLfRQJNy1ysvE89TLMNct-n_TccSsYcQrT78,45224
-matplotlib/mpl-data/stylelib/Solarize_Light2.mplstyle,sha256=PECeO60wwJe2sSDvxapBJRuKGek0qLcoaN8qOX6tgNQ,1255
-matplotlib/mpl-data/stylelib/_classic_test_patch.mplstyle,sha256=iopHpMaM3im_AK2aiHGuM2DKM5i9Kc84v6NQEoSb10Q,167
-matplotlib/mpl-data/stylelib/bmh.mplstyle,sha256=-KbhaI859BITHIoyUZIfpQDjfckgLAlDAS_ydKsm6mc,712
-matplotlib/mpl-data/stylelib/classic.mplstyle,sha256=0RjtrDi0vZOzWGnt9cme_At_9GqMwHzwEBCAH9OQZ7I,24511
-matplotlib/mpl-data/stylelib/dark_background.mplstyle,sha256=-EGmoFm_35Zk7oRp29UalT56HsOSuJbYMeQGdAATnz4,477
-matplotlib/mpl-data/stylelib/fast.mplstyle,sha256=yTa2YEIIP9xi5V_G0p2vSlxghuhNwjRi9gPECMxyRiM,288
-matplotlib/mpl-data/stylelib/fivethirtyeight.mplstyle,sha256=WNUmAFuBPcqQPVgt6AS1ldy8Be2XO01N-1YQL__Q6ZY,832
-matplotlib/mpl-data/stylelib/ggplot.mplstyle,sha256=xhjLwr8hiikEXKy8APMy0Bmvtz1g0WnG84gX7e9lArs,957
-matplotlib/mpl-data/stylelib/grayscale.mplstyle,sha256=KCLg-pXpns9cnKDXKN2WH6mV41OH-6cbT-5zKQotSdw,526
-matplotlib/mpl-data/stylelib/seaborn-bright.mplstyle,sha256=pDqn3-NUyVLvlfkYs8n8HzNZvmslVMChkeH-HtZuJIc,144
-matplotlib/mpl-data/stylelib/seaborn-colorblind.mplstyle,sha256=eCSzFj5_2vR6n5qu1rHE46wvSVGZcdVqz85ov40ZsH8,148
-matplotlib/mpl-data/stylelib/seaborn-dark-palette.mplstyle,sha256=p5ABKNQHRG7bk4HXqMQrRBjDlxGAo3RCXHdQmP7g-Ng,142
-matplotlib/mpl-data/stylelib/seaborn-dark.mplstyle,sha256=I4xQ75vE5_9X4k0cNDiqhhnF3OcrZ2xlPX8Ll7OCkoE,667
-matplotlib/mpl-data/stylelib/seaborn-darkgrid.mplstyle,sha256=2bXOSzS5gmPzRBrRmzVWyhg_7ZaBRQ6t_-O-cRuyZoA,670
-matplotlib/mpl-data/stylelib/seaborn-deep.mplstyle,sha256=44dLcXjjRgR-6yaopgGRInaVgz3jk8VJVQTbBIcxRB0,142
-matplotlib/mpl-data/stylelib/seaborn-muted.mplstyle,sha256=T4o3jvqKD_ImXDkp66XFOV_xrBVFUolJU34JDFk1Xkk,143
-matplotlib/mpl-data/stylelib/seaborn-notebook.mplstyle,sha256=PcvZQbYrDdducrNlavBPmQ1g2minio_9GkUUFRdgtoM,382
-matplotlib/mpl-data/stylelib/seaborn-paper.mplstyle,sha256=n0mboUp2C4Usq2j6tNWcu4TZ_YT4-kKgrYO0t-rz1yw,393
-matplotlib/mpl-data/stylelib/seaborn-pastel.mplstyle,sha256=8nV8qRpbUrnFZeyE6VcQ1oRuZPLil2W74M2U37DNMOE,144
-matplotlib/mpl-data/stylelib/seaborn-poster.mplstyle,sha256=dUaKqTE4MRfUq2rWVXbbou7kzD7Z9PE9Ko8aXLza8JA,403
-matplotlib/mpl-data/stylelib/seaborn-talk.mplstyle,sha256=7FnBaBEdWBbncTm6_ER-EQVa_bZgU7dncgez-ez8R74,403
-matplotlib/mpl-data/stylelib/seaborn-ticks.mplstyle,sha256=CITZmZFUFp40MK2Oz8tI8a7WRoCizQU9Z4J172YWfWw,665
-matplotlib/mpl-data/stylelib/seaborn-white.mplstyle,sha256=WjJ6LEU6rlCwUugToawciAbKP9oERFHr9rfFlUrdTx0,665
-matplotlib/mpl-data/stylelib/seaborn-whitegrid.mplstyle,sha256=ec4BjsNzmOvHptcJ3mdPxULF3S1_U1EUocuqfIpw-Nk,664
-matplotlib/mpl-data/stylelib/seaborn.mplstyle,sha256=_Xu6qXKzi4b3GymCOB1b1-ykKTQ8xhDliZ8ezHGTiAs,1130
-matplotlib/mpl-data/stylelib/tableau-colorblind10.mplstyle,sha256=BsirZVd1LmPWT4tBIz6loZPjZcInoQrIGfC7rvzqmJw,190
-matplotlib/offsetbox.py,sha256=1oReQSHV50aRsHqHIa3Km234FXx8sUZRLdiGbdGu2zU,58812
-matplotlib/patches.py,sha256=4JTt8OKfTg_BzSQVXYjsQLAFbZvvzR9T-1zsajaPpx8,151886
-matplotlib/path.py,sha256=ov2ghbmWhCV-PhxUPGEfsG409Nrkf9HP4u7oQSpGFtc,37640
-matplotlib/patheffects.py,sha256=ERzaWP5RZTnaEVWx77c8oB-JQeMpVJtY-hBdRqkQ4ZM,13235
-matplotlib/projections/__init__.py,sha256=4b447LtxkDz1nC1B9tb_J7cCpq1fjxwaEvzkHy-Y3KA,1816
-matplotlib/projections/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/projections/__pycache__/geo.cpython-38.pyc,,
-matplotlib/projections/__pycache__/polar.cpython-38.pyc,,
-matplotlib/projections/geo.py,sha256=OrTW_dk4QqrTv9lYBean9uz24MBIWyWcnkADyTOdNuc,17690
-matplotlib/projections/polar.py,sha256=1aHOdhpaJKpu5BNS2eRoeIgej-QUunRpIGcxXkv1s28,52508
-matplotlib/pylab.py,sha256=VOs5onux2-yPGn0exAPsR75U9ty2hOzvg8Nz1K7TWBg,9595
-matplotlib/pyplot.py,sha256=vM3sVw0yIb0EbehwlLAOWHfGnMSN4W9OfTDmcsBELvs,111042
-matplotlib/quiver.py,sha256=B3CGGxSNVLwOPx2IgyG2DCSPQHs1MAS0o9sL_4Mm7rY,48018
-matplotlib/rcsetup.py,sha256=BhPaDqHrifbncC47epnKBtvlkk-MzhNp1HlVYgcgvF8,58589
-matplotlib/sankey.py,sha256=3PygeZ3h19RFICw1hL6qt5TwRoBrP1AKSznWvKHc6Z4,36986
-matplotlib/scale.py,sha256=_G5Aq3ta2vc2WOLuL3_UlnZ8XsXbGRrwBuqAG_OxCxU,25209
-matplotlib/sphinxext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-matplotlib/sphinxext/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/sphinxext/__pycache__/mathmpl.cpython-38.pyc,,
-matplotlib/sphinxext/__pycache__/plot_directive.cpython-38.pyc,,
-matplotlib/sphinxext/mathmpl.py,sha256=jTqwBfxLLGjx-4TwEzwYvi2WdCoJpqHfDcbLKrgcKss,4276
-matplotlib/sphinxext/plot_directive.py,sha256=dAECzhJ1qVCq3nN3poGjKK2AAaAIwGikEHQIz_V0U0Y,26574
-matplotlib/spines.py,sha256=Xl9hIsBHzYaGq79UQb3Amfwfrq1-ZNsiS4wpPwstbp8,21227
-matplotlib/stackplot.py,sha256=fj4oqFbYA1G3RaTnV_Jic5mn5K3rza-JYp6jGR7e0yk,3917
-matplotlib/streamplot.py,sha256=9zniqozPg42NfXk4bx_Ro2RlkYYuR2CEJwJfJkt7jtI,22641
-matplotlib/style/__init__.py,sha256=EExOAUAq3u_rscUwkfKtZoEgLA5npmltCrYZOP9ftjw,67
-matplotlib/style/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/style/__pycache__/core.cpython-38.pyc,,
-matplotlib/style/core.py,sha256=EAubJQ90H__1bljwNfjpT8kxHp30r6KtXoveLvnfs4Q,8222
-matplotlib/table.py,sha256=FXhhFOy_-ZkHwyphkjFBQku1WgDjR3iYlmV4Wvls0cY,26674
-matplotlib/testing/__init__.py,sha256=MVV0ao_RHOKgDhpSN7QJBnyunje7tDeco-No_HtvvcQ,1428
-matplotlib/testing/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/testing/__pycache__/compare.cpython-38.pyc,,
-matplotlib/testing/__pycache__/conftest.cpython-38.pyc,,
-matplotlib/testing/__pycache__/decorators.cpython-38.pyc,,
-matplotlib/testing/__pycache__/disable_internet.cpython-38.pyc,,
-matplotlib/testing/__pycache__/exceptions.cpython-38.pyc,,
-matplotlib/testing/compare.py,sha256=67rAW447H4AUnGoT-AUP7s6CB2Q1N4oqhetFdvBdKZk,16969
-matplotlib/testing/conftest.py,sha256=juolFb13qZ_jwO6DsOxkfCKuPmPsQwbY6Oznx76tLYo,4317
-matplotlib/testing/decorators.py,sha256=t9XYPto5sIm4OObU5dyF6z5FjdhuNE2saBr-dnZ45wU,17704
-matplotlib/testing/disable_internet.py,sha256=ovCho7Nu6w-uoJeUPjJS7XGKJN0ktSNyF6NODaEyjb4,4925
-matplotlib/testing/exceptions.py,sha256=72QmjiHG7DwxSvlJf8mei-hRit5AH3NKh0-osBo4YbY,138
-matplotlib/testing/jpl_units/Duration.py,sha256=Leomw6a4XHddFgqMoYj63HfxV_-u6_MuQ3iaQ26TJcg,4946
-matplotlib/testing/jpl_units/Epoch.py,sha256=XpQMTIOs6VIVzuFYxRcv6JUuz4kqVCb1nGfBpYYbeJA,6305
-matplotlib/testing/jpl_units/EpochConverter.py,sha256=TAhtAyDHvvxDJL036DWEXrkZl_CwpVl2y5FNXloAoxo,4067
-matplotlib/testing/jpl_units/StrConverter.py,sha256=36hFTYbCM3Dh9_QR82dBbHh_7DSpsEthpnJYRICLlIc,4107
-matplotlib/testing/jpl_units/UnitDbl.py,sha256=sL0U984sJmka_0gzp6uhxSJuxnuh77aDAjtfCYdYJZ0,7793
-matplotlib/testing/jpl_units/UnitDblConverter.py,sha256=M5h3lOB4IEysqnR7VbkjUnMPS7wBtrZYWKvU3JUaJtI,4145
-matplotlib/testing/jpl_units/UnitDblFormatter.py,sha256=CRcbPtE3K0FlFJ4hkhi-SgQl1MUV-VlmIeOPIEPNwuI,681
-matplotlib/testing/jpl_units/__init__.py,sha256=Bp4Lz_eqRuxNWO_l3VvhuurFZaUmZIlvcF3N0UBmzHc,2692
-matplotlib/testing/jpl_units/__pycache__/Duration.cpython-38.pyc,,
-matplotlib/testing/jpl_units/__pycache__/Epoch.cpython-38.pyc,,
-matplotlib/testing/jpl_units/__pycache__/EpochConverter.cpython-38.pyc,,
-matplotlib/testing/jpl_units/__pycache__/StrConverter.cpython-38.pyc,,
-matplotlib/testing/jpl_units/__pycache__/UnitDbl.cpython-38.pyc,,
-matplotlib/testing/jpl_units/__pycache__/UnitDblConverter.cpython-38.pyc,,
-matplotlib/testing/jpl_units/__pycache__/UnitDblFormatter.cpython-38.pyc,,
-matplotlib/testing/jpl_units/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/tests/__init__.py,sha256=ns6SIKdszYNXD5h5PqKRCR06Z45H-sXrUX2VwujSRIM,366
-matplotlib/tests/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/tests/__pycache__/conftest.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_afm.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_agg.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_agg_filter.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_animation.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_arrow_patches.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_artist.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_axes.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_bases.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_cairo.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_nbagg.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_pdf.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_pgf.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_ps.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_qt.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_svg.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_tk.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_tools.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backend_webagg.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_backends_interactive.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_basic.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_bbox_tight.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_category.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_cbook.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_collections.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_colorbar.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_colors.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_compare_images.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_constrainedlayout.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_container.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_contour.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_cycles.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_dates.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_determinism.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_dviread.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_figure.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_font_manager.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_fontconfig_pattern.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_gridspec.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_image.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_legend.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_lines.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_marker.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_mathtext.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_matplotlib.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_mlab.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_offsetbox.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_patches.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_path.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_patheffects.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_pickle.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_png.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_preprocess_data.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_pyplot.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_quiver.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_rcparams.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_sankey.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_scale.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_simplification.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_skew.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_sphinxext.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_spines.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_streamplot.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_style.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_subplots.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_table.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_testing.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_texmanager.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_text.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_ticker.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_tightlayout.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_transforms.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_triangulation.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_ttconv.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_type1font.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_units.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_usetex.cpython-38.pyc,,
-matplotlib/tests/__pycache__/test_widgets.cpython-38.pyc,,
-matplotlib/tests/cmr10.pfb,sha256=_c7eh5QBjfXytY8JBfsgorQY7Y9ntz7hJEWFXfvlsb4,35752
-matplotlib/tests/conftest.py,sha256=QtpdWPUoXL_9F8WIytDc3--h0nPjbo8PToig7svIT1Y,258
-matplotlib/tests/mpltest.ttf,sha256=Jwb2O5KRVk_2CMqnhL0igeI3iGQCY3eChyS16N589zE,2264
-matplotlib/tests/test_afm.py,sha256=DGVfvABg6FRmbAq2ldRhM2wlqNfVrmRtSz12MCyqDXk,3710
-matplotlib/tests/test_agg.py,sha256=SC6WsFbq9Hs4dokpEqGqGPaFGS7zJpNxKRIRLUzD3Qk,7558
-matplotlib/tests/test_agg_filter.py,sha256=sfntvGVUuCaGqU3DdOnTRXqq0P1afVqWuaV_ZEYh8kQ,969
-matplotlib/tests/test_animation.py,sha256=WZ2kU7tjlDXL5Ryf89irQok884cWGtkVOJpNSjVyj3o,8916
-matplotlib/tests/test_arrow_patches.py,sha256=3EB9HIfdLCg_Nvq8zxEH9LJAV5OUbo6yndbZ-lIVcnQ,5593
-matplotlib/tests/test_artist.py,sha256=hMSfbg8Le0Li-vLEk2N9tZQtC1cUUE5Xn0O4CgYLugs,9418
-matplotlib/tests/test_axes.py,sha256=nRp8gbewUffIIfUBFlBxkq5E6FnH75wrCFY4Xp4GpG8,216153
-matplotlib/tests/test_backend_bases.py,sha256=I3Oiqk6Fm-fctj-aOxq5Av8Kqe3QLjlY-oTwTbdO6dw,3811
-matplotlib/tests/test_backend_cairo.py,sha256=gIjbQesBuvIBdpzoXXSdRmq3E2axCVX4h1Qfv6PNeKM,1936
-matplotlib/tests/test_backend_nbagg.py,sha256=dp9pYxWXN8ZBBjJcVE-1tJ61K7oeWtzcqIsAd7ABnfk,948
-matplotlib/tests/test_backend_pdf.py,sha256=GUqvImL8-HgpZGG0Zb41AE3KqVwtt8i00xcPutzGM1w,6696
-matplotlib/tests/test_backend_pgf.py,sha256=GAArsyhcLvWIHDtKgdv2kscRlgpNQ_oqyOXVGdVTw3Q,8636
-matplotlib/tests/test_backend_ps.py,sha256=E3eheQhOHcUhub4IzcWcDVvvnnVC6bHn6tv1NAF_KA4,3633
-matplotlib/tests/test_backend_qt.py,sha256=Oqtl2ZuS8Ly_ouDGkwndSheCs8U9OSiwBwJnnMmVGXI,9798
-matplotlib/tests/test_backend_svg.py,sha256=rPppxppM-G4mm4ISP4hq7pIVGTfS6Zyydt1jUoY2QqY,5863
-matplotlib/tests/test_backend_tk.py,sha256=sLqemf0mAFMIpv2414wKSVInLekL8bvzzaeREhE2UBU,934
-matplotlib/tests/test_backend_tools.py,sha256=C-B7NCkyWsQ5KzQEnI5Be16DsAHHZJU9P5v9--wsF-o,501
-matplotlib/tests/test_backend_webagg.py,sha256=u-UvO04iqxZbFlUrNIfyD0KIAxEhSOyqlrOqxO4DnDw,702
-matplotlib/tests/test_backends_interactive.py,sha256=QsdZhWATJPh3ZYM2F90MRQCyoW3ROUOGXYgrM0XUxsc,5018
-matplotlib/tests/test_basic.py,sha256=KRMwLx3J53urIx689lWHzkWkaWGTf0ZwhTyGrFDUfao,1268
-matplotlib/tests/test_bbox_tight.py,sha256=3nrCNbVtd-0K3LvndlPQBG9raTLdbXuDmoMWt5oVMSY,3902
-matplotlib/tests/test_category.py,sha256=SKBDW4R4q_7A0K1H-q801mTivxBgcLXigw4E6-tb1P4,10011
-matplotlib/tests/test_cbook.py,sha256=Z2Hp8UkeebK-BglQXm9WhiTpZC8CbSsSKUNy6hJoJbU,18684
-matplotlib/tests/test_collections.py,sha256=9Lyyydi1Ykk0BKXXWDPSYUQ1M9F-uJdVwqaZE1ZMKxI,23520
-matplotlib/tests/test_colorbar.py,sha256=OW2F_D6Vs7jEV8HOBh2kv_iV21u7sdyIqJcRakwEkTg,22065
-matplotlib/tests/test_colors.py,sha256=KYXZa1yFlkEGriaLMm-v2WnhROS2lvOUgseSHV2xC7w,33376
-matplotlib/tests/test_compare_images.py,sha256=n3Uoukid0GcjyQpd6ZrqIY9u3RLNE2XAPWwtcHIsqto,3155
-matplotlib/tests/test_constrainedlayout.py,sha256=9689kXb21xPGT3rqgZMxVT8HT4HXlzjO_aS6wq7b8kM,12981
-matplotlib/tests/test_container.py,sha256=75Di6cic-JY7JbOnsaz7N6Hcm3KUAJKaKbCoVSDPAuU,576
-matplotlib/tests/test_contour.py,sha256=G4dN6t8yrbpKp0aEI1VTrb-woyBKidGUqdDJ3b5D55U,12018
-matplotlib/tests/test_cycles.py,sha256=mgYXt63ov7th7IwGpLEoCh-ImubEp6wltzTbDchfQYI,7112
-matplotlib/tests/test_dates.py,sha256=1oDBr8xj2v_5tLHP_1rMkKA2nikoXSxK5u44ekL_NLA,32805
-matplotlib/tests/test_determinism.py,sha256=bu8E_NMdeN0X2KRMStjAgK3tklL5SG_IqYu4hov6Z-4,4586
-matplotlib/tests/test_dviread.py,sha256=kTk9Qv6q9Kk3fJcDAEWm35HF-sKsP6Ybec6N8jEHasE,2342
-matplotlib/tests/test_figure.py,sha256=EKv9PCtr5KU30dZ_tBjxfgrQryxYjf1u0YIS83mFfe8,15244
-matplotlib/tests/test_font_manager.py,sha256=OrOm9CD4FnUnSzoQEpRNcsDktw7gNBz3h7YMPGkudjI,7217
-matplotlib/tests/test_fontconfig_pattern.py,sha256=1MhBrF914MKxjbpdxKDqkfVyCZGnFBA06D2I6rqHRHo,2012
-matplotlib/tests/test_gridspec.py,sha256=zahj5Rd4pB0xtAc_3KX7fQWyBys0P-IQk-Cq0cs8VgY,626
-matplotlib/tests/test_image.py,sha256=RMReqvIC2celG9NhUkJzv7Cl2us5Pc3f8I4uhxAzGQs,36254
-matplotlib/tests/test_legend.py,sha256=oXMRtvzQgYMqNC0vPR8mhqQQl5n-IZRBSIZbr_N4hVk,20051
-matplotlib/tests/test_lines.py,sha256=zbpM3DO0F-aclKrTE2JliUZpBR1UV5coR6I5OXOvJbg,5970
-matplotlib/tests/test_marker.py,sha256=yGEoHoMji04-BPN-mmddO60pcpGwvL6FMO101xz70dg,4768
-matplotlib/tests/test_mathtext.py,sha256=xqmDclBoB-7253xFBgf_yI9JxdkYZfuYgJ66HFcyqQA,13331
-matplotlib/tests/test_matplotlib.py,sha256=DIBqISzUIYanSxNWJL9n2oob1dRLOOAr6TIz2BTWK1I,706
-matplotlib/tests/test_mlab.py,sha256=ZpoL_7s2ARzt3uhq1InSVEWahB-svI0siIutKqyyUpM,89334
-matplotlib/tests/test_offsetbox.py,sha256=f_I8sNuPmN4TXQAKGp5w3XQvnpWVSrHgEZr_0ZR7siE,6633
-matplotlib/tests/test_patches.py,sha256=NaNojcVYpt6Lw3xr4bcI1c6Tc0fjBlz5OkQMhZlLApg,16948
-matplotlib/tests/test_path.py,sha256=X6kEMiXLHVdRaZ9w2JF2ID2_DtIVonQDByvXpLbKXSo,12736
-matplotlib/tests/test_patheffects.py,sha256=I1C81Cms_QBK6cPg_xxKZBXKykZuGI5H2wwFtwnALZk,5207
-matplotlib/tests/test_pickle.py,sha256=BahI72bPhtSEylUvRwKgksK4N5i2vjsQ1APvEw3Om-0,5653
-matplotlib/tests/test_png.py,sha256=-ik0JJOAuZCED13VshP5RZsBOQpXu_Kv9I1oaZ_grxs,1705
-matplotlib/tests/test_preprocess_data.py,sha256=vVnEzVU-jd1hAQwh-b9IbWo-S_pIg4I9NCpSQ1lLChI,10034
-matplotlib/tests/test_pyplot.py,sha256=9KEPaGTyHduk7vi40kbva03HFk7bm8KrGlWjkBGMoQ0,1662
-matplotlib/tests/test_quiver.py,sha256=_dGa3bJmvNqcnBvFhGntvhBKRipROZUNOrSm-lMtc7Y,8087
-matplotlib/tests/test_rcparams.py,sha256=HnXA81intnBhogrXbCuaAfOV2nyvbGvOCESYElue6C4,20896
-matplotlib/tests/test_sankey.py,sha256=KdWhgZpEiCJ8o7yuFjnCgqFeodwKSCuuhV_mhIc04dM,310
-matplotlib/tests/test_scale.py,sha256=kolkvXNDsSm7P44yrVDNuz25lve4iGGreaG-JC8-VIA,5895
-matplotlib/tests/test_simplification.py,sha256=_dIImjiA0VHBEbOrGQluQKCS6SQFwEVvfL9pqIn_SHI,11048
-matplotlib/tests/test_skew.py,sha256=hngaWfqV6zqZSnRmVadBvtMIrg1snTZvu3fsqv5YddU,6310
-matplotlib/tests/test_sphinxext.py,sha256=VfFfCq5T3jaVN0Ut67SHpilUOzl-_zaJDnGxfGEtrgA,2022
-matplotlib/tests/test_spines.py,sha256=5jGy42khH7ndaHRCgJONXBOvM5ZnrzOhPSR42IAUAA0,3132
-matplotlib/tests/test_streamplot.py,sha256=_9iDNwQ0M1djl0eEX94QJtPYqCKFN5ncU_cIKJlm39w,3909
-matplotlib/tests/test_style.py,sha256=FKsTSWx43sls_PqZzOEJ-ZRaiBmSmVQCgCxfGTlyiNc,5677
-matplotlib/tests/test_subplots.py,sha256=RIk5cOGJmZwQz4UzZ_IEe1rzx4riAjO3bdltY5p1F6k,5992
-matplotlib/tests/test_table.py,sha256=UEvwlff7Jdx7ezPMc8nAdaCO0u11PzNpCZqYGLDS3O4,5685
-matplotlib/tests/test_testing.py,sha256=6pJ-SCQP1Bj4Qw5m5CEz2aWV4Bl7ovXE2uUpttiIu3Y,449
-matplotlib/tests/test_texmanager.py,sha256=zCtJ3JnZNfP2AQNy7q2LQAgaflSe7S5htJkJNylQSGE,459
-matplotlib/tests/test_text.py,sha256=49TKkDPy_tFRyxPLSp8-GgeS8TdU87JW24IUvA13NVM,20461
-matplotlib/tests/test_ticker.py,sha256=niDdQLrvTIUa4x0jWchca_LJJFQc7EQVfBopnF-DjEM,49453
-matplotlib/tests/test_tightlayout.py,sha256=Rg-Vw7VJSFxonhO5qnb2StPkMK7R4jpohMdFQbtPVSc,9685
-matplotlib/tests/test_transforms.py,sha256=1CO_STcfUU4yo4bJZLdTpJ7dF3E285LVbG-OBpFUchA,24892
-matplotlib/tests/test_triangulation.py,sha256=KWSRvg-_xE5Wz-_LAqB-EvI_5uy9isc9GTmhmi189Kw,45372
-matplotlib/tests/test_ttconv.py,sha256=w6U4-5OiEuXsOskvMz4E-f9iqPoxCt8dIC2TNB7PwXo,655
-matplotlib/tests/test_type1font.py,sha256=C0pCPBGOv49SR2xxDOq6LSXAEH_ZNvIWvr_jG-23Gmc,2097
-matplotlib/tests/test_units.py,sha256=DhE6O7PZhMUf4FMoc1ByTcMgpS9-gMmjqsiQnqBBTKc,5710
-matplotlib/tests/test_usetex.py,sha256=OrkN0Alth9lTFBWJbiQDsszhW70oO6TagLaD9XsCFmo,1245
-matplotlib/tests/test_widgets.py,sha256=ijPT0E0-nS1J3kBpxoWSok1GbqlZf22J5Csbto3nl4U,17654
-matplotlib/tests/tinypages/.gitignore,sha256=re9gqsLda7alFAVabOwnvrzS8ChI0uTxX1FxzsvqyEE,8
-matplotlib/tests/tinypages/README.md,sha256=l-sVwF8k46XxCZdwprn5wSibt6S03ICVLlMqJJN7EDo,124
-matplotlib/tests/tinypages/__pycache__/conf.cpython-38.pyc,,
-matplotlib/tests/tinypages/__pycache__/range4.cpython-38.pyc,,
-matplotlib/tests/tinypages/__pycache__/range6.cpython-38.pyc,,
-matplotlib/tests/tinypages/_static/.gitignore,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
-matplotlib/tests/tinypages/_static/README.txt,sha256=1nnoizmUuHn5GKx8RL6MwJPlkyGmu_KHhYIMTDSWUNM,303
-matplotlib/tests/tinypages/conf.py,sha256=0_a4wyqPA9oaOFpLLpSEzkZI-hwtyRbqLWBx9nf0sLA,8432
-matplotlib/tests/tinypages/index.rst,sha256=kLSy7c3SoIAVsKOFkbzB4zFVzk3HW3d_rJHlHcNGBAg,446
-matplotlib/tests/tinypages/range4.py,sha256=fs2krzi9sY9ysmJRQCdGs_Jh1L9vDXDrNse7c0aX_Rw,81
-matplotlib/tests/tinypages/range6.py,sha256=a2EaHrNwXz4GJqhRuc7luqRpt7sqLKhTKeid9Drt2QQ,281
-matplotlib/tests/tinypages/some_plots.rst,sha256=C9rwV9UVlhFvxm8VqV6PoAP1AQ8Kk0LGZI9va4joif0,2156
-matplotlib/texmanager.py,sha256=kiFNpjY5S8OJ2Q6WPZ2h6YueL_zrXZQyIdrFgP_XRnI,17097
-matplotlib/text.py,sha256=bt04zgIbjJUOqdZ8gomc_zWF3UOYL5mHWaHb9OxxYHM,81090
-matplotlib/textpath.py,sha256=dEZ1Vg4ZUI5M4iTHn-7I45KeR1FTit78jQ-3EyK6orc,17010
-matplotlib/ticker.py,sha256=Dp_BzFOaTG0Qy7W1H4-yo5JlNNLMJS2L8BiXYjCC4Xk,101242
-matplotlib/tight_bbox.py,sha256=bQAOXPKfVWoBkGZbC0ckRcldgLJ8eBUe2IsT8UQpgaY,2590
-matplotlib/tight_layout.py,sha256=BrNob3eytUkmtXtwgfD3jdRgNh_tIjDE89AZjAnhFdY,14586
-matplotlib/transforms.py,sha256=cynqPdAO9gtYxmDBr_zr1VTSlIlbtOAwfNzGqsVV208,97572
-matplotlib/tri/__init__.py,sha256=XMaejh88uov7Neu7MuYMyaNQqaxg49nXaiJfvjifrRM,256
-matplotlib/tri/__pycache__/__init__.cpython-38.pyc,,
-matplotlib/tri/__pycache__/triangulation.cpython-38.pyc,,
-matplotlib/tri/__pycache__/tricontour.cpython-38.pyc,,
-matplotlib/tri/__pycache__/trifinder.cpython-38.pyc,,
-matplotlib/tri/__pycache__/triinterpolate.cpython-38.pyc,,
-matplotlib/tri/__pycache__/tripcolor.cpython-38.pyc,,
-matplotlib/tri/__pycache__/triplot.cpython-38.pyc,,
-matplotlib/tri/__pycache__/trirefine.cpython-38.pyc,,
-matplotlib/tri/__pycache__/tritools.cpython-38.pyc,,
-matplotlib/tri/triangulation.py,sha256=NCY1Fx66H3MHrMA1-NW6G_shopBtFu1Ehm1f6XyRDBE,8315
-matplotlib/tri/tricontour.py,sha256=4gKIAi1CFKWK8BCqAXMD6PlUKxnrC9GvzeQz0Yknvik,9794
-matplotlib/tri/trifinder.py,sha256=umsDJX2kach9MVDvEirLdN9q31QQ9tdP67U71eFyGj8,3497
-matplotlib/tri/triinterpolate.py,sha256=EP-ZwNC3HlOGB4jNaHGUCncXeO7LocvT2QhTr-jKCrk,64886
-matplotlib/tri/tripcolor.py,sha256=H6DEToUjfU12hDkfekshYyuQoZc7Fa4r4W6MOR5d6Jw,5169
-matplotlib/tri/triplot.py,sha256=aZ9O_VVLH0AOne31u11ltLlyVyhqKtyzec7WH3b3pkk,2857
-matplotlib/tri/trirefine.py,sha256=uwAminHKuxgE0ZuwwllIpqK2Ww_q--VKzMicWUslA0s,13765
-matplotlib/tri/tritools.py,sha256=BggcSXDVoc2mSyJp7wQ51qaw8WhdL7ianZ-D7ezkuC8,12398
-matplotlib/ttconv.cpython-38-x86_64-linux-gnu.so,sha256=1jdaSZnni-N5-Ec75mfmTXKMD54BQfFW0F_kdcL7ifE,83952
-matplotlib/type1font.py,sha256=-D1P81hhDUVNAHZ55-Df4cPc-3R8ycY_judVBZphgsk,12168
-matplotlib/units.py,sha256=dgSbQsrJPRiKf5IJv-PM0xYMcvT3kle3gdPJsdjbRZk,7332
-matplotlib/widgets.py,sha256=lMHpWCFdFTwSCEO5uL4fjcsoDQMzkzlWyVXnx80FVn4,94615
-mpl_toolkits/axes_grid/__init__.py,sha256=VLlc0DaOkr9JumPa8W4zt9lGHp180ie8_WLPZVNSJMw,537
-mpl_toolkits/axes_grid/__pycache__/__init__.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/anchored_artists.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/angle_helper.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/axes_divider.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/axes_grid.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/axes_rgb.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/axes_size.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/axis_artist.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/axisline_style.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/axislines.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/clip_path.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/colorbar.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/floating_axes.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/grid_finder.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/grid_helper_curvelinear.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/inset_locator.cpython-38.pyc,,
-mpl_toolkits/axes_grid/__pycache__/parasite_axes.cpython-38.pyc,,
-mpl_toolkits/axes_grid/anchored_artists.py,sha256=_F6-9iacZidb5JpJ8jCOZ9PdiZaR5qpfBjf-3VjTzNc,291
-mpl_toolkits/axes_grid/angle_helper.py,sha256=Tb4Mb_NGkUdkisebe2dqfBdFmUZiSmGyUnftiSeSIls,51
-mpl_toolkits/axes_grid/axes_divider.py,sha256=tJlPia3Z8xLq6uXehBwAlD_4ywMvRTTkM73qNnCpo7Q,178
-mpl_toolkits/axes_grid/axes_grid.py,sha256=UPlVDwsze_w2aZeLaMg4WZVK3q2EvWePXTFZFvjCQz4,89
-mpl_toolkits/axes_grid/axes_rgb.py,sha256=d3h2tImoPxvVtl8i4IBA_i1vBQykZDYizcNDGdjRltE,201
-mpl_toolkits/axes_grid/axes_size.py,sha256=v4Nhxe7DVp1FkKX03DqJJ1aevDanDvgKT9r0ouDzTxw,48
-mpl_toolkits/axes_grid/axis_artist.py,sha256=zUlJFUHueDsMtzLi_mK2_Wf-nSBQgiTsMOFpo_SngZ0,50
-mpl_toolkits/axes_grid/axisline_style.py,sha256=lNVHXkFWhSWPXOOfF-wlVkDPzmzuStJyJzF-NS5Wf_g,53
-mpl_toolkits/axes_grid/axislines.py,sha256=kVyhb6laiImmuNE53QTQh3kgxz0sO1mcSMpnqIdjylA,48
-mpl_toolkits/axes_grid/clip_path.py,sha256=s-d36hUiy9I9BSr9wpxjgoAACCQrczHjw072JvArNvE,48
-mpl_toolkits/axes_grid/colorbar.py,sha256=DckRf6tadLeTNjx-Zk1u3agnSGZgizDjd0Dxw1-GRdw,171
-mpl_toolkits/axes_grid/floating_axes.py,sha256=i35OfV1ZMF-DkLo4bKmzFZP6LgCwXfdDKxYlGqjyKOM,52
-mpl_toolkits/axes_grid/grid_finder.py,sha256=Y221c-Jh_AFd3Oolzvr0B1Zrz9MoXPatUABQdLsFdpw,50
-mpl_toolkits/axes_grid/grid_helper_curvelinear.py,sha256=nRl_B-755X7UpVqqdwkqc_IwiTmM48z3eOMHuvJT5HI,62
-mpl_toolkits/axes_grid/inset_locator.py,sha256=qqXlT8JWokP0kV-8NHknZDINtK-jbXfkutH_1tcRe_o,216
-mpl_toolkits/axes_grid/parasite_axes.py,sha256=kCFtaRTd0O8ePL78GOYvhEKqn8rE9bk61v0kVgMb6UE,469
-mpl_toolkits/axes_grid1/__init__.py,sha256=-lw0ZfG4XUpuAolCpXKFwtS3w1LJ1ZToSEC9OSmB-4Q,204
-mpl_toolkits/axes_grid1/__pycache__/__init__.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/anchored_artists.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/axes_divider.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/axes_grid.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/axes_rgb.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/axes_size.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/colorbar.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/inset_locator.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/mpl_axes.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/__pycache__/parasite_axes.cpython-38.pyc,,
-mpl_toolkits/axes_grid1/anchored_artists.py,sha256=F9396ifiWLedXEsivC3-rJjhYOxZ84dHYFhlRMVt4wE,21031
-mpl_toolkits/axes_grid1/axes_divider.py,sha256=rZOhnowUzJ3mXb6LKkLPjDyxkz-EPJmA3MCafFa8VN8,29175
-mpl_toolkits/axes_grid1/axes_grid.py,sha256=2ThJGeKXb9avu0KN3ujBliY2HV26IHC1daxy74t8ITk,27888
-mpl_toolkits/axes_grid1/axes_rgb.py,sha256=NsMKkaMEeXd6N1AYVP1Pz-ulwNeof1pU4qkReoQ8xFc,6652
-mpl_toolkits/axes_grid1/axes_size.py,sha256=YBC1PUmUK1-0c7cuqgJQBpDwVrbZQaWXyWadvuOO5bs,8602
-mpl_toolkits/axes_grid1/colorbar.py,sha256=Y0-Uf9osbz31YBOTxxs_UFXbp6Xyc9Rais47tBMjTXI,27123
-mpl_toolkits/axes_grid1/inset_locator.py,sha256=0BA8z3BiT78sS2-ksVe8iKS6KLxVv_NTV38NTLmRuu4,23675
-mpl_toolkits/axes_grid1/mpl_axes.py,sha256=MJVYUN4YRtTWrq1wmyv_y61O002tiyFESmBSaJ8xkG4,4380
-mpl_toolkits/axes_grid1/parasite_axes.py,sha256=ug0YRJiTtA3YVikdKMGj-qjoeOFnqNw2QnRab0Qp7wI,13570
-mpl_toolkits/axisartist/__init__.py,sha256=2zsgjqTtP_NXv78MEaKabmfmkjA7yhy77pIcaR57YWs,748
-mpl_toolkits/axisartist/__pycache__/__init__.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/angle_helper.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/axes_divider.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/axes_grid.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/axes_rgb.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/axis_artist.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/axisline_style.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/axislines.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/clip_path.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/floating_axes.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/grid_finder.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/grid_helper_curvelinear.cpython-38.pyc,,
-mpl_toolkits/axisartist/__pycache__/parasite_axes.cpython-38.pyc,,
-mpl_toolkits/axisartist/angle_helper.py,sha256=KZiXfi0IPcGp6JFXewj0VLrUycSfI93ezoimkti3wpY,12632
-mpl_toolkits/axisartist/axes_divider.py,sha256=baPCBjM20SvAUeMjhvlS_cccRSM1y7ZKybtoW8upo2k,127
-mpl_toolkits/axisartist/axes_grid.py,sha256=vfd_EXHuYQ7iIVK2FOm6inLhb7huZxtOSvFyOVW2GmU,610
-mpl_toolkits/axisartist/axes_rgb.py,sha256=TpJCB8eA0wHZVXOxxfFoy1Tk_KFj68sZvo74doDeHYE,179
-mpl_toolkits/axisartist/axis_artist.py,sha256=gScMYbfAyxT5IgyEZRVto2NyZVLGpDQeJ1t9tk1d3OM,43453
-mpl_toolkits/axisartist/axisline_style.py,sha256=bQ3M5gAxS7HbCC3oOQgrSyNWdk_FbvXfX24Eatge0UE,5098
-mpl_toolkits/axisartist/axislines.py,sha256=mrQIihqbfBi2F-QgLRjZvHGM6rEojStBzojYpVNkjg0,20852
-mpl_toolkits/axisartist/clip_path.py,sha256=LE_IIP0byNr5ELJlD8_8fsAh215MUDoK19-BISuFB80,3777
-mpl_toolkits/axisartist/floating_axes.py,sha256=xSAJ5Myaa5Xm9DkOhJcdaPwzdPyvJnw5K9YPmDwB5ME,13122
-mpl_toolkits/axisartist/grid_finder.py,sha256=K1Gae38Jt2OFfScZaKbxkLLcWrHDm-2bAVsl56SC1F0,10388
-mpl_toolkits/axisartist/grid_helper_curvelinear.py,sha256=6QT9nTQ2dJ_NPsazS0Q0hC8W5IV7yzqYd_Fa8_gJXmI,14384
-mpl_toolkits/axisartist/parasite_axes.py,sha256=1sQwBEYuXHpaEeObb7cXh0I1xWroYtcvFiEmwrzqK3w,447
-mpl_toolkits/mplot3d/__init__.py,sha256=V2iPIP9VyRhoJsFWnQf5AkfyI1GSSP9H6hICEe9edJo,27
-mpl_toolkits/mplot3d/__pycache__/__init__.cpython-38.pyc,,
-mpl_toolkits/mplot3d/__pycache__/art3d.cpython-38.pyc,,
-mpl_toolkits/mplot3d/__pycache__/axes3d.cpython-38.pyc,,
-mpl_toolkits/mplot3d/__pycache__/axis3d.cpython-38.pyc,,
-mpl_toolkits/mplot3d/__pycache__/proj3d.cpython-38.pyc,,
-mpl_toolkits/mplot3d/art3d.py,sha256=MAR_fFyBwe3VkwlOeWMccwDWo8RR1VqhUjuipLPuIFU,27647
-mpl_toolkits/mplot3d/axes3d.py,sha256=iJ7LN-UKY7xMaGjYbeu-J1IuC54QX3irx7Kkh5gInzY,98609
-mpl_toolkits/mplot3d/axis3d.py,sha256=UdxPxUW7GDoOpBy4uByLmLZJfle2wu0oYGenDHjjcLA,16737
-mpl_toolkits/mplot3d/proj3d.py,sha256=5xwjogevdUCBaV9sx1RlNqO6fMCSIBi_1_uVZniy2pU,5499
-mpl_toolkits/tests/__init__.py,sha256=iPdasxJf0vpIi11tQ98OVSQgS0UaPUyOEGGfAryAhIA,381
-mpl_toolkits/tests/__pycache__/__init__.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/conftest.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axes_grid.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axes_grid1.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axisartist_angle_helper.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axisartist_axis_artist.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axisartist_axislines.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axisartist_clip_path.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axisartist_floating_axes.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axisartist_grid_finder.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_axisartist_grid_helper_curvelinear.cpython-38.pyc,,
-mpl_toolkits/tests/__pycache__/test_mplot3d.cpython-38.pyc,,
-mpl_toolkits/tests/baseline_images/test_axes_grid/imagegrid_cbar_mode.png,sha256=yvo6erXXc3Z9aO0rrEezBooCc6KhAw7wKv4WngOQmFA,87393
-mpl_toolkits/tests/baseline_images/test_axes_grid1/anchored_direction_arrows.png,sha256=XMZGgG7_9k96bKhI2G--XBVKpct5O5psbGH2Wvj5YA0,10784
-mpl_toolkits/tests/baseline_images/test_axes_grid1/anchored_direction_arrows_many_args.png,sha256=fkPsdmhd4S1g-QxMb55M63iAgWmC2G4ytcLOT9tMAD0,11039
-mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.pdf,sha256=eW2CuM_T4d95dC-DU0PmmQD7gqRQIO0rcQpvp-zu1i4,25446
-mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.png,sha256=VfRfs6p4akgjGxxNm6Bu83Pg0v1KmU7WPu97_-kzNFc,48825
-mpl_toolkits/tests/baseline_images/test_axes_grid1/divider_append_axes.svg,sha256=usfsa3y-s-N2KMOzsOZHTq-PZXgAPXsSM-lkxJ3ZUi0,172812
-mpl_toolkits/tests/baseline_images/test_axes_grid1/fill_facecolor.png,sha256=Tkrylxebxm8SuWZjQK0qXSX8m9QsQU6kYm7L2dgt4yg,14845
-mpl_toolkits/tests/baseline_images/test_axes_grid1/image_grid.png,sha256=HIg43mbdOUyEWY-jQ1DEpG7DMqCcWbX1Xf2itmW1YL4,3786
-mpl_toolkits/tests/baseline_images/test_axes_grid1/inset_axes.png,sha256=RQmR39E6Vskvl7G4LInHibW9E1VK0QgCvI-hBlb-E2E,9928
-mpl_toolkits/tests/baseline_images/test_axes_grid1/inset_locator.png,sha256=bQKKKUuoU_EZwZT_9FzzeVKsKwUUBOZV55g4vVUbnCU,9490
-mpl_toolkits/tests/baseline_images/test_axes_grid1/inverted_zoomed_axes.png,sha256=rvglsLg8Kl9jE_JukTJ5B3EHozsIYJsaYA0JIOicZL8,25997
-mpl_toolkits/tests/baseline_images/test_axes_grid1/twin_axes_empty_and_removed.png,sha256=0YzkFhxs4SBG_FEmnWB10bXIxl9aq7WJveQAqHm0JrQ,37701
-mpl_toolkits/tests/baseline_images/test_axes_grid1/zoomed_axes.png,sha256=mUu8zJtz8FMb7h5l4Cfp3oBi9jaNR5OoyaDgwqpAZp4,25893
-mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist.png,sha256=qdlk9UPScCAN9RBOhoNqLmJvmkXt8pCuwuQtrz5E8Bs,10151
-mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_labelbase.png,sha256=An5lovtvAiNA1NZI-E8kOj6eYTruQMqwf3J7pXwdk4A,10598
-mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_ticklabels.png,sha256=7vuAKkIqcpgJrc2AF7oslf-E_sDfSlCoymyc87u4AWs,5696
-mpl_toolkits/tests/baseline_images/test_axisartist_axis_artist/axis_artist_ticks.png,sha256=CkVtCWG13ViW0w2DsbzfXSvoFWHYaaqQYeEYpbKbOg8,5695
-mpl_toolkits/tests/baseline_images/test_axisartist_axislines/ParasiteAxesAuxTrans_meshplot.png,sha256=FOgl-Glmzhdp6V8mz4StofTsFXGysFkEcUeaWtmJDZs,34354
-mpl_toolkits/tests/baseline_images/test_axisartist_axislines/Subplot.png,sha256=tRpYCjR5zUkafA85DVmY3duTEouwCZq6jDwSF4UsBS8,26919
-mpl_toolkits/tests/baseline_images/test_axisartist_axislines/SubplotZero.png,sha256=3kCrz7HQMYrK3iDgYgf8kyigxRtIGFBbcUzJPtiXh_E,28682
-mpl_toolkits/tests/baseline_images/test_axisartist_clip_path/clip_path.png,sha256=BtMyb7ZawcgId9jl1_qW72lU_ZyxLN780uQ9bCLjbHA,25701
-mpl_toolkits/tests/baseline_images/test_axisartist_floating_axes/curvelinear3.png,sha256=4th7Y74_9YV6X25RqJW0Op9WDzGRCcxF1kfNogkgozE,52835
-mpl_toolkits/tests/baseline_images/test_axisartist_floating_axes/curvelinear4.png,sha256=cYjrSiH6Mvor-VhmwNUgX7Le3_k1rurpd8L5vhTf16s,29374
-mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/axis_direction.png,sha256=3fue92dg-ntYI0XX0nB31IFpgRT2V3izqjrmLvEdYN4,40536
-mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/custom_transform.png,sha256=4cQhIFK1z8oPUVyvkHNZ_m-GCbikmUbTvkvYVGy6U4o,15118
-mpl_toolkits/tests/baseline_images/test_axisartist_grid_helper_curvelinear/polar_box.png,sha256=wWaPM3I7_435SkVQqIggb8BHrWBMWrsSVyMZQQJ6fE4,62526
-mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_cla.png,sha256=htnP1CA8dd85KqdnOsHVlsehT90MUoQD8kFTyra0AuE,51409
-mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_labelpad.png,sha256=zrLsk8t7s970yaY3cqj6SOMbI6UY8Loe0Zbp0WqFtwQ,66817
-mpl_toolkits/tests/baseline_images/test_mplot3d/axes3d_ortho.png,sha256=SoyN30SsuvEECZyB_ReGP3ZKGZJazOp05dXa3YUn7Jc,47796
-mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d.png,sha256=Qw909B4nDmV9DlMuo1DKk7y5ndjtvni5d_DcysmG9VA,100466
-mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d_notshaded.png,sha256=soaHKytaVZHmPvHIEcPFQDJDqhEEuNO_JIVCZyjacxM,66294
-mpl_toolkits/tests/baseline_images/test_mplot3d/bar3d_shaded.png,sha256=laBssZyuviouRe3seffJWOz45OLunXC0dFHi-lYge1w,115939
-mpl_toolkits/tests/baseline_images/test_mplot3d/contour3d.png,sha256=tii1IakS8MC_Vuwd95HhcyM0iq4zGN5DxgRFfB9mKu8,83161
-mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d.png,sha256=Jb-fhAcgogE8jn9DSsaqInUfWC7D_5Pf3QRf7XWAX2Q,42575
-mpl_toolkits/tests/baseline_images/test_mplot3d/contourf3d_fill.png,sha256=dE8eHoj43eePB44F1nLM2RLj8iqw8rCYI3D0VD3gUg0,39694
-mpl_toolkits/tests/baseline_images/test_mplot3d/lines3d.png,sha256=DQT-NruHCeG5LKpjG-dlLln3aCoPKhua5PQnHTafBGU,60217
-mpl_toolkits/tests/baseline_images/test_mplot3d/mixedsubplot.png,sha256=iHxYbxRflxIpjoAtWo9KAvgK4CS-k4N03p0SX_xF4DA,39674
-mpl_toolkits/tests/baseline_images/test_mplot3d/plot_3d_from_2d.png,sha256=AWos5EJWMerD0tgVZyvBofz-5hnCq6fhGHKmQi-izAg,56593
-mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_alpha.png,sha256=AnZJbnnBnF_fny5FBTlSWblkNMlPI1dcQRlCfGPIjWI,52046
-mpl_toolkits/tests/baseline_images/test_mplot3d/poly3dcollection_closed.png,sha256=ePzSA-iFaQbmH603vw1jhs9vyIt45xXnbpIuUF3a1l8,52065
-mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_axes_cube.png,sha256=AJ0EoayvdBoywpOUWcxbMQ0oB7cTzcoWGgGyx2qgQMU,23182
-mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_axes_cube_ortho.png,sha256=5Phz7BclSciZpg4SDu-eUQ-v_ikHbEqReQWCdeHywQk,16210
-mpl_toolkits/tests/baseline_images/test_mplot3d/proj3d_lines_dists.png,sha256=XCd4hX2ckc5GCxcgenkRJ8MT7pX-3iMLylD2rCjNl-4,18898
-mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d.png,sha256=PBllNI1kHf1rz-oPK507OwsPNE9DPwivXAVJM9DemBI,104755
-mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_empty.png,sha256=98D3k5QIL7KugUwzqJhdLtp9dgDGgx8hGa9_u8cvX6o,37954
-mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_masked.png,sha256=67yp7-6f-vDiYTmCqMFfuIEGly5UHCCUOV84YJtLsX8,80392
-mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_pivot_middle.png,sha256=N4o26wMzfnyxndPbZ2VnsjIAiNYrFN9Aa40ficwO9AM,104735
-mpl_toolkits/tests/baseline_images/test_mplot3d/quiver3d_pivot_tail.png,sha256=Ff_UrWxD-VIMQLN1uXy5u_Yd5e1P427YfGM05nvU2kE,104951
-mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d.png,sha256=MDaocusHz6Itinjm2j6fnDh-rl1fqVjnqM89nP8bwZs,43155
-mpl_toolkits/tests/baseline_images/test_mplot3d/scatter3d_color.png,sha256=Y7De9BIFLp0Ova4fk9IcXloNjiwmifTrFA1IfVJA3aE,41598
-mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d.png,sha256=Ok0UmO2DELze2yK8mRx0CifmRAgvjyS1IvERsBRvFlU,54712
-mpl_toolkits/tests/baseline_images/test_mplot3d/surface3d_shaded.png,sha256=kWYGPWgG1ZrQVgd389xmIZ1cc59tAkKKiikKaJzHKkw,43474
-mpl_toolkits/tests/baseline_images/test_mplot3d/text3d.png,sha256=sO68K3cti2YsPkkjEIAvc7_pd8JaHpc_a78UVx4Htu4,78758
-mpl_toolkits/tests/baseline_images/test_mplot3d/tricontour.png,sha256=8IjYmJP6cBhnPGLz-WDyn7UUMYZ10Kz2MpjOFwDUVow,71328
-mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d.png,sha256=nO0gJBIluLEX3mlxXY3C6bx-9Jf_xJyXAnTXKnqrIkQ,99103
-mpl_toolkits/tests/baseline_images/test_mplot3d/trisurf3d_shaded.png,sha256=LSVF3lI7JnYXmCBAcn410k3JRE-3ssp84Dmgg3zr0FA,94328
-mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-alpha.png,sha256=LELjsQnfvfzLF8rNSh5azv9BdwF8TlCMn2wbBJNTtyQ,178141
-mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-edge-style.png,sha256=UJXpFMSWIFgUH2rLEv1nxDvHrnshlSz4d5ZB34upa3g,65759
-mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-named-colors.png,sha256=J8m66Bc5NoeZxGRwbBThV06_aybNvMeTtwUnmCRzNak,93580
-mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-rgb-data.png,sha256=5s02No0RWv8NYV_ccFUnDdBaUHQ8DTO90qddKBnN6mw,131458
-mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-simple.png,sha256=7VCcyzKKKz8E7txQV4wi-jEbtftaFW_ekWmA9E1qx3Y,60304
-mpl_toolkits/tests/baseline_images/test_mplot3d/voxels-xyz.png,sha256=KwDmkuK7FMtl0Q2ank7wcph9uTncUr7UdTh2hUYdZP8,121446
-mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3d.png,sha256=epmsR4rWGzh7prW3RL_t8ZcUEsphM5bc0t5j__iauOY,108371
-mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3dzerocstride.png,sha256=WaO_3NcaZPFzlui5SQYJ-TbUylHkSbieneCYPffNgAA,81117
-mpl_toolkits/tests/baseline_images/test_mplot3d/wireframe3dzerorstride.png,sha256=y1JvfuVOBiNhJoJ2HdOXyBYBBkQm-oaPcoekfT-cMso,84284
-mpl_toolkits/tests/conftest.py,sha256=Ph6QZKdfAnkPwU52StddC-uwtCHfANKX1dDXgtX122g,213
-mpl_toolkits/tests/test_axes_grid.py,sha256=SUnj9aImCEI-Q3_cM8e5BlizoNle9E1joKkE_q57OAg,2694
-mpl_toolkits/tests/test_axes_grid1.py,sha256=pUw19PTds6WRlLON5U9ZWmt6HxV56Q6DKDPVGM34ysk,17113
-mpl_toolkits/tests/test_axisartist_angle_helper.py,sha256=PwhJwBm2kk4uMyhdO5arQs8IlqSX2vN0hvUzI7YHqrw,5670
-mpl_toolkits/tests/test_axisartist_axis_artist.py,sha256=N4Khx8jSxkoiMz3KvumodmFKHZUtdwtjkzxLWPSdyuw,3008
-mpl_toolkits/tests/test_axisartist_axislines.py,sha256=4ujhndnDq-6albE4WwVFTVURfjG1xK1597smUGMxfFg,2331
-mpl_toolkits/tests/test_axisartist_clip_path.py,sha256=afS3nvNqCgvDpJdg_MvbwydtSWv5b6ciP-Iq2aNcNFQ,1004
-mpl_toolkits/tests/test_axisartist_floating_axes.py,sha256=xENnUpFU8EHPgnON6W1xqMVWIq8qxIzuGf1oMmSMFJo,4127
-mpl_toolkits/tests/test_axisartist_grid_finder.py,sha256=e65sLudWFIXeU08Sis3_SI1JEI6eq8YqKj-80F_Nohk,325
-mpl_toolkits/tests/test_axisartist_grid_helper_curvelinear.py,sha256=0AT6TdbxHGHlircgjNZyK2u1dw05YLXdOhLqXmsKyw4,7572
-mpl_toolkits/tests/test_mplot3d.py,sha256=TojtKh1gbRWl-kCWQcYaFMOS89txDRd02O0NBJuu-vE,31991
-pylab.py,sha256=u_By3CHla-rBMg57egFXIxZ3P_J6zEkSu_dNpBcH5pw,90

+ 0 - 5
venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/WHEEL

@@ -1,5 +0,0 @@
-Wheel-Version: 1.0
-Generator: bdist_wheel (0.31.1)
-Root-Is-Purelib: false
-Tag: cp38-cp38-manylinux1_x86_64
-

+ 0 - 1
venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/namespace_packages.txt

@@ -1 +0,0 @@
-mpl_toolkits

+ 0 - 3
venv/lib/python3.8/site-packages/matplotlib-3.2.1.dist-info/top_level.txt

@@ -1,3 +0,0 @@
-matplotlib
-mpl_toolkits
-pylab

BIN
venv/lib/python3.8/site-packages/matplotlib/.libs/libpng16-cfdb1654.so.16.21.0


BIN
venv/lib/python3.8/site-packages/matplotlib/.libs/libz-a147dcb0.so.1.2.3


+ 0 - 1601
venv/lib/python3.8/site-packages/matplotlib/__init__.py

@@ -1,1601 +0,0 @@
-"""
-This is an object-oriented plotting library.
-
-A procedural interface is provided by the companion pyplot module,
-which may be imported directly, e.g.::
-
-    import matplotlib.pyplot as plt
-
-or using ipython::
-
-    ipython
-
-at your terminal, followed by::
-
-    In [1]: %matplotlib
-    In [2]: import matplotlib.pyplot as plt
-
-at the ipython shell prompt.
-
-For the most part, direct use of the object-oriented library is
-encouraged when programming; pyplot is primarily for working
-interactively.  The
-exceptions are the pyplot commands :func:`~matplotlib.pyplot.figure`,
-:func:`~matplotlib.pyplot.subplot`,
-:func:`~matplotlib.pyplot.subplots`, and
-:func:`~pyplot.savefig`, which can greatly simplify scripting.
-
-Modules include:
-
-    :mod:`matplotlib.axes`
-        defines the :class:`~matplotlib.axes.Axes` class.  Most pyplot
-        commands are wrappers for :class:`~matplotlib.axes.Axes`
-        methods.  The axes module is the highest level of OO access to
-        the library.
-
-    :mod:`matplotlib.figure`
-        defines the :class:`~matplotlib.figure.Figure` class.
-
-    :mod:`matplotlib.artist`
-        defines the :class:`~matplotlib.artist.Artist` base class for
-        all classes that draw things.
-
-    :mod:`matplotlib.lines`
-        defines the :class:`~matplotlib.lines.Line2D` class for
-        drawing lines and markers
-
-    :mod:`matplotlib.patches`
-        defines classes for drawing polygons
-
-    :mod:`matplotlib.text`
-        defines the :class:`~matplotlib.text.Text`,
-        :class:`~matplotlib.text.TextWithDash`, and
-        :class:`~matplotlib.text.Annotate` classes
-
-    :mod:`matplotlib.image`
-        defines the :class:`~matplotlib.image.AxesImage` and
-        :class:`~matplotlib.image.FigureImage` classes
-
-    :mod:`matplotlib.collections`
-        classes for efficient drawing of groups of lines or polygons
-
-    :mod:`matplotlib.colors`
-        classes for interpreting color specifications and for making
-        colormaps
-
-    :mod:`matplotlib.cm`
-        colormaps and the :class:`~matplotlib.image.ScalarMappable`
-        mixin class for providing color mapping functionality to other
-        classes
-
-    :mod:`matplotlib.ticker`
-        classes for calculating tick mark locations and for formatting
-        tick labels
-
-    :mod:`matplotlib.backends`
-        a subpackage with modules for various gui libraries and output
-        formats
-
-The base matplotlib namespace includes:
-
-    :data:`~matplotlib.rcParams`
-        a global dictionary of default configuration settings.  It is
-        initialized by code which may be overridden by a matplotlibrc
-        file.
-
-    :func:`~matplotlib.rc`
-        a function for setting groups of rcParams values
-
-    :func:`~matplotlib.use`
-        a function for setting the matplotlib backend.  If used, this
-        function must be called immediately after importing matplotlib
-        for the first time.  In particular, it must be called
-        **before** importing pyplot (if pyplot is imported).
-
-matplotlib was initially written by John D. Hunter (1968-2012) and is now
-developed and maintained by a host of others.
-
-Occasionally the internal documentation (python docstrings) will refer
-to MATLAB&reg;, a registered trademark of The MathWorks, Inc.
-
-"""
-# NOTE: This file must remain Python 2 compatible for the foreseeable future,
-# to ensure that we error out properly for existing editable installs.
-
-import sys
-if sys.version_info < (3, 5):  # noqa: E402
-    raise ImportError("""
-Matplotlib 3.0+ does not support Python 2.x, 3.0, 3.1, 3.2, 3.3, or 3.4.
-Beginning with Matplotlib 3.0, Python 3.5 and above is required.
-
-See Matplotlib `INSTALL.rst` file for more information:
-
-    https://github.com/matplotlib/matplotlib/blob/master/INSTALL.rst
-
-""")
-
-import atexit
-from collections import namedtuple
-from collections.abc import MutableMapping
-import contextlib
-from distutils.version import LooseVersion
-import functools
-import importlib
-import inspect
-from inspect import Parameter
-import locale
-import logging
-import os
-from pathlib import Path
-import pprint
-import re
-import shutil
-import subprocess
-import tempfile
-import warnings
-
-# cbook must import matplotlib only within function
-# definitions, so it is safe to import from it here.
-from . import cbook, rcsetup
-from matplotlib.cbook import (
-    MatplotlibDeprecationWarning, dedent, get_label, sanitize_sequence)
-from matplotlib.cbook import mplDeprecation  # deprecated
-from matplotlib.rcsetup import defaultParams, validate_backend, cycler
-
-import numpy
-
-# Get the version from the _version.py versioneer file. For a git checkout,
-# this is computed based on the number of commits since the last tag.
-from ._version import get_versions
-__version__ = str(get_versions()['version'])
-del get_versions
-
-_log = logging.getLogger(__name__)
-
-__bibtex__ = r"""@Article{Hunter:2007,
-  Author    = {Hunter, J. D.},
-  Title     = {Matplotlib: A 2D graphics environment},
-  Journal   = {Computing in Science \& Engineering},
-  Volume    = {9},
-  Number    = {3},
-  Pages     = {90--95},
-  abstract  = {Matplotlib is a 2D graphics package used for Python
-  for application development, interactive scripting, and
-  publication-quality image generation across user
-  interfaces and operating systems.},
-  publisher = {IEEE COMPUTER SOC},
-  year      = 2007
-}"""
-
-
-@cbook.deprecated("3.2")
-def compare_versions(a, b):
-    "Return whether version *a* is greater than or equal to version *b*."
-    if isinstance(a, bytes):
-        cbook.warn_deprecated(
-            "3.0", message="compare_versions arguments should be strs.")
-        a = a.decode('ascii')
-    if isinstance(b, bytes):
-        cbook.warn_deprecated(
-            "3.0", message="compare_versions arguments should be strs.")
-        b = b.decode('ascii')
-    if a:
-        return LooseVersion(a) >= LooseVersion(b)
-    else:
-        return False
-
-
-def _check_versions():
-
-    # Quickfix to ensure Microsoft Visual C++ redistributable
-    # DLLs are loaded before importing kiwisolver
-    from . import ft2font
-
-    for modname, minver in [
-            ("cycler", "0.10"),
-            ("dateutil", "2.1"),
-            ("kiwisolver", "1.0.1"),
-            ("numpy", "1.11"),
-            ("pyparsing", "2.0.1"),
-    ]:
-        module = importlib.import_module(modname)
-        if LooseVersion(module.__version__) < minver:
-            raise ImportError("Matplotlib requires {}>={}; you have {}"
-                              .format(modname, minver, module.__version__))
-
-
-_check_versions()
-
-
-if not hasattr(sys, 'argv'):  # for modpython
-    sys.argv = ['modpython']
-
-
-# The decorator ensures this always returns the same handler (and it is only
-# attached once).
-@functools.lru_cache()
-def _ensure_handler():
-    """
-    The first time this function is called, attach a `StreamHandler` using the
-    same format as `logging.basicConfig` to the Matplotlib root logger.
-
-    Return this handler every time this function is called.
-    """
-    handler = logging.StreamHandler()
-    handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
-    _log.addHandler(handler)
-    return handler
-
-
-def set_loglevel(level):
-    """
-    Sets the Matplotlib's root logger and root logger handler level, creating
-    the handler if it does not exist yet.
-
-    Typically, one should call ``set_loglevel("info")`` or
-    ``set_loglevel("debug")`` to get additional debugging information.
-
-    Parameters
-    ----------
-    level : {"notset", "debug", "info", "warning", "error", "critical"}
-        The log level of the handler.
-
-    Notes
-    -----
-    The first time this function is called, an additional handler is attached
-    to Matplotlib's root handler; this handler is reused every time and this
-    function simply manipulates the logger and handler's level.
-    """
-    _log.setLevel(level.upper())
-    _ensure_handler().setLevel(level.upper())
-
-
-def _logged_cached(fmt, func=None):
-    """
-    Decorator that logs a function's return value, and memoizes that value.
-
-    After ::
-
-        @_logged_cached(fmt)
-        def func(): ...
-
-    the first call to *func* will log its return value at the DEBUG level using
-    %-format string *fmt*, and memoize it; later calls to *func* will directly
-    return that value.
-    """
-    if func is None:  # Return the actual decorator.
-        return functools.partial(_logged_cached, fmt)
-
-    called = False
-    ret = None
-
-    @functools.wraps(func)
-    def wrapper(**kwargs):
-        nonlocal called, ret
-        if not called:
-            ret = func(**kwargs)
-            called = True
-            _log.debug(fmt, ret)
-        return ret
-
-    return wrapper
-
-
-_ExecInfo = namedtuple("_ExecInfo", "executable version")
-
-
-class ExecutableNotFoundError(FileNotFoundError):
-    """
-    Error raised when an executable that Matplotlib optionally
-    depends on can't be found.
-    """
-    pass
-
-
-@functools.lru_cache()
-def _get_executable_info(name):
-    """
-    Get the version of some executable that Matplotlib optionally depends on.
-
-    .. warning:
-       The list of executables that this function supports is set according to
-       Matplotlib's internal needs, and may change without notice.
-
-    Parameters
-    ----------
-    name : str
-        The executable to query.  The following values are currently supported:
-        "dvipng", "gs", "inkscape", "magick", "pdftops".  This list is subject
-        to change without notice.
-
-    Returns
-    -------
-    If the executable is found, a namedtuple with fields ``executable`` (`str`)
-    and ``version`` (`distutils.version.LooseVersion`, or ``None`` if the
-    version cannot be determined).
-
-    Raises
-    ------
-    ExecutableNotFoundError
-        If the executable is not found or older than the oldest version
-        supported by Matplotlib.
-    ValueError
-        If the executable is not one that we know how to query.
-    """
-
-    def impl(args, regex, min_ver=None, ignore_exit_code=False):
-        # Execute the subprocess specified by args; capture stdout and stderr.
-        # Search for a regex match in the output; if the match succeeds, the
-        # first group of the match is the version.
-        # Return an _ExecInfo if the executable exists, and has a version of
-        # at least min_ver (if set); else, raise ExecutableNotFoundError.
-        try:
-            output = subprocess.check_output(
-                args, stderr=subprocess.STDOUT,
-                universal_newlines=True, errors="replace")
-        except subprocess.CalledProcessError as _cpe:
-            if ignore_exit_code:
-                output = _cpe.output
-            else:
-                raise ExecutableNotFoundError(str(_cpe)) from _cpe
-        except OSError as _ose:
-            raise ExecutableNotFoundError(str(_ose)) from _ose
-        match = re.search(regex, output)
-        if match:
-            version = LooseVersion(match.group(1))
-            if min_ver is not None and version < min_ver:
-                raise ExecutableNotFoundError(
-                    f"You have {args[0]} version {version} but the minimum "
-                    f"version supported by Matplotlib is {min_ver}")
-            return _ExecInfo(args[0], version)
-        else:
-            raise ExecutableNotFoundError(
-                f"Failed to determine the version of {args[0]} from "
-                f"{' '.join(args)}, which output {output}")
-
-    if name == "dvipng":
-        return impl(["dvipng", "-version"], "(?m)^dvipng(?: .*)? (.+)", "1.6")
-    elif name == "gs":
-        execs = (["gswin32c", "gswin64c", "mgs", "gs"]  # "mgs" for miktex.
-                 if sys.platform == "win32" else
-                 ["gs"])
-        for e in execs:
-            try:
-                return impl([e, "--version"], "(.*)", "9")
-            except ExecutableNotFoundError:
-                pass
-        message = "Failed to find a Ghostscript installation"
-        raise ExecutableNotFoundError(message)
-    elif name == "inkscape":
-        info = impl(["inkscape", "-V"], "^Inkscape ([^ ]*)")
-        if info and info.version >= "1.0":
-            raise ExecutableNotFoundError(
-                f"You have Inkscape version {info.version} but Matplotlib "
-                f"only supports Inkscape<1.0")
-        return info
-    elif name == "magick":
-        path = None
-        if sys.platform == "win32":
-            # Check the registry to avoid confusing ImageMagick's convert with
-            # Windows's builtin convert.exe.
-            import winreg
-            binpath = ""
-            for flag in [0, winreg.KEY_WOW64_32KEY, winreg.KEY_WOW64_64KEY]:
-                try:
-                    with winreg.OpenKeyEx(
-                            winreg.HKEY_LOCAL_MACHINE,
-                            r"Software\Imagemagick\Current",
-                            0, winreg.KEY_QUERY_VALUE | flag) as hkey:
-                        binpath = winreg.QueryValueEx(hkey, "BinPath")[0]
-                except OSError:
-                    pass
-            if binpath:
-                for name in ["convert.exe", "magick.exe"]:
-                    candidate = Path(binpath, name)
-                    if candidate.exists():
-                        path = str(candidate)
-                        break
-        else:
-            path = "convert"
-        if path is None:
-            raise ExecutableNotFoundError(
-                "Failed to find an ImageMagick installation")
-        return impl([path, "--version"], r"^Version: ImageMagick (\S*)")
-    elif name == "pdftops":
-        info = impl(["pdftops", "-v"], "^pdftops version (.*)",
-                    ignore_exit_code=True)
-        if info and not ("3.0" <= info.version
-                         # poppler version numbers.
-                         or "0.9" <= info.version <= "1.0"):
-            raise ExecutableNotFoundError(
-                f"You have pdftops version {info.version} but the minimum "
-                f"version supported by Matplotlib is 3.0")
-        return info
-    else:
-        raise ValueError("Unknown executable: {!r}".format(name))
-
-
-@cbook.deprecated("3.1")
-def checkdep_dvipng():
-    try:
-        s = subprocess.Popen(['dvipng', '-version'],
-                             stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-        stdout, stderr = s.communicate()
-        line = stdout.decode('ascii').split('\n')[1]
-        v = line.split()[-1]
-        return v
-    except (IndexError, ValueError, OSError):
-        return None
-
-
-@cbook.deprecated("3.1")
-def checkdep_ghostscript():
-    if checkdep_ghostscript.executable is None:
-        if sys.platform == 'win32':
-            # mgs is the name in miktex
-            gs_execs = ['gswin32c', 'gswin64c', 'mgs', 'gs']
-        else:
-            gs_execs = ['gs']
-        for gs_exec in gs_execs:
-            try:
-                s = subprocess.Popen(
-                    [gs_exec, '--version'], stdout=subprocess.PIPE,
-                    stderr=subprocess.PIPE)
-                stdout, stderr = s.communicate()
-                if s.returncode == 0:
-                    v = stdout[:-1].decode('ascii')
-                    if compare_versions(v, '9.0'):
-                        checkdep_ghostscript.executable = gs_exec
-                        checkdep_ghostscript.version = v
-            except (IndexError, ValueError, OSError):
-                pass
-    return checkdep_ghostscript.executable, checkdep_ghostscript.version
-checkdep_ghostscript.executable = None
-checkdep_ghostscript.version = None
-
-
-@cbook.deprecated("3.1")
-def checkdep_pdftops():
-    try:
-        s = subprocess.Popen(['pdftops', '-v'], stdout=subprocess.PIPE,
-                             stderr=subprocess.PIPE)
-        stdout, stderr = s.communicate()
-        lines = stderr.decode('ascii').split('\n')
-        for line in lines:
-            if 'version' in line:
-                v = line.split()[-1]
-        return v
-    except (IndexError, ValueError, UnboundLocalError, OSError):
-        return None
-
-
-@cbook.deprecated("3.1")
-def checkdep_inkscape():
-    if checkdep_inkscape.version is None:
-        try:
-            s = subprocess.Popen(['inkscape', '-V'],
-                                 stdout=subprocess.PIPE,
-                                 stderr=subprocess.PIPE)
-            stdout, stderr = s.communicate()
-            lines = stdout.decode('ascii').split('\n')
-            for line in lines:
-                if 'Inkscape' in line:
-                    v = line.split()[1]
-                    break
-            checkdep_inkscape.version = v
-        except (IndexError, ValueError, UnboundLocalError, OSError):
-            pass
-    return checkdep_inkscape.version
-checkdep_inkscape.version = None
-
-
-@cbook.deprecated("3.2")
-def checkdep_ps_distiller(s):
-    if not s:
-        return False
-    try:
-        _get_executable_info("gs")
-    except ExecutableNotFoundError:
-        _log.warning(
-            "Setting rcParams['ps.usedistiller'] requires ghostscript.")
-        return False
-    if s == "xpdf":
-        try:
-            _get_executable_info("pdftops")
-        except ExecutableNotFoundError:
-            _log.warning(
-                "Setting rcParams['ps.usedistiller'] to 'xpdf' requires xpdf.")
-            return False
-    return s
-
-
-def checkdep_usetex(s):
-    if not s:
-        return False
-    if not shutil.which("tex"):
-        _log.warning("usetex mode requires TeX.")
-        return False
-    try:
-        _get_executable_info("dvipng")
-    except ExecutableNotFoundError:
-        _log.warning("usetex mode requires dvipng.")
-        return False
-    try:
-        _get_executable_info("gs")
-    except ExecutableNotFoundError:
-        _log.warning("usetex mode requires ghostscript.")
-        return False
-    return True
-
-
-@cbook.deprecated("3.2", alternative="os.path.expanduser('~')")
-@_logged_cached('$HOME=%s')
-def get_home():
-    """
-    Return the user's home directory.
-
-    If the user's home directory cannot be found, return None.
-    """
-    try:
-        return str(Path.home())
-    except Exception:
-        return None
-
-
-def _create_tmp_config_or_cache_dir():
-    """
-    If the config or cache directory cannot be created, create a temporary one.
-    """
-    configdir = os.environ['MPLCONFIGDIR'] = (
-        tempfile.mkdtemp(prefix='matplotlib-'))
-    atexit.register(shutil.rmtree, configdir)
-    return configdir
-
-
-def _get_xdg_config_dir():
-    """
-    Return the XDG configuration directory, according to the `XDG
-    base directory spec
-    <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
-    """
-    return os.environ.get('XDG_CONFIG_HOME') or str(Path.home() / ".config")
-
-
-def _get_xdg_cache_dir():
-    """
-    Return the XDG cache directory, according to the `XDG
-    base directory spec
-    <http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html>`_.
-    """
-    return os.environ.get('XDG_CACHE_HOME') or str(Path.home() / ".cache")
-
-
-def _get_config_or_cache_dir(xdg_base):
-    configdir = os.environ.get('MPLCONFIGDIR')
-    if configdir:
-        configdir = Path(configdir).resolve()
-    elif sys.platform.startswith(('linux', 'freebsd')) and xdg_base:
-        configdir = Path(xdg_base, "matplotlib")
-    else:
-        configdir = Path.home() / ".matplotlib"
-    try:
-        configdir.mkdir(parents=True, exist_ok=True)
-    except OSError:
-        pass
-    else:
-        if os.access(str(configdir), os.W_OK) and configdir.is_dir():
-            return str(configdir)
-    return _create_tmp_config_or_cache_dir()
-
-
-@_logged_cached('CONFIGDIR=%s')
-def get_configdir():
-    """
-    Return the string representing the configuration directory.
-
-    The directory is chosen as follows:
-
-    1. If the MPLCONFIGDIR environment variable is supplied, choose that.
-    2a. On Linux, follow the XDG specification and look first in
-        `$XDG_CONFIG_HOME`, if defined, or `$HOME/.config`.
-    2b. On other platforms, choose `$HOME/.matplotlib`.
-    3. If the chosen directory exists and is writable, use that as the
-       configuration directory.
-    4. If possible, create a temporary directory, and use it as the
-       configuration directory.
-    5. A writable directory could not be found or created; return None.
-    """
-    return _get_config_or_cache_dir(_get_xdg_config_dir())
-
-
-@_logged_cached('CACHEDIR=%s')
-def get_cachedir():
-    """
-    Return the location of the cache directory.
-
-    The procedure used to find the directory is the same as for
-    _get_config_dir, except using `$XDG_CACHE_HOME`/`~/.cache` instead.
-    """
-    return _get_config_or_cache_dir(_get_xdg_cache_dir())
-
-
-@_logged_cached('matplotlib data path: %s')
-def get_data_path(*, _from_rc=None):
-    """Return the path to Matplotlib data."""
-    if _from_rc is not None:
-        cbook.warn_deprecated(
-            "3.2",
-            message=("Setting the datapath via matplotlibrc is "
-            "deprecated %(since)s and will be removed in %(removal)s. "
-            ""),
-            removal='3.3')
-        path = Path(_from_rc)
-        if path.is_dir():
-            defaultParams['datapath'][0] = str(path)
-            return str(path)
-        else:
-            warnings.warn(f"You passed datapath: {_from_rc!r} in your "
-                          f"matplotribrc file ({matplotlib_fname()}). "
-                          "However this path does not exist, falling back "
-                          "to standard paths.")
-
-    return _get_data_path()
-
-
-@_logged_cached('(private) matplotlib data path: %s')
-def _get_data_path():
-    if 'MATPLOTLIBDATA' in os.environ:
-        path = os.environ['MATPLOTLIBDATA']
-        if not os.path.isdir(path):
-            raise RuntimeError('Path in environment MATPLOTLIBDATA not a '
-                               'directory')
-        cbook.warn_deprecated(
-            "3.1", name="MATPLOTLIBDATA", obj_type="environment variable")
-        return path
-
-    path = Path(__file__).with_name("mpl-data")
-    if path.is_dir():
-        defaultParams['datapath'][0] = str(path)
-        return str(path)
-
-    cbook.warn_deprecated(
-        "3.2", message="Matplotlib installs where the data is not in the "
-        "mpl-data subdirectory of the package are deprecated since %(since)s "
-        "and support for them will be removed %(removal)s.")
-
-    def get_candidate_paths():
-        # setuptools' namespace_packages may hijack this init file
-        # so need to try something known to be in Matplotlib, not basemap.
-        import matplotlib.afm
-        yield Path(matplotlib.afm.__file__).with_name('mpl-data')
-        # py2exe zips pure python, so still need special check.
-        if getattr(sys, 'frozen', None):
-            yield Path(sys.executable).with_name('mpl-data')
-            # Try again assuming we need to step up one more directory.
-            yield Path(sys.executable).parent.with_name('mpl-data')
-            # Try again assuming sys.path[0] is a dir not a exe.
-            yield Path(sys.path[0]) / 'mpl-data'
-
-    for path in get_candidate_paths():
-        if path.is_dir():
-            defaultParams['datapath'][0] = str(path)
-            return str(path)
-
-    raise RuntimeError('Could not find the matplotlib data files')
-
-
-@cbook.deprecated("3.1")
-def get_py2exe_datafiles():
-    data_path = Path(get_data_path())
-    d = {}
-    for path in filter(Path.is_file, data_path.glob("**/*")):
-        (d.setdefault(str(path.parent.relative_to(data_path.parent)), [])
-         .append(str(path)))
-    return list(d.items())
-
-
-def matplotlib_fname():
-    """
-    Get the location of the config file.
-
-    The file location is determined in the following order
-
-    - ``$PWD/matplotlibrc``
-    - ``$MATPLOTLIBRC`` if it is not a directory
-    - ``$MATPLOTLIBRC/matplotlibrc``
-    - ``$MPLCONFIGDIR/matplotlibrc``
-    - On Linux,
-        - ``$XDG_CONFIG_HOME/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME``
-          is defined)
-        - or ``$HOME/.config/matplotlib/matplotlibrc`` (if ``$XDG_CONFIG_HOME``
-          is not defined)
-    - On other platforms,
-      - ``$HOME/.matplotlib/matplotlibrc`` if ``$HOME`` is defined
-    - Lastly, it looks in ``$MATPLOTLIBDATA/matplotlibrc``, which should always
-      exist.
-    """
-
-    def gen_candidates():
-        yield os.path.join(os.getcwd(), 'matplotlibrc')
-        try:
-            matplotlibrc = os.environ['MATPLOTLIBRC']
-        except KeyError:
-            pass
-        else:
-            yield matplotlibrc
-            yield os.path.join(matplotlibrc, 'matplotlibrc')
-        yield os.path.join(get_configdir(), 'matplotlibrc')
-        yield os.path.join(_get_data_path(), 'matplotlibrc')
-
-    for fname in gen_candidates():
-        if os.path.exists(fname) and not os.path.isdir(fname):
-            return fname
-
-    raise RuntimeError("Could not find matplotlibrc file; your Matplotlib "
-                       "install is broken")
-
-
-# rcParams deprecated and automatically mapped to another key.
-# Values are tuples of (version, new_name, f_old2new, f_new2old).
-_deprecated_map = {}
-
-# rcParams deprecated; some can manually be mapped to another key.
-# Values are tuples of (version, new_name_or_None).
-_deprecated_ignore_map = {
-    'pgf.debug': ('3.0', None),
-}
-
-# rcParams deprecated; can use None to suppress warnings; remain actually
-# listed in the rcParams (not included in _all_deprecated).
-# Values are tuples of (version,)
-_deprecated_remain_as_none = {
-    'text.latex.unicode': ('3.0',),
-    'savefig.frameon': ('3.1',),
-    'verbose.fileo': ('3.1',),
-    'verbose.level': ('3.1',),
-    'datapath': ('3.2.1',),
-}
-
-
-_all_deprecated = {*_deprecated_map, *_deprecated_ignore_map}
-
-
-class RcParams(MutableMapping, dict):
-    """
-    A dictionary object including validation.
-
-    Validating functions are defined and associated with rc parameters in
-    :mod:`matplotlib.rcsetup`.
-
-    See Also
-    --------
-    :ref:`customizing-with-matplotlibrc-files`
-    """
-
-    validate = {key: converter
-                for key, (default, converter) in defaultParams.items()
-                if key not in _all_deprecated}
-
-    # validate values on the way in
-    def __init__(self, *args, **kwargs):
-        self.update(*args, **kwargs)
-
-    def __setitem__(self, key, val):
-        try:
-            if key in _deprecated_map:
-                version, alt_key, alt_val, inverse_alt = _deprecated_map[key]
-                cbook.warn_deprecated(
-                    version, name=key, obj_type="rcparam", alternative=alt_key)
-                key = alt_key
-                val = alt_val(val)
-            elif key in _deprecated_remain_as_none and val is not None:
-                version, = _deprecated_remain_as_none[key]
-                cbook.warn_deprecated(
-                    version, name=key, obj_type="rcparam")
-            elif key in _deprecated_ignore_map:
-                version, alt_key = _deprecated_ignore_map[key]
-                cbook.warn_deprecated(
-                    version, name=key, obj_type="rcparam", alternative=alt_key)
-                return
-            elif key == 'backend':
-                if val is rcsetup._auto_backend_sentinel:
-                    if 'backend' in self:
-                        return
-            try:
-                cval = self.validate[key](val)
-            except ValueError as ve:
-                raise ValueError("Key %s: %s" % (key, str(ve)))
-            dict.__setitem__(self, key, cval)
-        except KeyError:
-            raise KeyError(
-                f"{key} is not a valid rc parameter (see rcParams.keys() for "
-                f"a list of valid parameters)")
-
-    def __getitem__(self, key):
-        if key in _deprecated_map:
-            version, alt_key, alt_val, inverse_alt = _deprecated_map[key]
-            cbook.warn_deprecated(
-                version, name=key, obj_type="rcparam", alternative=alt_key)
-            return inverse_alt(dict.__getitem__(self, alt_key))
-
-        elif key in _deprecated_ignore_map:
-            version, alt_key = _deprecated_ignore_map[key]
-            cbook.warn_deprecated(
-                version, name=key, obj_type="rcparam", alternative=alt_key)
-            return dict.__getitem__(self, alt_key) if alt_key else None
-
-        elif key == "backend":
-            val = dict.__getitem__(self, key)
-            if val is rcsetup._auto_backend_sentinel:
-                from matplotlib import pyplot as plt
-                plt.switch_backend(rcsetup._auto_backend_sentinel)
-
-        return dict.__getitem__(self, key)
-
-    def __repr__(self):
-        class_name = self.__class__.__name__
-        indent = len(class_name) + 1
-        with cbook._suppress_matplotlib_deprecation_warning():
-            repr_split = pprint.pformat(dict(self), indent=1,
-                                        width=80 - indent).split('\n')
-        repr_indented = ('\n' + ' ' * indent).join(repr_split)
-        return '{}({})'.format(class_name, repr_indented)
-
-    def __str__(self):
-        return '\n'.join(map('{0[0]}: {0[1]}'.format, sorted(self.items())))
-
-    def __iter__(self):
-        """Yield sorted list of keys."""
-        with cbook._suppress_matplotlib_deprecation_warning():
-            yield from sorted(dict.__iter__(self))
-
-    def __len__(self):
-        return dict.__len__(self)
-
-    def find_all(self, pattern):
-        """
-        Return the subset of this RcParams dictionary whose keys match,
-        using :func:`re.search`, the given ``pattern``.
-
-        .. note::
-
-            Changes to the returned dictionary are *not* propagated to
-            the parent RcParams dictionary.
-
-        """
-        pattern_re = re.compile(pattern)
-        return RcParams((key, value)
-                        for key, value in self.items()
-                        if pattern_re.search(key))
-
-    def copy(self):
-        return {k: dict.__getitem__(self, k) for k in self}
-
-
-def rc_params(fail_on_error=False):
-    """Construct a `RcParams` instance from the default Matplotlib rc file."""
-    return rc_params_from_file(matplotlib_fname(), fail_on_error)
-
-
-URL_REGEX = re.compile(r'^http://|^https://|^ftp://|^file:')
-
-
-def is_url(filename):
-    """Return True if string is an http, ftp, or file URL path."""
-    return URL_REGEX.match(filename) is not None
-
-
-@contextlib.contextmanager
-def _open_file_or_url(fname):
-    if not isinstance(fname, Path) and is_url(fname):
-        import urllib.request
-        with urllib.request.urlopen(fname) as f:
-            yield (line.decode('utf-8') for line in f)
-    else:
-        fname = os.path.expanduser(fname)
-        encoding = locale.getpreferredencoding(do_setlocale=False)
-        if encoding is None:
-            encoding = "utf-8"
-        with open(fname, encoding=encoding) as f:
-            yield f
-
-
-def _rc_params_in_file(fname, fail_on_error=False):
-    """
-    Construct a `RcParams` instance from file *fname*.
-
-    Unlike `rc_params_from_file`, the configuration class only contains the
-    parameters specified in the file (i.e. default values are not filled in).
-    """
-    _error_details_fmt = 'line #%d\n\t"%s"\n\tin file "%s"'
-
-    rc_temp = {}
-    with _open_file_or_url(fname) as fd:
-        try:
-            for line_no, line in enumerate(fd, 1):
-                strippedline = line.split('#', 1)[0].strip()
-                if not strippedline:
-                    continue
-                tup = strippedline.split(':', 1)
-                if len(tup) != 2:
-                    error_details = _error_details_fmt % (line_no, line, fname)
-                    _log.warning('Illegal %s', error_details)
-                    continue
-                key, val = tup
-                key = key.strip()
-                val = val.strip()
-                if key in rc_temp:
-                    _log.warning('Duplicate key in file %r line #%d.',
-                                 fname, line_no)
-                rc_temp[key] = (val, line, line_no)
-        except UnicodeDecodeError:
-            _log.warning('Cannot decode configuration file %s with encoding '
-                         '%s, check LANG and LC_* variables.',
-                         fname,
-                         locale.getpreferredencoding(do_setlocale=False)
-                         or 'utf-8 (default)')
-            raise
-
-    config = RcParams()
-
-    for key, (val, line, line_no) in rc_temp.items():
-        if key in defaultParams:
-            if fail_on_error:
-                config[key] = val  # try to convert to proper type or raise
-            else:
-                try:
-                    config[key] = val  # try to convert to proper type or skip
-                except Exception as msg:
-                    error_details = _error_details_fmt % (line_no, line, fname)
-                    _log.warning('Bad val %r on %s\n\t%s',
-                                 val, error_details, msg)
-        elif key in _deprecated_ignore_map:
-            version, alt_key = _deprecated_ignore_map[key]
-            cbook.warn_deprecated(
-                version, name=key, alternative=alt_key,
-                addendum="Please update your matplotlibrc.")
-        else:
-            version = 'master' if '.post' in __version__ else f'v{__version__}'
-            print(f"""
-Bad key "{key}" on line {line_no} in
-{fname}.
-You probably need to get an updated matplotlibrc file from
-https://github.com/matplotlib/matplotlib/blob/{version}/matplotlibrc.template
-or from the matplotlib source distribution""", file=sys.stderr)
-    return config
-
-
-def rc_params_from_file(fname, fail_on_error=False, use_default_template=True):
-    """
-    Construct a `RcParams` from file *fname*.
-
-    Parameters
-    ----------
-    fname : str or path-like
-        Name of file parsed for Matplotlib settings.
-    fail_on_error : bool
-        If True, raise an error when the parser fails to convert a parameter.
-    use_default_template : bool
-        If True, initialize with default parameters before updating with those
-        in the given file. If False, the configuration class only contains the
-        parameters specified in the file. (Useful for updating dicts.)
-    """
-    config_from_file = _rc_params_in_file(fname, fail_on_error)
-
-    if not use_default_template:
-        return config_from_file
-
-    iter_params = defaultParams.items()
-    with cbook._suppress_matplotlib_deprecation_warning():
-        config = RcParams([(key, default) for key, (default, _) in iter_params
-                           if key not in _all_deprecated])
-    config.update(config_from_file)
-
-    with cbook._suppress_matplotlib_deprecation_warning():
-        if config['datapath'] is None:
-            config['datapath'] = _get_data_path()
-        else:
-            config['datapath'] = get_data_path(_from_rc=config['datapath'])
-
-    if "".join(config['text.latex.preamble']):
-        _log.info("""
-*****************************************************************
-You have the following UNSUPPORTED LaTeX preamble customizations:
-%s
-Please do not ask for support with these customizations active.
-*****************************************************************
-""", '\n'.join(config['text.latex.preamble']))
-    _log.debug('loaded rc file %s', fname)
-
-    return config
-
-
-# this is the instance used by the matplotlib classes
-rcParams = rc_params()
-
-
-with cbook._suppress_matplotlib_deprecation_warning():
-    rcParamsOrig = RcParams(rcParams.copy())
-    rcParamsDefault = RcParams([(key, default) for key, (default, converter) in
-                                defaultParams.items()
-                                if key not in _all_deprecated])
-
-if rcParams['axes.formatter.use_locale']:
-    locale.setlocale(locale.LC_ALL, '')
-
-
-def rc(group, **kwargs):
-    """
-    Set the current rc params.  *group* is the grouping for the rc, e.g.,
-    for ``lines.linewidth`` the group is ``lines``, for
-    ``axes.facecolor``, the group is ``axes``, and so on.  Group may
-    also be a list or tuple of group names, e.g., (*xtick*, *ytick*).
-    *kwargs* is a dictionary attribute name/value pairs, e.g.,::
-
-      rc('lines', linewidth=2, color='r')
-
-    sets the current rc params and is equivalent to::
-
-      rcParams['lines.linewidth'] = 2
-      rcParams['lines.color'] = 'r'
-
-    The following aliases are available to save typing for interactive users:
-
-    =====   =================
-    Alias   Property
-    =====   =================
-    'lw'    'linewidth'
-    'ls'    'linestyle'
-    'c'     'color'
-    'fc'    'facecolor'
-    'ec'    'edgecolor'
-    'mew'   'markeredgewidth'
-    'aa'    'antialiased'
-    =====   =================
-
-    Thus you could abbreviate the above rc command as::
-
-          rc('lines', lw=2, c='r')
-
-    Note you can use python's kwargs dictionary facility to store
-    dictionaries of default parameters.  e.g., you can customize the
-    font rc as follows::
-
-      font = {'family' : 'monospace',
-              'weight' : 'bold',
-              'size'   : 'larger'}
-      rc('font', **font)  # pass in the font dict as kwargs
-
-    This enables you to easily switch between several configurations.  Use
-    ``matplotlib.style.use('default')`` or :func:`~matplotlib.rcdefaults` to
-    restore the default rc params after changes.
-
-    Notes
-    -----
-    Similar functionality is available by using the normal dict interface, i.e.
-    ``rcParams.update({"lines.linewidth": 2, ...})`` (but ``rcParams.update``
-    does not support abbreviations or grouping).
-    """
-
-    aliases = {
-        'lw':  'linewidth',
-        'ls':  'linestyle',
-        'c':   'color',
-        'fc':  'facecolor',
-        'ec':  'edgecolor',
-        'mew': 'markeredgewidth',
-        'aa':  'antialiased',
-        }
-
-    if isinstance(group, str):
-        group = (group,)
-    for g in group:
-        for k, v in kwargs.items():
-            name = aliases.get(k) or k
-            key = '%s.%s' % (g, name)
-            try:
-                rcParams[key] = v
-            except KeyError:
-                raise KeyError(('Unrecognized key "%s" for group "%s" and '
-                                'name "%s"') % (key, g, name))
-
-
-def rcdefaults():
-    """
-    Restore the rc params from Matplotlib's internal default style.
-
-    Style-blacklisted rc params (defined in
-    `matplotlib.style.core.STYLE_BLACKLIST`) are not updated.
-
-    See Also
-    --------
-    rc_file_defaults
-        Restore the rc params from the rc file originally loaded by Matplotlib.
-    matplotlib.style.use :
-        Use a specific style file.  Call ``style.use('default')`` to restore
-        the default style.
-    """
-    # Deprecation warnings were already handled when creating rcParamsDefault,
-    # no need to reemit them here.
-    with cbook._suppress_matplotlib_deprecation_warning():
-        from .style.core import STYLE_BLACKLIST
-        rcParams.clear()
-        rcParams.update({k: v for k, v in rcParamsDefault.items()
-                         if k not in STYLE_BLACKLIST})
-
-
-def rc_file_defaults():
-    """
-    Restore the rc params from the original rc file loaded by Matplotlib.
-
-    Style-blacklisted rc params (defined in
-    `matplotlib.style.core.STYLE_BLACKLIST`) are not updated.
-    """
-    # Deprecation warnings were already handled when creating rcParamsOrig, no
-    # need to reemit them here.
-    with cbook._suppress_matplotlib_deprecation_warning():
-        from .style.core import STYLE_BLACKLIST
-        rcParams.update({k: rcParamsOrig[k] for k in rcParamsOrig
-                         if k not in STYLE_BLACKLIST})
-
-
-def rc_file(fname, *, use_default_template=True):
-    """
-    Update rc params from file.
-
-    Style-blacklisted rc params (defined in
-    `matplotlib.style.core.STYLE_BLACKLIST`) are not updated.
-
-    Parameters
-    ----------
-    fname : str
-        Name of file parsed for matplotlib settings.
-
-    use_default_template : bool
-        If True, initialize with default parameters before updating with those
-        in the given file. If False, the current configuration persists
-        and only the parameters specified in the file are updated.
-    """
-    # Deprecation warnings were already handled in rc_params_from_file, no need
-    # to reemit them here.
-    with cbook._suppress_matplotlib_deprecation_warning():
-        from .style.core import STYLE_BLACKLIST
-        rc_from_file = rc_params_from_file(
-            fname, use_default_template=use_default_template)
-        rcParams.update({k: rc_from_file[k] for k in rc_from_file
-                         if k not in STYLE_BLACKLIST})
-
-
-class rc_context:
-    """
-    Return a context manager for managing rc settings.
-
-    This allows one to do::
-
-        with mpl.rc_context(fname='screen.rc'):
-            plt.plot(x, a)  # uses 'screen.rc'
-            with mpl.rc_context(fname='print.rc'):
-                plt.plot(x, b)  # uses 'print.rc'
-            plt.plot(x, c)  # uses 'screen.rc'
-
-    A dictionary can also be passed to the context manager::
-
-        with mpl.rc_context(rc={'text.usetex': True}, fname='screen.rc'):
-            plt.plot(x, a)
-
-    The 'rc' dictionary takes precedence over the settings loaded from
-    'fname'.  Passing a dictionary only is also valid. For example a
-    common usage is::
-
-        with mpl.rc_context(rc={'interactive': False}):
-            fig, ax = plt.subplots()
-            ax.plot(range(3), range(3))
-            fig.savefig('A.png', format='png')
-            plt.close(fig)
-    """
-    # While it may seem natural to implement rc_context using
-    # contextlib.contextmanager, that would entail always calling the finally:
-    # clause of the contextmanager (which restores the original rcs) including
-    # during garbage collection; as a result, something like `plt.xkcd();
-    # gc.collect()` would result in the style being lost (as `xkcd()` is
-    # implemented on top of rc_context, and nothing is holding onto context
-    # manager except possibly circular references.
-
-    def __init__(self, rc=None, fname=None):
-        self._orig = rcParams.copy()
-        try:
-            if fname:
-                rc_file(fname)
-            if rc:
-                rcParams.update(rc)
-        except Exception:
-            self.__fallback()
-            raise
-
-    def __fallback(self):
-        # If anything goes wrong, revert to the original rcs.
-        updated_backend = self._orig['backend']
-        dict.update(rcParams, self._orig)
-        # except for the backend.  If the context block triggered resolving
-        # the auto backend resolution keep that value around
-        if self._orig['backend'] is rcsetup._auto_backend_sentinel:
-            rcParams['backend'] = updated_backend
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, exc_type, exc_value, exc_tb):
-        self.__fallback()
-
-
-@cbook._rename_parameter("3.1", "arg", "backend")
-@cbook._delete_parameter("3.1", "warn")
-def use(backend, warn=False, force=True):
-    """
-    Select the backend used for rendering and GUI integration.
-
-    Parameters
-    ----------
-    backend : str
-        The backend to switch to.  This can either be one of the standard
-        backend names, which are case-insensitive:
-
-        - interactive backends:
-          GTK3Agg, GTK3Cairo, MacOSX, nbAgg,
-          Qt4Agg, Qt4Cairo, Qt5Agg, Qt5Cairo,
-          TkAgg, TkCairo, WebAgg, WX, WXAgg, WXCairo
-
-        - non-interactive backends:
-          agg, cairo, pdf, pgf, ps, svg, template
-
-        or a string of the form: ``module://my.module.name``.
-
-    warn : bool, optional, default: False
-        If True and not *force*, emit a warning if a failure-to-switch
-        `ImportError` has been suppressed.  This parameter is deprecated.
-
-    force : bool, optional, default: True
-        If True (the default), raise an `ImportError` if the backend cannot be
-        set up (either because it fails to import, or because an incompatible
-        GUI interactive framework is already running); if False, ignore the
-        failure.
-
-    See Also
-    --------
-    :ref:`backends`
-    matplotlib.get_backend
-    """
-    name = validate_backend(backend)
-    if dict.__getitem__(rcParams, 'backend') == name:
-        # Nothing to do if the requested backend is already set
-        pass
-    else:
-        # Update both rcParams and rcDefaults so restoring the defaults later
-        # with rcdefaults won't change the backend.  This is a bit of overkill
-        # as 'backend' is already in style.core.STYLE_BLACKLIST, but better to
-        # be safe.
-        rcParams['backend'] = rcParamsDefault['backend'] = name
-        try:
-            from matplotlib import pyplot as plt
-            plt.switch_backend(name)
-        except ImportError as exc:
-            if force:
-                raise
-            if warn:
-                cbook._warn_external(
-                    f"Failed to switch backend to {backend}: {exc}")
-
-
-if os.environ.get('MPLBACKEND'):
-    rcParams['backend'] = os.environ.get('MPLBACKEND')
-
-
-def get_backend():
-    """
-    Return the name of the current backend.
-
-    See Also
-    --------
-    matplotlib.use
-    """
-    return rcParams['backend']
-
-
-def interactive(b):
-    """
-    Set whether to redraw after every plotting command (e.g. `.pyplot.xlabel`).
-    """
-    rcParams['interactive'] = b
-
-
-def is_interactive():
-    """Return whether to redraw after every plotting command."""
-    return rcParams['interactive']
-
-
-@cbook.deprecated("3.1", alternative="rcParams['tk.window_focus']")
-def tk_window_focus():
-    """
-    Return true if focus maintenance under TkAgg on win32 is on.
-
-    This currently works only for python.exe and IPython.exe.
-    Both IDLE and Pythonwin.exe fail badly when tk_window_focus is on.
-    """
-    if rcParams['backend'] != 'TkAgg':
-        return False
-    return rcParams['tk.window_focus']
-
-
-default_test_modules = [
-    'matplotlib.tests',
-    'mpl_toolkits.tests',
-]
-
-
-def _init_tests():
-    # The version of FreeType to install locally for running the
-    # tests.  This must match the value in `setupext.py`
-    LOCAL_FREETYPE_VERSION = '2.6.1'
-
-    from matplotlib import ft2font
-    if (ft2font.__freetype_version__ != LOCAL_FREETYPE_VERSION or
-        ft2font.__freetype_build_type__ != 'local'):
-        _log.warning(
-            "Matplotlib is not built with the correct FreeType version to run "
-            "tests.  Set local_freetype=True in setup.cfg and rebuild. "
-            "Expect many image comparison failures below. "
-            "Expected freetype version {0}. "
-            "Found freetype version {1}. "
-            "Freetype build type is {2}local".format(
-                LOCAL_FREETYPE_VERSION,
-                ft2font.__freetype_version__,
-                "" if ft2font.__freetype_build_type__ == 'local' else "not "))
-
-    try:
-        import pytest
-    except ImportError:
-        print("matplotlib.test requires pytest to run.")
-        raise
-
-
-@cbook._delete_parameter("3.2", "switch_backend_warn")
-def test(verbosity=None, coverage=False, switch_backend_warn=True,
-         recursionlimit=0, **kwargs):
-    """Run the matplotlib test suite."""
-    _init_tests()
-    if not os.path.isdir(os.path.join(os.path.dirname(__file__), 'tests')):
-        raise ImportError("Matplotlib test data is not installed")
-
-    old_backend = get_backend()
-    old_recursionlimit = sys.getrecursionlimit()
-    try:
-        use('agg')
-        if recursionlimit:
-            sys.setrecursionlimit(recursionlimit)
-        import pytest
-
-        args = kwargs.pop('argv', [])
-        provide_default_modules = True
-        use_pyargs = True
-        for arg in args:
-            if any(arg.startswith(module_path)
-                   for module_path in default_test_modules):
-                provide_default_modules = False
-                break
-            if os.path.exists(arg):
-                provide_default_modules = False
-                use_pyargs = False
-                break
-        if use_pyargs:
-            args += ['--pyargs']
-        if provide_default_modules:
-            args += default_test_modules
-
-        if coverage:
-            args += ['--cov']
-
-        if verbosity:
-            args += ['-' + 'v' * verbosity]
-
-        retcode = pytest.main(args, **kwargs)
-    finally:
-        if old_backend.lower() != 'agg':
-            use(old_backend)
-        if recursionlimit:
-            sys.setrecursionlimit(old_recursionlimit)
-
-    return retcode
-
-
-test.__test__ = False  # pytest: this function is not a test
-
-
-def _replacer(data, value):
-    """
-    Either returns ``data[value]`` or passes ``data`` back, converts either to
-    a sequence.
-    """
-    try:
-        # if key isn't a string don't bother
-        if isinstance(value, str):
-            # try to use __getitem__
-            value = data[value]
-    except Exception:
-        # key does not exist, silently fall back to key
-        pass
-    return sanitize_sequence(value)
-
-
-def _label_from_arg(y, default_name):
-    try:
-        return y.name
-    except AttributeError:
-        if isinstance(default_name, str):
-            return default_name
-    return None
-
-
-_DATA_DOC_TITLE = """
-
-Notes
------
-"""
-
-_DATA_DOC_APPENDIX = """
-
-.. note::
-    In addition to the above described arguments, this function can take a
-    **data** keyword argument. If such a **data** argument is given, the
-    following arguments are replaced by **data[<arg>]**:
-
-    {replaced}
-
-    Objects passed as **data** must support item access (``data[<arg>]``) and
-    membership test (``<arg> in data``).
-"""
-
-
-def _add_data_doc(docstring, replace_names):
-    """Add documentation for a *data* field to the given docstring.
-
-    Parameters
-    ----------
-    docstring : str
-        The input docstring.
-    replace_names : list of str or None
-        The list of parameter names which arguments should be replaced by
-        ``data[name]`` (if ``data[name]`` does not throw an exception).  If
-        None, replacement is attempted for all arguments.
-
-    Returns
-    -------
-        The augmented docstring.
-    """
-    docstring = inspect.cleandoc(docstring) if docstring is not None else ""
-    repl = ("* All positional and all keyword arguments."
-            if replace_names is None else
-            ""
-            if len(replace_names) == 0 else
-            "* All arguments with the following names: {}.".format(
-                ", ".join(map(repr, sorted(replace_names)))))
-    addendum = _DATA_DOC_APPENDIX.format(replaced=repl)
-    if _DATA_DOC_TITLE not in docstring:
-        addendum = _DATA_DOC_TITLE + addendum
-    return docstring + addendum
-
-
-def _preprocess_data(func=None, *, replace_names=None, label_namer=None):
-    """
-    A decorator to add a 'data' kwarg to a function.
-
-    When applied::
-
-        @_preprocess_data()
-        def func(ax, *args, **kwargs): ...
-
-    the signature is modified to ``decorated(ax, *args, data=None, **kwargs)``
-    with the following behavior:
-
-    - if called with ``data=None``, forward the other arguments to ``func``;
-    - otherwise, *data* must be a mapping; for any argument passed in as a
-      string ``name``, replace the argument by ``data[name]`` (if this does not
-      throw an exception), then forward the arguments to ``func``.
-
-    In either case, any argument that is a `MappingView` is also converted to a
-    list.
-
-    Parameters
-    ----------
-    replace_names : list of str or None, optional, default: None
-        The list of parameter names for which lookup into *data* should be
-        attempted. If None, replacement is attempted for all arguments.
-    label_namer : str, optional, default: None
-        If set e.g. to "namer" (which must be a kwarg in the function's
-        signature -- not as ``**kwargs``), if the *namer* argument passed in is
-        a (string) key of *data* and no *label* kwarg is passed, then use the
-        (string) value of the *namer* as *label*. ::
-
-            @_preprocess_data(label_namer="foo")
-            def func(foo, label=None): ...
-
-            func("key", data={"key": value})
-            # is equivalent to
-            func.__wrapped__(value, label="key")
-    """
-
-    if func is None:  # Return the actual decorator.
-        return functools.partial(
-            _preprocess_data,
-            replace_names=replace_names, label_namer=label_namer)
-
-    sig = inspect.signature(func)
-    varargs_name = None
-    varkwargs_name = None
-    arg_names = []
-    params = list(sig.parameters.values())
-    for p in params:
-        if p.kind is Parameter.VAR_POSITIONAL:
-            varargs_name = p.name
-        elif p.kind is Parameter.VAR_KEYWORD:
-            varkwargs_name = p.name
-        else:
-            arg_names.append(p.name)
-    data_param = Parameter("data", Parameter.KEYWORD_ONLY, default=None)
-    if varkwargs_name:
-        params.insert(-1, data_param)
-    else:
-        params.append(data_param)
-    new_sig = sig.replace(parameters=params)
-    arg_names = arg_names[1:]  # remove the first "ax" / self arg
-
-    if replace_names is not None:
-        replace_names = set(replace_names)
-
-    assert (replace_names or set()) <= set(arg_names) or varkwargs_name, (
-        "Matplotlib internal error: invalid replace_names ({!r}) for {!r}"
-        .format(replace_names, func.__name__))
-    assert label_namer is None or label_namer in arg_names, (
-        "Matplotlib internal error: invalid label_namer ({!r}) for {!r}"
-            .format(label_namer, func.__name__))
-
-    @functools.wraps(func)
-    def inner(ax, *args, data=None, **kwargs):
-        if data is None:
-            return func(ax, *map(sanitize_sequence, args), **kwargs)
-
-        bound = new_sig.bind(ax, *args, **kwargs)
-        auto_label = (bound.arguments.get(label_namer)
-                      or bound.kwargs.get(label_namer))
-
-        for k, v in bound.arguments.items():
-            if k == varkwargs_name:
-                for k1, v1 in v.items():
-                    if replace_names is None or k1 in replace_names:
-                        v[k1] = _replacer(data, v1)
-            elif k == varargs_name:
-                if replace_names is None:
-                    bound.arguments[k] = tuple(_replacer(data, v1) for v1 in v)
-            else:
-                if replace_names is None or k in replace_names:
-                    bound.arguments[k] = _replacer(data, v)
-
-        new_args = bound.args
-        new_kwargs = bound.kwargs
-
-        args_and_kwargs = {**bound.arguments, **bound.kwargs}
-        if label_namer and "label" not in args_and_kwargs:
-            new_kwargs["label"] = _label_from_arg(
-                args_and_kwargs.get(label_namer), auto_label)
-
-        return func(*new_args, **new_kwargs)
-
-    inner.__doc__ = _add_data_doc(inner.__doc__, replace_names)
-    inner.__signature__ = new_sig
-    return inner
-
-
-_log.debug('matplotlib version %s', __version__)
-_log.debug('interactive is %s', is_interactive())
-_log.debug('platform is %s', sys.platform)
-_log.debug('loaded modules: %s', list(sys.modules))

+ 0 - 260
venv/lib/python3.8/site-packages/matplotlib/_animation_data.py

@@ -1,260 +0,0 @@
-# Javascript template for HTMLWriter
-JS_INCLUDE = """
-<link rel="stylesheet"
-href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/
-css/font-awesome.min.css">
-<script language="javascript">
-  function isInternetExplorer() {
-    ua = navigator.userAgent;
-    /* MSIE used to detect old browsers and Trident used to newer ones*/
-    return ua.indexOf("MSIE ") > -1 || ua.indexOf("Trident/") > -1;
-  }
-
-  /* Define the Animation class */
-  function Animation(frames, img_id, slider_id, interval, loop_select_id){
-    this.img_id = img_id;
-    this.slider_id = slider_id;
-    this.loop_select_id = loop_select_id;
-    this.interval = interval;
-    this.current_frame = 0;
-    this.direction = 0;
-    this.timer = null;
-    this.frames = new Array(frames.length);
-
-    for (var i=0; i<frames.length; i++)
-    {
-     this.frames[i] = new Image();
-     this.frames[i].src = frames[i];
-    }
-    var slider = document.getElementById(this.slider_id);
-    slider.max = this.frames.length - 1;
-    if (isInternetExplorer()) {
-        // switch from oninput to onchange because IE <= 11 does not conform
-        // with W3C specification. It ignores oninput and onchange behaves
-        // like oninput. In contrast, Mircosoft Edge behaves correctly.
-        slider.setAttribute('onchange', slider.getAttribute('oninput'));
-        slider.setAttribute('oninput', null);
-    }
-    this.set_frame(this.current_frame);
-  }
-
-  Animation.prototype.get_loop_state = function(){
-    var button_group = document[this.loop_select_id].state;
-    for (var i = 0; i < button_group.length; i++) {
-        var button = button_group[i];
-        if (button.checked) {
-            return button.value;
-        }
-    }
-    return undefined;
-  }
-
-  Animation.prototype.set_frame = function(frame){
-    this.current_frame = frame;
-    document.getElementById(this.img_id).src =
-            this.frames[this.current_frame].src;
-    document.getElementById(this.slider_id).value = this.current_frame;
-  }
-
-  Animation.prototype.next_frame = function()
-  {
-    this.set_frame(Math.min(this.frames.length - 1, this.current_frame + 1));
-  }
-
-  Animation.prototype.previous_frame = function()
-  {
-    this.set_frame(Math.max(0, this.current_frame - 1));
-  }
-
-  Animation.prototype.first_frame = function()
-  {
-    this.set_frame(0);
-  }
-
-  Animation.prototype.last_frame = function()
-  {
-    this.set_frame(this.frames.length - 1);
-  }
-
-  Animation.prototype.slower = function()
-  {
-    this.interval /= 0.7;
-    if(this.direction > 0){this.play_animation();}
-    else if(this.direction < 0){this.reverse_animation();}
-  }
-
-  Animation.prototype.faster = function()
-  {
-    this.interval *= 0.7;
-    if(this.direction > 0){this.play_animation();}
-    else if(this.direction < 0){this.reverse_animation();}
-  }
-
-  Animation.prototype.anim_step_forward = function()
-  {
-    this.current_frame += 1;
-    if(this.current_frame < this.frames.length){
-      this.set_frame(this.current_frame);
-    }else{
-      var loop_state = this.get_loop_state();
-      if(loop_state == "loop"){
-        this.first_frame();
-      }else if(loop_state == "reflect"){
-        this.last_frame();
-        this.reverse_animation();
-      }else{
-        this.pause_animation();
-        this.last_frame();
-      }
-    }
-  }
-
-  Animation.prototype.anim_step_reverse = function()
-  {
-    this.current_frame -= 1;
-    if(this.current_frame >= 0){
-      this.set_frame(this.current_frame);
-    }else{
-      var loop_state = this.get_loop_state();
-      if(loop_state == "loop"){
-        this.last_frame();
-      }else if(loop_state == "reflect"){
-        this.first_frame();
-        this.play_animation();
-      }else{
-        this.pause_animation();
-        this.first_frame();
-      }
-    }
-  }
-
-  Animation.prototype.pause_animation = function()
-  {
-    this.direction = 0;
-    if (this.timer){
-      clearInterval(this.timer);
-      this.timer = null;
-    }
-  }
-
-  Animation.prototype.play_animation = function()
-  {
-    this.pause_animation();
-    this.direction = 1;
-    var t = this;
-    if (!this.timer) this.timer = setInterval(function() {
-        t.anim_step_forward();
-    }, this.interval);
-  }
-
-  Animation.prototype.reverse_animation = function()
-  {
-    this.pause_animation();
-    this.direction = -1;
-    var t = this;
-    if (!this.timer) this.timer = setInterval(function() {
-        t.anim_step_reverse();
-    }, this.interval);
-  }
-</script>
-"""
-
-
-# Style definitions for the HTML template
-STYLE_INCLUDE = """
-<style>
-.animation {
-    display: inline-block;
-    text-align: center;
-}
-input[type=range].anim-slider {
-    width: 374px;
-    margin-left: auto;
-    margin-right: auto;
-}
-.anim-buttons {
-    margin: 8px 0px;
-}
-.anim-buttons button {
-    padding: 0;
-    width: 36px;
-}
-.anim-state label {
-    margin-right: 8px;
-}
-.anim-state input {
-    margin: 0;
-    vertical-align: middle;
-}
-</style>
-"""
-
-
-# HTML template for HTMLWriter
-DISPLAY_TEMPLATE = """
-<div class="animation">
-  <img id="_anim_img{id}">
-  <div class="anim-controls">
-    <input id="_anim_slider{id}" type="range" class="anim-slider"
-           name="points" min="0" max="1" step="1" value="0"
-           oninput="anim{id}.set_frame(parseInt(this.value));"></input>
-    <div class="anim-buttons">
-      <button onclick="anim{id}.slower()"><i class="fa fa-minus"></i></button>
-      <button onclick="anim{id}.first_frame()"><i class="fa fa-fast-backward">
-          </i></button>
-      <button onclick="anim{id}.previous_frame()">
-          <i class="fa fa-step-backward"></i></button>
-      <button onclick="anim{id}.reverse_animation()">
-          <i class="fa fa-play fa-flip-horizontal"></i></button>
-      <button onclick="anim{id}.pause_animation()"><i class="fa fa-pause">
-          </i></button>
-      <button onclick="anim{id}.play_animation()"><i class="fa fa-play"></i>
-          </button>
-      <button onclick="anim{id}.next_frame()"><i class="fa fa-step-forward">
-          </i></button>
-      <button onclick="anim{id}.last_frame()"><i class="fa fa-fast-forward">
-          </i></button>
-      <button onclick="anim{id}.faster()"><i class="fa fa-plus"></i></button>
-    </div>
-    <form action="#n" name="_anim_loop_select{id}" class="anim-state">
-      <input type="radio" name="state" value="once" id="_anim_radio1_{id}"
-             {once_checked}>
-      <label for="_anim_radio1_{id}">Once</label>
-      <input type="radio" name="state" value="loop" id="_anim_radio2_{id}"
-             {loop_checked}>
-      <label for="_anim_radio2_{id}">Loop</label>
-      <input type="radio" name="state" value="reflect" id="_anim_radio3_{id}"
-             {reflect_checked}>
-      <label for="_anim_radio3_{id}">Reflect</label>
-    </form>
-  </div>
-</div>
-
-
-<script language="javascript">
-  /* Instantiate the Animation class. */
-  /* The IDs given should match those used in the template above. */
-  (function() {{
-    var img_id = "_anim_img{id}";
-    var slider_id = "_anim_slider{id}";
-    var loop_select_id = "_anim_loop_select{id}";
-    var frames = new Array({Nframes});
-    {fill_frames}
-
-    /* set a timeout to make sure all the above elements are created before
-       the object is initialized. */
-    setTimeout(function() {{
-        anim{id} = new Animation(frames, img_id, slider_id, {interval},
-                                 loop_select_id);
-    }}, 0);
-  }})()
-</script>
-"""
-
-
-INCLUDED_FRAMES = """
-  for (var i=0; i<{Nframes}; i++){{
-    frames[i] = "{frame_dir}/frame" + ("0000000" + i).slice(-7) +
-                ".{frame_format}";
-  }}
-"""

+ 0 - 1426
venv/lib/python3.8/site-packages/matplotlib/_cm.py

@@ -1,1426 +0,0 @@
-"""
-Nothing here but dictionaries for generating LinearSegmentedColormaps,
-and a dictionary of these dictionaries.
-
-Documentation for each is in pyplot.colormaps().  Please update this
-with the purpose and type of your colormap if you add data for one here.
-"""
-
-from functools import partial
-
-import numpy as np
-
-_binary_data = {
-    'red':    ((0., 1., 1.), (1., 0., 0.)),
-    'green':  ((0., 1., 1.), (1., 0., 0.)),
-    'blue':   ((0., 1., 1.), (1., 0., 0.))
-    }
-
-_autumn_data = {'red':   ((0., 1.0, 1.0), (1.0, 1.0, 1.0)),
-                'green': ((0., 0., 0.), (1.0, 1.0, 1.0)),
-                'blue':  ((0., 0., 0.), (1.0, 0., 0.))}
-
-_bone_data = {'red':   ((0., 0., 0.),
-                        (0.746032, 0.652778, 0.652778),
-                        (1.0, 1.0, 1.0)),
-              'green': ((0., 0., 0.),
-                        (0.365079, 0.319444, 0.319444),
-                        (0.746032, 0.777778, 0.777778),
-                        (1.0, 1.0, 1.0)),
-              'blue':  ((0., 0., 0.),
-                        (0.365079, 0.444444, 0.444444),
-                        (1.0, 1.0, 1.0))}
-
-_cool_data = {'red':   ((0., 0., 0.), (1.0, 1.0, 1.0)),
-              'green': ((0., 1., 1.), (1.0, 0.,  0.)),
-              'blue':  ((0., 1., 1.), (1.0, 1.,  1.))}
-
-_copper_data = {'red':   ((0., 0., 0.),
-                          (0.809524, 1.000000, 1.000000),
-                          (1.0, 1.0, 1.0)),
-                'green': ((0., 0., 0.),
-                          (1.0, 0.7812, 0.7812)),
-                'blue':  ((0., 0., 0.),
-                          (1.0, 0.4975, 0.4975))}
-
-def _flag_red(x): return 0.75 * np.sin((x * 31.5 + 0.25) * np.pi) + 0.5
-def _flag_green(x): return np.sin(x * 31.5 * np.pi)
-def _flag_blue(x): return 0.75 * np.sin((x * 31.5 - 0.25) * np.pi) + 0.5
-_flag_data = {'red': _flag_red, 'green': _flag_green, 'blue': _flag_blue}
-
-def _prism_red(x): return 0.75 * np.sin((x * 20.9 + 0.25) * np.pi) + 0.67
-def _prism_green(x): return 0.75 * np.sin((x * 20.9 - 0.25) * np.pi) + 0.33
-def _prism_blue(x): return -1.1 * np.sin((x * 20.9) * np.pi)
-_prism_data = {'red': _prism_red, 'green': _prism_green, 'blue': _prism_blue}
-
-def _ch_helper(gamma, s, r, h, p0, p1, x):
-    """Helper function for generating picklable cubehelix color maps."""
-    # Apply gamma factor to emphasise low or high intensity values
-    xg = x ** gamma
-    # Calculate amplitude and angle of deviation from the black to white
-    # diagonal in the plane of constant perceived intensity.
-    a = h * xg * (1 - xg) / 2
-    phi = 2 * np.pi * (s / 3 + r * x)
-    return xg + a * (p0 * np.cos(phi) + p1 * np.sin(phi))
-
-def cubehelix(gamma=1.0, s=0.5, r=-1.5, h=1.0):
-    """
-    Return custom data dictionary of (r, g, b) conversion functions, which can
-    be used with :func:`register_cmap`, for the cubehelix color scheme.
-
-    Unlike most other color schemes cubehelix was designed by D.A. Green to
-    be monotonically increasing in terms of perceived brightness.
-    Also, when printed on a black and white postscript printer, the scheme
-    results in a greyscale with monotonically increasing brightness.
-    This color scheme is named cubehelix because the (r, g, b) values produced
-    can be visualised as a squashed helix around the diagonal in the
-    (r, g, b) color cube.
-
-    For a unit color cube (i.e. 3-D coordinates for (r, g, b) each in the
-    range 0 to 1) the color scheme starts at (r, g, b) = (0, 0, 0), i.e. black,
-    and finishes at (r, g, b) = (1, 1, 1), i.e. white. For some fraction *x*,
-    between 0 and 1, the color is the corresponding grey value at that
-    fraction along the black to white diagonal (x, x, x) plus a color
-    element. This color element is calculated in a plane of constant
-    perceived intensity and controlled by the following parameters.
-
-    Optional keyword arguments:
-
-      =========   =======================================================
-      Keyword     Description
-      =========   =======================================================
-      gamma       gamma factor to emphasise either low intensity values
-                  (gamma < 1), or high intensity values (gamma > 1);
-                  defaults to 1.0.
-      s           the start color; defaults to 0.5 (i.e. purple).
-      r           the number of r, g, b rotations in color that are made
-                  from the start to the end of the color scheme; defaults
-                  to -1.5 (i.e. -> B -> G -> R -> B).
-      h           the hue parameter which controls how saturated the
-                  colors are. If this parameter is zero then the color
-                  scheme is purely a greyscale; defaults to 1.0.
-      =========   =======================================================
-    """
-    return {'red': partial(_ch_helper, gamma, s, r, h, -0.14861, 1.78277),
-            'green': partial(_ch_helper, gamma, s, r, h, -0.29227, -0.90649),
-            'blue': partial(_ch_helper, gamma, s, r, h, 1.97294, 0.0)}
-
-_cubehelix_data = cubehelix()
-
-_bwr_data = ((0.0, 0.0, 1.0), (1.0, 1.0, 1.0), (1.0, 0.0, 0.0))
-_brg_data = ((0.0, 0.0, 1.0), (1.0, 0.0, 0.0), (0.0, 1.0, 0.0))
-
-# Gnuplot palette functions
-def _g0(x): return 0
-def _g1(x): return 0.5
-def _g2(x): return 1
-def _g3(x): return x
-def _g4(x): return x ** 2
-def _g5(x): return x ** 3
-def _g6(x): return x ** 4
-def _g7(x): return np.sqrt(x)
-def _g8(x): return np.sqrt(np.sqrt(x))
-def _g9(x): return np.sin(x * np.pi / 2)
-def _g10(x): return np.cos(x * np.pi / 2)
-def _g11(x): return np.abs(x - 0.5)
-def _g12(x): return (2 * x - 1) ** 2
-def _g13(x): return np.sin(x * np.pi)
-def _g14(x): return np.abs(np.cos(x * np.pi))
-def _g15(x): return np.sin(x * 2 * np.pi)
-def _g16(x): return np.cos(x * 2 * np.pi)
-def _g17(x): return np.abs(np.sin(x * 2 * np.pi))
-def _g18(x): return np.abs(np.cos(x * 2 * np.pi))
-def _g19(x): return np.abs(np.sin(x * 4 * np.pi))
-def _g20(x): return np.abs(np.cos(x * 4 * np.pi))
-def _g21(x): return 3 * x
-def _g22(x): return 3 * x - 1
-def _g23(x): return 3 * x - 2
-def _g24(x): return np.abs(3 * x - 1)
-def _g25(x): return np.abs(3 * x - 2)
-def _g26(x): return (3 * x - 1) / 2
-def _g27(x): return (3 * x - 2) / 2
-def _g28(x): return np.abs((3 * x - 1) / 2)
-def _g29(x): return np.abs((3 * x - 2) / 2)
-def _g30(x): return x / 0.32 - 0.78125
-def _g31(x): return 2 * x - 0.84
-def _g32(x):
-    ret = np.zeros(len(x))
-    m = (x < 0.25)
-    ret[m] = 4 * x[m]
-    m = (x >= 0.25) & (x < 0.92)
-    ret[m] = -2 * x[m] + 1.84
-    m = (x >= 0.92)
-    ret[m] = x[m] / 0.08 - 11.5
-    return ret
-def _g33(x): return np.abs(2 * x - 0.5)
-def _g34(x): return 2 * x
-def _g35(x): return 2 * x - 0.5
-def _g36(x): return 2 * x - 1
-
-gfunc = {i: globals()["_g{}".format(i)] for i in range(37)}
-
-_gnuplot_data = {
-        'red': gfunc[7],
-        'green': gfunc[5],
-        'blue': gfunc[15],
-}
-
-_gnuplot2_data = {
-        'red': gfunc[30],
-        'green': gfunc[31],
-        'blue': gfunc[32],
-}
-
-_ocean_data = {
-        'red': gfunc[23],
-        'green': gfunc[28],
-        'blue': gfunc[3],
-}
-
-_afmhot_data = {
-        'red': gfunc[34],
-        'green': gfunc[35],
-        'blue': gfunc[36],
-}
-
-_rainbow_data = {
-        'red': gfunc[33],
-        'green': gfunc[13],
-        'blue': gfunc[10],
-}
-
-_seismic_data = (
-        (0.0, 0.0, 0.3), (0.0, 0.0, 1.0),
-        (1.0, 1.0, 1.0), (1.0, 0.0, 0.0),
-        (0.5, 0.0, 0.0))
-
-_terrain_data = (
-        (0.00, (0.2, 0.2, 0.6)),
-        (0.15, (0.0, 0.6, 1.0)),
-        (0.25, (0.0, 0.8, 0.4)),
-        (0.50, (1.0, 1.0, 0.6)),
-        (0.75, (0.5, 0.36, 0.33)),
-        (1.00, (1.0, 1.0, 1.0)))
-
-_gray_data = {'red':   ((0., 0, 0), (1., 1, 1)),
-              'green': ((0., 0, 0), (1., 1, 1)),
-              'blue':  ((0., 0, 0), (1., 1, 1))}
-
-_hot_data = {'red':   ((0., 0.0416, 0.0416),
-                       (0.365079, 1.000000, 1.000000),
-                       (1.0, 1.0, 1.0)),
-             'green': ((0., 0., 0.),
-                       (0.365079, 0.000000, 0.000000),
-                       (0.746032, 1.000000, 1.000000),
-                       (1.0, 1.0, 1.0)),
-             'blue':  ((0., 0., 0.),
-                       (0.746032, 0.000000, 0.000000),
-                       (1.0, 1.0, 1.0))}
-
-_hsv_data = {'red':   ((0., 1., 1.),
-                       (0.158730, 1.000000, 1.000000),
-                       (0.174603, 0.968750, 0.968750),
-                       (0.333333, 0.031250, 0.031250),
-                       (0.349206, 0.000000, 0.000000),
-                       (0.666667, 0.000000, 0.000000),
-                       (0.682540, 0.031250, 0.031250),
-                       (0.841270, 0.968750, 0.968750),
-                       (0.857143, 1.000000, 1.000000),
-                       (1.0, 1.0, 1.0)),
-             'green': ((0., 0., 0.),
-                       (0.158730, 0.937500, 0.937500),
-                       (0.174603, 1.000000, 1.000000),
-                       (0.507937, 1.000000, 1.000000),
-                       (0.666667, 0.062500, 0.062500),
-                       (0.682540, 0.000000, 0.000000),
-                       (1.0, 0., 0.)),
-             'blue':  ((0., 0., 0.),
-                       (0.333333, 0.000000, 0.000000),
-                       (0.349206, 0.062500, 0.062500),
-                       (0.507937, 1.000000, 1.000000),
-                       (0.841270, 1.000000, 1.000000),
-                       (0.857143, 0.937500, 0.937500),
-                       (1.0, 0.09375, 0.09375))}
-
-_jet_data = {'red':   ((0., 0, 0), (0.35, 0, 0), (0.66, 1, 1), (0.89, 1, 1),
-                         (1, 0.5, 0.5)),
-             'green': ((0., 0, 0), (0.125, 0, 0), (0.375, 1, 1), (0.64, 1, 1),
-                         (0.91, 0, 0), (1, 0, 0)),
-             'blue':  ((0., 0.5, 0.5), (0.11, 1, 1), (0.34, 1, 1),
-                         (0.65, 0, 0), (1, 0, 0))}
-
-_pink_data = {'red':   ((0., 0.1178, 0.1178), (0.015873, 0.195857, 0.195857),
-                        (0.031746, 0.250661, 0.250661),
-                        (0.047619, 0.295468, 0.295468),
-                        (0.063492, 0.334324, 0.334324),
-                        (0.079365, 0.369112, 0.369112),
-                        (0.095238, 0.400892, 0.400892),
-                        (0.111111, 0.430331, 0.430331),
-                        (0.126984, 0.457882, 0.457882),
-                        (0.142857, 0.483867, 0.483867),
-                        (0.158730, 0.508525, 0.508525),
-                        (0.174603, 0.532042, 0.532042),
-                        (0.190476, 0.554563, 0.554563),
-                        (0.206349, 0.576204, 0.576204),
-                        (0.222222, 0.597061, 0.597061),
-                        (0.238095, 0.617213, 0.617213),
-                        (0.253968, 0.636729, 0.636729),
-                        (0.269841, 0.655663, 0.655663),
-                        (0.285714, 0.674066, 0.674066),
-                        (0.301587, 0.691980, 0.691980),
-                        (0.317460, 0.709441, 0.709441),
-                        (0.333333, 0.726483, 0.726483),
-                        (0.349206, 0.743134, 0.743134),
-                        (0.365079, 0.759421, 0.759421),
-                        (0.380952, 0.766356, 0.766356),
-                        (0.396825, 0.773229, 0.773229),
-                        (0.412698, 0.780042, 0.780042),
-                        (0.428571, 0.786796, 0.786796),
-                        (0.444444, 0.793492, 0.793492),
-                        (0.460317, 0.800132, 0.800132),
-                        (0.476190, 0.806718, 0.806718),
-                        (0.492063, 0.813250, 0.813250),
-                        (0.507937, 0.819730, 0.819730),
-                        (0.523810, 0.826160, 0.826160),
-                        (0.539683, 0.832539, 0.832539),
-                        (0.555556, 0.838870, 0.838870),
-                        (0.571429, 0.845154, 0.845154),
-                        (0.587302, 0.851392, 0.851392),
-                        (0.603175, 0.857584, 0.857584),
-                        (0.619048, 0.863731, 0.863731),
-                        (0.634921, 0.869835, 0.869835),
-                        (0.650794, 0.875897, 0.875897),
-                        (0.666667, 0.881917, 0.881917),
-                        (0.682540, 0.887896, 0.887896),
-                        (0.698413, 0.893835, 0.893835),
-                        (0.714286, 0.899735, 0.899735),
-                        (0.730159, 0.905597, 0.905597),
-                        (0.746032, 0.911421, 0.911421),
-                        (0.761905, 0.917208, 0.917208),
-                        (0.777778, 0.922958, 0.922958),
-                        (0.793651, 0.928673, 0.928673),
-                        (0.809524, 0.934353, 0.934353),
-                        (0.825397, 0.939999, 0.939999),
-                        (0.841270, 0.945611, 0.945611),
-                        (0.857143, 0.951190, 0.951190),
-                        (0.873016, 0.956736, 0.956736),
-                        (0.888889, 0.962250, 0.962250),
-                        (0.904762, 0.967733, 0.967733),
-                        (0.920635, 0.973185, 0.973185),
-                        (0.936508, 0.978607, 0.978607),
-                        (0.952381, 0.983999, 0.983999),
-                        (0.968254, 0.989361, 0.989361),
-                        (0.984127, 0.994695, 0.994695), (1.0, 1.0, 1.0)),
-              'green': ((0., 0., 0.), (0.015873, 0.102869, 0.102869),
-                        (0.031746, 0.145479, 0.145479),
-                        (0.047619, 0.178174, 0.178174),
-                        (0.063492, 0.205738, 0.205738),
-                        (0.079365, 0.230022, 0.230022),
-                        (0.095238, 0.251976, 0.251976),
-                        (0.111111, 0.272166, 0.272166),
-                        (0.126984, 0.290957, 0.290957),
-                        (0.142857, 0.308607, 0.308607),
-                        (0.158730, 0.325300, 0.325300),
-                        (0.174603, 0.341178, 0.341178),
-                        (0.190476, 0.356348, 0.356348),
-                        (0.206349, 0.370899, 0.370899),
-                        (0.222222, 0.384900, 0.384900),
-                        (0.238095, 0.398410, 0.398410),
-                        (0.253968, 0.411476, 0.411476),
-                        (0.269841, 0.424139, 0.424139),
-                        (0.285714, 0.436436, 0.436436),
-                        (0.301587, 0.448395, 0.448395),
-                        (0.317460, 0.460044, 0.460044),
-                        (0.333333, 0.471405, 0.471405),
-                        (0.349206, 0.482498, 0.482498),
-                        (0.365079, 0.493342, 0.493342),
-                        (0.380952, 0.517549, 0.517549),
-                        (0.396825, 0.540674, 0.540674),
-                        (0.412698, 0.562849, 0.562849),
-                        (0.428571, 0.584183, 0.584183),
-                        (0.444444, 0.604765, 0.604765),
-                        (0.460317, 0.624669, 0.624669),
-                        (0.476190, 0.643958, 0.643958),
-                        (0.492063, 0.662687, 0.662687),
-                        (0.507937, 0.680900, 0.680900),
-                        (0.523810, 0.698638, 0.698638),
-                        (0.539683, 0.715937, 0.715937),
-                        (0.555556, 0.732828, 0.732828),
-                        (0.571429, 0.749338, 0.749338),
-                        (0.587302, 0.765493, 0.765493),
-                        (0.603175, 0.781313, 0.781313),
-                        (0.619048, 0.796819, 0.796819),
-                        (0.634921, 0.812029, 0.812029),
-                        (0.650794, 0.826960, 0.826960),
-                        (0.666667, 0.841625, 0.841625),
-                        (0.682540, 0.856040, 0.856040),
-                        (0.698413, 0.870216, 0.870216),
-                        (0.714286, 0.884164, 0.884164),
-                        (0.730159, 0.897896, 0.897896),
-                        (0.746032, 0.911421, 0.911421),
-                        (0.761905, 0.917208, 0.917208),
-                        (0.777778, 0.922958, 0.922958),
-                        (0.793651, 0.928673, 0.928673),
-                        (0.809524, 0.934353, 0.934353),
-                        (0.825397, 0.939999, 0.939999),
-                        (0.841270, 0.945611, 0.945611),
-                        (0.857143, 0.951190, 0.951190),
-                        (0.873016, 0.956736, 0.956736),
-                        (0.888889, 0.962250, 0.962250),
-                        (0.904762, 0.967733, 0.967733),
-                        (0.920635, 0.973185, 0.973185),
-                        (0.936508, 0.978607, 0.978607),
-                        (0.952381, 0.983999, 0.983999),
-                        (0.968254, 0.989361, 0.989361),
-                        (0.984127, 0.994695, 0.994695), (1.0, 1.0, 1.0)),
-              'blue':  ((0., 0., 0.), (0.015873, 0.102869, 0.102869),
-                        (0.031746, 0.145479, 0.145479),
-                        (0.047619, 0.178174, 0.178174),
-                        (0.063492, 0.205738, 0.205738),
-                        (0.079365, 0.230022, 0.230022),
-                        (0.095238, 0.251976, 0.251976),
-                        (0.111111, 0.272166, 0.272166),
-                        (0.126984, 0.290957, 0.290957),
-                        (0.142857, 0.308607, 0.308607),
-                        (0.158730, 0.325300, 0.325300),
-                        (0.174603, 0.341178, 0.341178),
-                        (0.190476, 0.356348, 0.356348),
-                        (0.206349, 0.370899, 0.370899),
-                        (0.222222, 0.384900, 0.384900),
-                        (0.238095, 0.398410, 0.398410),
-                        (0.253968, 0.411476, 0.411476),
-                        (0.269841, 0.424139, 0.424139),
-                        (0.285714, 0.436436, 0.436436),
-                        (0.301587, 0.448395, 0.448395),
-                        (0.317460, 0.460044, 0.460044),
-                        (0.333333, 0.471405, 0.471405),
-                        (0.349206, 0.482498, 0.482498),
-                        (0.365079, 0.493342, 0.493342),
-                        (0.380952, 0.503953, 0.503953),
-                        (0.396825, 0.514344, 0.514344),
-                        (0.412698, 0.524531, 0.524531),
-                        (0.428571, 0.534522, 0.534522),
-                        (0.444444, 0.544331, 0.544331),
-                        (0.460317, 0.553966, 0.553966),
-                        (0.476190, 0.563436, 0.563436),
-                        (0.492063, 0.572750, 0.572750),
-                        (0.507937, 0.581914, 0.581914),
-                        (0.523810, 0.590937, 0.590937),
-                        (0.539683, 0.599824, 0.599824),
-                        (0.555556, 0.608581, 0.608581),
-                        (0.571429, 0.617213, 0.617213),
-                        (0.587302, 0.625727, 0.625727),
-                        (0.603175, 0.634126, 0.634126),
-                        (0.619048, 0.642416, 0.642416),
-                        (0.634921, 0.650600, 0.650600),
-                        (0.650794, 0.658682, 0.658682),
-                        (0.666667, 0.666667, 0.666667),
-                        (0.682540, 0.674556, 0.674556),
-                        (0.698413, 0.682355, 0.682355),
-                        (0.714286, 0.690066, 0.690066),
-                        (0.730159, 0.697691, 0.697691),
-                        (0.746032, 0.705234, 0.705234),
-                        (0.761905, 0.727166, 0.727166),
-                        (0.777778, 0.748455, 0.748455),
-                        (0.793651, 0.769156, 0.769156),
-                        (0.809524, 0.789314, 0.789314),
-                        (0.825397, 0.808969, 0.808969),
-                        (0.841270, 0.828159, 0.828159),
-                        (0.857143, 0.846913, 0.846913),
-                        (0.873016, 0.865261, 0.865261),
-                        (0.888889, 0.883229, 0.883229),
-                        (0.904762, 0.900837, 0.900837),
-                        (0.920635, 0.918109, 0.918109),
-                        (0.936508, 0.935061, 0.935061),
-                        (0.952381, 0.951711, 0.951711),
-                        (0.968254, 0.968075, 0.968075),
-                        (0.984127, 0.984167, 0.984167), (1.0, 1.0, 1.0))}
-
-_spring_data = {'red':   ((0., 1., 1.), (1.0, 1.0, 1.0)),
-                'green': ((0., 0., 0.), (1.0, 1.0, 1.0)),
-                'blue':  ((0., 1., 1.), (1.0, 0.0, 0.0))}
-
-
-_summer_data = {'red':   ((0., 0., 0.), (1.0, 1.0, 1.0)),
-                'green': ((0., 0.5, 0.5), (1.0, 1.0, 1.0)),
-                'blue':  ((0., 0.4, 0.4), (1.0, 0.4, 0.4))}
-
-
-_winter_data = {'red':   ((0., 0., 0.), (1.0, 0.0, 0.0)),
-                'green': ((0., 0., 0.), (1.0, 1.0, 1.0)),
-                'blue':  ((0., 1., 1.), (1.0, 0.5, 0.5))}
-
-_nipy_spectral_data = {
-      'red': [(0.0, 0.0, 0.0), (0.05, 0.4667, 0.4667),
-              (0.10, 0.5333, 0.5333), (0.15, 0.0, 0.0),
-              (0.20, 0.0, 0.0), (0.25, 0.0, 0.0),
-              (0.30, 0.0, 0.0), (0.35, 0.0, 0.0),
-              (0.40, 0.0, 0.0), (0.45, 0.0, 0.0),
-              (0.50, 0.0, 0.0), (0.55, 0.0, 0.0),
-              (0.60, 0.0, 0.0), (0.65, 0.7333, 0.7333),
-              (0.70, 0.9333, 0.9333), (0.75, 1.0, 1.0),
-              (0.80, 1.0, 1.0), (0.85, 1.0, 1.0),
-              (0.90, 0.8667, 0.8667), (0.95, 0.80, 0.80),
-              (1.0, 0.80, 0.80)],
-    'green': [(0.0, 0.0, 0.0), (0.05, 0.0, 0.0),
-              (0.10, 0.0, 0.0), (0.15, 0.0, 0.0),
-              (0.20, 0.0, 0.0), (0.25, 0.4667, 0.4667),
-              (0.30, 0.6000, 0.6000), (0.35, 0.6667, 0.6667),
-              (0.40, 0.6667, 0.6667), (0.45, 0.6000, 0.6000),
-              (0.50, 0.7333, 0.7333), (0.55, 0.8667, 0.8667),
-              (0.60, 1.0, 1.0), (0.65, 1.0, 1.0),
-              (0.70, 0.9333, 0.9333), (0.75, 0.8000, 0.8000),
-              (0.80, 0.6000, 0.6000), (0.85, 0.0, 0.0),
-              (0.90, 0.0, 0.0), (0.95, 0.0, 0.0),
-              (1.0, 0.80, 0.80)],
-     'blue': [(0.0, 0.0, 0.0), (0.05, 0.5333, 0.5333),
-              (0.10, 0.6000, 0.6000), (0.15, 0.6667, 0.6667),
-              (0.20, 0.8667, 0.8667), (0.25, 0.8667, 0.8667),
-              (0.30, 0.8667, 0.8667), (0.35, 0.6667, 0.6667),
-              (0.40, 0.5333, 0.5333), (0.45, 0.0, 0.0),
-              (0.5, 0.0, 0.0), (0.55, 0.0, 0.0),
-              (0.60, 0.0, 0.0), (0.65, 0.0, 0.0),
-              (0.70, 0.0, 0.0), (0.75, 0.0, 0.0),
-              (0.80, 0.0, 0.0), (0.85, 0.0, 0.0),
-              (0.90, 0.0, 0.0), (0.95, 0.0, 0.0),
-              (1.0, 0.80, 0.80)],
-}
-
-
-# 34 colormaps based on color specifications and designs
-# developed by Cynthia Brewer (http://colorbrewer.org).
-# The ColorBrewer palettes have been included under the terms
-# of an Apache-stype license (for details, see the file
-# LICENSE_COLORBREWER in the license directory of the matplotlib
-# source distribution).
-
-# RGB values taken from Brewer's Excel sheet, divided by 255
-
-_Blues_data = (
-    (0.96862745098039216,  0.98431372549019602,  1.0                ),
-    (0.87058823529411766,  0.92156862745098034,  0.96862745098039216),
-    (0.77647058823529413,  0.85882352941176465,  0.93725490196078431),
-    (0.61960784313725492,  0.792156862745098  ,  0.88235294117647056),
-    (0.41960784313725491,  0.68235294117647061,  0.83921568627450982),
-    (0.25882352941176473,  0.5725490196078431 ,  0.77647058823529413),
-    (0.12941176470588237,  0.44313725490196076,  0.70980392156862748),
-    (0.03137254901960784,  0.31764705882352939,  0.61176470588235299),
-    (0.03137254901960784,  0.18823529411764706,  0.41960784313725491)
-    )
-
-_BrBG_data = (
-    (0.32941176470588235,  0.18823529411764706,  0.0196078431372549 ),
-    (0.5490196078431373 ,  0.31764705882352939,  0.0392156862745098 ),
-    (0.74901960784313726,  0.50588235294117645,  0.17647058823529413),
-    (0.87450980392156863,  0.76078431372549016,  0.49019607843137253),
-    (0.96470588235294119,  0.90980392156862744,  0.76470588235294112),
-    (0.96078431372549022,  0.96078431372549022,  0.96078431372549022),
-    (0.7803921568627451 ,  0.91764705882352937,  0.89803921568627454),
-    (0.50196078431372548,  0.80392156862745101,  0.75686274509803919),
-    (0.20784313725490197,  0.59215686274509804,  0.5607843137254902 ),
-    (0.00392156862745098,  0.4                ,  0.36862745098039218),
-    (0.0                ,  0.23529411764705882,  0.18823529411764706)
-    )
-
-_BuGn_data = (
-    (0.96862745098039216,  0.9882352941176471 ,  0.99215686274509807),
-    (0.89803921568627454,  0.96078431372549022,  0.97647058823529409),
-    (0.8                ,  0.92549019607843142,  0.90196078431372551),
-    (0.6                ,  0.84705882352941175,  0.78823529411764703),
-    (0.4                ,  0.76078431372549016,  0.64313725490196083),
-    (0.25490196078431371,  0.68235294117647061,  0.46274509803921571),
-    (0.13725490196078433,  0.54509803921568623,  0.27058823529411763),
-    (0.0                ,  0.42745098039215684,  0.17254901960784313),
-    (0.0                ,  0.26666666666666666,  0.10588235294117647)
-    )
-
-_BuPu_data = (
-    (0.96862745098039216,  0.9882352941176471 ,  0.99215686274509807),
-    (0.8784313725490196 ,  0.92549019607843142,  0.95686274509803926),
-    (0.74901960784313726,  0.82745098039215681,  0.90196078431372551),
-    (0.61960784313725492,  0.73725490196078436,  0.85490196078431369),
-    (0.5490196078431373 ,  0.58823529411764708,  0.77647058823529413),
-    (0.5490196078431373 ,  0.41960784313725491,  0.69411764705882351),
-    (0.53333333333333333,  0.25490196078431371,  0.61568627450980395),
-    (0.50588235294117645,  0.05882352941176471,  0.48627450980392156),
-    (0.30196078431372547,  0.0                ,  0.29411764705882354)
-    )
-
-_GnBu_data = (
-    (0.96862745098039216,  0.9882352941176471 ,  0.94117647058823528),
-    (0.8784313725490196 ,  0.95294117647058818,  0.85882352941176465),
-    (0.8                ,  0.92156862745098034,  0.77254901960784317),
-    (0.6588235294117647 ,  0.8666666666666667 ,  0.70980392156862748),
-    (0.4823529411764706 ,  0.8                ,  0.7686274509803922 ),
-    (0.30588235294117649,  0.70196078431372544,  0.82745098039215681),
-    (0.16862745098039217,  0.5490196078431373 ,  0.74509803921568629),
-    (0.03137254901960784,  0.40784313725490196,  0.67450980392156867),
-    (0.03137254901960784,  0.25098039215686274,  0.50588235294117645)
-    )
-
-_Greens_data = (
-    (0.96862745098039216,  0.9882352941176471 ,  0.96078431372549022),
-    (0.89803921568627454,  0.96078431372549022,  0.8784313725490196 ),
-    (0.7803921568627451 ,  0.9137254901960784 ,  0.75294117647058822),
-    (0.63137254901960782,  0.85098039215686272,  0.60784313725490191),
-    (0.45490196078431372,  0.7686274509803922 ,  0.46274509803921571),
-    (0.25490196078431371,  0.6705882352941176 ,  0.36470588235294116),
-    (0.13725490196078433,  0.54509803921568623,  0.27058823529411763),
-    (0.0                ,  0.42745098039215684,  0.17254901960784313),
-    (0.0                ,  0.26666666666666666,  0.10588235294117647)
-    )
-
-_Greys_data = (
-    (1.0                ,  1.0                ,  1.0                ),
-    (0.94117647058823528,  0.94117647058823528,  0.94117647058823528),
-    (0.85098039215686272,  0.85098039215686272,  0.85098039215686272),
-    (0.74117647058823533,  0.74117647058823533,  0.74117647058823533),
-    (0.58823529411764708,  0.58823529411764708,  0.58823529411764708),
-    (0.45098039215686275,  0.45098039215686275,  0.45098039215686275),
-    (0.32156862745098042,  0.32156862745098042,  0.32156862745098042),
-    (0.14509803921568629,  0.14509803921568629,  0.14509803921568629),
-    (0.0                ,  0.0                ,  0.0                )
-    )
-
-_Oranges_data = (
-    (1.0                ,  0.96078431372549022,  0.92156862745098034),
-    (0.99607843137254903,  0.90196078431372551,  0.80784313725490198),
-    (0.99215686274509807,  0.81568627450980391,  0.63529411764705879),
-    (0.99215686274509807,  0.68235294117647061,  0.41960784313725491),
-    (0.99215686274509807,  0.55294117647058827,  0.23529411764705882),
-    (0.94509803921568625,  0.41176470588235292,  0.07450980392156863),
-    (0.85098039215686272,  0.28235294117647058,  0.00392156862745098),
-    (0.65098039215686276,  0.21176470588235294,  0.01176470588235294),
-    (0.49803921568627452,  0.15294117647058825,  0.01568627450980392)
-    )
-
-_OrRd_data = (
-    (1.0                ,  0.96862745098039216,  0.92549019607843142),
-    (0.99607843137254903,  0.90980392156862744,  0.78431372549019607),
-    (0.99215686274509807,  0.83137254901960789,  0.61960784313725492),
-    (0.99215686274509807,  0.73333333333333328,  0.51764705882352946),
-    (0.9882352941176471 ,  0.55294117647058827,  0.34901960784313724),
-    (0.93725490196078431,  0.396078431372549  ,  0.28235294117647058),
-    (0.84313725490196079,  0.18823529411764706,  0.12156862745098039),
-    (0.70196078431372544,  0.0                ,  0.0                ),
-    (0.49803921568627452,  0.0                ,  0.0                )
-    )
-
-_PiYG_data = (
-    (0.55686274509803924,  0.00392156862745098,  0.32156862745098042),
-    (0.77254901960784317,  0.10588235294117647,  0.49019607843137253),
-    (0.87058823529411766,  0.46666666666666667,  0.68235294117647061),
-    (0.94509803921568625,  0.71372549019607845,  0.85490196078431369),
-    (0.99215686274509807,  0.8784313725490196 ,  0.93725490196078431),
-    (0.96862745098039216,  0.96862745098039216,  0.96862745098039216),
-    (0.90196078431372551,  0.96078431372549022,  0.81568627450980391),
-    (0.72156862745098038,  0.88235294117647056,  0.52549019607843139),
-    (0.49803921568627452,  0.73725490196078436,  0.25490196078431371),
-    (0.30196078431372547,  0.5725490196078431 ,  0.12941176470588237),
-    (0.15294117647058825,  0.39215686274509803,  0.09803921568627451)
-    )
-
-_PRGn_data = (
-    (0.25098039215686274,  0.0                ,  0.29411764705882354),
-    (0.46274509803921571,  0.16470588235294117,  0.51372549019607838),
-    (0.6                ,  0.4392156862745098 ,  0.6705882352941176 ),
-    (0.76078431372549016,  0.6470588235294118 ,  0.81176470588235294),
-    (0.90588235294117647,  0.83137254901960789,  0.90980392156862744),
-    (0.96862745098039216,  0.96862745098039216,  0.96862745098039216),
-    (0.85098039215686272,  0.94117647058823528,  0.82745098039215681),
-    (0.65098039215686276,  0.85882352941176465,  0.62745098039215685),
-    (0.35294117647058826,  0.68235294117647061,  0.38039215686274508),
-    (0.10588235294117647,  0.47058823529411764,  0.21568627450980393),
-    (0.0                ,  0.26666666666666666,  0.10588235294117647)
-    )
-
-_PuBu_data = (
-    (1.0                ,  0.96862745098039216,  0.98431372549019602),
-    (0.92549019607843142,  0.90588235294117647,  0.94901960784313721),
-    (0.81568627450980391,  0.81960784313725488,  0.90196078431372551),
-    (0.65098039215686276,  0.74117647058823533,  0.85882352941176465),
-    (0.45490196078431372,  0.66274509803921566,  0.81176470588235294),
-    (0.21176470588235294,  0.56470588235294117,  0.75294117647058822),
-    (0.0196078431372549 ,  0.4392156862745098 ,  0.69019607843137254),
-    (0.01568627450980392,  0.35294117647058826,  0.55294117647058827),
-    (0.00784313725490196,  0.2196078431372549 ,  0.34509803921568627)
-    )
-
-_PuBuGn_data = (
-    (1.0                ,  0.96862745098039216,  0.98431372549019602),
-    (0.92549019607843142,  0.88627450980392153,  0.94117647058823528),
-    (0.81568627450980391,  0.81960784313725488,  0.90196078431372551),
-    (0.65098039215686276,  0.74117647058823533,  0.85882352941176465),
-    (0.40392156862745099,  0.66274509803921566,  0.81176470588235294),
-    (0.21176470588235294,  0.56470588235294117,  0.75294117647058822),
-    (0.00784313725490196,  0.50588235294117645,  0.54117647058823526),
-    (0.00392156862745098,  0.42352941176470588,  0.34901960784313724),
-    (0.00392156862745098,  0.27450980392156865,  0.21176470588235294)
-    )
-
-_PuOr_data = (
-    (0.49803921568627452,  0.23137254901960785,  0.03137254901960784),
-    (0.70196078431372544,  0.34509803921568627,  0.02352941176470588),
-    (0.8784313725490196 ,  0.50980392156862742,  0.07843137254901961),
-    (0.99215686274509807,  0.72156862745098038,  0.38823529411764707),
-    (0.99607843137254903,  0.8784313725490196 ,  0.71372549019607845),
-    (0.96862745098039216,  0.96862745098039216,  0.96862745098039216),
-    (0.84705882352941175,  0.85490196078431369,  0.92156862745098034),
-    (0.69803921568627447,  0.6705882352941176 ,  0.82352941176470584),
-    (0.50196078431372548,  0.45098039215686275,  0.67450980392156867),
-    (0.32941176470588235,  0.15294117647058825,  0.53333333333333333),
-    (0.17647058823529413,  0.0                ,  0.29411764705882354)
-    )
-
-_PuRd_data = (
-    (0.96862745098039216,  0.95686274509803926,  0.97647058823529409),
-    (0.90588235294117647,  0.88235294117647056,  0.93725490196078431),
-    (0.83137254901960789,  0.72549019607843135,  0.85490196078431369),
-    (0.78823529411764703,  0.58039215686274515,  0.7803921568627451 ),
-    (0.87450980392156863,  0.396078431372549  ,  0.69019607843137254),
-    (0.90588235294117647,  0.16078431372549021,  0.54117647058823526),
-    (0.80784313725490198,  0.07058823529411765,  0.33725490196078434),
-    (0.59607843137254901,  0.0                ,  0.2627450980392157 ),
-    (0.40392156862745099,  0.0                ,  0.12156862745098039)
-    )
-
-_Purples_data = (
-    (0.9882352941176471 ,  0.98431372549019602,  0.99215686274509807),
-    (0.93725490196078431,  0.92941176470588238,  0.96078431372549022),
-    (0.85490196078431369,  0.85490196078431369,  0.92156862745098034),
-    (0.73725490196078436,  0.74117647058823533,  0.86274509803921573),
-    (0.61960784313725492,  0.60392156862745094,  0.78431372549019607),
-    (0.50196078431372548,  0.49019607843137253,  0.72941176470588232),
-    (0.41568627450980394,  0.31764705882352939,  0.63921568627450975),
-    (0.32941176470588235,  0.15294117647058825,  0.5607843137254902 ),
-    (0.24705882352941178,  0.0                ,  0.49019607843137253)
-    )
-
-_RdBu_data = (
-    (0.40392156862745099,  0.0                ,  0.12156862745098039),
-    (0.69803921568627447,  0.09411764705882353,  0.16862745098039217),
-    (0.83921568627450982,  0.37647058823529411,  0.30196078431372547),
-    (0.95686274509803926,  0.6470588235294118 ,  0.50980392156862742),
-    (0.99215686274509807,  0.85882352941176465,  0.7803921568627451 ),
-    (0.96862745098039216,  0.96862745098039216,  0.96862745098039216),
-    (0.81960784313725488,  0.89803921568627454,  0.94117647058823528),
-    (0.5725490196078431 ,  0.77254901960784317,  0.87058823529411766),
-    (0.2627450980392157 ,  0.57647058823529407,  0.76470588235294112),
-    (0.12941176470588237,  0.4                ,  0.67450980392156867),
-    (0.0196078431372549 ,  0.18823529411764706,  0.38039215686274508)
-    )
-
-_RdGy_data = (
-    (0.40392156862745099,  0.0                ,  0.12156862745098039),
-    (0.69803921568627447,  0.09411764705882353,  0.16862745098039217),
-    (0.83921568627450982,  0.37647058823529411,  0.30196078431372547),
-    (0.95686274509803926,  0.6470588235294118 ,  0.50980392156862742),
-    (0.99215686274509807,  0.85882352941176465,  0.7803921568627451 ),
-    (1.0                ,  1.0                ,  1.0                ),
-    (0.8784313725490196 ,  0.8784313725490196 ,  0.8784313725490196 ),
-    (0.72941176470588232,  0.72941176470588232,  0.72941176470588232),
-    (0.52941176470588236,  0.52941176470588236,  0.52941176470588236),
-    (0.30196078431372547,  0.30196078431372547,  0.30196078431372547),
-    (0.10196078431372549,  0.10196078431372549,  0.10196078431372549)
-    )
-
-_RdPu_data = (
-    (1.0                ,  0.96862745098039216,  0.95294117647058818),
-    (0.99215686274509807,  0.8784313725490196 ,  0.86666666666666667),
-    (0.9882352941176471 ,  0.77254901960784317,  0.75294117647058822),
-    (0.98039215686274506,  0.62352941176470589,  0.70980392156862748),
-    (0.96862745098039216,  0.40784313725490196,  0.63137254901960782),
-    (0.86666666666666667,  0.20392156862745098,  0.59215686274509804),
-    (0.68235294117647061,  0.00392156862745098,  0.49411764705882355),
-    (0.47843137254901963,  0.00392156862745098,  0.46666666666666667),
-    (0.28627450980392155,  0.0                ,  0.41568627450980394)
-    )
-
-_RdYlBu_data = (
-    (0.6470588235294118 , 0.0                 , 0.14901960784313725),
-    (0.84313725490196079, 0.18823529411764706 , 0.15294117647058825),
-    (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ),
-    (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508),
-    (0.99607843137254903, 0.8784313725490196  , 0.56470588235294117),
-    (1.0                , 1.0                 , 0.74901960784313726),
-    (0.8784313725490196 , 0.95294117647058818 , 0.97254901960784312),
-    (0.6705882352941176 , 0.85098039215686272 , 0.9137254901960784 ),
-    (0.45490196078431372, 0.67843137254901964 , 0.81960784313725488),
-    (0.27058823529411763, 0.45882352941176469 , 0.70588235294117652),
-    (0.19215686274509805, 0.21176470588235294 , 0.58431372549019611)
-    )
-
-_RdYlGn_data = (
-    (0.6470588235294118 , 0.0                 , 0.14901960784313725),
-    (0.84313725490196079, 0.18823529411764706 , 0.15294117647058825),
-    (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ),
-    (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508),
-    (0.99607843137254903, 0.8784313725490196  , 0.54509803921568623),
-    (1.0                , 1.0                 , 0.74901960784313726),
-    (0.85098039215686272, 0.93725490196078431 , 0.54509803921568623),
-    (0.65098039215686276, 0.85098039215686272 , 0.41568627450980394),
-    (0.4                , 0.74117647058823533 , 0.38823529411764707),
-    (0.10196078431372549, 0.59607843137254901 , 0.31372549019607843),
-    (0.0                , 0.40784313725490196 , 0.21568627450980393)
-    )
-
-_Reds_data = (
-    (1.0                , 0.96078431372549022 , 0.94117647058823528),
-    (0.99607843137254903, 0.8784313725490196  , 0.82352941176470584),
-    (0.9882352941176471 , 0.73333333333333328 , 0.63137254901960782),
-    (0.9882352941176471 , 0.5725490196078431  , 0.44705882352941179),
-    (0.98431372549019602, 0.41568627450980394 , 0.29019607843137257),
-    (0.93725490196078431, 0.23137254901960785 , 0.17254901960784313),
-    (0.79607843137254897, 0.094117647058823528, 0.11372549019607843),
-    (0.6470588235294118 , 0.058823529411764705, 0.08235294117647058),
-    (0.40392156862745099, 0.0                 , 0.05098039215686274)
-    )
-
-_Spectral_data = (
-    (0.61960784313725492, 0.003921568627450980, 0.25882352941176473),
-    (0.83529411764705885, 0.24313725490196078 , 0.30980392156862746),
-    (0.95686274509803926, 0.42745098039215684 , 0.2627450980392157 ),
-    (0.99215686274509807, 0.68235294117647061 , 0.38039215686274508),
-    (0.99607843137254903, 0.8784313725490196  , 0.54509803921568623),
-    (1.0                , 1.0                 , 0.74901960784313726),
-    (0.90196078431372551, 0.96078431372549022 , 0.59607843137254901),
-    (0.6705882352941176 , 0.8666666666666667  , 0.64313725490196083),
-    (0.4                , 0.76078431372549016 , 0.6470588235294118 ),
-    (0.19607843137254902, 0.53333333333333333 , 0.74117647058823533),
-    (0.36862745098039218, 0.30980392156862746 , 0.63529411764705879)
-    )
-
-_YlGn_data = (
-    (1.0                , 1.0                 , 0.89803921568627454),
-    (0.96862745098039216, 0.9882352941176471  , 0.72549019607843135),
-    (0.85098039215686272, 0.94117647058823528 , 0.63921568627450975),
-    (0.67843137254901964, 0.8666666666666667  , 0.55686274509803924),
-    (0.47058823529411764, 0.77647058823529413 , 0.47450980392156861),
-    (0.25490196078431371, 0.6705882352941176  , 0.36470588235294116),
-    (0.13725490196078433, 0.51764705882352946 , 0.2627450980392157 ),
-    (0.0                , 0.40784313725490196 , 0.21568627450980393),
-    (0.0                , 0.27058823529411763 , 0.16078431372549021)
-    )
-
-_YlGnBu_data = (
-    (1.0                , 1.0                 , 0.85098039215686272),
-    (0.92941176470588238, 0.97254901960784312 , 0.69411764705882351),
-    (0.7803921568627451 , 0.9137254901960784  , 0.70588235294117652),
-    (0.49803921568627452, 0.80392156862745101 , 0.73333333333333328),
-    (0.25490196078431371, 0.71372549019607845 , 0.7686274509803922 ),
-    (0.11372549019607843, 0.56862745098039214 , 0.75294117647058822),
-    (0.13333333333333333, 0.36862745098039218 , 0.6588235294117647 ),
-    (0.14509803921568629, 0.20392156862745098 , 0.58039215686274515),
-    (0.03137254901960784, 0.11372549019607843 , 0.34509803921568627)
-    )
-
-_YlOrBr_data = (
-    (1.0                , 1.0                 , 0.89803921568627454),
-    (1.0                , 0.96862745098039216 , 0.73725490196078436),
-    (0.99607843137254903, 0.8901960784313725  , 0.56862745098039214),
-    (0.99607843137254903, 0.7686274509803922  , 0.30980392156862746),
-    (0.99607843137254903, 0.6                 , 0.16078431372549021),
-    (0.92549019607843142, 0.4392156862745098  , 0.07843137254901961),
-    (0.8                , 0.29803921568627451 , 0.00784313725490196),
-    (0.6                , 0.20392156862745098 , 0.01568627450980392),
-    (0.4                , 0.14509803921568629 , 0.02352941176470588)
-    )
-
-_YlOrRd_data = (
-    (1.0                , 1.0                 , 0.8                ),
-    (1.0                , 0.92941176470588238 , 0.62745098039215685),
-    (0.99607843137254903, 0.85098039215686272 , 0.46274509803921571),
-    (0.99607843137254903, 0.69803921568627447 , 0.29803921568627451),
-    (0.99215686274509807, 0.55294117647058827 , 0.23529411764705882),
-    (0.9882352941176471 , 0.30588235294117649 , 0.16470588235294117),
-    (0.8901960784313725 , 0.10196078431372549 , 0.10980392156862745),
-    (0.74117647058823533, 0.0                 , 0.14901960784313725),
-    (0.50196078431372548, 0.0                 , 0.14901960784313725)
-    )
-
-
-# ColorBrewer's qualitative maps, implemented using ListedColormap
-# for use with mpl.colors.NoNorm
-
-_Accent_data = (
-    (0.49803921568627452, 0.78823529411764703, 0.49803921568627452),
-    (0.74509803921568629, 0.68235294117647061, 0.83137254901960789),
-    (0.99215686274509807, 0.75294117647058822, 0.52549019607843139),
-    (1.0,                 1.0,                 0.6                ),
-    (0.2196078431372549,  0.42352941176470588, 0.69019607843137254),
-    (0.94117647058823528, 0.00784313725490196, 0.49803921568627452),
-    (0.74901960784313726, 0.35686274509803922, 0.09019607843137254),
-    (0.4,                 0.4,                 0.4                ),
-    )
-
-_Dark2_data = (
-    (0.10588235294117647, 0.61960784313725492, 0.46666666666666667),
-    (0.85098039215686272, 0.37254901960784315, 0.00784313725490196),
-    (0.45882352941176469, 0.4392156862745098,  0.70196078431372544),
-    (0.90588235294117647, 0.16078431372549021, 0.54117647058823526),
-    (0.4,                 0.65098039215686276, 0.11764705882352941),
-    (0.90196078431372551, 0.6705882352941176,  0.00784313725490196),
-    (0.65098039215686276, 0.46274509803921571, 0.11372549019607843),
-    (0.4,                 0.4,                 0.4                ),
-    )
-
-_Paired_data = (
-    (0.65098039215686276, 0.80784313725490198, 0.8901960784313725 ),
-    (0.12156862745098039, 0.47058823529411764, 0.70588235294117652),
-    (0.69803921568627447, 0.87450980392156863, 0.54117647058823526),
-    (0.2,                 0.62745098039215685, 0.17254901960784313),
-    (0.98431372549019602, 0.60392156862745094, 0.6                ),
-    (0.8901960784313725,  0.10196078431372549, 0.10980392156862745),
-    (0.99215686274509807, 0.74901960784313726, 0.43529411764705883),
-    (1.0,                 0.49803921568627452, 0.0                ),
-    (0.792156862745098,   0.69803921568627447, 0.83921568627450982),
-    (0.41568627450980394, 0.23921568627450981, 0.60392156862745094),
-    (1.0,                 1.0,                 0.6                ),
-    (0.69411764705882351, 0.34901960784313724, 0.15686274509803921),
-    )
-
-_Pastel1_data = (
-    (0.98431372549019602, 0.70588235294117652, 0.68235294117647061),
-    (0.70196078431372544, 0.80392156862745101, 0.8901960784313725 ),
-    (0.8,                 0.92156862745098034, 0.77254901960784317),
-    (0.87058823529411766, 0.79607843137254897, 0.89411764705882357),
-    (0.99607843137254903, 0.85098039215686272, 0.65098039215686276),
-    (1.0,                 1.0,                 0.8                ),
-    (0.89803921568627454, 0.84705882352941175, 0.74117647058823533),
-    (0.99215686274509807, 0.85490196078431369, 0.92549019607843142),
-    (0.94901960784313721, 0.94901960784313721, 0.94901960784313721),
-    )
-
-_Pastel2_data = (
-    (0.70196078431372544, 0.88627450980392153, 0.80392156862745101),
-    (0.99215686274509807, 0.80392156862745101, 0.67450980392156867),
-    (0.79607843137254897, 0.83529411764705885, 0.90980392156862744),
-    (0.95686274509803926, 0.792156862745098,   0.89411764705882357),
-    (0.90196078431372551, 0.96078431372549022, 0.78823529411764703),
-    (1.0,                 0.94901960784313721, 0.68235294117647061),
-    (0.94509803921568625, 0.88627450980392153, 0.8                ),
-    (0.8,                 0.8,                 0.8                ),
-    )
-
-_Set1_data = (
-    (0.89411764705882357, 0.10196078431372549, 0.10980392156862745),
-    (0.21568627450980393, 0.49411764705882355, 0.72156862745098038),
-    (0.30196078431372547, 0.68627450980392157, 0.29019607843137257),
-    (0.59607843137254901, 0.30588235294117649, 0.63921568627450975),
-    (1.0,                 0.49803921568627452, 0.0                ),
-    (1.0,                 1.0,                 0.2                ),
-    (0.65098039215686276, 0.33725490196078434, 0.15686274509803921),
-    (0.96862745098039216, 0.50588235294117645, 0.74901960784313726),
-    (0.6,                 0.6,                 0.6),
-    )
-
-_Set2_data = (
-    (0.4,                 0.76078431372549016, 0.6470588235294118 ),
-    (0.9882352941176471,  0.55294117647058827, 0.3843137254901961 ),
-    (0.55294117647058827, 0.62745098039215685, 0.79607843137254897),
-    (0.90588235294117647, 0.54117647058823526, 0.76470588235294112),
-    (0.65098039215686276, 0.84705882352941175, 0.32941176470588235),
-    (1.0,                 0.85098039215686272, 0.18431372549019609),
-    (0.89803921568627454, 0.7686274509803922,  0.58039215686274515),
-    (0.70196078431372544, 0.70196078431372544, 0.70196078431372544),
-    )
-
-_Set3_data = (
-    (0.55294117647058827, 0.82745098039215681, 0.7803921568627451 ),
-    (1.0,                 1.0,                 0.70196078431372544),
-    (0.74509803921568629, 0.72941176470588232, 0.85490196078431369),
-    (0.98431372549019602, 0.50196078431372548, 0.44705882352941179),
-    (0.50196078431372548, 0.69411764705882351, 0.82745098039215681),
-    (0.99215686274509807, 0.70588235294117652, 0.3843137254901961 ),
-    (0.70196078431372544, 0.87058823529411766, 0.41176470588235292),
-    (0.9882352941176471,  0.80392156862745101, 0.89803921568627454),
-    (0.85098039215686272, 0.85098039215686272, 0.85098039215686272),
-    (0.73725490196078436, 0.50196078431372548, 0.74117647058823533),
-    (0.8,                 0.92156862745098034, 0.77254901960784317),
-    (1.0,                 0.92941176470588238, 0.43529411764705883),
-    )
-
-
-# The next 7 palettes are from the Yorick scientific visualization package,
-# an evolution of the GIST package, both by David H. Munro.
-# They are released under a BSD-like license (see LICENSE_YORICK in
-# the license directory of the matplotlib source distribution).
-#
-# Most palette functions have been reduced to simple function descriptions
-# by Reinier Heeres, since the rgb components were mostly straight lines.
-# gist_earth_data and gist_ncar_data were simplified by a script and some
-# manual effort.
-
-_gist_earth_data = \
-{'red': (
-(0.0, 0.0, 0.0000),
-(0.2824, 0.1882, 0.1882),
-(0.4588, 0.2714, 0.2714),
-(0.5490, 0.4719, 0.4719),
-(0.6980, 0.7176, 0.7176),
-(0.7882, 0.7553, 0.7553),
-(1.0000, 0.9922, 0.9922),
-), 'green': (
-(0.0, 0.0, 0.0000),
-(0.0275, 0.0000, 0.0000),
-(0.1098, 0.1893, 0.1893),
-(0.1647, 0.3035, 0.3035),
-(0.2078, 0.3841, 0.3841),
-(0.2824, 0.5020, 0.5020),
-(0.5216, 0.6397, 0.6397),
-(0.6980, 0.7171, 0.7171),
-(0.7882, 0.6392, 0.6392),
-(0.7922, 0.6413, 0.6413),
-(0.8000, 0.6447, 0.6447),
-(0.8078, 0.6481, 0.6481),
-(0.8157, 0.6549, 0.6549),
-(0.8667, 0.6991, 0.6991),
-(0.8745, 0.7103, 0.7103),
-(0.8824, 0.7216, 0.7216),
-(0.8902, 0.7323, 0.7323),
-(0.8980, 0.7430, 0.7430),
-(0.9412, 0.8275, 0.8275),
-(0.9569, 0.8635, 0.8635),
-(0.9647, 0.8816, 0.8816),
-(0.9961, 0.9733, 0.9733),
-(1.0000, 0.9843, 0.9843),
-), 'blue': (
-(0.0, 0.0, 0.0000),
-(0.0039, 0.1684, 0.1684),
-(0.0078, 0.2212, 0.2212),
-(0.0275, 0.4329, 0.4329),
-(0.0314, 0.4549, 0.4549),
-(0.2824, 0.5004, 0.5004),
-(0.4667, 0.2748, 0.2748),
-(0.5451, 0.3205, 0.3205),
-(0.7843, 0.3961, 0.3961),
-(0.8941, 0.6651, 0.6651),
-(1.0000, 0.9843, 0.9843),
-)}
-
-_gist_gray_data = {
-        'red': gfunc[3],
-        'green': gfunc[3],
-        'blue': gfunc[3],
-}
-
-def _gist_heat_red(x): return 1.5 * x
-def _gist_heat_green(x): return 2 * x - 1
-def _gist_heat_blue(x): return 4 * x - 3
-_gist_heat_data = {
-    'red': _gist_heat_red, 'green': _gist_heat_green, 'blue': _gist_heat_blue}
-
-_gist_ncar_data = \
-{'red': (
-(0.0, 0.0, 0.0000),
-(0.3098, 0.0000, 0.0000),
-(0.3725, 0.3993, 0.3993),
-(0.4235, 0.5003, 0.5003),
-(0.5333, 1.0000, 1.0000),
-(0.7922, 1.0000, 1.0000),
-(0.8471, 0.6218, 0.6218),
-(0.8980, 0.9235, 0.9235),
-(1.0000, 0.9961, 0.9961),
-), 'green': (
-(0.0, 0.0, 0.0000),
-(0.0510, 0.3722, 0.3722),
-(0.1059, 0.0000, 0.0000),
-(0.1569, 0.7202, 0.7202),
-(0.1608, 0.7537, 0.7537),
-(0.1647, 0.7752, 0.7752),
-(0.2157, 1.0000, 1.0000),
-(0.2588, 0.9804, 0.9804),
-(0.2706, 0.9804, 0.9804),
-(0.3176, 1.0000, 1.0000),
-(0.3686, 0.8081, 0.8081),
-(0.4275, 1.0000, 1.0000),
-(0.5216, 1.0000, 1.0000),
-(0.6314, 0.7292, 0.7292),
-(0.6863, 0.2796, 0.2796),
-(0.7451, 0.0000, 0.0000),
-(0.7922, 0.0000, 0.0000),
-(0.8431, 0.1753, 0.1753),
-(0.8980, 0.5000, 0.5000),
-(1.0000, 0.9725, 0.9725),
-), 'blue': (
-(0.0, 0.5020, 0.5020),
-(0.0510, 0.0222, 0.0222),
-(0.1098, 1.0000, 1.0000),
-(0.2039, 1.0000, 1.0000),
-(0.2627, 0.6145, 0.6145),
-(0.3216, 0.0000, 0.0000),
-(0.4157, 0.0000, 0.0000),
-(0.4745, 0.2342, 0.2342),
-(0.5333, 0.0000, 0.0000),
-(0.5804, 0.0000, 0.0000),
-(0.6314, 0.0549, 0.0549),
-(0.6902, 0.0000, 0.0000),
-(0.7373, 0.0000, 0.0000),
-(0.7922, 0.9738, 0.9738),
-(0.8000, 1.0000, 1.0000),
-(0.8431, 1.0000, 1.0000),
-(0.8980, 0.9341, 0.9341),
-(1.0000, 0.9961, 0.9961),
-)}
-
-_gist_rainbow_data = (
-        (0.000, (1.00, 0.00, 0.16)),
-        (0.030, (1.00, 0.00, 0.00)),
-        (0.215, (1.00, 1.00, 0.00)),
-        (0.400, (0.00, 1.00, 0.00)),
-        (0.586, (0.00, 1.00, 1.00)),
-        (0.770, (0.00, 0.00, 1.00)),
-        (0.954, (1.00, 0.00, 1.00)),
-        (1.000, (1.00, 0.00, 0.75))
-)
-
-_gist_stern_data = {
-        'red': (
-            (0.000, 0.000, 0.000), (0.0547, 1.000, 1.000),
-            (0.250, 0.027, 0.250),  # (0.2500, 0.250, 0.250),
-            (1.000, 1.000, 1.000)),
-        'green': ((0, 0, 0), (1, 1, 1)),
-        'blue': (
-            (0.000, 0.000, 0.000), (0.500, 1.000, 1.000),
-            (0.735, 0.000, 0.000), (1.000, 1.000, 1.000))
-}
-
-def _gist_yarg(x): return 1 - x
-_gist_yarg_data = {'red': _gist_yarg, 'green': _gist_yarg, 'blue': _gist_yarg}
-
-# This bipolar color map was generated from CoolWarmFloat33.csv of
-# "Diverging Color Maps for Scientific Visualization" by Kenneth Moreland.
-# <http://www.kennethmoreland.com/color-maps/>
-_coolwarm_data = {
-    'red': [
-        (0.0, 0.2298057, 0.2298057),
-        (0.03125, 0.26623388, 0.26623388),
-        (0.0625, 0.30386891, 0.30386891),
-        (0.09375, 0.342804478, 0.342804478),
-        (0.125, 0.38301334, 0.38301334),
-        (0.15625, 0.424369608, 0.424369608),
-        (0.1875, 0.46666708, 0.46666708),
-        (0.21875, 0.509635204, 0.509635204),
-        (0.25, 0.552953156, 0.552953156),
-        (0.28125, 0.596262162, 0.596262162),
-        (0.3125, 0.639176211, 0.639176211),
-        (0.34375, 0.681291281, 0.681291281),
-        (0.375, 0.722193294, 0.722193294),
-        (0.40625, 0.761464949, 0.761464949),
-        (0.4375, 0.798691636, 0.798691636),
-        (0.46875, 0.833466556, 0.833466556),
-        (0.5, 0.865395197, 0.865395197),
-        (0.53125, 0.897787179, 0.897787179),
-        (0.5625, 0.924127593, 0.924127593),
-        (0.59375, 0.944468518, 0.944468518),
-        (0.625, 0.958852946, 0.958852946),
-        (0.65625, 0.96732803, 0.96732803),
-        (0.6875, 0.969954137, 0.969954137),
-        (0.71875, 0.966811177, 0.966811177),
-        (0.75, 0.958003065, 0.958003065),
-        (0.78125, 0.943660866, 0.943660866),
-        (0.8125, 0.923944917, 0.923944917),
-        (0.84375, 0.89904617, 0.89904617),
-        (0.875, 0.869186849, 0.869186849),
-        (0.90625, 0.834620542, 0.834620542),
-        (0.9375, 0.795631745, 0.795631745),
-        (0.96875, 0.752534934, 0.752534934),
-        (1.0, 0.705673158, 0.705673158)],
-    'green': [
-        (0.0, 0.298717966, 0.298717966),
-        (0.03125, 0.353094838, 0.353094838),
-        (0.0625, 0.406535296, 0.406535296),
-        (0.09375, 0.458757618, 0.458757618),
-        (0.125, 0.50941904, 0.50941904),
-        (0.15625, 0.558148092, 0.558148092),
-        (0.1875, 0.604562568, 0.604562568),
-        (0.21875, 0.648280772, 0.648280772),
-        (0.25, 0.688929332, 0.688929332),
-        (0.28125, 0.726149107, 0.726149107),
-        (0.3125, 0.759599947, 0.759599947),
-        (0.34375, 0.788964712, 0.788964712),
-        (0.375, 0.813952739, 0.813952739),
-        (0.40625, 0.834302879, 0.834302879),
-        (0.4375, 0.849786142, 0.849786142),
-        (0.46875, 0.860207984, 0.860207984),
-        (0.5, 0.86541021, 0.86541021),
-        (0.53125, 0.848937047, 0.848937047),
-        (0.5625, 0.827384882, 0.827384882),
-        (0.59375, 0.800927443, 0.800927443),
-        (0.625, 0.769767752, 0.769767752),
-        (0.65625, 0.734132809, 0.734132809),
-        (0.6875, 0.694266682, 0.694266682),
-        (0.71875, 0.650421156, 0.650421156),
-        (0.75, 0.602842431, 0.602842431),
-        (0.78125, 0.551750968, 0.551750968),
-        (0.8125, 0.49730856, 0.49730856),
-        (0.84375, 0.439559467, 0.439559467),
-        (0.875, 0.378313092, 0.378313092),
-        (0.90625, 0.312874446, 0.312874446),
-        (0.9375, 0.24128379, 0.24128379),
-        (0.96875, 0.157246067, 0.157246067),
-        (1.0, 0.01555616, 0.01555616)],
-    'blue': [
-        (0.0, 0.753683153, 0.753683153),
-        (0.03125, 0.801466763, 0.801466763),
-        (0.0625, 0.84495867, 0.84495867),
-        (0.09375, 0.883725899, 0.883725899),
-        (0.125, 0.917387822, 0.917387822),
-        (0.15625, 0.945619588, 0.945619588),
-        (0.1875, 0.968154911, 0.968154911),
-        (0.21875, 0.98478814, 0.98478814),
-        (0.25, 0.995375608, 0.995375608),
-        (0.28125, 0.999836203, 0.999836203),
-        (0.3125, 0.998151185, 0.998151185),
-        (0.34375, 0.990363227, 0.990363227),
-        (0.375, 0.976574709, 0.976574709),
-        (0.40625, 0.956945269, 0.956945269),
-        (0.4375, 0.931688648, 0.931688648),
-        (0.46875, 0.901068838, 0.901068838),
-        (0.5, 0.865395561, 0.865395561),
-        (0.53125, 0.820880546, 0.820880546),
-        (0.5625, 0.774508472, 0.774508472),
-        (0.59375, 0.726736146, 0.726736146),
-        (0.625, 0.678007945, 0.678007945),
-        (0.65625, 0.628751763, 0.628751763),
-        (0.6875, 0.579375448, 0.579375448),
-        (0.71875, 0.530263762, 0.530263762),
-        (0.75, 0.481775914, 0.481775914),
-        (0.78125, 0.434243684, 0.434243684),
-        (0.8125, 0.387970225, 0.387970225),
-        (0.84375, 0.343229596, 0.343229596),
-        (0.875, 0.300267182, 0.300267182),
-        (0.90625, 0.259301199, 0.259301199),
-        (0.9375, 0.220525627, 0.220525627),
-        (0.96875, 0.184115123, 0.184115123),
-        (1.0, 0.150232812, 0.150232812)]
-    }
-
-# Implementation of Carey Rappaport's CMRmap.
-# See `A Color Map for Effective Black-and-White Rendering of Color-Scale
-# Images' by Carey Rappaport
-# http://www.mathworks.com/matlabcentral/fileexchange/2662-cmrmap-m
-_CMRmap_data = {'red':     ((0.000, 0.00, 0.00),
-                           (0.125, 0.15, 0.15),
-                           (0.250, 0.30, 0.30),
-                           (0.375, 0.60, 0.60),
-                           (0.500, 1.00, 1.00),
-                           (0.625, 0.90, 0.90),
-                           (0.750, 0.90, 0.90),
-                           (0.875, 0.90, 0.90),
-                           (1.000, 1.00, 1.00)),
-                'green':  ((0.000, 0.00, 0.00),
-                           (0.125, 0.15, 0.15),
-                           (0.250, 0.15, 0.15),
-                           (0.375, 0.20, 0.20),
-                           (0.500, 0.25, 0.25),
-                           (0.625, 0.50, 0.50),
-                           (0.750, 0.75, 0.75),
-                           (0.875, 0.90, 0.90),
-                           (1.000, 1.00, 1.00)),
-                'blue':   ((0.000, 0.00, 0.00),
-                           (0.125, 0.50, 0.50),
-                           (0.250, 0.75, 0.75),
-                           (0.375, 0.50, 0.50),
-                           (0.500, 0.15, 0.15),
-                           (0.625, 0.00, 0.00),
-                           (0.750, 0.10, 0.10),
-                           (0.875, 0.50, 0.50),
-                           (1.000, 1.00, 1.00))}
-
-
-# An MIT licensed, colorblind-friendly heatmap from Wistia:
-#   https://github.com/wistia/heatmap-palette
-#   http://wistia.com/blog/heatmaps-for-colorblindness
-#
-# >>> import matplotlib.colors as c
-# >>> colors = ["#e4ff7a", "#ffe81a", "#ffbd00", "#ffa000", "#fc7f00"]
-# >>> cm = c.LinearSegmentedColormap.from_list('wistia', colors)
-# >>> _wistia_data = cm._segmentdata
-# >>> del _wistia_data['alpha']
-#
-_wistia_data = {
-    'red': [(0.0, 0.8941176470588236, 0.8941176470588236),
-            (0.25, 1.0, 1.0),
-            (0.5, 1.0, 1.0),
-            (0.75, 1.0, 1.0),
-            (1.0, 0.9882352941176471, 0.9882352941176471)],
-    'green': [(0.0, 1.0, 1.0),
-              (0.25, 0.9098039215686274, 0.9098039215686274),
-              (0.5, 0.7411764705882353, 0.7411764705882353),
-              (0.75, 0.6274509803921569, 0.6274509803921569),
-              (1.0, 0.4980392156862745, 0.4980392156862745)],
-    'blue': [(0.0, 0.47843137254901963, 0.47843137254901963),
-             (0.25, 0.10196078431372549, 0.10196078431372549),
-             (0.5, 0.0, 0.0),
-             (0.75, 0.0, 0.0),
-             (1.0, 0.0, 0.0)],
-}
-
-
-# Categorical palettes from Vega:
-# https://github.com/vega/vega/wiki/Scales
-# (divided by 255)
-#
-
-_tab10_data = (
-    (0.12156862745098039, 0.4666666666666667,  0.7058823529411765  ),  # 1f77b4
-    (1.0,                 0.4980392156862745,  0.054901960784313725),  # ff7f0e
-    (0.17254901960784313, 0.6274509803921569,  0.17254901960784313 ),  # 2ca02c
-    (0.8392156862745098,  0.15294117647058825, 0.1568627450980392  ),  # d62728
-    (0.5803921568627451,  0.403921568627451,   0.7411764705882353  ),  # 9467bd
-    (0.5490196078431373,  0.33725490196078434, 0.29411764705882354 ),  # 8c564b
-    (0.8901960784313725,  0.4666666666666667,  0.7607843137254902  ),  # e377c2
-    (0.4980392156862745,  0.4980392156862745,  0.4980392156862745  ),  # 7f7f7f
-    (0.7372549019607844,  0.7411764705882353,  0.13333333333333333 ),  # bcbd22
-    (0.09019607843137255, 0.7450980392156863,  0.8117647058823529),    # 17becf
-)
-
-_tab20_data = (
-    (0.12156862745098039, 0.4666666666666667,  0.7058823529411765  ),  # 1f77b4
-    (0.6823529411764706,  0.7803921568627451,  0.9098039215686274  ),  # aec7e8
-    (1.0,                 0.4980392156862745,  0.054901960784313725),  # ff7f0e
-    (1.0,                 0.7333333333333333,  0.47058823529411764 ),  # ffbb78
-    (0.17254901960784313, 0.6274509803921569,  0.17254901960784313 ),  # 2ca02c
-    (0.596078431372549,   0.8745098039215686,  0.5411764705882353  ),  # 98df8a
-    (0.8392156862745098,  0.15294117647058825, 0.1568627450980392  ),  # d62728
-    (1.0,                 0.596078431372549,   0.5882352941176471  ),  # ff9896
-    (0.5803921568627451,  0.403921568627451,   0.7411764705882353  ),  # 9467bd
-    (0.7725490196078432,  0.6901960784313725,  0.8352941176470589  ),  # c5b0d5
-    (0.5490196078431373,  0.33725490196078434, 0.29411764705882354 ),  # 8c564b
-    (0.7686274509803922,  0.611764705882353,   0.5803921568627451  ),  # c49c94
-    (0.8901960784313725,  0.4666666666666667,  0.7607843137254902  ),  # e377c2
-    (0.9686274509803922,  0.7137254901960784,  0.8235294117647058  ),  # f7b6d2
-    (0.4980392156862745,  0.4980392156862745,  0.4980392156862745  ),  # 7f7f7f
-    (0.7803921568627451,  0.7803921568627451,  0.7803921568627451  ),  # c7c7c7
-    (0.7372549019607844,  0.7411764705882353,  0.13333333333333333 ),  # bcbd22
-    (0.8588235294117647,  0.8588235294117647,  0.5529411764705883  ),  # dbdb8d
-    (0.09019607843137255, 0.7450980392156863,  0.8117647058823529  ),  # 17becf
-    (0.6196078431372549,  0.8549019607843137,  0.8980392156862745),    # 9edae5
-)
-
-_tab20b_data = (
-    (0.2235294117647059,  0.23137254901960785, 0.4745098039215686 ),  # 393b79
-    (0.3215686274509804,  0.32941176470588235, 0.6392156862745098 ),  # 5254a3
-    (0.4196078431372549,  0.43137254901960786, 0.8117647058823529 ),  # 6b6ecf
-    (0.611764705882353,   0.6196078431372549,  0.8705882352941177 ),  # 9c9ede
-    (0.38823529411764707, 0.4745098039215686,  0.2235294117647059 ),  # 637939
-    (0.5490196078431373,  0.6352941176470588,  0.3215686274509804 ),  # 8ca252
-    (0.7098039215686275,  0.8117647058823529,  0.4196078431372549 ),  # b5cf6b
-    (0.807843137254902,   0.8588235294117647,  0.611764705882353  ),  # cedb9c
-    (0.5490196078431373,  0.42745098039215684, 0.19215686274509805),  # 8c6d31
-    (0.7411764705882353,  0.6196078431372549,  0.2235294117647059 ),  # bd9e39
-    (0.9058823529411765,  0.7294117647058823,  0.3215686274509804 ),  # e7ba52
-    (0.9058823529411765,  0.796078431372549,   0.5803921568627451 ),  # e7cb94
-    (0.5176470588235295,  0.23529411764705882, 0.2235294117647059 ),  # 843c39
-    (0.6784313725490196,  0.28627450980392155, 0.2901960784313726 ),  # ad494a
-    (0.8392156862745098,  0.3803921568627451,  0.4196078431372549 ),  # d6616b
-    (0.9058823529411765,  0.5882352941176471,  0.611764705882353  ),  # e7969c
-    (0.4823529411764706,  0.2549019607843137,  0.45098039215686275),  # 7b4173
-    (0.6470588235294118,  0.3176470588235294,  0.5803921568627451 ),  # a55194
-    (0.807843137254902,   0.42745098039215684, 0.7411764705882353 ),  # ce6dbd
-    (0.8705882352941177,  0.6196078431372549,  0.8392156862745098 ),  # de9ed6
-)
-
-_tab20c_data = (
-    (0.19215686274509805, 0.5098039215686274,  0.7411764705882353  ),  # 3182bd
-    (0.4196078431372549,  0.6823529411764706,  0.8392156862745098  ),  # 6baed6
-    (0.6196078431372549,  0.792156862745098,   0.8823529411764706  ),  # 9ecae1
-    (0.7764705882352941,  0.8588235294117647,  0.9372549019607843  ),  # c6dbef
-    (0.9019607843137255,  0.3333333333333333,  0.050980392156862744),  # e6550d
-    (0.9921568627450981,  0.5529411764705883,  0.23529411764705882 ),  # fd8d3c
-    (0.9921568627450981,  0.6823529411764706,  0.4196078431372549  ),  # fdae6b
-    (0.9921568627450981,  0.8156862745098039,  0.6352941176470588  ),  # fdd0a2
-    (0.19215686274509805, 0.6392156862745098,  0.32941176470588235 ),  # 31a354
-    (0.4549019607843137,  0.7686274509803922,  0.4627450980392157  ),  # 74c476
-    (0.6313725490196078,  0.8509803921568627,  0.6078431372549019  ),  # a1d99b
-    (0.7803921568627451,  0.9137254901960784,  0.7529411764705882  ),  # c7e9c0
-    (0.4588235294117647,  0.4196078431372549,  0.6941176470588235  ),  # 756bb1
-    (0.6196078431372549,  0.6039215686274509,  0.7843137254901961  ),  # 9e9ac8
-    (0.7372549019607844,  0.7411764705882353,  0.8627450980392157  ),  # bcbddc
-    (0.8549019607843137,  0.8549019607843137,  0.9215686274509803  ),  # dadaeb
-    (0.38823529411764707, 0.38823529411764707, 0.38823529411764707 ),  # 636363
-    (0.5882352941176471,  0.5882352941176471,  0.5882352941176471  ),  # 969696
-    (0.7411764705882353,  0.7411764705882353,  0.7411764705882353  ),  # bdbdbd
-    (0.8509803921568627,  0.8509803921568627,  0.8509803921568627  ),  # d9d9d9
-)
-
-
-datad = {
-    'Blues': _Blues_data,
-    'BrBG': _BrBG_data,
-    'BuGn': _BuGn_data,
-    'BuPu': _BuPu_data,
-    'CMRmap': _CMRmap_data,
-    'GnBu': _GnBu_data,
-    'Greens': _Greens_data,
-    'Greys': _Greys_data,
-    'OrRd': _OrRd_data,
-    'Oranges': _Oranges_data,
-    'PRGn': _PRGn_data,
-    'PiYG': _PiYG_data,
-    'PuBu': _PuBu_data,
-    'PuBuGn': _PuBuGn_data,
-    'PuOr': _PuOr_data,
-    'PuRd': _PuRd_data,
-    'Purples': _Purples_data,
-    'RdBu': _RdBu_data,
-    'RdGy': _RdGy_data,
-    'RdPu': _RdPu_data,
-    'RdYlBu': _RdYlBu_data,
-    'RdYlGn': _RdYlGn_data,
-    'Reds': _Reds_data,
-    'Spectral': _Spectral_data,
-    'Wistia': _wistia_data,
-    'YlGn': _YlGn_data,
-    'YlGnBu': _YlGnBu_data,
-    'YlOrBr': _YlOrBr_data,
-    'YlOrRd': _YlOrRd_data,
-    'afmhot': _afmhot_data,
-    'autumn': _autumn_data,
-    'binary': _binary_data,
-    'bone': _bone_data,
-    'brg': _brg_data,
-    'bwr': _bwr_data,
-    'cool': _cool_data,
-    'coolwarm': _coolwarm_data,
-    'copper': _copper_data,
-    'cubehelix': _cubehelix_data,
-    'flag': _flag_data,
-    'gist_earth': _gist_earth_data,
-    'gist_gray': _gist_gray_data,
-    'gist_heat': _gist_heat_data,
-    'gist_ncar': _gist_ncar_data,
-    'gist_rainbow': _gist_rainbow_data,
-    'gist_stern': _gist_stern_data,
-    'gist_yarg': _gist_yarg_data,
-    'gnuplot': _gnuplot_data,
-    'gnuplot2': _gnuplot2_data,
-    'gray': _gray_data,
-    'hot': _hot_data,
-    'hsv': _hsv_data,
-    'jet': _jet_data,
-    'nipy_spectral': _nipy_spectral_data,
-    'ocean': _ocean_data,
-    'pink': _pink_data,
-    'prism': _prism_data,
-    'rainbow': _rainbow_data,
-    'seismic': _seismic_data,
-    'spring': _spring_data,
-    'summer': _summer_data,
-    'terrain': _terrain_data,
-    'winter': _winter_data,
-    # Qualitative
-    'Accent': {'listed': _Accent_data},
-    'Dark2': {'listed': _Dark2_data},
-    'Paired': {'listed': _Paired_data},
-    'Pastel1': {'listed': _Pastel1_data},
-    'Pastel2': {'listed': _Pastel2_data},
-    'Set1': {'listed': _Set1_data},
-    'Set2': {'listed': _Set2_data},
-    'Set3': {'listed': _Set3_data},
-    'tab10': {'listed': _tab10_data},
-    'tab20': {'listed': _tab20_data},
-    'tab20b': {'listed': _tab20b_data},
-    'tab20c': {'listed': _tab20c_data},
-}

+ 0 - 1813
venv/lib/python3.8/site-packages/matplotlib/_cm_listed.py

@@ -1,1813 +0,0 @@
-from .colors import ListedColormap
-
-_magma_data = [[0.001462, 0.000466, 0.013866],
-               [0.002258, 0.001295, 0.018331],
-               [0.003279, 0.002305, 0.023708],
-               [0.004512, 0.003490, 0.029965],
-               [0.005950, 0.004843, 0.037130],
-               [0.007588, 0.006356, 0.044973],
-               [0.009426, 0.008022, 0.052844],
-               [0.011465, 0.009828, 0.060750],
-               [0.013708, 0.011771, 0.068667],
-               [0.016156, 0.013840, 0.076603],
-               [0.018815, 0.016026, 0.084584],
-               [0.021692, 0.018320, 0.092610],
-               [0.024792, 0.020715, 0.100676],
-               [0.028123, 0.023201, 0.108787],
-               [0.031696, 0.025765, 0.116965],
-               [0.035520, 0.028397, 0.125209],
-               [0.039608, 0.031090, 0.133515],
-               [0.043830, 0.033830, 0.141886],
-               [0.048062, 0.036607, 0.150327],
-               [0.052320, 0.039407, 0.158841],
-               [0.056615, 0.042160, 0.167446],
-               [0.060949, 0.044794, 0.176129],
-               [0.065330, 0.047318, 0.184892],
-               [0.069764, 0.049726, 0.193735],
-               [0.074257, 0.052017, 0.202660],
-               [0.078815, 0.054184, 0.211667],
-               [0.083446, 0.056225, 0.220755],
-               [0.088155, 0.058133, 0.229922],
-               [0.092949, 0.059904, 0.239164],
-               [0.097833, 0.061531, 0.248477],
-               [0.102815, 0.063010, 0.257854],
-               [0.107899, 0.064335, 0.267289],
-               [0.113094, 0.065492, 0.276784],
-               [0.118405, 0.066479, 0.286321],
-               [0.123833, 0.067295, 0.295879],
-               [0.129380, 0.067935, 0.305443],
-               [0.135053, 0.068391, 0.315000],
-               [0.140858, 0.068654, 0.324538],
-               [0.146785, 0.068738, 0.334011],
-               [0.152839, 0.068637, 0.343404],
-               [0.159018, 0.068354, 0.352688],
-               [0.165308, 0.067911, 0.361816],
-               [0.171713, 0.067305, 0.370771],
-               [0.178212, 0.066576, 0.379497],
-               [0.184801, 0.065732, 0.387973],
-               [0.191460, 0.064818, 0.396152],
-               [0.198177, 0.063862, 0.404009],
-               [0.204935, 0.062907, 0.411514],
-               [0.211718, 0.061992, 0.418647],
-               [0.218512, 0.061158, 0.425392],
-               [0.225302, 0.060445, 0.431742],
-               [0.232077, 0.059889, 0.437695],
-               [0.238826, 0.059517, 0.443256],
-               [0.245543, 0.059352, 0.448436],
-               [0.252220, 0.059415, 0.453248],
-               [0.258857, 0.059706, 0.457710],
-               [0.265447, 0.060237, 0.461840],
-               [0.271994, 0.060994, 0.465660],
-               [0.278493, 0.061978, 0.469190],
-               [0.284951, 0.063168, 0.472451],
-               [0.291366, 0.064553, 0.475462],
-               [0.297740, 0.066117, 0.478243],
-               [0.304081, 0.067835, 0.480812],
-               [0.310382, 0.069702, 0.483186],
-               [0.316654, 0.071690, 0.485380],
-               [0.322899, 0.073782, 0.487408],
-               [0.329114, 0.075972, 0.489287],
-               [0.335308, 0.078236, 0.491024],
-               [0.341482, 0.080564, 0.492631],
-               [0.347636, 0.082946, 0.494121],
-               [0.353773, 0.085373, 0.495501],
-               [0.359898, 0.087831, 0.496778],
-               [0.366012, 0.090314, 0.497960],
-               [0.372116, 0.092816, 0.499053],
-               [0.378211, 0.095332, 0.500067],
-               [0.384299, 0.097855, 0.501002],
-               [0.390384, 0.100379, 0.501864],
-               [0.396467, 0.102902, 0.502658],
-               [0.402548, 0.105420, 0.503386],
-               [0.408629, 0.107930, 0.504052],
-               [0.414709, 0.110431, 0.504662],
-               [0.420791, 0.112920, 0.505215],
-               [0.426877, 0.115395, 0.505714],
-               [0.432967, 0.117855, 0.506160],
-               [0.439062, 0.120298, 0.506555],
-               [0.445163, 0.122724, 0.506901],
-               [0.451271, 0.125132, 0.507198],
-               [0.457386, 0.127522, 0.507448],
-               [0.463508, 0.129893, 0.507652],
-               [0.469640, 0.132245, 0.507809],
-               [0.475780, 0.134577, 0.507921],
-               [0.481929, 0.136891, 0.507989],
-               [0.488088, 0.139186, 0.508011],
-               [0.494258, 0.141462, 0.507988],
-               [0.500438, 0.143719, 0.507920],
-               [0.506629, 0.145958, 0.507806],
-               [0.512831, 0.148179, 0.507648],
-               [0.519045, 0.150383, 0.507443],
-               [0.525270, 0.152569, 0.507192],
-               [0.531507, 0.154739, 0.506895],
-               [0.537755, 0.156894, 0.506551],
-               [0.544015, 0.159033, 0.506159],
-               [0.550287, 0.161158, 0.505719],
-               [0.556571, 0.163269, 0.505230],
-               [0.562866, 0.165368, 0.504692],
-               [0.569172, 0.167454, 0.504105],
-               [0.575490, 0.169530, 0.503466],
-               [0.581819, 0.171596, 0.502777],
-               [0.588158, 0.173652, 0.502035],
-               [0.594508, 0.175701, 0.501241],
-               [0.600868, 0.177743, 0.500394],
-               [0.607238, 0.179779, 0.499492],
-               [0.613617, 0.181811, 0.498536],
-               [0.620005, 0.183840, 0.497524],
-               [0.626401, 0.185867, 0.496456],
-               [0.632805, 0.187893, 0.495332],
-               [0.639216, 0.189921, 0.494150],
-               [0.645633, 0.191952, 0.492910],
-               [0.652056, 0.193986, 0.491611],
-               [0.658483, 0.196027, 0.490253],
-               [0.664915, 0.198075, 0.488836],
-               [0.671349, 0.200133, 0.487358],
-               [0.677786, 0.202203, 0.485819],
-               [0.684224, 0.204286, 0.484219],
-               [0.690661, 0.206384, 0.482558],
-               [0.697098, 0.208501, 0.480835],
-               [0.703532, 0.210638, 0.479049],
-               [0.709962, 0.212797, 0.477201],
-               [0.716387, 0.214982, 0.475290],
-               [0.722805, 0.217194, 0.473316],
-               [0.729216, 0.219437, 0.471279],
-               [0.735616, 0.221713, 0.469180],
-               [0.742004, 0.224025, 0.467018],
-               [0.748378, 0.226377, 0.464794],
-               [0.754737, 0.228772, 0.462509],
-               [0.761077, 0.231214, 0.460162],
-               [0.767398, 0.233705, 0.457755],
-               [0.773695, 0.236249, 0.455289],
-               [0.779968, 0.238851, 0.452765],
-               [0.786212, 0.241514, 0.450184],
-               [0.792427, 0.244242, 0.447543],
-               [0.798608, 0.247040, 0.444848],
-               [0.804752, 0.249911, 0.442102],
-               [0.810855, 0.252861, 0.439305],
-               [0.816914, 0.255895, 0.436461],
-               [0.822926, 0.259016, 0.433573],
-               [0.828886, 0.262229, 0.430644],
-               [0.834791, 0.265540, 0.427671],
-               [0.840636, 0.268953, 0.424666],
-               [0.846416, 0.272473, 0.421631],
-               [0.852126, 0.276106, 0.418573],
-               [0.857763, 0.279857, 0.415496],
-               [0.863320, 0.283729, 0.412403],
-               [0.868793, 0.287728, 0.409303],
-               [0.874176, 0.291859, 0.406205],
-               [0.879464, 0.296125, 0.403118],
-               [0.884651, 0.300530, 0.400047],
-               [0.889731, 0.305079, 0.397002],
-               [0.894700, 0.309773, 0.393995],
-               [0.899552, 0.314616, 0.391037],
-               [0.904281, 0.319610, 0.388137],
-               [0.908884, 0.324755, 0.385308],
-               [0.913354, 0.330052, 0.382563],
-               [0.917689, 0.335500, 0.379915],
-               [0.921884, 0.341098, 0.377376],
-               [0.925937, 0.346844, 0.374959],
-               [0.929845, 0.352734, 0.372677],
-               [0.933606, 0.358764, 0.370541],
-               [0.937221, 0.364929, 0.368567],
-               [0.940687, 0.371224, 0.366762],
-               [0.944006, 0.377643, 0.365136],
-               [0.947180, 0.384178, 0.363701],
-               [0.950210, 0.390820, 0.362468],
-               [0.953099, 0.397563, 0.361438],
-               [0.955849, 0.404400, 0.360619],
-               [0.958464, 0.411324, 0.360014],
-               [0.960949, 0.418323, 0.359630],
-               [0.963310, 0.425390, 0.359469],
-               [0.965549, 0.432519, 0.359529],
-               [0.967671, 0.439703, 0.359810],
-               [0.969680, 0.446936, 0.360311],
-               [0.971582, 0.454210, 0.361030],
-               [0.973381, 0.461520, 0.361965],
-               [0.975082, 0.468861, 0.363111],
-               [0.976690, 0.476226, 0.364466],
-               [0.978210, 0.483612, 0.366025],
-               [0.979645, 0.491014, 0.367783],
-               [0.981000, 0.498428, 0.369734],
-               [0.982279, 0.505851, 0.371874],
-               [0.983485, 0.513280, 0.374198],
-               [0.984622, 0.520713, 0.376698],
-               [0.985693, 0.528148, 0.379371],
-               [0.986700, 0.535582, 0.382210],
-               [0.987646, 0.543015, 0.385210],
-               [0.988533, 0.550446, 0.388365],
-               [0.989363, 0.557873, 0.391671],
-               [0.990138, 0.565296, 0.395122],
-               [0.990871, 0.572706, 0.398714],
-               [0.991558, 0.580107, 0.402441],
-               [0.992196, 0.587502, 0.406299],
-               [0.992785, 0.594891, 0.410283],
-               [0.993326, 0.602275, 0.414390],
-               [0.993834, 0.609644, 0.418613],
-               [0.994309, 0.616999, 0.422950],
-               [0.994738, 0.624350, 0.427397],
-               [0.995122, 0.631696, 0.431951],
-               [0.995480, 0.639027, 0.436607],
-               [0.995810, 0.646344, 0.441361],
-               [0.996096, 0.653659, 0.446213],
-               [0.996341, 0.660969, 0.451160],
-               [0.996580, 0.668256, 0.456192],
-               [0.996775, 0.675541, 0.461314],
-               [0.996925, 0.682828, 0.466526],
-               [0.997077, 0.690088, 0.471811],
-               [0.997186, 0.697349, 0.477182],
-               [0.997254, 0.704611, 0.482635],
-               [0.997325, 0.711848, 0.488154],
-               [0.997351, 0.719089, 0.493755],
-               [0.997351, 0.726324, 0.499428],
-               [0.997341, 0.733545, 0.505167],
-               [0.997285, 0.740772, 0.510983],
-               [0.997228, 0.747981, 0.516859],
-               [0.997138, 0.755190, 0.522806],
-               [0.997019, 0.762398, 0.528821],
-               [0.996898, 0.769591, 0.534892],
-               [0.996727, 0.776795, 0.541039],
-               [0.996571, 0.783977, 0.547233],
-               [0.996369, 0.791167, 0.553499],
-               [0.996162, 0.798348, 0.559820],
-               [0.995932, 0.805527, 0.566202],
-               [0.995680, 0.812706, 0.572645],
-               [0.995424, 0.819875, 0.579140],
-               [0.995131, 0.827052, 0.585701],
-               [0.994851, 0.834213, 0.592307],
-               [0.994524, 0.841387, 0.598983],
-               [0.994222, 0.848540, 0.605696],
-               [0.993866, 0.855711, 0.612482],
-               [0.993545, 0.862859, 0.619299],
-               [0.993170, 0.870024, 0.626189],
-               [0.992831, 0.877168, 0.633109],
-               [0.992440, 0.884330, 0.640099],
-               [0.992089, 0.891470, 0.647116],
-               [0.991688, 0.898627, 0.654202],
-               [0.991332, 0.905763, 0.661309],
-               [0.990930, 0.912915, 0.668481],
-               [0.990570, 0.920049, 0.675675],
-               [0.990175, 0.927196, 0.682926],
-               [0.989815, 0.934329, 0.690198],
-               [0.989434, 0.941470, 0.697519],
-               [0.989077, 0.948604, 0.704863],
-               [0.988717, 0.955742, 0.712242],
-               [0.988367, 0.962878, 0.719649],
-               [0.988033, 0.970012, 0.727077],
-               [0.987691, 0.977154, 0.734536],
-               [0.987387, 0.984288, 0.742002],
-               [0.987053, 0.991438, 0.749504]]
-
-_inferno_data = [[0.001462, 0.000466, 0.013866],
-                 [0.002267, 0.001270, 0.018570],
-                 [0.003299, 0.002249, 0.024239],
-                 [0.004547, 0.003392, 0.030909],
-                 [0.006006, 0.004692, 0.038558],
-                 [0.007676, 0.006136, 0.046836],
-                 [0.009561, 0.007713, 0.055143],
-                 [0.011663, 0.009417, 0.063460],
-                 [0.013995, 0.011225, 0.071862],
-                 [0.016561, 0.013136, 0.080282],
-                 [0.019373, 0.015133, 0.088767],
-                 [0.022447, 0.017199, 0.097327],
-                 [0.025793, 0.019331, 0.105930],
-                 [0.029432, 0.021503, 0.114621],
-                 [0.033385, 0.023702, 0.123397],
-                 [0.037668, 0.025921, 0.132232],
-                 [0.042253, 0.028139, 0.141141],
-                 [0.046915, 0.030324, 0.150164],
-                 [0.051644, 0.032474, 0.159254],
-                 [0.056449, 0.034569, 0.168414],
-                 [0.061340, 0.036590, 0.177642],
-                 [0.066331, 0.038504, 0.186962],
-                 [0.071429, 0.040294, 0.196354],
-                 [0.076637, 0.041905, 0.205799],
-                 [0.081962, 0.043328, 0.215289],
-                 [0.087411, 0.044556, 0.224813],
-                 [0.092990, 0.045583, 0.234358],
-                 [0.098702, 0.046402, 0.243904],
-                 [0.104551, 0.047008, 0.253430],
-                 [0.110536, 0.047399, 0.262912],
-                 [0.116656, 0.047574, 0.272321],
-                 [0.122908, 0.047536, 0.281624],
-                 [0.129285, 0.047293, 0.290788],
-                 [0.135778, 0.046856, 0.299776],
-                 [0.142378, 0.046242, 0.308553],
-                 [0.149073, 0.045468, 0.317085],
-                 [0.155850, 0.044559, 0.325338],
-                 [0.162689, 0.043554, 0.333277],
-                 [0.169575, 0.042489, 0.340874],
-                 [0.176493, 0.041402, 0.348111],
-                 [0.183429, 0.040329, 0.354971],
-                 [0.190367, 0.039309, 0.361447],
-                 [0.197297, 0.038400, 0.367535],
-                 [0.204209, 0.037632, 0.373238],
-                 [0.211095, 0.037030, 0.378563],
-                 [0.217949, 0.036615, 0.383522],
-                 [0.224763, 0.036405, 0.388129],
-                 [0.231538, 0.036405, 0.392400],
-                 [0.238273, 0.036621, 0.396353],
-                 [0.244967, 0.037055, 0.400007],
-                 [0.251620, 0.037705, 0.403378],
-                 [0.258234, 0.038571, 0.406485],
-                 [0.264810, 0.039647, 0.409345],
-                 [0.271347, 0.040922, 0.411976],
-                 [0.277850, 0.042353, 0.414392],
-                 [0.284321, 0.043933, 0.416608],
-                 [0.290763, 0.045644, 0.418637],
-                 [0.297178, 0.047470, 0.420491],
-                 [0.303568, 0.049396, 0.422182],
-                 [0.309935, 0.051407, 0.423721],
-                 [0.316282, 0.053490, 0.425116],
-                 [0.322610, 0.055634, 0.426377],
-                 [0.328921, 0.057827, 0.427511],
-                 [0.335217, 0.060060, 0.428524],
-                 [0.341500, 0.062325, 0.429425],
-                 [0.347771, 0.064616, 0.430217],
-                 [0.354032, 0.066925, 0.430906],
-                 [0.360284, 0.069247, 0.431497],
-                 [0.366529, 0.071579, 0.431994],
-                 [0.372768, 0.073915, 0.432400],
-                 [0.379001, 0.076253, 0.432719],
-                 [0.385228, 0.078591, 0.432955],
-                 [0.391453, 0.080927, 0.433109],
-                 [0.397674, 0.083257, 0.433183],
-                 [0.403894, 0.085580, 0.433179],
-                 [0.410113, 0.087896, 0.433098],
-                 [0.416331, 0.090203, 0.432943],
-                 [0.422549, 0.092501, 0.432714],
-                 [0.428768, 0.094790, 0.432412],
-                 [0.434987, 0.097069, 0.432039],
-                 [0.441207, 0.099338, 0.431594],
-                 [0.447428, 0.101597, 0.431080],
-                 [0.453651, 0.103848, 0.430498],
-                 [0.459875, 0.106089, 0.429846],
-                 [0.466100, 0.108322, 0.429125],
-                 [0.472328, 0.110547, 0.428334],
-                 [0.478558, 0.112764, 0.427475],
-                 [0.484789, 0.114974, 0.426548],
-                 [0.491022, 0.117179, 0.425552],
-                 [0.497257, 0.119379, 0.424488],
-                 [0.503493, 0.121575, 0.423356],
-                 [0.509730, 0.123769, 0.422156],
-                 [0.515967, 0.125960, 0.420887],
-                 [0.522206, 0.128150, 0.419549],
-                 [0.528444, 0.130341, 0.418142],
-                 [0.534683, 0.132534, 0.416667],
-                 [0.540920, 0.134729, 0.415123],
-                 [0.547157, 0.136929, 0.413511],
-                 [0.553392, 0.139134, 0.411829],
-                 [0.559624, 0.141346, 0.410078],
-                 [0.565854, 0.143567, 0.408258],
-                 [0.572081, 0.145797, 0.406369],
-                 [0.578304, 0.148039, 0.404411],
-                 [0.584521, 0.150294, 0.402385],
-                 [0.590734, 0.152563, 0.400290],
-                 [0.596940, 0.154848, 0.398125],
-                 [0.603139, 0.157151, 0.395891],
-                 [0.609330, 0.159474, 0.393589],
-                 [0.615513, 0.161817, 0.391219],
-                 [0.621685, 0.164184, 0.388781],
-                 [0.627847, 0.166575, 0.386276],
-                 [0.633998, 0.168992, 0.383704],
-                 [0.640135, 0.171438, 0.381065],
-                 [0.646260, 0.173914, 0.378359],
-                 [0.652369, 0.176421, 0.375586],
-                 [0.658463, 0.178962, 0.372748],
-                 [0.664540, 0.181539, 0.369846],
-                 [0.670599, 0.184153, 0.366879],
-                 [0.676638, 0.186807, 0.363849],
-                 [0.682656, 0.189501, 0.360757],
-                 [0.688653, 0.192239, 0.357603],
-                 [0.694627, 0.195021, 0.354388],
-                 [0.700576, 0.197851, 0.351113],
-                 [0.706500, 0.200728, 0.347777],
-                 [0.712396, 0.203656, 0.344383],
-                 [0.718264, 0.206636, 0.340931],
-                 [0.724103, 0.209670, 0.337424],
-                 [0.729909, 0.212759, 0.333861],
-                 [0.735683, 0.215906, 0.330245],
-                 [0.741423, 0.219112, 0.326576],
-                 [0.747127, 0.222378, 0.322856],
-                 [0.752794, 0.225706, 0.319085],
-                 [0.758422, 0.229097, 0.315266],
-                 [0.764010, 0.232554, 0.311399],
-                 [0.769556, 0.236077, 0.307485],
-                 [0.775059, 0.239667, 0.303526],
-                 [0.780517, 0.243327, 0.299523],
-                 [0.785929, 0.247056, 0.295477],
-                 [0.791293, 0.250856, 0.291390],
-                 [0.796607, 0.254728, 0.287264],
-                 [0.801871, 0.258674, 0.283099],
-                 [0.807082, 0.262692, 0.278898],
-                 [0.812239, 0.266786, 0.274661],
-                 [0.817341, 0.270954, 0.270390],
-                 [0.822386, 0.275197, 0.266085],
-                 [0.827372, 0.279517, 0.261750],
-                 [0.832299, 0.283913, 0.257383],
-                 [0.837165, 0.288385, 0.252988],
-                 [0.841969, 0.292933, 0.248564],
-                 [0.846709, 0.297559, 0.244113],
-                 [0.851384, 0.302260, 0.239636],
-                 [0.855992, 0.307038, 0.235133],
-                 [0.860533, 0.311892, 0.230606],
-                 [0.865006, 0.316822, 0.226055],
-                 [0.869409, 0.321827, 0.221482],
-                 [0.873741, 0.326906, 0.216886],
-                 [0.878001, 0.332060, 0.212268],
-                 [0.882188, 0.337287, 0.207628],
-                 [0.886302, 0.342586, 0.202968],
-                 [0.890341, 0.347957, 0.198286],
-                 [0.894305, 0.353399, 0.193584],
-                 [0.898192, 0.358911, 0.188860],
-                 [0.902003, 0.364492, 0.184116],
-                 [0.905735, 0.370140, 0.179350],
-                 [0.909390, 0.375856, 0.174563],
-                 [0.912966, 0.381636, 0.169755],
-                 [0.916462, 0.387481, 0.164924],
-                 [0.919879, 0.393389, 0.160070],
-                 [0.923215, 0.399359, 0.155193],
-                 [0.926470, 0.405389, 0.150292],
-                 [0.929644, 0.411479, 0.145367],
-                 [0.932737, 0.417627, 0.140417],
-                 [0.935747, 0.423831, 0.135440],
-                 [0.938675, 0.430091, 0.130438],
-                 [0.941521, 0.436405, 0.125409],
-                 [0.944285, 0.442772, 0.120354],
-                 [0.946965, 0.449191, 0.115272],
-                 [0.949562, 0.455660, 0.110164],
-                 [0.952075, 0.462178, 0.105031],
-                 [0.954506, 0.468744, 0.099874],
-                 [0.956852, 0.475356, 0.094695],
-                 [0.959114, 0.482014, 0.089499],
-                 [0.961293, 0.488716, 0.084289],
-                 [0.963387, 0.495462, 0.079073],
-                 [0.965397, 0.502249, 0.073859],
-                 [0.967322, 0.509078, 0.068659],
-                 [0.969163, 0.515946, 0.063488],
-                 [0.970919, 0.522853, 0.058367],
-                 [0.972590, 0.529798, 0.053324],
-                 [0.974176, 0.536780, 0.048392],
-                 [0.975677, 0.543798, 0.043618],
-                 [0.977092, 0.550850, 0.039050],
-                 [0.978422, 0.557937, 0.034931],
-                 [0.979666, 0.565057, 0.031409],
-                 [0.980824, 0.572209, 0.028508],
-                 [0.981895, 0.579392, 0.026250],
-                 [0.982881, 0.586606, 0.024661],
-                 [0.983779, 0.593849, 0.023770],
-                 [0.984591, 0.601122, 0.023606],
-                 [0.985315, 0.608422, 0.024202],
-                 [0.985952, 0.615750, 0.025592],
-                 [0.986502, 0.623105, 0.027814],
-                 [0.986964, 0.630485, 0.030908],
-                 [0.987337, 0.637890, 0.034916],
-                 [0.987622, 0.645320, 0.039886],
-                 [0.987819, 0.652773, 0.045581],
-                 [0.987926, 0.660250, 0.051750],
-                 [0.987945, 0.667748, 0.058329],
-                 [0.987874, 0.675267, 0.065257],
-                 [0.987714, 0.682807, 0.072489],
-                 [0.987464, 0.690366, 0.079990],
-                 [0.987124, 0.697944, 0.087731],
-                 [0.986694, 0.705540, 0.095694],
-                 [0.986175, 0.713153, 0.103863],
-                 [0.985566, 0.720782, 0.112229],
-                 [0.984865, 0.728427, 0.120785],
-                 [0.984075, 0.736087, 0.129527],
-                 [0.983196, 0.743758, 0.138453],
-                 [0.982228, 0.751442, 0.147565],
-                 [0.981173, 0.759135, 0.156863],
-                 [0.980032, 0.766837, 0.166353],
-                 [0.978806, 0.774545, 0.176037],
-                 [0.977497, 0.782258, 0.185923],
-                 [0.976108, 0.789974, 0.196018],
-                 [0.974638, 0.797692, 0.206332],
-                 [0.973088, 0.805409, 0.216877],
-                 [0.971468, 0.813122, 0.227658],
-                 [0.969783, 0.820825, 0.238686],
-                 [0.968041, 0.828515, 0.249972],
-                 [0.966243, 0.836191, 0.261534],
-                 [0.964394, 0.843848, 0.273391],
-                 [0.962517, 0.851476, 0.285546],
-                 [0.960626, 0.859069, 0.298010],
-                 [0.958720, 0.866624, 0.310820],
-                 [0.956834, 0.874129, 0.323974],
-                 [0.954997, 0.881569, 0.337475],
-                 [0.953215, 0.888942, 0.351369],
-                 [0.951546, 0.896226, 0.365627],
-                 [0.950018, 0.903409, 0.380271],
-                 [0.948683, 0.910473, 0.395289],
-                 [0.947594, 0.917399, 0.410665],
-                 [0.946809, 0.924168, 0.426373],
-                 [0.946392, 0.930761, 0.442367],
-                 [0.946403, 0.937159, 0.458592],
-                 [0.946903, 0.943348, 0.474970],
-                 [0.947937, 0.949318, 0.491426],
-                 [0.949545, 0.955063, 0.507860],
-                 [0.951740, 0.960587, 0.524203],
-                 [0.954529, 0.965896, 0.540361],
-                 [0.957896, 0.971003, 0.556275],
-                 [0.961812, 0.975924, 0.571925],
-                 [0.966249, 0.980678, 0.587206],
-                 [0.971162, 0.985282, 0.602154],
-                 [0.976511, 0.989753, 0.616760],
-                 [0.982257, 0.994109, 0.631017],
-                 [0.988362, 0.998364, 0.644924]]
-
-_plasma_data = [[0.050383, 0.029803, 0.527975],
-                [0.063536, 0.028426, 0.533124],
-                [0.075353, 0.027206, 0.538007],
-                [0.086222, 0.026125, 0.542658],
-                [0.096379, 0.025165, 0.547103],
-                [0.105980, 0.024309, 0.551368],
-                [0.115124, 0.023556, 0.555468],
-                [0.123903, 0.022878, 0.559423],
-                [0.132381, 0.022258, 0.563250],
-                [0.140603, 0.021687, 0.566959],
-                [0.148607, 0.021154, 0.570562],
-                [0.156421, 0.020651, 0.574065],
-                [0.164070, 0.020171, 0.577478],
-                [0.171574, 0.019706, 0.580806],
-                [0.178950, 0.019252, 0.584054],
-                [0.186213, 0.018803, 0.587228],
-                [0.193374, 0.018354, 0.590330],
-                [0.200445, 0.017902, 0.593364],
-                [0.207435, 0.017442, 0.596333],
-                [0.214350, 0.016973, 0.599239],
-                [0.221197, 0.016497, 0.602083],
-                [0.227983, 0.016007, 0.604867],
-                [0.234715, 0.015502, 0.607592],
-                [0.241396, 0.014979, 0.610259],
-                [0.248032, 0.014439, 0.612868],
-                [0.254627, 0.013882, 0.615419],
-                [0.261183, 0.013308, 0.617911],
-                [0.267703, 0.012716, 0.620346],
-                [0.274191, 0.012109, 0.622722],
-                [0.280648, 0.011488, 0.625038],
-                [0.287076, 0.010855, 0.627295],
-                [0.293478, 0.010213, 0.629490],
-                [0.299855, 0.009561, 0.631624],
-                [0.306210, 0.008902, 0.633694],
-                [0.312543, 0.008239, 0.635700],
-                [0.318856, 0.007576, 0.637640],
-                [0.325150, 0.006915, 0.639512],
-                [0.331426, 0.006261, 0.641316],
-                [0.337683, 0.005618, 0.643049],
-                [0.343925, 0.004991, 0.644710],
-                [0.350150, 0.004382, 0.646298],
-                [0.356359, 0.003798, 0.647810],
-                [0.362553, 0.003243, 0.649245],
-                [0.368733, 0.002724, 0.650601],
-                [0.374897, 0.002245, 0.651876],
-                [0.381047, 0.001814, 0.653068],
-                [0.387183, 0.001434, 0.654177],
-                [0.393304, 0.001114, 0.655199],
-                [0.399411, 0.000859, 0.656133],
-                [0.405503, 0.000678, 0.656977],
-                [0.411580, 0.000577, 0.657730],
-                [0.417642, 0.000564, 0.658390],
-                [0.423689, 0.000646, 0.658956],
-                [0.429719, 0.000831, 0.659425],
-                [0.435734, 0.001127, 0.659797],
-                [0.441732, 0.001540, 0.660069],
-                [0.447714, 0.002080, 0.660240],
-                [0.453677, 0.002755, 0.660310],
-                [0.459623, 0.003574, 0.660277],
-                [0.465550, 0.004545, 0.660139],
-                [0.471457, 0.005678, 0.659897],
-                [0.477344, 0.006980, 0.659549],
-                [0.483210, 0.008460, 0.659095],
-                [0.489055, 0.010127, 0.658534],
-                [0.494877, 0.011990, 0.657865],
-                [0.500678, 0.014055, 0.657088],
-                [0.506454, 0.016333, 0.656202],
-                [0.512206, 0.018833, 0.655209],
-                [0.517933, 0.021563, 0.654109],
-                [0.523633, 0.024532, 0.652901],
-                [0.529306, 0.027747, 0.651586],
-                [0.534952, 0.031217, 0.650165],
-                [0.540570, 0.034950, 0.648640],
-                [0.546157, 0.038954, 0.647010],
-                [0.551715, 0.043136, 0.645277],
-                [0.557243, 0.047331, 0.643443],
-                [0.562738, 0.051545, 0.641509],
-                [0.568201, 0.055778, 0.639477],
-                [0.573632, 0.060028, 0.637349],
-                [0.579029, 0.064296, 0.635126],
-                [0.584391, 0.068579, 0.632812],
-                [0.589719, 0.072878, 0.630408],
-                [0.595011, 0.077190, 0.627917],
-                [0.600266, 0.081516, 0.625342],
-                [0.605485, 0.085854, 0.622686],
-                [0.610667, 0.090204, 0.619951],
-                [0.615812, 0.094564, 0.617140],
-                [0.620919, 0.098934, 0.614257],
-                [0.625987, 0.103312, 0.611305],
-                [0.631017, 0.107699, 0.608287],
-                [0.636008, 0.112092, 0.605205],
-                [0.640959, 0.116492, 0.602065],
-                [0.645872, 0.120898, 0.598867],
-                [0.650746, 0.125309, 0.595617],
-                [0.655580, 0.129725, 0.592317],
-                [0.660374, 0.134144, 0.588971],
-                [0.665129, 0.138566, 0.585582],
-                [0.669845, 0.142992, 0.582154],
-                [0.674522, 0.147419, 0.578688],
-                [0.679160, 0.151848, 0.575189],
-                [0.683758, 0.156278, 0.571660],
-                [0.688318, 0.160709, 0.568103],
-                [0.692840, 0.165141, 0.564522],
-                [0.697324, 0.169573, 0.560919],
-                [0.701769, 0.174005, 0.557296],
-                [0.706178, 0.178437, 0.553657],
-                [0.710549, 0.182868, 0.550004],
-                [0.714883, 0.187299, 0.546338],
-                [0.719181, 0.191729, 0.542663],
-                [0.723444, 0.196158, 0.538981],
-                [0.727670, 0.200586, 0.535293],
-                [0.731862, 0.205013, 0.531601],
-                [0.736019, 0.209439, 0.527908],
-                [0.740143, 0.213864, 0.524216],
-                [0.744232, 0.218288, 0.520524],
-                [0.748289, 0.222711, 0.516834],
-                [0.752312, 0.227133, 0.513149],
-                [0.756304, 0.231555, 0.509468],
-                [0.760264, 0.235976, 0.505794],
-                [0.764193, 0.240396, 0.502126],
-                [0.768090, 0.244817, 0.498465],
-                [0.771958, 0.249237, 0.494813],
-                [0.775796, 0.253658, 0.491171],
-                [0.779604, 0.258078, 0.487539],
-                [0.783383, 0.262500, 0.483918],
-                [0.787133, 0.266922, 0.480307],
-                [0.790855, 0.271345, 0.476706],
-                [0.794549, 0.275770, 0.473117],
-                [0.798216, 0.280197, 0.469538],
-                [0.801855, 0.284626, 0.465971],
-                [0.805467, 0.289057, 0.462415],
-                [0.809052, 0.293491, 0.458870],
-                [0.812612, 0.297928, 0.455338],
-                [0.816144, 0.302368, 0.451816],
-                [0.819651, 0.306812, 0.448306],
-                [0.823132, 0.311261, 0.444806],
-                [0.826588, 0.315714, 0.441316],
-                [0.830018, 0.320172, 0.437836],
-                [0.833422, 0.324635, 0.434366],
-                [0.836801, 0.329105, 0.430905],
-                [0.840155, 0.333580, 0.427455],
-                [0.843484, 0.338062, 0.424013],
-                [0.846788, 0.342551, 0.420579],
-                [0.850066, 0.347048, 0.417153],
-                [0.853319, 0.351553, 0.413734],
-                [0.856547, 0.356066, 0.410322],
-                [0.859750, 0.360588, 0.406917],
-                [0.862927, 0.365119, 0.403519],
-                [0.866078, 0.369660, 0.400126],
-                [0.869203, 0.374212, 0.396738],
-                [0.872303, 0.378774, 0.393355],
-                [0.875376, 0.383347, 0.389976],
-                [0.878423, 0.387932, 0.386600],
-                [0.881443, 0.392529, 0.383229],
-                [0.884436, 0.397139, 0.379860],
-                [0.887402, 0.401762, 0.376494],
-                [0.890340, 0.406398, 0.373130],
-                [0.893250, 0.411048, 0.369768],
-                [0.896131, 0.415712, 0.366407],
-                [0.898984, 0.420392, 0.363047],
-                [0.901807, 0.425087, 0.359688],
-                [0.904601, 0.429797, 0.356329],
-                [0.907365, 0.434524, 0.352970],
-                [0.910098, 0.439268, 0.349610],
-                [0.912800, 0.444029, 0.346251],
-                [0.915471, 0.448807, 0.342890],
-                [0.918109, 0.453603, 0.339529],
-                [0.920714, 0.458417, 0.336166],
-                [0.923287, 0.463251, 0.332801],
-                [0.925825, 0.468103, 0.329435],
-                [0.928329, 0.472975, 0.326067],
-                [0.930798, 0.477867, 0.322697],
-                [0.933232, 0.482780, 0.319325],
-                [0.935630, 0.487712, 0.315952],
-                [0.937990, 0.492667, 0.312575],
-                [0.940313, 0.497642, 0.309197],
-                [0.942598, 0.502639, 0.305816],
-                [0.944844, 0.507658, 0.302433],
-                [0.947051, 0.512699, 0.299049],
-                [0.949217, 0.517763, 0.295662],
-                [0.951344, 0.522850, 0.292275],
-                [0.953428, 0.527960, 0.288883],
-                [0.955470, 0.533093, 0.285490],
-                [0.957469, 0.538250, 0.282096],
-                [0.959424, 0.543431, 0.278701],
-                [0.961336, 0.548636, 0.275305],
-                [0.963203, 0.553865, 0.271909],
-                [0.965024, 0.559118, 0.268513],
-                [0.966798, 0.564396, 0.265118],
-                [0.968526, 0.569700, 0.261721],
-                [0.970205, 0.575028, 0.258325],
-                [0.971835, 0.580382, 0.254931],
-                [0.973416, 0.585761, 0.251540],
-                [0.974947, 0.591165, 0.248151],
-                [0.976428, 0.596595, 0.244767],
-                [0.977856, 0.602051, 0.241387],
-                [0.979233, 0.607532, 0.238013],
-                [0.980556, 0.613039, 0.234646],
-                [0.981826, 0.618572, 0.231287],
-                [0.983041, 0.624131, 0.227937],
-                [0.984199, 0.629718, 0.224595],
-                [0.985301, 0.635330, 0.221265],
-                [0.986345, 0.640969, 0.217948],
-                [0.987332, 0.646633, 0.214648],
-                [0.988260, 0.652325, 0.211364],
-                [0.989128, 0.658043, 0.208100],
-                [0.989935, 0.663787, 0.204859],
-                [0.990681, 0.669558, 0.201642],
-                [0.991365, 0.675355, 0.198453],
-                [0.991985, 0.681179, 0.195295],
-                [0.992541, 0.687030, 0.192170],
-                [0.993032, 0.692907, 0.189084],
-                [0.993456, 0.698810, 0.186041],
-                [0.993814, 0.704741, 0.183043],
-                [0.994103, 0.710698, 0.180097],
-                [0.994324, 0.716681, 0.177208],
-                [0.994474, 0.722691, 0.174381],
-                [0.994553, 0.728728, 0.171622],
-                [0.994561, 0.734791, 0.168938],
-                [0.994495, 0.740880, 0.166335],
-                [0.994355, 0.746995, 0.163821],
-                [0.994141, 0.753137, 0.161404],
-                [0.993851, 0.759304, 0.159092],
-                [0.993482, 0.765499, 0.156891],
-                [0.993033, 0.771720, 0.154808],
-                [0.992505, 0.777967, 0.152855],
-                [0.991897, 0.784239, 0.151042],
-                [0.991209, 0.790537, 0.149377],
-                [0.990439, 0.796859, 0.147870],
-                [0.989587, 0.803205, 0.146529],
-                [0.988648, 0.809579, 0.145357],
-                [0.987621, 0.815978, 0.144363],
-                [0.986509, 0.822401, 0.143557],
-                [0.985314, 0.828846, 0.142945],
-                [0.984031, 0.835315, 0.142528],
-                [0.982653, 0.841812, 0.142303],
-                [0.981190, 0.848329, 0.142279],
-                [0.979644, 0.854866, 0.142453],
-                [0.977995, 0.861432, 0.142808],
-                [0.976265, 0.868016, 0.143351],
-                [0.974443, 0.874622, 0.144061],
-                [0.972530, 0.881250, 0.144923],
-                [0.970533, 0.887896, 0.145919],
-                [0.968443, 0.894564, 0.147014],
-                [0.966271, 0.901249, 0.148180],
-                [0.964021, 0.907950, 0.149370],
-                [0.961681, 0.914672, 0.150520],
-                [0.959276, 0.921407, 0.151566],
-                [0.956808, 0.928152, 0.152409],
-                [0.954287, 0.934908, 0.152921],
-                [0.951726, 0.941671, 0.152925],
-                [0.949151, 0.948435, 0.152178],
-                [0.946602, 0.955190, 0.150328],
-                [0.944152, 0.961916, 0.146861],
-                [0.941896, 0.968590, 0.140956],
-                [0.940015, 0.975158, 0.131326]]
-
-_viridis_data = [[0.267004, 0.004874, 0.329415],
-                 [0.268510, 0.009605, 0.335427],
-                 [0.269944, 0.014625, 0.341379],
-                 [0.271305, 0.019942, 0.347269],
-                 [0.272594, 0.025563, 0.353093],
-                 [0.273809, 0.031497, 0.358853],
-                 [0.274952, 0.037752, 0.364543],
-                 [0.276022, 0.044167, 0.370164],
-                 [0.277018, 0.050344, 0.375715],
-                 [0.277941, 0.056324, 0.381191],
-                 [0.278791, 0.062145, 0.386592],
-                 [0.279566, 0.067836, 0.391917],
-                 [0.280267, 0.073417, 0.397163],
-                 [0.280894, 0.078907, 0.402329],
-                 [0.281446, 0.084320, 0.407414],
-                 [0.281924, 0.089666, 0.412415],
-                 [0.282327, 0.094955, 0.417331],
-                 [0.282656, 0.100196, 0.422160],
-                 [0.282910, 0.105393, 0.426902],
-                 [0.283091, 0.110553, 0.431554],
-                 [0.283197, 0.115680, 0.436115],
-                 [0.283229, 0.120777, 0.440584],
-                 [0.283187, 0.125848, 0.444960],
-                 [0.283072, 0.130895, 0.449241],
-                 [0.282884, 0.135920, 0.453427],
-                 [0.282623, 0.140926, 0.457517],
-                 [0.282290, 0.145912, 0.461510],
-                 [0.281887, 0.150881, 0.465405],
-                 [0.281412, 0.155834, 0.469201],
-                 [0.280868, 0.160771, 0.472899],
-                 [0.280255, 0.165693, 0.476498],
-                 [0.279574, 0.170599, 0.479997],
-                 [0.278826, 0.175490, 0.483397],
-                 [0.278012, 0.180367, 0.486697],
-                 [0.277134, 0.185228, 0.489898],
-                 [0.276194, 0.190074, 0.493001],
-                 [0.275191, 0.194905, 0.496005],
-                 [0.274128, 0.199721, 0.498911],
-                 [0.273006, 0.204520, 0.501721],
-                 [0.271828, 0.209303, 0.504434],
-                 [0.270595, 0.214069, 0.507052],
-                 [0.269308, 0.218818, 0.509577],
-                 [0.267968, 0.223549, 0.512008],
-                 [0.266580, 0.228262, 0.514349],
-                 [0.265145, 0.232956, 0.516599],
-                 [0.263663, 0.237631, 0.518762],
-                 [0.262138, 0.242286, 0.520837],
-                 [0.260571, 0.246922, 0.522828],
-                 [0.258965, 0.251537, 0.524736],
-                 [0.257322, 0.256130, 0.526563],
-                 [0.255645, 0.260703, 0.528312],
-                 [0.253935, 0.265254, 0.529983],
-                 [0.252194, 0.269783, 0.531579],
-                 [0.250425, 0.274290, 0.533103],
-                 [0.248629, 0.278775, 0.534556],
-                 [0.246811, 0.283237, 0.535941],
-                 [0.244972, 0.287675, 0.537260],
-                 [0.243113, 0.292092, 0.538516],
-                 [0.241237, 0.296485, 0.539709],
-                 [0.239346, 0.300855, 0.540844],
-                 [0.237441, 0.305202, 0.541921],
-                 [0.235526, 0.309527, 0.542944],
-                 [0.233603, 0.313828, 0.543914],
-                 [0.231674, 0.318106, 0.544834],
-                 [0.229739, 0.322361, 0.545706],
-                 [0.227802, 0.326594, 0.546532],
-                 [0.225863, 0.330805, 0.547314],
-                 [0.223925, 0.334994, 0.548053],
-                 [0.221989, 0.339161, 0.548752],
-                 [0.220057, 0.343307, 0.549413],
-                 [0.218130, 0.347432, 0.550038],
-                 [0.216210, 0.351535, 0.550627],
-                 [0.214298, 0.355619, 0.551184],
-                 [0.212395, 0.359683, 0.551710],
-                 [0.210503, 0.363727, 0.552206],
-                 [0.208623, 0.367752, 0.552675],
-                 [0.206756, 0.371758, 0.553117],
-                 [0.204903, 0.375746, 0.553533],
-                 [0.203063, 0.379716, 0.553925],
-                 [0.201239, 0.383670, 0.554294],
-                 [0.199430, 0.387607, 0.554642],
-                 [0.197636, 0.391528, 0.554969],
-                 [0.195860, 0.395433, 0.555276],
-                 [0.194100, 0.399323, 0.555565],
-                 [0.192357, 0.403199, 0.555836],
-                 [0.190631, 0.407061, 0.556089],
-                 [0.188923, 0.410910, 0.556326],
-                 [0.187231, 0.414746, 0.556547],
-                 [0.185556, 0.418570, 0.556753],
-                 [0.183898, 0.422383, 0.556944],
-                 [0.182256, 0.426184, 0.557120],
-                 [0.180629, 0.429975, 0.557282],
-                 [0.179019, 0.433756, 0.557430],
-                 [0.177423, 0.437527, 0.557565],
-                 [0.175841, 0.441290, 0.557685],
-                 [0.174274, 0.445044, 0.557792],
-                 [0.172719, 0.448791, 0.557885],
-                 [0.171176, 0.452530, 0.557965],
-                 [0.169646, 0.456262, 0.558030],
-                 [0.168126, 0.459988, 0.558082],
-                 [0.166617, 0.463708, 0.558119],
-                 [0.165117, 0.467423, 0.558141],
-                 [0.163625, 0.471133, 0.558148],
-                 [0.162142, 0.474838, 0.558140],
-                 [0.160665, 0.478540, 0.558115],
-                 [0.159194, 0.482237, 0.558073],
-                 [0.157729, 0.485932, 0.558013],
-                 [0.156270, 0.489624, 0.557936],
-                 [0.154815, 0.493313, 0.557840],
-                 [0.153364, 0.497000, 0.557724],
-                 [0.151918, 0.500685, 0.557587],
-                 [0.150476, 0.504369, 0.557430],
-                 [0.149039, 0.508051, 0.557250],
-                 [0.147607, 0.511733, 0.557049],
-                 [0.146180, 0.515413, 0.556823],
-                 [0.144759, 0.519093, 0.556572],
-                 [0.143343, 0.522773, 0.556295],
-                 [0.141935, 0.526453, 0.555991],
-                 [0.140536, 0.530132, 0.555659],
-                 [0.139147, 0.533812, 0.555298],
-                 [0.137770, 0.537492, 0.554906],
-                 [0.136408, 0.541173, 0.554483],
-                 [0.135066, 0.544853, 0.554029],
-                 [0.133743, 0.548535, 0.553541],
-                 [0.132444, 0.552216, 0.553018],
-                 [0.131172, 0.555899, 0.552459],
-                 [0.129933, 0.559582, 0.551864],
-                 [0.128729, 0.563265, 0.551229],
-                 [0.127568, 0.566949, 0.550556],
-                 [0.126453, 0.570633, 0.549841],
-                 [0.125394, 0.574318, 0.549086],
-                 [0.124395, 0.578002, 0.548287],
-                 [0.123463, 0.581687, 0.547445],
-                 [0.122606, 0.585371, 0.546557],
-                 [0.121831, 0.589055, 0.545623],
-                 [0.121148, 0.592739, 0.544641],
-                 [0.120565, 0.596422, 0.543611],
-                 [0.120092, 0.600104, 0.542530],
-                 [0.119738, 0.603785, 0.541400],
-                 [0.119512, 0.607464, 0.540218],
-                 [0.119423, 0.611141, 0.538982],
-                 [0.119483, 0.614817, 0.537692],
-                 [0.119699, 0.618490, 0.536347],
-                 [0.120081, 0.622161, 0.534946],
-                 [0.120638, 0.625828, 0.533488],
-                 [0.121380, 0.629492, 0.531973],
-                 [0.122312, 0.633153, 0.530398],
-                 [0.123444, 0.636809, 0.528763],
-                 [0.124780, 0.640461, 0.527068],
-                 [0.126326, 0.644107, 0.525311],
-                 [0.128087, 0.647749, 0.523491],
-                 [0.130067, 0.651384, 0.521608],
-                 [0.132268, 0.655014, 0.519661],
-                 [0.134692, 0.658636, 0.517649],
-                 [0.137339, 0.662252, 0.515571],
-                 [0.140210, 0.665859, 0.513427],
-                 [0.143303, 0.669459, 0.511215],
-                 [0.146616, 0.673050, 0.508936],
-                 [0.150148, 0.676631, 0.506589],
-                 [0.153894, 0.680203, 0.504172],
-                 [0.157851, 0.683765, 0.501686],
-                 [0.162016, 0.687316, 0.499129],
-                 [0.166383, 0.690856, 0.496502],
-                 [0.170948, 0.694384, 0.493803],
-                 [0.175707, 0.697900, 0.491033],
-                 [0.180653, 0.701402, 0.488189],
-                 [0.185783, 0.704891, 0.485273],
-                 [0.191090, 0.708366, 0.482284],
-                 [0.196571, 0.711827, 0.479221],
-                 [0.202219, 0.715272, 0.476084],
-                 [0.208030, 0.718701, 0.472873],
-                 [0.214000, 0.722114, 0.469588],
-                 [0.220124, 0.725509, 0.466226],
-                 [0.226397, 0.728888, 0.462789],
-                 [0.232815, 0.732247, 0.459277],
-                 [0.239374, 0.735588, 0.455688],
-                 [0.246070, 0.738910, 0.452024],
-                 [0.252899, 0.742211, 0.448284],
-                 [0.259857, 0.745492, 0.444467],
-                 [0.266941, 0.748751, 0.440573],
-                 [0.274149, 0.751988, 0.436601],
-                 [0.281477, 0.755203, 0.432552],
-                 [0.288921, 0.758394, 0.428426],
-                 [0.296479, 0.761561, 0.424223],
-                 [0.304148, 0.764704, 0.419943],
-                 [0.311925, 0.767822, 0.415586],
-                 [0.319809, 0.770914, 0.411152],
-                 [0.327796, 0.773980, 0.406640],
-                 [0.335885, 0.777018, 0.402049],
-                 [0.344074, 0.780029, 0.397381],
-                 [0.352360, 0.783011, 0.392636],
-                 [0.360741, 0.785964, 0.387814],
-                 [0.369214, 0.788888, 0.382914],
-                 [0.377779, 0.791781, 0.377939],
-                 [0.386433, 0.794644, 0.372886],
-                 [0.395174, 0.797475, 0.367757],
-                 [0.404001, 0.800275, 0.362552],
-                 [0.412913, 0.803041, 0.357269],
-                 [0.421908, 0.805774, 0.351910],
-                 [0.430983, 0.808473, 0.346476],
-                 [0.440137, 0.811138, 0.340967],
-                 [0.449368, 0.813768, 0.335384],
-                 [0.458674, 0.816363, 0.329727],
-                 [0.468053, 0.818921, 0.323998],
-                 [0.477504, 0.821444, 0.318195],
-                 [0.487026, 0.823929, 0.312321],
-                 [0.496615, 0.826376, 0.306377],
-                 [0.506271, 0.828786, 0.300362],
-                 [0.515992, 0.831158, 0.294279],
-                 [0.525776, 0.833491, 0.288127],
-                 [0.535621, 0.835785, 0.281908],
-                 [0.545524, 0.838039, 0.275626],
-                 [0.555484, 0.840254, 0.269281],
-                 [0.565498, 0.842430, 0.262877],
-                 [0.575563, 0.844566, 0.256415],
-                 [0.585678, 0.846661, 0.249897],
-                 [0.595839, 0.848717, 0.243329],
-                 [0.606045, 0.850733, 0.236712],
-                 [0.616293, 0.852709, 0.230052],
-                 [0.626579, 0.854645, 0.223353],
-                 [0.636902, 0.856542, 0.216620],
-                 [0.647257, 0.858400, 0.209861],
-                 [0.657642, 0.860219, 0.203082],
-                 [0.668054, 0.861999, 0.196293],
-                 [0.678489, 0.863742, 0.189503],
-                 [0.688944, 0.865448, 0.182725],
-                 [0.699415, 0.867117, 0.175971],
-                 [0.709898, 0.868751, 0.169257],
-                 [0.720391, 0.870350, 0.162603],
-                 [0.730889, 0.871916, 0.156029],
-                 [0.741388, 0.873449, 0.149561],
-                 [0.751884, 0.874951, 0.143228],
-                 [0.762373, 0.876424, 0.137064],
-                 [0.772852, 0.877868, 0.131109],
-                 [0.783315, 0.879285, 0.125405],
-                 [0.793760, 0.880678, 0.120005],
-                 [0.804182, 0.882046, 0.114965],
-                 [0.814576, 0.883393, 0.110347],
-                 [0.824940, 0.884720, 0.106217],
-                 [0.835270, 0.886029, 0.102646],
-                 [0.845561, 0.887322, 0.099702],
-                 [0.855810, 0.888601, 0.097452],
-                 [0.866013, 0.889868, 0.095953],
-                 [0.876168, 0.891125, 0.095250],
-                 [0.886271, 0.892374, 0.095374],
-                 [0.896320, 0.893616, 0.096335],
-                 [0.906311, 0.894855, 0.098125],
-                 [0.916242, 0.896091, 0.100717],
-                 [0.926106, 0.897330, 0.104071],
-                 [0.935904, 0.898570, 0.108131],
-                 [0.945636, 0.899815, 0.112838],
-                 [0.955300, 0.901065, 0.118128],
-                 [0.964894, 0.902323, 0.123941],
-                 [0.974417, 0.903590, 0.130215],
-                 [0.983868, 0.904867, 0.136897],
-                 [0.993248, 0.906157, 0.143936]]
-
-_cividis_data = [[0.000000, 0.135112, 0.304751],
-                 [0.000000, 0.138068, 0.311105],
-                 [0.000000, 0.141013, 0.317579],
-                 [0.000000, 0.143951, 0.323982],
-                 [0.000000, 0.146877, 0.330479],
-                 [0.000000, 0.149791, 0.337065],
-                 [0.000000, 0.152673, 0.343704],
-                 [0.000000, 0.155377, 0.350500],
-                 [0.000000, 0.157932, 0.357521],
-                 [0.000000, 0.160495, 0.364534],
-                 [0.000000, 0.163058, 0.371608],
-                 [0.000000, 0.165621, 0.378769],
-                 [0.000000, 0.168204, 0.385902],
-                 [0.000000, 0.170800, 0.393100],
-                 [0.000000, 0.173420, 0.400353],
-                 [0.000000, 0.176082, 0.407577],
-                 [0.000000, 0.178802, 0.414764],
-                 [0.000000, 0.181610, 0.421859],
-                 [0.000000, 0.184550, 0.428802],
-                 [0.000000, 0.186915, 0.435532],
-                 [0.000000, 0.188769, 0.439563],
-                 [0.000000, 0.190950, 0.441085],
-                 [0.000000, 0.193366, 0.441561],
-                 [0.003602, 0.195911, 0.441564],
-                 [0.017852, 0.198528, 0.441248],
-                 [0.032110, 0.201199, 0.440785],
-                 [0.046205, 0.203903, 0.440196],
-                 [0.058378, 0.206629, 0.439531],
-                 [0.068968, 0.209372, 0.438863],
-                 [0.078624, 0.212122, 0.438105],
-                 [0.087465, 0.214879, 0.437342],
-                 [0.095645, 0.217643, 0.436593],
-                 [0.103401, 0.220406, 0.435790],
-                 [0.110658, 0.223170, 0.435067],
-                 [0.117612, 0.225935, 0.434308],
-                 [0.124291, 0.228697, 0.433547],
-                 [0.130669, 0.231458, 0.432840],
-                 [0.136830, 0.234216, 0.432148],
-                 [0.142852, 0.236972, 0.431404],
-                 [0.148638, 0.239724, 0.430752],
-                 [0.154261, 0.242475, 0.430120],
-                 [0.159733, 0.245221, 0.429528],
-                 [0.165113, 0.247965, 0.428908],
-                 [0.170362, 0.250707, 0.428325],
-                 [0.175490, 0.253444, 0.427790],
-                 [0.180503, 0.256180, 0.427299],
-                 [0.185453, 0.258914, 0.426788],
-                 [0.190303, 0.261644, 0.426329],
-                 [0.195057, 0.264372, 0.425924],
-                 [0.199764, 0.267099, 0.425497],
-                 [0.204385, 0.269823, 0.425126],
-                 [0.208926, 0.272546, 0.424809],
-                 [0.213431, 0.275266, 0.424480],
-                 [0.217863, 0.277985, 0.424206],
-                 [0.222264, 0.280702, 0.423914],
-                 [0.226598, 0.283419, 0.423678],
-                 [0.230871, 0.286134, 0.423498],
-                 [0.235120, 0.288848, 0.423304],
-                 [0.239312, 0.291562, 0.423167],
-                 [0.243485, 0.294274, 0.423014],
-                 [0.247605, 0.296986, 0.422917],
-                 [0.251675, 0.299698, 0.422873],
-                 [0.255731, 0.302409, 0.422814],
-                 [0.259740, 0.305120, 0.422810],
-                 [0.263738, 0.307831, 0.422789],
-                 [0.267693, 0.310542, 0.422821],
-                 [0.271639, 0.313253, 0.422837],
-                 [0.275513, 0.315965, 0.422979],
-                 [0.279411, 0.318677, 0.423031],
-                 [0.283240, 0.321390, 0.423211],
-                 [0.287065, 0.324103, 0.423373],
-                 [0.290884, 0.326816, 0.423517],
-                 [0.294669, 0.329531, 0.423716],
-                 [0.298421, 0.332247, 0.423973],
-                 [0.302169, 0.334963, 0.424213],
-                 [0.305886, 0.337681, 0.424512],
-                 [0.309601, 0.340399, 0.424790],
-                 [0.313287, 0.343120, 0.425120],
-                 [0.316941, 0.345842, 0.425512],
-                 [0.320595, 0.348565, 0.425889],
-                 [0.324250, 0.351289, 0.426250],
-                 [0.327875, 0.354016, 0.426670],
-                 [0.331474, 0.356744, 0.427144],
-                 [0.335073, 0.359474, 0.427605],
-                 [0.338673, 0.362206, 0.428053],
-                 [0.342246, 0.364939, 0.428559],
-                 [0.345793, 0.367676, 0.429127],
-                 [0.349341, 0.370414, 0.429685],
-                 [0.352892, 0.373153, 0.430226],
-                 [0.356418, 0.375896, 0.430823],
-                 [0.359916, 0.378641, 0.431501],
-                 [0.363446, 0.381388, 0.432075],
-                 [0.366923, 0.384139, 0.432796],
-                 [0.370430, 0.386890, 0.433428],
-                 [0.373884, 0.389646, 0.434209],
-                 [0.377371, 0.392404, 0.434890],
-                 [0.380830, 0.395164, 0.435653],
-                 [0.384268, 0.397928, 0.436475],
-                 [0.387705, 0.400694, 0.437305],
-                 [0.391151, 0.403464, 0.438096],
-                 [0.394568, 0.406236, 0.438986],
-                 [0.397991, 0.409011, 0.439848],
-                 [0.401418, 0.411790, 0.440708],
-                 [0.404820, 0.414572, 0.441642],
-                 [0.408226, 0.417357, 0.442570],
-                 [0.411607, 0.420145, 0.443577],
-                 [0.414992, 0.422937, 0.444578],
-                 [0.418383, 0.425733, 0.445560],
-                 [0.421748, 0.428531, 0.446640],
-                 [0.425120, 0.431334, 0.447692],
-                 [0.428462, 0.434140, 0.448864],
-                 [0.431817, 0.436950, 0.449982],
-                 [0.435168, 0.439763, 0.451134],
-                 [0.438504, 0.442580, 0.452341],
-                 [0.441810, 0.445402, 0.453659],
-                 [0.445148, 0.448226, 0.454885],
-                 [0.448447, 0.451053, 0.456264],
-                 [0.451759, 0.453887, 0.457582],
-                 [0.455072, 0.456718, 0.458976],
-                 [0.458366, 0.459552, 0.460457],
-                 [0.461616, 0.462405, 0.461969],
-                 [0.464947, 0.465241, 0.463395],
-                 [0.468254, 0.468083, 0.464908],
-                 [0.471501, 0.470960, 0.466357],
-                 [0.474812, 0.473832, 0.467681],
-                 [0.478186, 0.476699, 0.468845],
-                 [0.481622, 0.479573, 0.469767],
-                 [0.485141, 0.482451, 0.470384],
-                 [0.488697, 0.485318, 0.471008],
-                 [0.492278, 0.488198, 0.471453],
-                 [0.495913, 0.491076, 0.471751],
-                 [0.499552, 0.493960, 0.472032],
-                 [0.503185, 0.496851, 0.472305],
-                 [0.506866, 0.499743, 0.472432],
-                 [0.510540, 0.502643, 0.472550],
-                 [0.514226, 0.505546, 0.472640],
-                 [0.517920, 0.508454, 0.472707],
-                 [0.521643, 0.511367, 0.472639],
-                 [0.525348, 0.514285, 0.472660],
-                 [0.529086, 0.517207, 0.472543],
-                 [0.532829, 0.520135, 0.472401],
-                 [0.536553, 0.523067, 0.472352],
-                 [0.540307, 0.526005, 0.472163],
-                 [0.544069, 0.528948, 0.471947],
-                 [0.547840, 0.531895, 0.471704],
-                 [0.551612, 0.534849, 0.471439],
-                 [0.555393, 0.537807, 0.471147],
-                 [0.559181, 0.540771, 0.470829],
-                 [0.562972, 0.543741, 0.470488],
-                 [0.566802, 0.546715, 0.469988],
-                 [0.570607, 0.549695, 0.469593],
-                 [0.574417, 0.552682, 0.469172],
-                 [0.578236, 0.555673, 0.468724],
-                 [0.582087, 0.558670, 0.468118],
-                 [0.585916, 0.561674, 0.467618],
-                 [0.589753, 0.564682, 0.467090],
-                 [0.593622, 0.567697, 0.466401],
-                 [0.597469, 0.570718, 0.465821],
-                 [0.601354, 0.573743, 0.465074],
-                 [0.605211, 0.576777, 0.464441],
-                 [0.609105, 0.579816, 0.463638],
-                 [0.612977, 0.582861, 0.462950],
-                 [0.616852, 0.585913, 0.462237],
-                 [0.620765, 0.588970, 0.461351],
-                 [0.624654, 0.592034, 0.460583],
-                 [0.628576, 0.595104, 0.459641],
-                 [0.632506, 0.598180, 0.458668],
-                 [0.636412, 0.601264, 0.457818],
-                 [0.640352, 0.604354, 0.456791],
-                 [0.644270, 0.607450, 0.455886],
-                 [0.648222, 0.610553, 0.454801],
-                 [0.652178, 0.613664, 0.453689],
-                 [0.656114, 0.616780, 0.452702],
-                 [0.660082, 0.619904, 0.451534],
-                 [0.664055, 0.623034, 0.450338],
-                 [0.668008, 0.626171, 0.449270],
-                 [0.671991, 0.629316, 0.448018],
-                 [0.675981, 0.632468, 0.446736],
-                 [0.679979, 0.635626, 0.445424],
-                 [0.683950, 0.638793, 0.444251],
-                 [0.687957, 0.641966, 0.442886],
-                 [0.691971, 0.645145, 0.441491],
-                 [0.695985, 0.648334, 0.440072],
-                 [0.700008, 0.651529, 0.438624],
-                 [0.704037, 0.654731, 0.437147],
-                 [0.708067, 0.657942, 0.435647],
-                 [0.712105, 0.661160, 0.434117],
-                 [0.716177, 0.664384, 0.432386],
-                 [0.720222, 0.667618, 0.430805],
-                 [0.724274, 0.670859, 0.429194],
-                 [0.728334, 0.674107, 0.427554],
-                 [0.732422, 0.677364, 0.425717],
-                 [0.736488, 0.680629, 0.424028],
-                 [0.740589, 0.683900, 0.422131],
-                 [0.744664, 0.687181, 0.420393],
-                 [0.748772, 0.690470, 0.418448],
-                 [0.752886, 0.693766, 0.416472],
-                 [0.756975, 0.697071, 0.414659],
-                 [0.761096, 0.700384, 0.412638],
-                 [0.765223, 0.703705, 0.410587],
-                 [0.769353, 0.707035, 0.408516],
-                 [0.773486, 0.710373, 0.406422],
-                 [0.777651, 0.713719, 0.404112],
-                 [0.781795, 0.717074, 0.401966],
-                 [0.785965, 0.720438, 0.399613],
-                 [0.790116, 0.723810, 0.397423],
-                 [0.794298, 0.727190, 0.395016],
-                 [0.798480, 0.730580, 0.392597],
-                 [0.802667, 0.733978, 0.390153],
-                 [0.806859, 0.737385, 0.387684],
-                 [0.811054, 0.740801, 0.385198],
-                 [0.815274, 0.744226, 0.382504],
-                 [0.819499, 0.747659, 0.379785],
-                 [0.823729, 0.751101, 0.377043],
-                 [0.827959, 0.754553, 0.374292],
-                 [0.832192, 0.758014, 0.371529],
-                 [0.836429, 0.761483, 0.368747],
-                 [0.840693, 0.764962, 0.365746],
-                 [0.844957, 0.768450, 0.362741],
-                 [0.849223, 0.771947, 0.359729],
-                 [0.853515, 0.775454, 0.356500],
-                 [0.857809, 0.778969, 0.353259],
-                 [0.862105, 0.782494, 0.350011],
-                 [0.866421, 0.786028, 0.346571],
-                 [0.870717, 0.789572, 0.343333],
-                 [0.875057, 0.793125, 0.339685],
-                 [0.879378, 0.796687, 0.336241],
-                 [0.883720, 0.800258, 0.332599],
-                 [0.888081, 0.803839, 0.328770],
-                 [0.892440, 0.807430, 0.324968],
-                 [0.896818, 0.811030, 0.320982],
-                 [0.901195, 0.814639, 0.317021],
-                 [0.905589, 0.818257, 0.312889],
-                 [0.910000, 0.821885, 0.308594],
-                 [0.914407, 0.825522, 0.304348],
-                 [0.918828, 0.829168, 0.299960],
-                 [0.923279, 0.832822, 0.295244],
-                 [0.927724, 0.836486, 0.290611],
-                 [0.932180, 0.840159, 0.285880],
-                 [0.936660, 0.843841, 0.280876],
-                 [0.941147, 0.847530, 0.275815],
-                 [0.945654, 0.851228, 0.270532],
-                 [0.950178, 0.854933, 0.265085],
-                 [0.954725, 0.858646, 0.259365],
-                 [0.959284, 0.862365, 0.253563],
-                 [0.963872, 0.866089, 0.247445],
-                 [0.968469, 0.869819, 0.241310],
-                 [0.973114, 0.873550, 0.234677],
-                 [0.977780, 0.877281, 0.227954],
-                 [0.982497, 0.881008, 0.220878],
-                 [0.987293, 0.884718, 0.213336],
-                 [0.992218, 0.888385, 0.205468],
-                 [0.994847, 0.892954, 0.203445],
-                 [0.995249, 0.898384, 0.207561],
-                 [0.995503, 0.903866, 0.212370],
-                 [0.995737, 0.909344, 0.217772]]
-
-_twilight_data = [
-    [0.88575015840754434, 0.85000924943067835,  0.8879736506427196],
-    [0.88378520195539056, 0.85072940540310626,  0.88723222096949894],
-    [0.88172231059285788, 0.85127594077653468,  0.88638056925514819],
-    [0.8795410528270573,  0.85165675407495722,  0.8854143767924102],
-    [0.87724880858965482, 0.85187028338870274,  0.88434120381311432],
-    [0.87485347508575972, 0.85191526123023187,  0.88316926967613829],
-    [0.87233134085124076, 0.85180165478080894,  0.88189704355001619],
-    [0.86970474853509816, 0.85152403004797894,  0.88053883390003362],
-    [0.86696015505333579, 0.8510896085314068,   0.87909766977173343],
-    [0.86408985081463996, 0.85050391167507788,  0.87757925784892632],
-    [0.86110245436899846, 0.84976754857001258,  0.87599242923439569],
-    [0.85798259245670372, 0.84888934810281835,  0.87434038553446281],
-    [0.85472593189256985, 0.84787488124672816,  0.8726282980930582],
-    [0.85133714570857189, 0.84672735796116472,  0.87086081657350445],
-    [0.84780710702577922, 0.8454546229209523,   0.86904036783694438],
-    [0.8441261828674842,  0.84406482711037389,  0.86716973322690072],
-    [0.84030420805957784, 0.8425605950855084,   0.865250882410458],
-    [0.83634031809191178, 0.84094796518951942,  0.86328528001070159],
-    [0.83222705712934408, 0.83923490627754482,  0.86127563500427884],
-    [0.82796894316013536, 0.83742600751395202,  0.85922399451306786],
-    [0.82357429680252847, 0.83552487764795436,  0.85713191328514948],
-    [0.81904654677937527, 0.8335364929949034,   0.85500206287010105],
-    [0.81438982121143089, 0.83146558694197847,  0.85283759062147024],
-    [0.8095999819094809,  0.82931896673505456,  0.85064441601050367],
-    [0.80469164429814577, 0.82709838780560663,  0.84842449296974021],
-    [0.79967075421267997, 0.82480781812080928,  0.84618210029578533],
-    [0.79454305089231114, 0.82245116226304615,  0.84392184786827984],
-    [0.78931445564608915, 0.82003213188702007,  0.8416486380471222],
-    [0.78399101042764918, 0.81755426400533426,  0.83936747464036732],
-    [0.77857892008227592, 0.81502089378742548,  0.8370834463093898],
-    [0.77308416590170936, 0.81243524735466011,  0.83480172950579679],
-    [0.76751108504417864, 0.8098007598713145,   0.83252816638059668],
-    [0.76186907937980286, 0.80711949387647486,  0.830266486168872],
-    [0.75616443584381976, 0.80439408733477935,  0.82802138994719998],
-    [0.75040346765406696, 0.80162699008965321,  0.82579737851082424],
-    [0.74459247771890169, 0.79882047719583249,  0.82359867586156521],
-    [0.73873771700494939, 0.79597665735031009,  0.82142922780433014],
-    [0.73284543645523459, 0.79309746468844067,  0.81929263384230377],
-    [0.72692177512829703, 0.7901846863592763,   0.81719217466726379],
-    [0.72097280665536778, 0.78723995923452639,  0.81513073920879264],
-    [0.71500403076252128, 0.78426487091581187,  0.81311116559949914],
-    [0.70902078134539304, 0.78126088716070907,  0.81113591855117928],
-    [0.7030297722540817,  0.77822904973358131,  0.80920618848056969],
-    [0.6970365443886174,  0.77517050008066057,  0.80732335380063447],
-    [0.69104641009309098, 0.77208629460678091,  0.80548841690679074],
-    [0.68506446154395928, 0.7689774029354699,   0.80370206267176914],
-    [0.67909554499882152, 0.76584472131395898,  0.8019646617300199],
-    [0.67314422559426212, 0.76268908733890484,  0.80027628545809526],
-    [0.66721479803752815, 0.7595112803730375,   0.79863674654537764],
-    [0.6613112930078745,  0.75631202708719025,  0.7970456043491897],
-    [0.65543692326454717, 0.75309208756768431,  0.79550271129031047],
-    [0.64959573004253479, 0.74985201221941766,  0.79400674021499107],
-    [0.6437910831099849,  0.7465923800833657,   0.79255653201306053],
-    [0.63802586828545982, 0.74331376714033193,  0.79115100459573173],
-    [0.6323027138710603,  0.74001672160131404,  0.78978892762640429],
-    [0.62662402022604591, 0.73670175403699445,  0.78846901316334561],
-    [0.62099193064817548, 0.73336934798923203,  0.78718994624696581],
-    [0.61540846411770478, 0.73001995232739691,  0.78595022706750484],
-    [0.60987543176093062, 0.72665398759758293,  0.78474835732694714],
-    [0.60439434200274855, 0.7232718614323369,   0.78358295593535587],
-    [0.5989665814482068,  0.71987394892246725,  0.78245259899346642],
-    [0.59359335696837223, 0.7164606049658685,   0.78135588237640097],
-    [0.58827579780555495, 0.71303214646458135,  0.78029141405636515],
-    [0.58301487036932409, 0.70958887676997473,  0.77925781820476592],
-    [0.5778116438998202,  0.70613106157153982,  0.77825345121025524],
-    [0.5726668948158774,  0.7026589535425779,   0.77727702680911992],
-    [0.56758117853861967, 0.69917279302646274,  0.77632748534275298],
-    [0.56255515357219343, 0.69567278381629649,  0.77540359142309845],
-    [0.55758940419605174, 0.69215911458254054,  0.7745041337932782],
-    [0.55268450589347129, 0.68863194515166382,  0.7736279426902245],
-    [0.54784098153018634, 0.68509142218509878,  0.77277386473440868],
-    [0.54305932424018233, 0.68153767253065878,  0.77194079697835083],
-    [0.53834015575176275, 0.67797081129095405,  0.77112734439057717],
-    [0.53368389147728401, 0.67439093705212727,  0.7703325054879735],
-    [0.529090861832473,   0.67079812302806219,  0.76955552292313134],
-    [0.52456151470593582, 0.66719242996142225,  0.76879541714230948],
-    [0.52009627392235558, 0.66357391434030388,  0.76805119403344102],
-    [0.5156955988596057,  0.65994260812897998,  0.76732191489596169],
-    [0.51135992541601927, 0.65629853981831865,  0.76660663780645333],
-    [0.50708969576451657, 0.65264172403146448,  0.76590445660835849],
-    [0.5028853540415561,  0.64897216734095264,  0.76521446718174913],
-    [0.49874733661356069, 0.6452898684900934,   0.76453578734180083],
-    [0.4946761847863938,  0.64159484119504429,  0.76386719002130909],
-    [0.49067224938561221, 0.63788704858847078,  0.76320812763163837],
-    [0.4867359599430568,  0.63416646251100506,  0.76255780085924041],
-    [0.4828677867260272,  0.6304330455306234,   0.76191537149895305],
-    [0.47906816236197386, 0.62668676251860134,  0.76128000375662419],
-    [0.47533752394906287, 0.62292757283835809,  0.76065085571817748],
-    [0.47167629518877091, 0.61915543242884641,  0.76002709227883047],
-    [0.46808490970531597, 0.61537028695790286,  0.75940789891092741],
-    [0.46456376716303932, 0.61157208822864151,  0.75879242623025811],
-    [0.46111326647023881, 0.607760777169989,    0.75817986436807139],
-    [0.45773377230160567, 0.60393630046586455,  0.75756936901859162],
-    [0.45442563977552913, 0.60009859503858665,  0.75696013660606487],
-    [0.45118918687617743, 0.59624762051353541,  0.75635120643246645],
-    [0.44802470933589172, 0.59238331452146575,  0.75574176474107924],
-    [0.44493246854215379, 0.5885055998308617,   0.7551311041857901],
-    [0.44191271766696399, 0.58461441100175571,  0.75451838884410671],
-    [0.43896563958048396, 0.58070969241098491,  0.75390276208285945],
-    [0.43609138958356369, 0.57679137998186081,  0.7532834105961016],
-    [0.43329008867358393, 0.57285941625606673,  0.75265946532566674],
-    [0.43056179073057571, 0.56891374572457176,  0.75203008099312696],
-    [0.42790652284925834, 0.5649543060909209,   0.75139443521914839],
-    [0.42532423665011354, 0.56098104959950301,  0.75075164989005116],
-    [0.42281485675772662, 0.55699392126996583,  0.75010086988227642],
-    [0.42037822361396326, 0.55299287158108168,  0.7494412559451894],
-    [0.41801414079233629, 0.54897785421888889,  0.74877193167001121],
-    [0.4157223260454232,  0.54494882715350401,  0.74809204459000522],
-    [0.41350245743314729, 0.54090574771098476,  0.74740073297543086],
-    [0.41135414697304568, 0.53684857765005933,  0.74669712855065784],
-    [0.4092768899914751,  0.53277730177130322,  0.74598030635707824],
-    [0.40727018694219069, 0.52869188011057411,  0.74524942637581271],
-    [0.40533343789303178, 0.52459228174983119,  0.74450365836708132],
-    [0.40346600333905397, 0.52047847653840029,  0.74374215223567086],
-    [0.40166714010896104, 0.51635044969688759,  0.7429640345324835],
-    [0.39993606933454834, 0.51220818143218516,  0.74216844571317986],
-    [0.3982719152586337,  0.50805166539276136,  0.74135450918099721],
-    [0.39667374905665609, 0.50388089053847973,  0.74052138580516735],
-    [0.39514058808207631, 0.49969585326377758,  0.73966820211715711],
-    [0.39367135736822567, 0.49549655777451179,  0.738794102296364],
-    [0.39226494876209317, 0.49128300332899261,  0.73789824784475078],
-    [0.39092017571994903, 0.48705520251223039,  0.73697977133881254],
-    [0.38963580160340855, 0.48281316715123496,  0.73603782546932739],
-    [0.38841053300842432, 0.47855691131792805,  0.73507157641157261],
-    [0.38724301459330251, 0.47428645933635388,  0.73408016787854391],
-    [0.38613184178892102, 0.4700018340988123,   0.7330627749243106],
-    [0.38507556793651387, 0.46570306719930193,  0.73201854033690505],
-    [0.38407269378943537, 0.46139018782416635,  0.73094665432902683],
-    [0.38312168084402748, 0.45706323581407199,  0.72984626791353258],
-    [0.38222094988570376, 0.45272225034283325,  0.72871656144003782],
-    [0.38136887930454161, 0.44836727669277859,  0.72755671317141346],
-    [0.38056380696565623, 0.44399837208633719,  0.72636587045135315],
-    [0.37980403744848751, 0.43961558821222629,  0.72514323778761092],
-    [0.37908789283110761, 0.43521897612544935,  0.72388798691323131],
-    [0.378413635091359,   0.43080859411413064,  0.72259931993061044],
-    [0.37777949753513729, 0.4263845142616835,   0.72127639993530235],
-    [0.37718371844251231, 0.42194680223454828,  0.71991841524475775],
-    [0.37662448930806297, 0.41749553747893614,  0.71852454736176108],
-    [0.37610001286385814, 0.41303079952477062,  0.71709396919920232],
-    [0.37560846919442398, 0.40855267638072096,  0.71562585091587549],
-    [0.37514802505380473, 0.4040612609993941,   0.7141193695725726],
-    [0.37471686019302231, 0.3995566498711684,   0.71257368516500463],
-    [0.37431313199312338, 0.39503894828283309,  0.71098796522377461],
-    [0.37393499330475782, 0.39050827529375831,  0.70936134293478448],
-    [0.3735806215098284,  0.38596474386057539,  0.70769297607310577],
-    [0.37324816143326384, 0.38140848555753937,  0.70598200974806036],
-    [0.37293578646665032, 0.37683963835219841,  0.70422755780589941],
-    [0.37264166757849604, 0.37225835004836849,  0.7024287314570723],
-    [0.37236397858465387, 0.36766477862108266,  0.70058463496520773],
-    [0.37210089702443822, 0.36305909736982378,  0.69869434615073722],
-    [0.3718506155898596,  0.35844148285875221,  0.69675695810256544],
-    [0.37161133234400479, 0.3538121372967869,   0.69477149919380887],
-    [0.37138124223736607, 0.34917126878479027,  0.69273703471928827],
-    [0.37115856636209105, 0.34451911410230168,  0.69065253586464992],
-    [0.37094151551337329, 0.33985591488818123,  0.68851703379505125],
-    [0.37072833279422668, 0.33518193808489577,  0.68632948169606767],
-    [0.37051738634484427, 0.33049741244307851,  0.68408888788857214],
-    [0.37030682071842685, 0.32580269697872455,  0.68179411684486679],
-    [0.37009487130772695, 0.3210981375964933,   0.67944405399056851],
-    [0.36987980329025361, 0.31638410101153364,  0.67703755438090574],
-    [0.36965987626565955, 0.31166098762951971,  0.67457344743419545],
-    [0.36943334591276228, 0.30692923551862339,  0.67205052849120617],
-    [0.36919847837592484, 0.30218932176507068,  0.66946754331614522],
-    [0.36895355306596778, 0.29744175492366276,  0.66682322089824264],
-    [0.36869682231895268, 0.29268709856150099,  0.66411625298236909],
-    [0.36842655638020444, 0.28792596437778462,  0.66134526910944602],
-    [0.36814101479899719, 0.28315901221182987,  0.65850888806972308],
-    [0.36783843696531082, 0.27838697181297761,  0.65560566838453704],
-    [0.36751707094367697, 0.27361063317090978,  0.65263411711618635],
-    [0.36717513650699446, 0.26883085667326956,  0.64959272297892245],
-    [0.36681085540107988, 0.26404857724525643,  0.64647991652908243],
-    [0.36642243251550632, 0.25926481158628106,  0.64329409140765537],
-    [0.36600853966739794, 0.25448043878086224,  0.64003361803368586],
-    [0.36556698373538982, 0.24969683475296395,  0.63669675187488584],
-    [0.36509579845886808, 0.24491536803550484,  0.63328173520055586],
-    [0.36459308890125008, 0.24013747024823828,  0.62978680155026101],
-    [0.36405693022088509, 0.23536470386204195,  0.62621013451953023],
-    [0.36348537610385145, 0.23059876218396419,  0.62254988622392882],
-    [0.36287643560041027, 0.22584149293287031,  0.61880417410823019],
-    [0.36222809558295926, 0.22109488427338303,  0.61497112346096128],
-    [0.36153829010998356, 0.21636111429594002,  0.61104880679640927],
-    [0.36080493826624654, 0.21164251793458128,  0.60703532172064711],
-    [0.36002681809096376, 0.20694122817889948,  0.60292845431916875],
-    [0.35920088560930186, 0.20226037920758122,  0.5987265295935138],
-    [0.35832489966617809, 0.197602942459778,    0.59442768517501066],
-    [0.35739663292915563, 0.19297208197842461,  0.59003011251063131],
-    [0.35641381143126327, 0.18837119869242164,  0.5855320765920552],
-    [0.35537415306906722, 0.18380392577704466,  0.58093191431832802],
-    [0.35427534960663759, 0.17927413271618647,  0.57622809660668717],
-    [0.35311574421123737, 0.17478570377561287,  0.57141871523555288],
-    [0.35189248608873791, 0.17034320478524959,  0.56650284911216653],
-    [0.35060304441931012, 0.16595129984720861,  0.56147964703993225],
-    [0.34924513554955644, 0.16161477763045118,  0.55634837474163779],
-    [0.34781653238777782, 0.15733863511152979,  0.55110853452703257],
-    [0.34631507175793091, 0.15312802296627787,  0.5457599924248665],
-    [0.34473901574536375, 0.14898820589826409,  0.54030245920406539],
-    [0.34308600291572294, 0.14492465359918028,  0.53473704282067103],
-    [0.34135411074506483, 0.1409427920655632,   0.52906500940336754],
-    [0.33954168752669694, 0.13704801896718169,  0.52328797535085236],
-    [0.33764732090671112, 0.13324562282438077,  0.51740807573979475],
-    [0.33566978565015315, 0.12954074251271822,  0.51142807215168951],
-    [0.33360804901486002, 0.12593818301005921,  0.50535164796654897],
-    [0.33146154891145124, 0.12244245263391232,  0.49918274588431072],
-    [0.32923005203231409, 0.11905764321981127,  0.49292595612342666],
-    [0.3269137124539796,  0.1157873496841953,   0.48658646495697461],
-    [0.32451307931207785, 0.11263459791730848,  0.48017007211645196],
-    [0.32202882276069322, 0.10960114111258401,  0.47368494725726878],
-    [0.31946262395497965, 0.10668879882392659,  0.46713728801395243],
-    [0.31681648089023501, 0.10389861387653518,  0.46053414662739794],
-    [0.31409278414755532, 0.10123077676403242,  0.45388335612058467],
-    [0.31129434479712365, 0.098684771934052201, 0.44719313715161618],
-    [0.30842444457210105, 0.096259385340577736, 0.44047194882050544],
-    [0.30548675819945936, 0.093952764840823738, 0.43372849999361113],
-    [0.30248536364574252, 0.091761187397303601, 0.42697404043749887],
-    [0.29942483960214772, 0.089682253716750038, 0.42021619665853854],
-    [0.29631000388905288, 0.087713250960463951, 0.41346259134143476],
-    [0.29314593096985248, 0.085850656889620708, 0.40672178082365834],
-    [0.28993792445176608, 0.08409078829085731,  0.40000214725256295],
-    [0.28669151388283165, 0.082429873848480689, 0.39331182532243375],
-    [0.28341239797185225, 0.080864153365499375, 0.38665868550105914],
-    [0.28010638576975472, 0.079389994802261526, 0.38005028528138707],
-    [0.27677939615815589, 0.078003941033788216, 0.37349382846504675],
-    [0.27343739342450812, 0.076702800237496066, 0.36699616136347685],
-    [0.27008637749114051, 0.075483675584275545, 0.36056376228111864],
-    [0.26673233211995284, 0.074344018028546205, 0.35420276066240958],
-    [0.26338121807151404, 0.073281657939897077, 0.34791888996380105],
-    [0.26003895187439957, 0.072294781043362205, 0.3417175669546984],
-    [0.25671191651083902, 0.071380106242082242, 0.33560648984600089],
-    [0.25340685873736807, 0.070533582926851829, 0.3295945757321303],
-    [0.25012845306199383, 0.069758206429106989, 0.32368100685760637],
-    [0.24688226237958999, 0.069053639449204451, 0.31786993834254956],
-    [0.24367372557466271, 0.068419855150922693, 0.31216524050888372],
-    [0.24050813332295939, 0.067857103814855602, 0.30657054493678321],
-    [0.23739062429054825, 0.067365888050555517, 0.30108922184065873],
-    [0.23433055727563878, 0.066935599661639394, 0.29574009929867601],
-    [0.23132955273021344, 0.066576186939090592, 0.29051361067988485],
-    [0.2283917709422868,  0.06628997924139618,  0.28541074411068496],
-    [0.22552164337737857, 0.066078173119395595, 0.28043398847505197],
-    [0.22272706739121817, 0.065933790675651943, 0.27559714652053702],
-    [0.22001251100779617, 0.065857918918907604, 0.27090279994325861],
-    [0.21737845072382705, 0.065859661233562045, 0.26634209349669508],
-    [0.21482843531473683, 0.065940385613778491, 0.26191675992376573],
-    [0.21237411048541005, 0.066085024661758446, 0.25765165093569542],
-    [0.21001214221188125, 0.066308573918947178, 0.2535289048041211],
-    [0.2077442377448806,  0.06661453200418091,  0.24954644291943817],
-    [0.20558051999470117, 0.066990462397868739, 0.24572497420147632],
-    [0.20352007949514977, 0.067444179612424215, 0.24205576625191821],
-    [0.20156133764129841, 0.067983271026200248, 0.23852974228695395],
-    [0.19971571438603364, 0.068592710553704722, 0.23517094067076993],
-    [0.19794834061899208, 0.069314066071660657, 0.23194647381302336],
-    [0.1960826032659409,  0.070321227242423623, 0.22874673279569585],
-    [0.19410351363791453, 0.071608304856891569, 0.22558727307410353],
-    [0.19199449184606268, 0.073182830649273306, 0.22243385243433622],
-    [0.18975853639094634, 0.075019861862143766, 0.2193005075652994],
-    [0.18739228342697645, 0.077102096899588329, 0.21618875376309582],
-    [0.18488035509396164, 0.079425730279723883, 0.21307651648984993],
-    [0.18774482037046955, 0.077251588468039312, 0.21387448578597812],
-    [0.19049578401722037, 0.075311278416787641, 0.2146562337112265],
-    [0.1931548636579131,  0.073606819040117955, 0.21542362939081539],
-    [0.19571853588267552, 0.072157781039602742, 0.21617499187076789],
-    [0.19819343656336558, 0.070974625252738788, 0.21690975060032436],
-    [0.20058760685133747, 0.070064576149984209, 0.21762721310371608],
-    [0.20290365333558247, 0.069435248580458964, 0.21833167885096033],
-    [0.20531725273301316, 0.068919592266397572, 0.21911516689288835],
-    [0.20785704662965598, 0.068484398797025281, 0.22000133917653536],
-    [0.21052882914958676, 0.06812195249816172,  0.22098759107715404],
-    [0.2133313859647627,  0.067830148426026665, 0.22207043213024291],
-    [0.21625279838647882, 0.067616330270516389, 0.22324568672294431],
-    [0.21930503925136402, 0.067465786362940039, 0.22451023616807558],
-    [0.22247308588973624, 0.067388214053092838, 0.22585960379408354],
-    [0.2257539681670791,  0.067382132300147474, 0.22728984778098055],
-    [0.22915620278592841, 0.067434730871152565, 0.22879681433956656],
-    [0.23266299920501882, 0.067557104388479783, 0.23037617493752832],
-    [0.23627495835774248, 0.06774359820987802,  0.23202360805926608],
-    [0.23999586188690308, 0.067985029964779953, 0.23373434258507808],
-    [0.24381149720247919, 0.068289851529011875, 0.23550427698321885],
-    [0.24772092990501099, 0.068653337909486523, 0.2373288009471749],
-    [0.25172899728289466, 0.069064630826035506, 0.23920260612763083],
-    [0.25582135547481771, 0.06953231029187984,  0.24112190491594204],
-    [0.25999463887892144, 0.070053855603861875, 0.24308218808684579],
-    [0.26425512207060942, 0.070616595622995437, 0.24507758869355967],
-    [0.26859095948172862, 0.071226716277922458, 0.24710443563450618],
-    [0.27299701518897301, 0.071883555446163511, 0.24915847093232929],
-    [0.27747150809142801, 0.072582969899254779, 0.25123493995942769],
-    [0.28201746297366942, 0.073315693214040967, 0.25332800295084507],
-    [0.28662309235899847, 0.074088460826808866, 0.25543478673717029],
-    [0.29128515387578635, 0.074899049847466703, 0.25755101595750435],
-    [0.2960004726065818,  0.075745336000958424, 0.25967245030364566],
-    [0.30077276812918691, 0.076617824336164764, 0.26179294097819672],
-    [0.30559226007249934, 0.077521963107537312, 0.26391006692119662],
-    [0.31045520848595526, 0.078456871676182177, 0.2660200572779356],
-    [0.31535870009205808, 0.079420997315243186, 0.26811904076941961],
-    [0.32029986557994061, 0.080412994737554838, 0.27020322893039511],
-    [0.32527888860401261, 0.081428390076546092, 0.27226772884656186],
-    [0.33029174471181438, 0.08246763389003825,  0.27430929404579435],
-    [0.33533353224455448, 0.083532434119003962, 0.27632534356790039],
-    [0.34040164359597463, 0.084622236191702671, 0.27831254595259397],
-    [0.34549355713871799, 0.085736654965126335, 0.28026769921081435],
-    [0.35060678246032478, 0.08687555176033529,  0.28218770540182386],
-    [0.35573889947341125, 0.088038974350243354, 0.2840695897279818],
-    [0.36088752387578377, 0.089227194362745205, 0.28591050458531014],
-    [0.36605031412464006, 0.090440685427697898, 0.2877077458811747],
-    [0.37122508431309342, 0.091679997480262732, 0.28945865397633169],
-    [0.3764103053221462,  0.092945198093777909, 0.29116024157313919],
-    [0.38160247377467543, 0.094238731263712183, 0.29281107506269488],
-    [0.38679939079544168, 0.09556181960083443,  0.29440901248173756],
-    [0.39199887556812907, 0.09691583650296684,  0.29595212005509081],
-    [0.39719876876325577, 0.098302320968278623, 0.29743856476285779],
-    [0.40239692379737496, 0.099722930314950553, 0.29886674369733968],
-    [0.40759120392688708, 0.10117945586419633,  0.30023519507728602],
-    [0.41277985630360303, 0.1026734006932461,   0.30154226437468967],
-    [0.41796105205173684, 0.10420644885760968,  0.30278652039631843],
-    [0.42313214269556043, 0.10578120994917611,  0.3039675809469457],
-    [0.42829101315789753, 0.1073997763055258,   0.30508479060294547],
-    [0.4334355841041439,  0.1090642347484701,   0.30613767928289148],
-    [0.43856378187931538, 0.11077667828375456,  0.30712600062348083],
-    [0.44367358645071275, 0.11253912421257944,  0.30804973095465449],
-    [0.44876299173174822, 0.11435355574622549,  0.30890905921943196],
-    [0.45383005086999889, 0.11622183788331528,  0.30970441249844921],
-    [0.45887288947308297, 0.11814571137706886,  0.31043636979038808],
-    [0.46389102840284874, 0.12012561256850712,  0.31110343446582983],
-    [0.46888111384598413, 0.12216445576414045,  0.31170911458932665],
-    [0.473841437035254,   0.12426354237989065,  0.31225470169927194],
-    [0.47877034239726296, 0.12642401401409453,  0.31274172735821959],
-    [0.48366628618847957, 0.12864679022013889,  0.31317188565991266],
-    [0.48852847371852987, 0.13093210934893723,  0.31354553695453014],
-    [0.49335504375145617, 0.13328091630401023,  0.31386561956734976],
-    [0.49814435462074153, 0.13569380302451714,  0.314135190862664],
-    [0.50289524974970612, 0.13817086581280427,  0.31435662153833671],
-    [0.50760681181053691, 0.14071192654913128,  0.31453200120082569],
-    [0.51227835105321762, 0.14331656120063752,  0.3146630922831542],
-    [0.51690848800544464, 0.14598463068714407,  0.31475407592280041],
-    [0.52149652863229956, 0.14871544765633712,  0.31480767954534428],
-    [0.52604189625477482, 0.15150818660835483,  0.31482653406646727],
-    [0.53054420489856446, 0.15436183633886777,  0.31481299789187128],
-    [0.5350027976174474,  0.15727540775107324,  0.31477085207396532],
-    [0.53941736649199057, 0.16024769309971934,  0.31470295028655965],
-    [0.54378771313608565, 0.16327738551419116,  0.31461204226295625],
-    [0.54811370033467621, 0.1663630904279047,   0.31450102990914708],
-    [0.55239521572711914, 0.16950338809328983,  0.31437291554615371],
-    [0.55663229034969341, 0.17269677158182117,  0.31423043195101424],
-    [0.56082499039117173, 0.17594170887918095,  0.31407639883970623],
-    [0.56497343529017696, 0.17923664950367169,  0.3139136046337036],
-    [0.56907784784011428, 0.18258004462335425,  0.31374440956796529],
-    [0.57313845754107873, 0.18597036007065024,  0.31357126868520002],
-    [0.57715550812992045, 0.18940601489760422,  0.31339704333572083],
-    [0.58112932761586555, 0.19288548904692518,  0.31322399394183942],
-    [0.58506024396466882, 0.19640737049066315,  0.31305401163732732],
-    [0.58894861935544707, 0.19997020971775276,  0.31288922211590126],
-    [0.59279480536520257, 0.20357251410079796,  0.31273234839304942],
-    [0.59659918109122367, 0.207212956082026,    0.31258523031121233],
-    [0.60036213010411577, 0.21089030138947745,  0.31244934410414688],
-    [0.60408401696732739, 0.21460331490206347,  0.31232652641170694],
-    [0.60776523994818654, 0.21835070166659282,  0.31221903291870201],
-    [0.6114062072731884,  0.22213124697023234,  0.31212881396435238],
-    [0.61500723236391375, 0.22594402043981826,  0.31205680685765741],
-    [0.61856865258877192, 0.22978799249179921,  0.31200463838728931],
-    [0.62209079821082613, 0.2336621873300741,   0.31197383273627388],
-    [0.62557416500434959, 0.23756535071152696,  0.31196698314912269],
-    [0.62901892016985872, 0.24149689191922535,  0.31198447195645718],
-    [0.63242534854210275, 0.24545598775548677,  0.31202765974624452],
-    [0.6357937104834237,  0.24944185818822678,  0.31209793953300591],
-    [0.6391243387840212,  0.25345365461983138,  0.31219689612063978],
-    [0.642417577481186,   0.257490519876798,    0.31232631707560987],
-    [0.64567349382645434, 0.26155203161615281,  0.31248673753935263],
-    [0.64889230169458245, 0.26563755336209077,  0.31267941819570189],
-    [0.65207417290277303, 0.26974650525236699,  0.31290560605819168],
-    [0.65521932609327127, 0.27387826652410152,  0.3131666792687211],
-    [0.6583280801134499,  0.27803210957665631,  0.3134643447952643],
-    [0.66140037532601781, 0.28220778870555907,  0.31379912926498488],
-    [0.66443632469878844, 0.28640483614256179,  0.31417223403606975],
-    [0.66743603766369131, 0.29062280081258873,  0.31458483752056837],
-    [0.67039959547676198, 0.29486126309253047,  0.31503813956872212],
-    [0.67332725564817331, 0.29911962764489264,  0.31553372323982209],
-    [0.67621897924409746, 0.30339762792450425,  0.3160724937230589],
-    [0.67907474028157344, 0.30769497879760166,  0.31665545668946665],
-    [0.68189457150944521, 0.31201133280550686,  0.31728380489244951],
-    [0.68467850942494535, 0.31634634821222207,  0.31795870784057567],
-    [0.68742656435169625, 0.32069970535138104,  0.31868137622277692],
-    [0.6901389321505248,  0.32507091815606004,  0.31945332332898302],
-    [0.69281544846764931, 0.32945984647042675,  0.3202754315314667],
-    [0.69545608346891119, 0.33386622163232865,  0.32114884306985791],
-    [0.6980608153581771,  0.33828976326048621,  0.32207478855218091],
-    [0.70062962477242097, 0.34273019305341756,  0.32305449047765694],
-    [0.70316249458814151, 0.34718723719597999,  0.32408913679491225],
-    [0.70565951122610093, 0.35166052978120937,  0.32518014084085567],
-    [0.70812059568420482, 0.35614985523380299,  0.32632861885644465],
-    [0.7105456546582587,  0.36065500290840113,  0.32753574162788762],
-    [0.71293466839773467, 0.36517570519856757,  0.3288027427038317],
-    [0.71528760614847287, 0.36971170225223449,  0.3301308728723546],
-    [0.71760444908133847, 0.37426272710686193,  0.33152138620958932],
-    [0.71988521490549851, 0.37882848839337313,  0.33297555200245399],
-    [0.7221299918421461,  0.38340864508963057,  0.33449469983585844],
-    [0.72433865647781592, 0.38800301593162145,  0.33607995965691828],
-    [0.72651122900227549, 0.3926113126792577,   0.3377325942005665],
-    [0.72864773856716547, 0.39723324476747235,  0.33945384341064017],
-    [0.73074820754845171, 0.401868526884681,    0.3412449533046818],
-    [0.73281270506268747, 0.4065168468778026,   0.34310715173410822],
-    [0.73484133598564938, 0.41117787004519513,  0.34504169470809071],
-    [0.73683422173585866, 0.41585125850290111,  0.34704978520758401],
-    [0.73879140024599266, 0.42053672992315327,  0.34913260148542435],
-    [0.74071301619506091, 0.4252339389526239,   0.35129130890802607],
-    [0.7425992159973317,  0.42994254036133867,  0.35352709245374592],
-    [0.74445018676570673, 0.43466217184617112,  0.35584108091122535],
-    [0.74626615789163442, 0.43939245044973502,  0.35823439142300639],
-    [0.74804739275559562, 0.44413297780351974,  0.36070813602540136],
-    [0.74979420547170472, 0.44888333481548809,  0.36326337558360278],
-    [0.75150685045891663, 0.45364314496866825,  0.36590112443835765],
-    [0.75318566369046569, 0.45841199172949604,  0.36862236642234769],
-    [0.75483105066959544, 0.46318942799460555,  0.3714280448394211],
-    [0.75644341577140706, 0.46797501437948458,  0.37431909037543515],
-    [0.75802325538455839, 0.4727682731566229,   0.37729635531096678],
-    [0.75957111105340058, 0.47756871222057079,  0.380360657784311],
-    [0.7610876378057071,  0.48237579130289127,  0.38351275723852291],
-    [0.76257333554052609, 0.48718906673415824,  0.38675335037837993],
-    [0.76402885609288662, 0.49200802533379656,  0.39008308392311997],
-    [0.76545492593330511, 0.49683212909727231,  0.39350254000115381],
-    [0.76685228950643891, 0.5016608471009063,   0.39701221751773474],
-    [0.76822176599735303, 0.50649362371287909,  0.40061257089416885],
-    [0.7695642334401418,  0.5113298901696085,   0.40430398069682483],
-    [0.77088091962302474, 0.51616892643469103,  0.40808667584648967],
-    [0.77217257229605551, 0.5210102658711383,   0.41196089987122869],
-    [0.77344021829889886, 0.52585332093451564,  0.41592679539764366],
-    [0.77468494746063199, 0.53069749384776732,  0.41998440356963762],
-    [0.77590790730685699, 0.53554217882461186,  0.42413367909988375],
-    [0.7771103295521099,  0.54038674910561235,  0.42837450371258479],
-    [0.77829345807633121, 0.54523059488426595,  0.432706647838971],
-    [0.77945862731506643, 0.55007308413977274,  0.43712979856444761],
-    [0.78060774749483774, 0.55491335744890613,  0.44164332426364639],
-    [0.78174180478981836, 0.55975098052594863,  0.44624687186865436],
-    [0.78286225264440912, 0.56458533111166875,  0.45093985823706345],
-    [0.78397060836414478, 0.56941578326710418,  0.45572154742892063],
-    [0.78506845019606841, 0.5742417003617839,   0.46059116206904965],
-    [0.78615737132332963, 0.5790624629815756,   0.46554778281918402],
-    [0.78723904108188347, 0.58387743744557208,  0.47059039582133383],
-    [0.78831514045623963, 0.58868600173562435,  0.47571791879076081],
-    [0.78938737766251943, 0.5934875421745599,   0.48092913815357724],
-    [0.79045776847727878, 0.59828134277062461,  0.48622257801969754],
-    [0.79152832843475607, 0.60306670593147205,  0.49159667021646397],
-    [0.79260034304237448, 0.60784322087037024,  0.49705020621532009],
-    [0.79367559698664958, 0.61261029334072192,  0.50258161291269432],
-    [0.79475585972654039, 0.61736734400220705,  0.50818921213102985],
-    [0.79584292379583765, 0.62211378808451145,  0.51387124091909786],
-    [0.79693854719951607, 0.62684905679296699,  0.5196258425240281],
-    [0.79804447815136637, 0.63157258225089552,  0.52545108144834785],
-    [0.7991624518501963,  0.63628379372029187,  0.53134495942561433],
-    [0.80029415389753977, 0.64098213306749863,  0.53730535185141037],
-    [0.80144124292560048, 0.64566703459218766,  0.5433300863249918],
-    [0.80260531146112946, 0.65033793748103852,  0.54941691584603647],
-    [0.80378792531077625, 0.65499426549472628,  0.55556350867083815],
-    [0.80499054790810298, 0.65963545027564163,  0.56176745110546977],
-    [0.80621460526927058, 0.66426089585282289,  0.56802629178649788],
-    [0.8074614045096935,  0.6688700095398864,   0.57433746373459582],
-    [0.80873219170089694, 0.67346216702194517,  0.58069834805576737],
-    [0.81002809466520687, 0.67803672673971815,  0.58710626908082753],
-    [0.81135014011763329, 0.68259301546243389,  0.59355848909050757],
-    [0.81269922039881493, 0.68713033714618876,  0.60005214820435104],
-    [0.81407611046993344, 0.69164794791482131,  0.6065843782630862],
-    [0.81548146627279483, 0.69614505508308089,  0.61315221209322646],
-    [0.81691575775055891, 0.70062083014783982,  0.61975260637257923],
-    [0.81837931164498223, 0.70507438189635097,  0.62638245478933297],
-    [0.81987230650455289, 0.70950474978787481,  0.63303857040067113],
-    [0.8213947205565636,  0.7139109141951604,   0.63971766697672761],
-    [0.82294635110428427, 0.71829177331290062,  0.6464164243818421],
-    [0.8245268129450285,  0.72264614312088882,  0.65313137915422603],
-    [0.82613549710580259, 0.72697275518238258,  0.65985900156216504],
-    [0.8277716072353446,  0.73127023324078089,  0.66659570204682972],
-    [0.82943407816481474, 0.7355371221572935,   0.67333772009301907],
-    [0.83112163529096306, 0.73977184647638616,  0.68008125203631464],
-    [0.83283277185777982, 0.74397271817459876,  0.68682235874648545],
-    [0.8345656905566583,  0.7481379479992134,   0.69355697649863846],
-    [0.83631898844737929, 0.75226548952875261,  0.70027999028864962],
-    [0.83809123476131964, 0.75635314860808633,  0.70698561390212977],
-    [0.83987839884120874, 0.76039907199779677,  0.71367147811129228],
-    [0.84167750766845151, 0.76440101200982946,  0.72033299387284622],
-    [0.84348529222933699, 0.76835660399870176,  0.72696536998972039],
-    [0.84529810731955113, 0.77226338601044719,  0.73356368240541492],
-    [0.84711195507965098, 0.77611880236047159,  0.74012275762807056],
-    [0.84892245563117641, 0.77992021407650147,  0.74663719293664366],
-    [0.85072697023178789, 0.78366457342383888,  0.7530974636118285],
-    [0.85251907207708444, 0.78734936133548439,  0.7594994148789691],
-    [0.85429219611470464, 0.79097196777091994,  0.76583801477914104],
-    [0.85604022314725403, 0.79452963601550608,  0.77210610037674143],
-    [0.85775662943504905, 0.79801963142713928,  0.77829571667247499],
-    [0.8594346370300241,  0.8014392309950078,   0.78439788751383921],
-    [0.86107117027565516, 0.80478517909812231,  0.79039529663736285],
-    [0.86265601051127572, 0.80805523804261525,  0.796282666437655],
-    [0.86418343723941027, 0.81124644224653542,  0.80204612696863953],
-    [0.86564934325605325, 0.81435544067514909,  0.80766972324164554],
-    [0.86705314907048503, 0.81737804041911244,  0.81313419626911398],
-    [0.86839954695818633, 0.82030875512181523,  0.81841638963128993],
-    [0.86969131502613806, 0.82314158859569164,  0.82350476683173168],
-    [0.87093846717297507, 0.82586857889438514,  0.82838497261149613],
-    [0.87215331978454325, 0.82848052823709672,  0.8330486712880828],
-    [0.87335171360916275, 0.83096715251272624,  0.83748851001197089],
-    [0.87453793320260187, 0.83331972948645461,  0.84171925358069011],
-    [0.87571458709961403, 0.8355302318472394,   0.84575537519027078],
-    [0.87687848451614692, 0.83759238071186537,  0.84961373549150254],
-    [0.87802298436649007, 0.83950165618540074,  0.85330645352458923],
-    [0.87913244240792765, 0.84125554884475906,  0.85685572291039636],
-    [0.88019293315695812, 0.84285224824778615,  0.86027399927156634],
-    [0.88119169871341951, 0.84429066717717349,  0.86356595168669881],
-    [0.88211542489401606, 0.84557007254559347,  0.86673765046233331],
-    [0.88295168595448525, 0.84668970275699273,  0.86979617048190971],
-    [0.88369127145898041, 0.84764891761519268,  0.87274147101441557],
-    [0.88432713054113543, 0.84844741572055415,  0.87556785228242973],
-    [0.88485138159908572, 0.84908426422893801,  0.87828235285372469],
-    [0.88525897972630474, 0.84955892810989209,  0.88088414794024839],
-    [0.88554714811952384, 0.84987174283631584,  0.88336206121170946],
-    [0.88571155122845646, 0.85002186115856315,  0.88572538990087124]]
-
-_twilight_shifted_data = (_twilight_data[len(_twilight_data)//2:] +
-                          _twilight_data[:len(_twilight_data)//2])
-_twilight_shifted_data.reverse()
-
-cmaps = {
-    name: ListedColormap(data, name=name) for name, data in [
-        ('magma', _magma_data),
-        ('inferno', _inferno_data),
-        ('plasma', _plasma_data),
-        ('viridis', _viridis_data),
-        ('cividis', _cividis_data),
-        ('twilight', _twilight_data),
-        ('twilight_shifted', _twilight_shifted_data),
-    ]}

+ 0 - 1147
venv/lib/python3.8/site-packages/matplotlib/_color_data.py

@@ -1,1147 +0,0 @@
-from collections import OrderedDict
-
-
-BASE_COLORS = {
-    'b': (0, 0, 1),        # blue
-    'g': (0, 0.5, 0),      # green
-    'r': (1, 0, 0),        # red
-    'c': (0, 0.75, 0.75),  # cyan
-    'm': (0.75, 0, 0.75),  # magenta
-    'y': (0.75, 0.75, 0),  # yellow
-    'k': (0, 0, 0),        # black
-    'w': (1, 1, 1),        # white
-}
-
-
-# These colors are from Tableau
-TABLEAU_COLORS = (
-    ('blue', '#1f77b4'),
-    ('orange', '#ff7f0e'),
-    ('green', '#2ca02c'),
-    ('red', '#d62728'),
-    ('purple', '#9467bd'),
-    ('brown', '#8c564b'),
-    ('pink', '#e377c2'),
-    ('gray', '#7f7f7f'),
-    ('olive', '#bcbd22'),
-    ('cyan', '#17becf'),
-)
-
-# Normalize name to "tab:<name>" to avoid name collisions.
-TABLEAU_COLORS = OrderedDict(
-    ('tab:' + name, value) for name, value in TABLEAU_COLORS)
-
-# This mapping of color names -> hex values is taken from
-# a survey run by Randall Munroe see:
-# https://blog.xkcd.com/2010/05/03/color-survey-results/
-# for more details.  The results are hosted at
-# https://xkcd.com/color/rgb
-# and also available as a text file at
-# https://xkcd.com/color/rgb.txt
-#
-# License: http://creativecommons.org/publicdomain/zero/1.0/
-XKCD_COLORS = {
-    'cloudy blue': '#acc2d9',
-    'dark pastel green': '#56ae57',
-    'dust': '#b2996e',
-    'electric lime': '#a8ff04',
-    'fresh green': '#69d84f',
-    'light eggplant': '#894585',
-    'nasty green': '#70b23f',
-    'really light blue': '#d4ffff',
-    'tea': '#65ab7c',
-    'warm purple': '#952e8f',
-    'yellowish tan': '#fcfc81',
-    'cement': '#a5a391',
-    'dark grass green': '#388004',
-    'dusty teal': '#4c9085',
-    'grey teal': '#5e9b8a',
-    'macaroni and cheese': '#efb435',
-    'pinkish tan': '#d99b82',
-    'spruce': '#0a5f38',
-    'strong blue': '#0c06f7',
-    'toxic green': '#61de2a',
-    'windows blue': '#3778bf',
-    'blue blue': '#2242c7',
-    'blue with a hint of purple': '#533cc6',
-    'booger': '#9bb53c',
-    'bright sea green': '#05ffa6',
-    'dark green blue': '#1f6357',
-    'deep turquoise': '#017374',
-    'green teal': '#0cb577',
-    'strong pink': '#ff0789',
-    'bland': '#afa88b',
-    'deep aqua': '#08787f',
-    'lavender pink': '#dd85d7',
-    'light moss green': '#a6c875',
-    'light seafoam green': '#a7ffb5',
-    'olive yellow': '#c2b709',
-    'pig pink': '#e78ea5',
-    'deep lilac': '#966ebd',
-    'desert': '#ccad60',
-    'dusty lavender': '#ac86a8',
-    'purpley grey': '#947e94',
-    'purply': '#983fb2',
-    'candy pink': '#ff63e9',
-    'light pastel green': '#b2fba5',
-    'boring green': '#63b365',
-    'kiwi green': '#8ee53f',
-    'light grey green': '#b7e1a1',
-    'orange pink': '#ff6f52',
-    'tea green': '#bdf8a3',
-    'very light brown': '#d3b683',
-    'egg shell': '#fffcc4',
-    'eggplant purple': '#430541',
-    'powder pink': '#ffb2d0',
-    'reddish grey': '#997570',
-    'baby shit brown': '#ad900d',
-    'liliac': '#c48efd',
-    'stormy blue': '#507b9c',
-    'ugly brown': '#7d7103',
-    'custard': '#fffd78',
-    'darkish pink': '#da467d',
-    'deep brown': '#410200',
-    'greenish beige': '#c9d179',
-    'manilla': '#fffa86',
-    'off blue': '#5684ae',
-    'battleship grey': '#6b7c85',
-    'browny green': '#6f6c0a',
-    'bruise': '#7e4071',
-    'kelley green': '#009337',
-    'sickly yellow': '#d0e429',
-    'sunny yellow': '#fff917',
-    'azul': '#1d5dec',
-    'darkgreen': '#054907',
-    'green/yellow': '#b5ce08',
-    'lichen': '#8fb67b',
-    'light light green': '#c8ffb0',
-    'pale gold': '#fdde6c',
-    'sun yellow': '#ffdf22',
-    'tan green': '#a9be70',
-    'burple': '#6832e3',
-    'butterscotch': '#fdb147',
-    'toupe': '#c7ac7d',
-    'dark cream': '#fff39a',
-    'indian red': '#850e04',
-    'light lavendar': '#efc0fe',
-    'poison green': '#40fd14',
-    'baby puke green': '#b6c406',
-    'bright yellow green': '#9dff00',
-    'charcoal grey': '#3c4142',
-    'squash': '#f2ab15',
-    'cinnamon': '#ac4f06',
-    'light pea green': '#c4fe82',
-    'radioactive green': '#2cfa1f',
-    'raw sienna': '#9a6200',
-    'baby purple': '#ca9bf7',
-    'cocoa': '#875f42',
-    'light royal blue': '#3a2efe',
-    'orangeish': '#fd8d49',
-    'rust brown': '#8b3103',
-    'sand brown': '#cba560',
-    'swamp': '#698339',
-    'tealish green': '#0cdc73',
-    'burnt siena': '#b75203',
-    'camo': '#7f8f4e',
-    'dusk blue': '#26538d',
-    'fern': '#63a950',
-    'old rose': '#c87f89',
-    'pale light green': '#b1fc99',
-    'peachy pink': '#ff9a8a',
-    'rosy pink': '#f6688e',
-    'light bluish green': '#76fda8',
-    'light bright green': '#53fe5c',
-    'light neon green': '#4efd54',
-    'light seafoam': '#a0febf',
-    'tiffany blue': '#7bf2da',
-    'washed out green': '#bcf5a6',
-    'browny orange': '#ca6b02',
-    'nice blue': '#107ab0',
-    'sapphire': '#2138ab',
-    'greyish teal': '#719f91',
-    'orangey yellow': '#fdb915',
-    'parchment': '#fefcaf',
-    'straw': '#fcf679',
-    'very dark brown': '#1d0200',
-    'terracota': '#cb6843',
-    'ugly blue': '#31668a',
-    'clear blue': '#247afd',
-    'creme': '#ffffb6',
-    'foam green': '#90fda9',
-    'grey/green': '#86a17d',
-    'light gold': '#fddc5c',
-    'seafoam blue': '#78d1b6',
-    'topaz': '#13bbaf',
-    'violet pink': '#fb5ffc',
-    'wintergreen': '#20f986',
-    'yellow tan': '#ffe36e',
-    'dark fuchsia': '#9d0759',
-    'indigo blue': '#3a18b1',
-    'light yellowish green': '#c2ff89',
-    'pale magenta': '#d767ad',
-    'rich purple': '#720058',
-    'sunflower yellow': '#ffda03',
-    'green/blue': '#01c08d',
-    'leather': '#ac7434',
-    'racing green': '#014600',
-    'vivid purple': '#9900fa',
-    'dark royal blue': '#02066f',
-    'hazel': '#8e7618',
-    'muted pink': '#d1768f',
-    'booger green': '#96b403',
-    'canary': '#fdff63',
-    'cool grey': '#95a3a6',
-    'dark taupe': '#7f684e',
-    'darkish purple': '#751973',
-    'true green': '#089404',
-    'coral pink': '#ff6163',
-    'dark sage': '#598556',
-    'dark slate blue': '#214761',
-    'flat blue': '#3c73a8',
-    'mushroom': '#ba9e88',
-    'rich blue': '#021bf9',
-    'dirty purple': '#734a65',
-    'greenblue': '#23c48b',
-    'icky green': '#8fae22',
-    'light khaki': '#e6f2a2',
-    'warm blue': '#4b57db',
-    'dark hot pink': '#d90166',
-    'deep sea blue': '#015482',
-    'carmine': '#9d0216',
-    'dark yellow green': '#728f02',
-    'pale peach': '#ffe5ad',
-    'plum purple': '#4e0550',
-    'golden rod': '#f9bc08',
-    'neon red': '#ff073a',
-    'old pink': '#c77986',
-    'very pale blue': '#d6fffe',
-    'blood orange': '#fe4b03',
-    'grapefruit': '#fd5956',
-    'sand yellow': '#fce166',
-    'clay brown': '#b2713d',
-    'dark blue grey': '#1f3b4d',
-    'flat green': '#699d4c',
-    'light green blue': '#56fca2',
-    'warm pink': '#fb5581',
-    'dodger blue': '#3e82fc',
-    'gross green': '#a0bf16',
-    'ice': '#d6fffa',
-    'metallic blue': '#4f738e',
-    'pale salmon': '#ffb19a',
-    'sap green': '#5c8b15',
-    'algae': '#54ac68',
-    'bluey grey': '#89a0b0',
-    'greeny grey': '#7ea07a',
-    'highlighter green': '#1bfc06',
-    'light light blue': '#cafffb',
-    'light mint': '#b6ffbb',
-    'raw umber': '#a75e09',
-    'vivid blue': '#152eff',
-    'deep lavender': '#8d5eb7',
-    'dull teal': '#5f9e8f',
-    'light greenish blue': '#63f7b4',
-    'mud green': '#606602',
-    'pinky': '#fc86aa',
-    'red wine': '#8c0034',
-    'shit green': '#758000',
-    'tan brown': '#ab7e4c',
-    'darkblue': '#030764',
-    'rosa': '#fe86a4',
-    'lipstick': '#d5174e',
-    'pale mauve': '#fed0fc',
-    'claret': '#680018',
-    'dandelion': '#fedf08',
-    'orangered': '#fe420f',
-    'poop green': '#6f7c00',
-    'ruby': '#ca0147',
-    'dark': '#1b2431',
-    'greenish turquoise': '#00fbb0',
-    'pastel red': '#db5856',
-    'piss yellow': '#ddd618',
-    'bright cyan': '#41fdfe',
-    'dark coral': '#cf524e',
-    'algae green': '#21c36f',
-    'darkish red': '#a90308',
-    'reddy brown': '#6e1005',
-    'blush pink': '#fe828c',
-    'camouflage green': '#4b6113',
-    'lawn green': '#4da409',
-    'putty': '#beae8a',
-    'vibrant blue': '#0339f8',
-    'dark sand': '#a88f59',
-    'purple/blue': '#5d21d0',
-    'saffron': '#feb209',
-    'twilight': '#4e518b',
-    'warm brown': '#964e02',
-    'bluegrey': '#85a3b2',
-    'bubble gum pink': '#ff69af',
-    'duck egg blue': '#c3fbf4',
-    'greenish cyan': '#2afeb7',
-    'petrol': '#005f6a',
-    'royal': '#0c1793',
-    'butter': '#ffff81',
-    'dusty orange': '#f0833a',
-    'off yellow': '#f1f33f',
-    'pale olive green': '#b1d27b',
-    'orangish': '#fc824a',
-    'leaf': '#71aa34',
-    'light blue grey': '#b7c9e2',
-    'dried blood': '#4b0101',
-    'lightish purple': '#a552e6',
-    'rusty red': '#af2f0d',
-    'lavender blue': '#8b88f8',
-    'light grass green': '#9af764',
-    'light mint green': '#a6fbb2',
-    'sunflower': '#ffc512',
-    'velvet': '#750851',
-    'brick orange': '#c14a09',
-    'lightish red': '#fe2f4a',
-    'pure blue': '#0203e2',
-    'twilight blue': '#0a437a',
-    'violet red': '#a50055',
-    'yellowy brown': '#ae8b0c',
-    'carnation': '#fd798f',
-    'muddy yellow': '#bfac05',
-    'dark seafoam green': '#3eaf76',
-    'deep rose': '#c74767',
-    'dusty red': '#b9484e',
-    'grey/blue': '#647d8e',
-    'lemon lime': '#bffe28',
-    'purple/pink': '#d725de',
-    'brown yellow': '#b29705',
-    'purple brown': '#673a3f',
-    'wisteria': '#a87dc2',
-    'banana yellow': '#fafe4b',
-    'lipstick red': '#c0022f',
-    'water blue': '#0e87cc',
-    'brown grey': '#8d8468',
-    'vibrant purple': '#ad03de',
-    'baby green': '#8cff9e',
-    'barf green': '#94ac02',
-    'eggshell blue': '#c4fff7',
-    'sandy yellow': '#fdee73',
-    'cool green': '#33b864',
-    'pale': '#fff9d0',
-    'blue/grey': '#758da3',
-    'hot magenta': '#f504c9',
-    'greyblue': '#77a1b5',
-    'purpley': '#8756e4',
-    'baby shit green': '#889717',
-    'brownish pink': '#c27e79',
-    'dark aquamarine': '#017371',
-    'diarrhea': '#9f8303',
-    'light mustard': '#f7d560',
-    'pale sky blue': '#bdf6fe',
-    'turtle green': '#75b84f',
-    'bright olive': '#9cbb04',
-    'dark grey blue': '#29465b',
-    'greeny brown': '#696006',
-    'lemon green': '#adf802',
-    'light periwinkle': '#c1c6fc',
-    'seaweed green': '#35ad6b',
-    'sunshine yellow': '#fffd37',
-    'ugly purple': '#a442a0',
-    'medium pink': '#f36196',
-    'puke brown': '#947706',
-    'very light pink': '#fff4f2',
-    'viridian': '#1e9167',
-    'bile': '#b5c306',
-    'faded yellow': '#feff7f',
-    'very pale green': '#cffdbc',
-    'vibrant green': '#0add08',
-    'bright lime': '#87fd05',
-    'spearmint': '#1ef876',
-    'light aquamarine': '#7bfdc7',
-    'light sage': '#bcecac',
-    'yellowgreen': '#bbf90f',
-    'baby poo': '#ab9004',
-    'dark seafoam': '#1fb57a',
-    'deep teal': '#00555a',
-    'heather': '#a484ac',
-    'rust orange': '#c45508',
-    'dirty blue': '#3f829d',
-    'fern green': '#548d44',
-    'bright lilac': '#c95efb',
-    'weird green': '#3ae57f',
-    'peacock blue': '#016795',
-    'avocado green': '#87a922',
-    'faded orange': '#f0944d',
-    'grape purple': '#5d1451',
-    'hot green': '#25ff29',
-    'lime yellow': '#d0fe1d',
-    'mango': '#ffa62b',
-    'shamrock': '#01b44c',
-    'bubblegum': '#ff6cb5',
-    'purplish brown': '#6b4247',
-    'vomit yellow': '#c7c10c',
-    'pale cyan': '#b7fffa',
-    'key lime': '#aeff6e',
-    'tomato red': '#ec2d01',
-    'lightgreen': '#76ff7b',
-    'merlot': '#730039',
-    'night blue': '#040348',
-    'purpleish pink': '#df4ec8',
-    'apple': '#6ecb3c',
-    'baby poop green': '#8f9805',
-    'green apple': '#5edc1f',
-    'heliotrope': '#d94ff5',
-    'yellow/green': '#c8fd3d',
-    'almost black': '#070d0d',
-    'cool blue': '#4984b8',
-    'leafy green': '#51b73b',
-    'mustard brown': '#ac7e04',
-    'dusk': '#4e5481',
-    'dull brown': '#876e4b',
-    'frog green': '#58bc08',
-    'vivid green': '#2fef10',
-    'bright light green': '#2dfe54',
-    'fluro green': '#0aff02',
-    'kiwi': '#9cef43',
-    'seaweed': '#18d17b',
-    'navy green': '#35530a',
-    'ultramarine blue': '#1805db',
-    'iris': '#6258c4',
-    'pastel orange': '#ff964f',
-    'yellowish orange': '#ffab0f',
-    'perrywinkle': '#8f8ce7',
-    'tealish': '#24bca8',
-    'dark plum': '#3f012c',
-    'pear': '#cbf85f',
-    'pinkish orange': '#ff724c',
-    'midnight purple': '#280137',
-    'light urple': '#b36ff6',
-    'dark mint': '#48c072',
-    'greenish tan': '#bccb7a',
-    'light burgundy': '#a8415b',
-    'turquoise blue': '#06b1c4',
-    'ugly pink': '#cd7584',
-    'sandy': '#f1da7a',
-    'electric pink': '#ff0490',
-    'muted purple': '#805b87',
-    'mid green': '#50a747',
-    'greyish': '#a8a495',
-    'neon yellow': '#cfff04',
-    'banana': '#ffff7e',
-    'carnation pink': '#ff7fa7',
-    'tomato': '#ef4026',
-    'sea': '#3c9992',
-    'muddy brown': '#886806',
-    'turquoise green': '#04f489',
-    'buff': '#fef69e',
-    'fawn': '#cfaf7b',
-    'muted blue': '#3b719f',
-    'pale rose': '#fdc1c5',
-    'dark mint green': '#20c073',
-    'amethyst': '#9b5fc0',
-    'blue/green': '#0f9b8e',
-    'chestnut': '#742802',
-    'sick green': '#9db92c',
-    'pea': '#a4bf20',
-    'rusty orange': '#cd5909',
-    'stone': '#ada587',
-    'rose red': '#be013c',
-    'pale aqua': '#b8ffeb',
-    'deep orange': '#dc4d01',
-    'earth': '#a2653e',
-    'mossy green': '#638b27',
-    'grassy green': '#419c03',
-    'pale lime green': '#b1ff65',
-    'light grey blue': '#9dbcd4',
-    'pale grey': '#fdfdfe',
-    'asparagus': '#77ab56',
-    'blueberry': '#464196',
-    'purple red': '#990147',
-    'pale lime': '#befd73',
-    'greenish teal': '#32bf84',
-    'caramel': '#af6f09',
-    'deep magenta': '#a0025c',
-    'light peach': '#ffd8b1',
-    'milk chocolate': '#7f4e1e',
-    'ocher': '#bf9b0c',
-    'off green': '#6ba353',
-    'purply pink': '#f075e6',
-    'lightblue': '#7bc8f6',
-    'dusky blue': '#475f94',
-    'golden': '#f5bf03',
-    'light beige': '#fffeb6',
-    'butter yellow': '#fffd74',
-    'dusky purple': '#895b7b',
-    'french blue': '#436bad',
-    'ugly yellow': '#d0c101',
-    'greeny yellow': '#c6f808',
-    'orangish red': '#f43605',
-    'shamrock green': '#02c14d',
-    'orangish brown': '#b25f03',
-    'tree green': '#2a7e19',
-    'deep violet': '#490648',
-    'gunmetal': '#536267',
-    'blue/purple': '#5a06ef',
-    'cherry': '#cf0234',
-    'sandy brown': '#c4a661',
-    'warm grey': '#978a84',
-    'dark indigo': '#1f0954',
-    'midnight': '#03012d',
-    'bluey green': '#2bb179',
-    'grey pink': '#c3909b',
-    'soft purple': '#a66fb5',
-    'blood': '#770001',
-    'brown red': '#922b05',
-    'medium grey': '#7d7f7c',
-    'berry': '#990f4b',
-    'poo': '#8f7303',
-    'purpley pink': '#c83cb9',
-    'light salmon': '#fea993',
-    'snot': '#acbb0d',
-    'easter purple': '#c071fe',
-    'light yellow green': '#ccfd7f',
-    'dark navy blue': '#00022e',
-    'drab': '#828344',
-    'light rose': '#ffc5cb',
-    'rouge': '#ab1239',
-    'purplish red': '#b0054b',
-    'slime green': '#99cc04',
-    'baby poop': '#937c00',
-    'irish green': '#019529',
-    'pink/purple': '#ef1de7',
-    'dark navy': '#000435',
-    'greeny blue': '#42b395',
-    'light plum': '#9d5783',
-    'pinkish grey': '#c8aca9',
-    'dirty orange': '#c87606',
-    'rust red': '#aa2704',
-    'pale lilac': '#e4cbff',
-    'orangey red': '#fa4224',
-    'primary blue': '#0804f9',
-    'kermit green': '#5cb200',
-    'brownish purple': '#76424e',
-    'murky green': '#6c7a0e',
-    'wheat': '#fbdd7e',
-    'very dark purple': '#2a0134',
-    'bottle green': '#044a05',
-    'watermelon': '#fd4659',
-    'deep sky blue': '#0d75f8',
-    'fire engine red': '#fe0002',
-    'yellow ochre': '#cb9d06',
-    'pumpkin orange': '#fb7d07',
-    'pale olive': '#b9cc81',
-    'light lilac': '#edc8ff',
-    'lightish green': '#61e160',
-    'carolina blue': '#8ab8fe',
-    'mulberry': '#920a4e',
-    'shocking pink': '#fe02a2',
-    'auburn': '#9a3001',
-    'bright lime green': '#65fe08',
-    'celadon': '#befdb7',
-    'pinkish brown': '#b17261',
-    'poo brown': '#885f01',
-    'bright sky blue': '#02ccfe',
-    'celery': '#c1fd95',
-    'dirt brown': '#836539',
-    'strawberry': '#fb2943',
-    'dark lime': '#84b701',
-    'copper': '#b66325',
-    'medium brown': '#7f5112',
-    'muted green': '#5fa052',
-    "robin's egg": '#6dedfd',
-    'bright aqua': '#0bf9ea',
-    'bright lavender': '#c760ff',
-    'ivory': '#ffffcb',
-    'very light purple': '#f6cefc',
-    'light navy': '#155084',
-    'pink red': '#f5054f',
-    'olive brown': '#645403',
-    'poop brown': '#7a5901',
-    'mustard green': '#a8b504',
-    'ocean green': '#3d9973',
-    'very dark blue': '#000133',
-    'dusty green': '#76a973',
-    'light navy blue': '#2e5a88',
-    'minty green': '#0bf77d',
-    'adobe': '#bd6c48',
-    'barney': '#ac1db8',
-    'jade green': '#2baf6a',
-    'bright light blue': '#26f7fd',
-    'light lime': '#aefd6c',
-    'dark khaki': '#9b8f55',
-    'orange yellow': '#ffad01',
-    'ocre': '#c69c04',
-    'maize': '#f4d054',
-    'faded pink': '#de9dac',
-    'british racing green': '#05480d',
-    'sandstone': '#c9ae74',
-    'mud brown': '#60460f',
-    'light sea green': '#98f6b0',
-    'robin egg blue': '#8af1fe',
-    'aqua marine': '#2ee8bb',
-    'dark sea green': '#11875d',
-    'soft pink': '#fdb0c0',
-    'orangey brown': '#b16002',
-    'cherry red': '#f7022a',
-    'burnt yellow': '#d5ab09',
-    'brownish grey': '#86775f',
-    'camel': '#c69f59',
-    'purplish grey': '#7a687f',
-    'marine': '#042e60',
-    'greyish pink': '#c88d94',
-    'pale turquoise': '#a5fbd5',
-    'pastel yellow': '#fffe71',
-    'bluey purple': '#6241c7',
-    'canary yellow': '#fffe40',
-    'faded red': '#d3494e',
-    'sepia': '#985e2b',
-    'coffee': '#a6814c',
-    'bright magenta': '#ff08e8',
-    'mocha': '#9d7651',
-    'ecru': '#feffca',
-    'purpleish': '#98568d',
-    'cranberry': '#9e003a',
-    'darkish green': '#287c37',
-    'brown orange': '#b96902',
-    'dusky rose': '#ba6873',
-    'melon': '#ff7855',
-    'sickly green': '#94b21c',
-    'silver': '#c5c9c7',
-    'purply blue': '#661aee',
-    'purpleish blue': '#6140ef',
-    'hospital green': '#9be5aa',
-    'shit brown': '#7b5804',
-    'mid blue': '#276ab3',
-    'amber': '#feb308',
-    'easter green': '#8cfd7e',
-    'soft blue': '#6488ea',
-    'cerulean blue': '#056eee',
-    'golden brown': '#b27a01',
-    'bright turquoise': '#0ffef9',
-    'red pink': '#fa2a55',
-    'red purple': '#820747',
-    'greyish brown': '#7a6a4f',
-    'vermillion': '#f4320c',
-    'russet': '#a13905',
-    'steel grey': '#6f828a',
-    'lighter purple': '#a55af4',
-    'bright violet': '#ad0afd',
-    'prussian blue': '#004577',
-    'slate green': '#658d6d',
-    'dirty pink': '#ca7b80',
-    'dark blue green': '#005249',
-    'pine': '#2b5d34',
-    'yellowy green': '#bff128',
-    'dark gold': '#b59410',
-    'bluish': '#2976bb',
-    'darkish blue': '#014182',
-    'dull red': '#bb3f3f',
-    'pinky red': '#fc2647',
-    'bronze': '#a87900',
-    'pale teal': '#82cbb2',
-    'military green': '#667c3e',
-    'barbie pink': '#fe46a5',
-    'bubblegum pink': '#fe83cc',
-    'pea soup green': '#94a617',
-    'dark mustard': '#a88905',
-    'shit': '#7f5f00',
-    'medium purple': '#9e43a2',
-    'very dark green': '#062e03',
-    'dirt': '#8a6e45',
-    'dusky pink': '#cc7a8b',
-    'red violet': '#9e0168',
-    'lemon yellow': '#fdff38',
-    'pistachio': '#c0fa8b',
-    'dull yellow': '#eedc5b',
-    'dark lime green': '#7ebd01',
-    'denim blue': '#3b5b92',
-    'teal blue': '#01889f',
-    'lightish blue': '#3d7afd',
-    'purpley blue': '#5f34e7',
-    'light indigo': '#6d5acf',
-    'swamp green': '#748500',
-    'brown green': '#706c11',
-    'dark maroon': '#3c0008',
-    'hot purple': '#cb00f5',
-    'dark forest green': '#002d04',
-    'faded blue': '#658cbb',
-    'drab green': '#749551',
-    'light lime green': '#b9ff66',
-    'snot green': '#9dc100',
-    'yellowish': '#faee66',
-    'light blue green': '#7efbb3',
-    'bordeaux': '#7b002c',
-    'light mauve': '#c292a1',
-    'ocean': '#017b92',
-    'marigold': '#fcc006',
-    'muddy green': '#657432',
-    'dull orange': '#d8863b',
-    'steel': '#738595',
-    'electric purple': '#aa23ff',
-    'fluorescent green': '#08ff08',
-    'yellowish brown': '#9b7a01',
-    'blush': '#f29e8e',
-    'soft green': '#6fc276',
-    'bright orange': '#ff5b00',
-    'lemon': '#fdff52',
-    'purple grey': '#866f85',
-    'acid green': '#8ffe09',
-    'pale lavender': '#eecffe',
-    'violet blue': '#510ac9',
-    'light forest green': '#4f9153',
-    'burnt red': '#9f2305',
-    'khaki green': '#728639',
-    'cerise': '#de0c62',
-    'faded purple': '#916e99',
-    'apricot': '#ffb16d',
-    'dark olive green': '#3c4d03',
-    'grey brown': '#7f7053',
-    'green grey': '#77926f',
-    'true blue': '#010fcc',
-    'pale violet': '#ceaefa',
-    'periwinkle blue': '#8f99fb',
-    'light sky blue': '#c6fcff',
-    'blurple': '#5539cc',
-    'green brown': '#544e03',
-    'bluegreen': '#017a79',
-    'bright teal': '#01f9c6',
-    'brownish yellow': '#c9b003',
-    'pea soup': '#929901',
-    'forest': '#0b5509',
-    'barney purple': '#a00498',
-    'ultramarine': '#2000b1',
-    'purplish': '#94568c',
-    'puke yellow': '#c2be0e',
-    'bluish grey': '#748b97',
-    'dark periwinkle': '#665fd1',
-    'dark lilac': '#9c6da5',
-    'reddish': '#c44240',
-    'light maroon': '#a24857',
-    'dusty purple': '#825f87',
-    'terra cotta': '#c9643b',
-    'avocado': '#90b134',
-    'marine blue': '#01386a',
-    'teal green': '#25a36f',
-    'slate grey': '#59656d',
-    'lighter green': '#75fd63',
-    'electric green': '#21fc0d',
-    'dusty blue': '#5a86ad',
-    'golden yellow': '#fec615',
-    'bright yellow': '#fffd01',
-    'light lavender': '#dfc5fe',
-    'umber': '#b26400',
-    'poop': '#7f5e00',
-    'dark peach': '#de7e5d',
-    'jungle green': '#048243',
-    'eggshell': '#ffffd4',
-    'denim': '#3b638c',
-    'yellow brown': '#b79400',
-    'dull purple': '#84597e',
-    'chocolate brown': '#411900',
-    'wine red': '#7b0323',
-    'neon blue': '#04d9ff',
-    'dirty green': '#667e2c',
-    'light tan': '#fbeeac',
-    'ice blue': '#d7fffe',
-    'cadet blue': '#4e7496',
-    'dark mauve': '#874c62',
-    'very light blue': '#d5ffff',
-    'grey purple': '#826d8c',
-    'pastel pink': '#ffbacd',
-    'very light green': '#d1ffbd',
-    'dark sky blue': '#448ee4',
-    'evergreen': '#05472a',
-    'dull pink': '#d5869d',
-    'aubergine': '#3d0734',
-    'mahogany': '#4a0100',
-    'reddish orange': '#f8481c',
-    'deep green': '#02590f',
-    'vomit green': '#89a203',
-    'purple pink': '#e03fd8',
-    'dusty pink': '#d58a94',
-    'faded green': '#7bb274',
-    'camo green': '#526525',
-    'pinky purple': '#c94cbe',
-    'pink purple': '#db4bda',
-    'brownish red': '#9e3623',
-    'dark rose': '#b5485d',
-    'mud': '#735c12',
-    'brownish': '#9c6d57',
-    'emerald green': '#028f1e',
-    'pale brown': '#b1916e',
-    'dull blue': '#49759c',
-    'burnt umber': '#a0450e',
-    'medium green': '#39ad48',
-    'clay': '#b66a50',
-    'light aqua': '#8cffdb',
-    'light olive green': '#a4be5c',
-    'brownish orange': '#cb7723',
-    'dark aqua': '#05696b',
-    'purplish pink': '#ce5dae',
-    'dark salmon': '#c85a53',
-    'greenish grey': '#96ae8d',
-    'jade': '#1fa774',
-    'ugly green': '#7a9703',
-    'dark beige': '#ac9362',
-    'emerald': '#01a049',
-    'pale red': '#d9544d',
-    'light magenta': '#fa5ff7',
-    'sky': '#82cafc',
-    'light cyan': '#acfffc',
-    'yellow orange': '#fcb001',
-    'reddish purple': '#910951',
-    'reddish pink': '#fe2c54',
-    'orchid': '#c875c4',
-    'dirty yellow': '#cdc50a',
-    'orange red': '#fd411e',
-    'deep red': '#9a0200',
-    'orange brown': '#be6400',
-    'cobalt blue': '#030aa7',
-    'neon pink': '#fe019a',
-    'rose pink': '#f7879a',
-    'greyish purple': '#887191',
-    'raspberry': '#b00149',
-    'aqua green': '#12e193',
-    'salmon pink': '#fe7b7c',
-    'tangerine': '#ff9408',
-    'brownish green': '#6a6e09',
-    'red brown': '#8b2e16',
-    'greenish brown': '#696112',
-    'pumpkin': '#e17701',
-    'pine green': '#0a481e',
-    'charcoal': '#343837',
-    'baby pink': '#ffb7ce',
-    'cornflower': '#6a79f7',
-    'blue violet': '#5d06e9',
-    'chocolate': '#3d1c02',
-    'greyish green': '#82a67d',
-    'scarlet': '#be0119',
-    'green yellow': '#c9ff27',
-    'dark olive': '#373e02',
-    'sienna': '#a9561e',
-    'pastel purple': '#caa0ff',
-    'terracotta': '#ca6641',
-    'aqua blue': '#02d8e9',
-    'sage green': '#88b378',
-    'blood red': '#980002',
-    'deep pink': '#cb0162',
-    'grass': '#5cac2d',
-    'moss': '#769958',
-    'pastel blue': '#a2bffe',
-    'bluish green': '#10a674',
-    'green blue': '#06b48b',
-    'dark tan': '#af884a',
-    'greenish blue': '#0b8b87',
-    'pale orange': '#ffa756',
-    'vomit': '#a2a415',
-    'forrest green': '#154406',
-    'dark lavender': '#856798',
-    'dark violet': '#34013f',
-    'purple blue': '#632de9',
-    'dark cyan': '#0a888a',
-    'olive drab': '#6f7632',
-    'pinkish': '#d46a7e',
-    'cobalt': '#1e488f',
-    'neon purple': '#bc13fe',
-    'light turquoise': '#7ef4cc',
-    'apple green': '#76cd26',
-    'dull green': '#74a662',
-    'wine': '#80013f',
-    'powder blue': '#b1d1fc',
-    'off white': '#ffffe4',
-    'electric blue': '#0652ff',
-    'dark turquoise': '#045c5a',
-    'blue purple': '#5729ce',
-    'azure': '#069af3',
-    'bright red': '#ff000d',
-    'pinkish red': '#f10c45',
-    'cornflower blue': '#5170d7',
-    'light olive': '#acbf69',
-    'grape': '#6c3461',
-    'greyish blue': '#5e819d',
-    'purplish blue': '#601ef9',
-    'yellowish green': '#b0dd16',
-    'greenish yellow': '#cdfd02',
-    'medium blue': '#2c6fbb',
-    'dusty rose': '#c0737a',
-    'light violet': '#d6b4fc',
-    'midnight blue': '#020035',
-    'bluish purple': '#703be7',
-    'red orange': '#fd3c06',
-    'dark magenta': '#960056',
-    'greenish': '#40a368',
-    'ocean blue': '#03719c',
-    'coral': '#fc5a50',
-    'cream': '#ffffc2',
-    'reddish brown': '#7f2b0a',
-    'burnt sienna': '#b04e0f',
-    'brick': '#a03623',
-    'sage': '#87ae73',
-    'grey green': '#789b73',
-    'white': '#ffffff',
-    "robin's egg blue": '#98eff9',
-    'moss green': '#658b38',
-    'steel blue': '#5a7d9a',
-    'eggplant': '#380835',
-    'light yellow': '#fffe7a',
-    'leaf green': '#5ca904',
-    'light grey': '#d8dcd6',
-    'puke': '#a5a502',
-    'pinkish purple': '#d648d7',
-    'sea blue': '#047495',
-    'pale purple': '#b790d4',
-    'slate blue': '#5b7c99',
-    'blue grey': '#607c8e',
-    'hunter green': '#0b4008',
-    'fuchsia': '#ed0dd9',
-    'crimson': '#8c000f',
-    'pale yellow': '#ffff84',
-    'ochre': '#bf9005',
-    'mustard yellow': '#d2bd0a',
-    'light red': '#ff474c',
-    'cerulean': '#0485d1',
-    'pale pink': '#ffcfdc',
-    'deep blue': '#040273',
-    'rust': '#a83c09',
-    'light teal': '#90e4c1',
-    'slate': '#516572',
-    'goldenrod': '#fac205',
-    'dark yellow': '#d5b60a',
-    'dark grey': '#363737',
-    'army green': '#4b5d16',
-    'grey blue': '#6b8ba4',
-    'seafoam': '#80f9ad',
-    'puce': '#a57e52',
-    'spring green': '#a9f971',
-    'dark orange': '#c65102',
-    'sand': '#e2ca76',
-    'pastel green': '#b0ff9d',
-    'mint': '#9ffeb0',
-    'light orange': '#fdaa48',
-    'bright pink': '#fe01b1',
-    'chartreuse': '#c1f80a',
-    'deep purple': '#36013f',
-    'dark brown': '#341c02',
-    'taupe': '#b9a281',
-    'pea green': '#8eab12',
-    'puke green': '#9aae07',
-    'kelly green': '#02ab2e',
-    'seafoam green': '#7af9ab',
-    'blue green': '#137e6d',
-    'khaki': '#aaa662',
-    'burgundy': '#610023',
-    'dark teal': '#014d4e',
-    'brick red': '#8f1402',
-    'royal purple': '#4b006e',
-    'plum': '#580f41',
-    'mint green': '#8fff9f',
-    'gold': '#dbb40c',
-    'baby blue': '#a2cffe',
-    'yellow green': '#c0fb2d',
-    'bright purple': '#be03fd',
-    'dark red': '#840000',
-    'pale blue': '#d0fefe',
-    'grass green': '#3f9b0b',
-    'navy': '#01153e',
-    'aquamarine': '#04d8b2',
-    'burnt orange': '#c04e01',
-    'neon green': '#0cff0c',
-    'bright blue': '#0165fc',
-    'rose': '#cf6275',
-    'light pink': '#ffd1df',
-    'mustard': '#ceb301',
-    'indigo': '#380282',
-    'lime': '#aaff32',
-    'sea green': '#53fca1',
-    'periwinkle': '#8e82fe',
-    'dark pink': '#cb416b',
-    'olive green': '#677a04',
-    'peach': '#ffb07c',
-    'pale green': '#c7fdb5',
-    'light brown': '#ad8150',
-    'hot pink': '#ff028d',
-    'black': '#000000',
-    'lilac': '#cea2fd',
-    'navy blue': '#001146',
-    'royal blue': '#0504aa',
-    'beige': '#e6daa6',
-    'salmon': '#ff796c',
-    'olive': '#6e750e',
-    'maroon': '#650021',
-    'bright green': '#01ff07',
-    'dark purple': '#35063e',
-    'mauve': '#ae7181',
-    'forest green': '#06470c',
-    'aqua': '#13eac9',
-    'cyan': '#00ffff',
-    'tan': '#d1b26f',
-    'dark blue': '#00035b',
-    'lavender': '#c79fef',
-    'turquoise': '#06c2ac',
-    'dark green': '#033500',
-    'violet': '#9a0eea',
-    'light purple': '#bf77f6',
-    'lime green': '#89fe05',
-    'grey': '#929591',
-    'sky blue': '#75bbfd',
-    'yellow': '#ffff14',
-    'magenta': '#c20078',
-    'light green': '#96f97b',
-    'orange': '#f97306',
-    'teal': '#029386',
-    'light blue': '#95d0fc',
-    'red': '#e50000',
-    'brown': '#653700',
-    'pink': '#ff81c0',
-    'blue': '#0343df',
-    'green': '#15b01a',
-    'purple': '#7e1e9c'}
-
-# Normalize name to "xkcd:<name>" to avoid name collisions.
-XKCD_COLORS = {'xkcd:' + name: value for name, value in XKCD_COLORS.items()}
-
-
-# https://drafts.csswg.org/css-color-4/#named-colors
-CSS4_COLORS = {
-    'aliceblue':            '#F0F8FF',
-    'antiquewhite':         '#FAEBD7',
-    'aqua':                 '#00FFFF',
-    'aquamarine':           '#7FFFD4',
-    'azure':                '#F0FFFF',
-    'beige':                '#F5F5DC',
-    'bisque':               '#FFE4C4',
-    'black':                '#000000',
-    'blanchedalmond':       '#FFEBCD',
-    'blue':                 '#0000FF',
-    'blueviolet':           '#8A2BE2',
-    'brown':                '#A52A2A',
-    'burlywood':            '#DEB887',
-    'cadetblue':            '#5F9EA0',
-    'chartreuse':           '#7FFF00',
-    'chocolate':            '#D2691E',
-    'coral':                '#FF7F50',
-    'cornflowerblue':       '#6495ED',
-    'cornsilk':             '#FFF8DC',
-    'crimson':              '#DC143C',
-    'cyan':                 '#00FFFF',
-    'darkblue':             '#00008B',
-    'darkcyan':             '#008B8B',
-    'darkgoldenrod':        '#B8860B',
-    'darkgray':             '#A9A9A9',
-    'darkgreen':            '#006400',
-    'darkgrey':             '#A9A9A9',
-    'darkkhaki':            '#BDB76B',
-    'darkmagenta':          '#8B008B',
-    'darkolivegreen':       '#556B2F',
-    'darkorange':           '#FF8C00',
-    'darkorchid':           '#9932CC',
-    'darkred':              '#8B0000',
-    'darksalmon':           '#E9967A',
-    'darkseagreen':         '#8FBC8F',
-    'darkslateblue':        '#483D8B',
-    'darkslategray':        '#2F4F4F',
-    'darkslategrey':        '#2F4F4F',
-    'darkturquoise':        '#00CED1',
-    'darkviolet':           '#9400D3',
-    'deeppink':             '#FF1493',
-    'deepskyblue':          '#00BFFF',
-    'dimgray':              '#696969',
-    'dimgrey':              '#696969',
-    'dodgerblue':           '#1E90FF',
-    'firebrick':            '#B22222',
-    'floralwhite':          '#FFFAF0',
-    'forestgreen':          '#228B22',
-    'fuchsia':              '#FF00FF',
-    'gainsboro':            '#DCDCDC',
-    'ghostwhite':           '#F8F8FF',
-    'gold':                 '#FFD700',
-    'goldenrod':            '#DAA520',
-    'gray':                 '#808080',
-    'green':                '#008000',
-    'greenyellow':          '#ADFF2F',
-    'grey':                 '#808080',
-    'honeydew':             '#F0FFF0',
-    'hotpink':              '#FF69B4',
-    'indianred':            '#CD5C5C',
-    'indigo':               '#4B0082',
-    'ivory':                '#FFFFF0',
-    'khaki':                '#F0E68C',
-    'lavender':             '#E6E6FA',
-    'lavenderblush':        '#FFF0F5',
-    'lawngreen':            '#7CFC00',
-    'lemonchiffon':         '#FFFACD',
-    'lightblue':            '#ADD8E6',
-    'lightcoral':           '#F08080',
-    'lightcyan':            '#E0FFFF',
-    'lightgoldenrodyellow': '#FAFAD2',
-    'lightgray':            '#D3D3D3',
-    'lightgreen':           '#90EE90',
-    'lightgrey':            '#D3D3D3',
-    'lightpink':            '#FFB6C1',
-    'lightsalmon':          '#FFA07A',
-    'lightseagreen':        '#20B2AA',
-    'lightskyblue':         '#87CEFA',
-    'lightslategray':       '#778899',
-    'lightslategrey':       '#778899',
-    'lightsteelblue':       '#B0C4DE',
-    'lightyellow':          '#FFFFE0',
-    'lime':                 '#00FF00',
-    'limegreen':            '#32CD32',
-    'linen':                '#FAF0E6',
-    'magenta':              '#FF00FF',
-    'maroon':               '#800000',
-    'mediumaquamarine':     '#66CDAA',
-    'mediumblue':           '#0000CD',
-    'mediumorchid':         '#BA55D3',
-    'mediumpurple':         '#9370DB',
-    'mediumseagreen':       '#3CB371',
-    'mediumslateblue':      '#7B68EE',
-    'mediumspringgreen':    '#00FA9A',
-    'mediumturquoise':      '#48D1CC',
-    'mediumvioletred':      '#C71585',
-    'midnightblue':         '#191970',
-    'mintcream':            '#F5FFFA',
-    'mistyrose':            '#FFE4E1',
-    'moccasin':             '#FFE4B5',
-    'navajowhite':          '#FFDEAD',
-    'navy':                 '#000080',
-    'oldlace':              '#FDF5E6',
-    'olive':                '#808000',
-    'olivedrab':            '#6B8E23',
-    'orange':               '#FFA500',
-    'orangered':            '#FF4500',
-    'orchid':               '#DA70D6',
-    'palegoldenrod':        '#EEE8AA',
-    'palegreen':            '#98FB98',
-    'paleturquoise':        '#AFEEEE',
-    'palevioletred':        '#DB7093',
-    'papayawhip':           '#FFEFD5',
-    'peachpuff':            '#FFDAB9',
-    'peru':                 '#CD853F',
-    'pink':                 '#FFC0CB',
-    'plum':                 '#DDA0DD',
-    'powderblue':           '#B0E0E6',
-    'purple':               '#800080',
-    'rebeccapurple':        '#663399',
-    'red':                  '#FF0000',
-    'rosybrown':            '#BC8F8F',
-    'royalblue':            '#4169E1',
-    'saddlebrown':          '#8B4513',
-    'salmon':               '#FA8072',
-    'sandybrown':           '#F4A460',
-    'seagreen':             '#2E8B57',
-    'seashell':             '#FFF5EE',
-    'sienna':               '#A0522D',
-    'silver':               '#C0C0C0',
-    'skyblue':              '#87CEEB',
-    'slateblue':            '#6A5ACD',
-    'slategray':            '#708090',
-    'slategrey':            '#708090',
-    'snow':                 '#FFFAFA',
-    'springgreen':          '#00FF7F',
-    'steelblue':            '#4682B4',
-    'tan':                  '#D2B48C',
-    'teal':                 '#008080',
-    'thistle':              '#D8BFD8',
-    'tomato':               '#FF6347',
-    'turquoise':            '#40E0D0',
-    'violet':               '#EE82EE',
-    'wheat':                '#F5DEB3',
-    'white':                '#FFFFFF',
-    'whitesmoke':           '#F5F5F5',
-    'yellow':               '#FFFF00',
-    'yellowgreen':          '#9ACD32'}

+ 0 - 726
venv/lib/python3.8/site-packages/matplotlib/_constrained_layout.py

@@ -1,726 +0,0 @@
-"""
-This module provides the routine to adjust subplot layouts so that there are
-no overlapping axes or axes decorations.  All axes decorations are dealt with
-(labels, ticks, titles, ticklabels) and some dependent artists are also dealt
-with (colorbar, suptitle, legend).
-
-Layout is done via :meth:`~matplotlib.gridspec`, with one constraint per
-gridspec, so it is possible to have overlapping axes if the gridspecs
-overlap (i.e. using :meth:`~matplotlib.gridspec.GridSpecFromSubplotSpec`).
-Axes placed using ``figure.subplots()`` or ``figure.add_subplots()`` will
-participate in the layout.  Axes manually placed via ``figure.add_axes()``
-will not.
-
-See Tutorial: :doc:`/tutorials/intermediate/constrainedlayout_guide`
-
-"""
-
-# Development Notes:
-
-# What gets a layoutbox:
-#  - figure
-#    - gridspec
-#      - subplotspec
-#        EITHER:
-#         - axes + pos for the axes (i.e. the total area taken by axis and
-#            the actual "position" argument that needs to be sent to
-#             ax.set_position.)
-#           - The axes layout box will also encompass the legend, and that is
-#             how legends get included (axes legends, not figure legends)
-#         - colorbars are siblings of the axes if they are single-axes
-#           colorbars
-#        OR:
-#         - a gridspec can be inside a subplotspec.
-#           - subplotspec
-#           EITHER:
-#            - axes...
-#           OR:
-#            - gridspec... with arbitrary nesting...
-#      - colorbars are siblings of the subplotspecs if they are multi-axes
-#        colorbars.
-#   - suptitle:
-#      - right now suptitles are just stacked atop everything else in figure.
-#        Could imagine suptitles being gridspec suptitles, but not implemented
-#
-#   Todo:    AnchoredOffsetbox connected to gridspecs or axes.  This would
-#        be more general way to add extra-axes annotations.
-
-import logging
-
-import numpy as np
-
-import matplotlib.cbook as cbook
-import matplotlib._layoutbox as layoutbox
-
-_log = logging.getLogger(__name__)
-
-
-def _in_same_column(colnum0min, colnum0max, colnumCmin, colnumCmax):
-    return (colnumCmin <= colnum0min <= colnumCmax
-            or colnumCmin <= colnum0max <= colnumCmax)
-
-
-def _in_same_row(rownum0min, rownum0max, rownumCmin, rownumCmax):
-    return (rownumCmin <= rownum0min <= rownumCmax
-            or rownumCmin <= rownum0max <= rownumCmax)
-
-
-def _axes_all_finite_sized(fig):
-    """Return whether all axes in the figure have a finite width and height."""
-    for ax in fig.axes:
-        if ax._layoutbox is not None:
-            newpos = ax._poslayoutbox.get_rect()
-            if newpos[2] <= 0 or newpos[3] <= 0:
-                return False
-    return True
-
-
-######################################################
-def do_constrained_layout(fig, renderer, h_pad, w_pad,
-        hspace=None, wspace=None):
-    """
-    Do the constrained_layout.  Called at draw time in
-     ``figure.constrained_layout()``
-
-    Parameters
-    ----------
-    fig : Figure
-      is the ``figure`` instance to do the layout in.
-
-    renderer : Renderer
-      the renderer to use.
-
-     h_pad, w_pad : float
-       are in figure-normalized units, and are a padding around the axes
-       elements.
-
-     hspace, wspace : float
-        are in fractions of the subplot sizes.
-
-    """
-
-    # Steps:
-    #
-    # 1. get a list of unique gridspecs in this figure.  Each gridspec will be
-    # constrained separately.
-    # 2. Check for gaps in the gridspecs.  i.e. if not every axes slot in the
-    # gridspec has been filled.  If empty, add a ghost axis that is made so
-    # that it cannot be seen (though visible=True).  This is needed to make
-    # a blank spot in the layout.
-    # 3. Compare the tight_bbox of each axes to its `position`, and assume that
-    # the difference is the space needed by the elements around the edge of
-    # the axes (decorations) like the title, ticklabels, x-labels, etc.  This
-    # can include legends who overspill the axes boundaries.
-    # 4. Constrain gridspec elements to line up:
-    #     a) if colnum0 != colnumC, the two subplotspecs are stacked next to
-    #     each other, with the appropriate order.
-    #     b) if colnum0 == colnumC, line up the left or right side of the
-    #     _poslayoutbox (depending if it is the min or max num that is equal).
-    #     c) do the same for rows...
-    # 5. The above doesn't constrain relative sizes of the _poslayoutboxes
-    # at all, and indeed zero-size is a solution that the solver often finds
-    # more convenient than expanding the sizes.  Right now the solution is to
-    # compare subplotspec sizes (i.e. drowsC and drows0) and constrain the
-    # larger _poslayoutbox to be larger than the ratio of the sizes. i.e. if
-    # drows0 > drowsC, then ax._poslayoutbox > axc._poslayoutbox*drowsC/drows0.
-    # This works fine *if* the decorations are similar between the axes.
-    # If the larger subplotspec has much larger axes decorations, then the
-    # constraint above is incorrect.
-    #
-    # We need the greater than in the above, in general, rather than an equals
-    # sign.  Consider the case of the left column having 2 rows, and the right
-    # column having 1 row.  We want the top and bottom of the _poslayoutboxes
-    # to line up. So that means if there are decorations on the left column
-    # axes they will be smaller than half as large as the right hand axis.
-    #
-    # This can break down if the decoration size for the right hand axis (the
-    # margins) is very large.  There must be a math way to check for this case.
-
-    invTransFig = fig.transFigure.inverted().transform_bbox
-
-    # list of unique gridspecs that contain child axes:
-    gss = set()
-    for ax in fig.axes:
-        if hasattr(ax, 'get_subplotspec'):
-            gs = ax.get_subplotspec().get_gridspec()
-            if gs._layoutbox is not None:
-                gss.add(gs)
-    if len(gss) == 0:
-        cbook._warn_external('There are no gridspecs with layoutboxes. '
-                             'Possibly did not call parent GridSpec with the'
-                             ' figure= keyword')
-
-    if fig._layoutbox.constrained_layout_called < 1:
-        for gs in gss:
-            # fill in any empty gridspec slots w/ ghost axes...
-            _make_ghost_gridspec_slots(fig, gs)
-
-    for nnn in range(2):
-        # do the algorithm twice.  This has to be done because decorators
-        # change size after the first re-position (i.e. x/yticklabels get
-        # larger/smaller).  This second reposition tends to be much milder,
-        # so doing twice makes things work OK.
-        for ax in fig.axes:
-            _log.debug(ax._layoutbox)
-            if ax._layoutbox is not None:
-                # make margins for each layout box based on the size of
-                # the decorators.
-                _make_layout_margins(ax, renderer, h_pad, w_pad)
-
-        # do layout for suptitle.
-        suptitle = fig._suptitle
-        do_suptitle = (suptitle is not None and
-                       suptitle._layoutbox is not None and
-                       suptitle.get_in_layout())
-        if do_suptitle:
-            bbox = invTransFig(
-                suptitle.get_window_extent(renderer=renderer))
-            height = bbox.y1 - bbox.y0
-            if np.isfinite(height):
-                # reserve at top of figure include an h_pad above and below
-                suptitle._layoutbox.edit_height(height + h_pad * 2)
-
-        # OK, the above lines up ax._poslayoutbox with ax._layoutbox
-        # now we need to
-        #   1) arrange the subplotspecs.  We do it at this level because
-        #      the subplotspecs are meant to contain other dependent axes
-        #      like colorbars or legends.
-        #   2) line up the right and left side of the ax._poslayoutbox
-        #      that have the same subplotspec maxes.
-
-        if fig._layoutbox.constrained_layout_called < 1:
-            # arrange the subplotspecs...  This is all done relative to each
-            # other.  Some subplotspecs contain axes, and others contain
-            # gridspecs the ones that contain gridspecs are a set proportion
-            # of their parent gridspec.  The ones that contain axes are
-            # not so constrained.
-            figlb = fig._layoutbox
-            for child in figlb.children:
-                if child._is_gridspec_layoutbox():
-                    # This routine makes all the subplot spec containers
-                    # have the correct arrangement.  It just stacks the
-                    # subplot layoutboxes in the correct order...
-                    _arrange_subplotspecs(child, hspace=hspace, wspace=wspace)
-
-            for gs in gss:
-                _align_spines(fig, gs)
-
-        fig._layoutbox.constrained_layout_called += 1
-        fig._layoutbox.update_variables()
-
-        # check if any axes collapsed to zero.  If not, don't change positions:
-        if _axes_all_finite_sized(fig):
-            # Now set the position of the axes...
-            for ax in fig.axes:
-                if ax._layoutbox is not None:
-                    newpos = ax._poslayoutbox.get_rect()
-                    # Now set the new position.
-                    # ax.set_position will zero out the layout for
-                    # this axis, allowing users to hard-code the position,
-                    # so this does the same w/o zeroing layout.
-                    ax._set_position(newpos, which='original')
-            if do_suptitle:
-                newpos = suptitle._layoutbox.get_rect()
-                suptitle.set_y(1.0 - h_pad)
-            else:
-                if suptitle is not None and suptitle._layoutbox is not None:
-                    suptitle._layoutbox.edit_height(0)
-        else:
-            cbook._warn_external('constrained_layout not applied.  At least '
-                                 'one axes collapsed to zero width or height.')
-
-
-def _make_ghost_gridspec_slots(fig, gs):
-    """
-    Check for unoccupied gridspec slots and make ghost axes for these
-    slots...  Do for each gs separately.  This is a pretty big kludge
-    but shouldn't have too much ill effect.  The worst is that
-    someone querying the figure will wonder why there are more
-    axes than they thought.
-    """
-    nrows, ncols = gs.get_geometry()
-    hassubplotspec = np.zeros(nrows * ncols, dtype=bool)
-    axs = []
-    for ax in fig.axes:
-        if (hasattr(ax, 'get_subplotspec')
-                and ax._layoutbox is not None
-                and ax.get_subplotspec().get_gridspec() == gs):
-            axs += [ax]
-    for ax in axs:
-        ss0 = ax.get_subplotspec()
-        hassubplotspec[ss0.num1:(ss0.num2 + 1)] = True
-    for nn, hss in enumerate(hassubplotspec):
-        if not hss:
-            # this gridspec slot doesn't have an axis so we
-            # make a "ghost".
-            ax = fig.add_subplot(gs[nn])
-            ax.set_visible(False)
-
-
-def _make_layout_margins(ax, renderer, h_pad, w_pad):
-    """
-    For each axes, make a margin between the *pos* layoutbox and the
-    *axes* layoutbox be a minimum size that can accommodate the
-    decorations on the axis.
-    """
-    fig = ax.figure
-    invTransFig = fig.transFigure.inverted().transform_bbox
-    pos = ax.get_position(original=True)
-    tightbbox = ax.get_tightbbox(renderer=renderer)
-    if tightbbox is None:
-        bbox = pos
-    else:
-        bbox = invTransFig(tightbbox)
-
-    # this can go wrong:
-    if not (np.isfinite(bbox.width) and np.isfinite(bbox.height)):
-        # just abort, this is likely a bad set of co-ordinates that
-        # is transitory...
-        return
-    # use stored h_pad if it exists
-    h_padt = ax._poslayoutbox.h_pad
-    if h_padt is None:
-        h_padt = h_pad
-    w_padt = ax._poslayoutbox.w_pad
-    if w_padt is None:
-        w_padt = w_pad
-    ax._poslayoutbox.edit_left_margin_min(-bbox.x0 +
-            pos.x0 + w_padt)
-    ax._poslayoutbox.edit_right_margin_min(bbox.x1 -
-            pos.x1 + w_padt)
-    ax._poslayoutbox.edit_bottom_margin_min(
-            -bbox.y0 + pos.y0 + h_padt)
-    ax._poslayoutbox.edit_top_margin_min(bbox.y1-pos.y1+h_padt)
-    _log.debug('left %f', (-bbox.x0 + pos.x0 + w_pad))
-    _log.debug('right %f', (bbox.x1 - pos.x1 + w_pad))
-    _log.debug('bottom %f', (-bbox.y0 + pos.y0 + h_padt))
-    _log.debug('bbox.y0 %f', bbox.y0)
-    _log.debug('pos.y0 %f', pos.y0)
-    # Sometimes its possible for the solver to collapse
-    # rather than expand axes, so they all have zero height
-    # or width.  This stops that...  It *should* have been
-    # taken into account w/ pref_width...
-    if fig._layoutbox.constrained_layout_called < 1:
-        ax._poslayoutbox.constrain_height_min(20, strength='weak')
-        ax._poslayoutbox.constrain_width_min(20, strength='weak')
-        ax._layoutbox.constrain_height_min(20, strength='weak')
-        ax._layoutbox.constrain_width_min(20, strength='weak')
-        ax._poslayoutbox.constrain_top_margin(0, strength='weak')
-        ax._poslayoutbox.constrain_bottom_margin(0,
-                strength='weak')
-        ax._poslayoutbox.constrain_right_margin(0, strength='weak')
-        ax._poslayoutbox.constrain_left_margin(0, strength='weak')
-
-
-def _align_spines(fig, gs):
-    """
-    - Align right/left and bottom/top spines of appropriate subplots.
-    - Compare size of subplotspec including height and width ratios
-       and make sure that the axes spines are at least as large
-       as they should be.
-    """
-    # for each gridspec...
-    nrows, ncols = gs.get_geometry()
-    width_ratios = gs.get_width_ratios()
-    height_ratios = gs.get_height_ratios()
-    if width_ratios is None:
-        width_ratios = np.ones(ncols)
-    if height_ratios is None:
-        height_ratios = np.ones(nrows)
-
-    # get axes in this gridspec....
-    axs = []
-    for ax in fig.axes:
-        if (hasattr(ax, 'get_subplotspec')
-                and ax._layoutbox is not None):
-            if ax.get_subplotspec().get_gridspec() == gs:
-                axs += [ax]
-    rownummin = np.zeros(len(axs), dtype=np.int8)
-    rownummax = np.zeros(len(axs), dtype=np.int8)
-    colnummin = np.zeros(len(axs), dtype=np.int8)
-    colnummax = np.zeros(len(axs), dtype=np.int8)
-    width = np.zeros(len(axs))
-    height = np.zeros(len(axs))
-
-    for n, ax in enumerate(axs):
-        ss0 = ax.get_subplotspec()
-        rownummin[n], colnummin[n] = divmod(ss0.num1, ncols)
-        rownummax[n], colnummax[n] = divmod(ss0.num2, ncols)
-        width[n] = np.sum(
-                width_ratios[colnummin[n]:(colnummax[n] + 1)])
-        height[n] = np.sum(
-                height_ratios[rownummin[n]:(rownummax[n] + 1)])
-
-    for nn, ax in enumerate(axs[:-1]):
-        # now compare ax to all the axs:
-        #
-        # If the subplotspecs have the same colnumXmax, then line
-        # up their right sides.  If they have the same min, then
-        # line up their left sides (and vertical equivalents).
-        rownum0min, colnum0min = rownummin[nn], colnummin[nn]
-        rownum0max, colnum0max = rownummax[nn], colnummax[nn]
-        width0, height0 = width[nn], height[nn]
-        alignleft = False
-        alignright = False
-        alignbot = False
-        aligntop = False
-        alignheight = False
-        alignwidth = False
-        for mm in range(nn+1, len(axs)):
-            axc = axs[mm]
-            rownumCmin, colnumCmin = rownummin[mm], colnummin[mm]
-            rownumCmax, colnumCmax = rownummax[mm], colnummax[mm]
-            widthC, heightC = width[mm], height[mm]
-            # Horizontally align axes spines if they have the
-            # same min or max:
-            if not alignleft and colnum0min == colnumCmin:
-                # we want the _poslayoutboxes to line up on left
-                # side of the axes spines...
-                layoutbox.align([ax._poslayoutbox,
-                                 axc._poslayoutbox],
-                                'left')
-                alignleft = True
-
-            if not alignright and colnum0max == colnumCmax:
-                # line up right sides of _poslayoutbox
-                layoutbox.align([ax._poslayoutbox,
-                                 axc._poslayoutbox],
-                                'right')
-                alignright = True
-            # Vertically align axes spines if they have the
-            # same min or max:
-            if not aligntop and rownum0min == rownumCmin:
-                # line up top of _poslayoutbox
-                _log.debug('rownum0min == rownumCmin')
-                layoutbox.align([ax._poslayoutbox, axc._poslayoutbox],
-                                'top')
-                aligntop = True
-
-            if not alignbot and rownum0max == rownumCmax:
-                # line up bottom of _poslayoutbox
-                _log.debug('rownum0max == rownumCmax')
-                layoutbox.align([ax._poslayoutbox, axc._poslayoutbox],
-                                'bottom')
-                alignbot = True
-            ###########
-            # Now we make the widths and heights of position boxes
-            # similar. (i.e the spine locations)
-            # This allows vertically stacked subplots to have
-            # different sizes if they occupy different amounts
-            # of the gridspec:  i.e.
-            # gs = gridspec.GridSpec(3, 1)
-            # ax1 = gs[0,:]
-            # ax2 = gs[1:,:]
-            # then drows0 = 1, and drowsC = 2, and ax2
-            # should be at least twice as large as ax1.
-            # But it can be more than twice as large because
-            # it needs less room for the labeling.
-            #
-            # For height, this only needs to be done if the
-            # subplots share a column.  For width if they
-            # share a row.
-
-            drowsC = (rownumCmax - rownumCmin + 1)
-            drows0 = (rownum0max - rownum0min + 1)
-            dcolsC = (colnumCmax - colnumCmin + 1)
-            dcols0 = (colnum0max - colnum0min + 1)
-
-            if not alignheight and drows0 == drowsC:
-                ax._poslayoutbox.constrain_height(
-                        axc._poslayoutbox.height * height0 / heightC)
-                alignheight = True
-            elif _in_same_column(colnum0min, colnum0max,
-                    colnumCmin, colnumCmax):
-                if height0 > heightC:
-                    ax._poslayoutbox.constrain_height_min(
-                        axc._poslayoutbox.height * height0 / heightC)
-                    # these constraints stop the smaller axes from
-                    # being allowed to go to zero height...
-                    axc._poslayoutbox.constrain_height_min(
-                        ax._poslayoutbox.height * heightC /
-                        (height0*1.8))
-                elif height0 < heightC:
-                    axc._poslayoutbox.constrain_height_min(
-                        ax._poslayoutbox.height * heightC / height0)
-                    ax._poslayoutbox.constrain_height_min(
-                        ax._poslayoutbox.height * height0 /
-                        (heightC*1.8))
-            # widths...
-            if not alignwidth and dcols0 == dcolsC:
-                ax._poslayoutbox.constrain_width(
-                        axc._poslayoutbox.width * width0 / widthC)
-                alignwidth = True
-            elif _in_same_row(rownum0min, rownum0max,
-                    rownumCmin, rownumCmax):
-                if width0 > widthC:
-                    ax._poslayoutbox.constrain_width_min(
-                            axc._poslayoutbox.width * width0 / widthC)
-                    axc._poslayoutbox.constrain_width_min(
-                            ax._poslayoutbox.width * widthC /
-                            (width0*1.8))
-                elif width0 < widthC:
-                    axc._poslayoutbox.constrain_width_min(
-                            ax._poslayoutbox.width * widthC / width0)
-                    ax._poslayoutbox.constrain_width_min(
-                            axc._poslayoutbox.width * width0 /
-                            (widthC*1.8))
-
-
-def _arrange_subplotspecs(gs, hspace=0, wspace=0):
-    """Recursively arrange the subplotspec children of the given gridspec."""
-    sschildren = []
-    for child in gs.children:
-        if child._is_subplotspec_layoutbox():
-            for child2 in child.children:
-                # check for gridspec children...
-                if child2._is_gridspec_layoutbox():
-                    _arrange_subplotspecs(child2, hspace=hspace, wspace=wspace)
-            sschildren += [child]
-    # now arrange the subplots...
-    for child0 in sschildren:
-        ss0 = child0.artist
-        nrows, ncols = ss0.get_gridspec().get_geometry()
-        rowNum0min, colNum0min = divmod(ss0.num1, ncols)
-        rowNum0max, colNum0max = divmod(ss0.num2, ncols)
-        sschildren = sschildren[1:]
-        for childc in sschildren:
-            ssc = childc.artist
-            rowNumCmin, colNumCmin = divmod(ssc.num1, ncols)
-            rowNumCmax, colNumCmax = divmod(ssc.num2, ncols)
-            # OK, this tells us the relative layout of ax
-            # with axc
-            thepad = wspace / ncols
-            if colNum0max < colNumCmin:
-                layoutbox.hstack([ss0._layoutbox, ssc._layoutbox],
-                        padding=thepad)
-            if colNumCmax < colNum0min:
-                layoutbox.hstack([ssc._layoutbox, ss0._layoutbox],
-                        padding=thepad)
-
-            ####
-            # vertical alignment
-            thepad = hspace / nrows
-            if rowNum0max < rowNumCmin:
-                layoutbox.vstack([ss0._layoutbox,
-                                 ssc._layoutbox],
-                                 padding=thepad)
-            if rowNumCmax < rowNum0min:
-                layoutbox.vstack([ssc._layoutbox,
-                                  ss0._layoutbox],
-                                  padding=thepad)
-
-
-def layoutcolorbarsingle(ax, cax, shrink, aspect, location, pad=0.05):
-    """
-    Do the layout for a colorbar, to not overly pollute colorbar.py
-
-    *pad* is in fraction of the original axis size.
-    """
-    axlb = ax._layoutbox
-    axpos = ax._poslayoutbox
-    axsslb = ax.get_subplotspec()._layoutbox
-    lb = layoutbox.LayoutBox(
-            parent=axsslb,
-            name=axsslb.name + '.cbar',
-            artist=cax)
-
-    if location in ('left', 'right'):
-        lbpos = layoutbox.LayoutBox(
-                parent=lb,
-                name=lb.name + '.pos',
-                tightwidth=False,
-                pos=True,
-                subplot=False,
-                artist=cax)
-
-        if location == 'right':
-            # arrange to right of parent axis
-            layoutbox.hstack([axlb, lb], padding=pad * axlb.width,
-                             strength='strong')
-        else:
-            layoutbox.hstack([lb, axlb], padding=pad * axlb.width)
-        # constrain the height and center...
-        layoutbox.match_heights([axpos, lbpos], [1, shrink])
-        layoutbox.align([axpos, lbpos], 'v_center')
-        # set the width of the pos box
-        lbpos.constrain_width(shrink * axpos.height * (1/aspect),
-                              strength='strong')
-    elif location in ('bottom', 'top'):
-        lbpos = layoutbox.LayoutBox(
-                parent=lb,
-                name=lb.name + '.pos',
-                tightheight=True,
-                pos=True,
-                subplot=False,
-                artist=cax)
-
-        if location == 'bottom':
-            layoutbox.vstack([axlb, lb], padding=pad * axlb.height)
-        else:
-            layoutbox.vstack([lb, axlb], padding=pad * axlb.height)
-        # constrain the height and center...
-        layoutbox.match_widths([axpos, lbpos],
-                               [1, shrink], strength='strong')
-        layoutbox.align([axpos, lbpos], 'h_center')
-        # set the height of the pos box
-        lbpos.constrain_height(axpos.width * aspect * shrink,
-                                strength='medium')
-
-    return lb, lbpos
-
-
-def _getmaxminrowcolumn(axs):
-    # helper to get the min/max rows and columns of a list of axes.
-    maxrow = -100000
-    minrow = 1000000
-    maxax = None
-    minax = None
-    maxcol = -100000
-    mincol = 1000000
-    maxax_col = None
-    minax_col = None
-
-    for ax in axs:
-        subspec = ax.get_subplotspec()
-        nrows, ncols, row_start, row_stop, col_start, col_stop = \
-            subspec.get_rows_columns()
-        if row_stop > maxrow:
-            maxrow = row_stop
-            maxax = ax
-        if row_start < minrow:
-            minrow = row_start
-            minax = ax
-        if col_stop > maxcol:
-            maxcol = col_stop
-            maxax_col = ax
-        if col_start < mincol:
-            mincol = col_start
-            minax_col = ax
-    return (minrow, maxrow, minax, maxax, mincol, maxcol, minax_col, maxax_col)
-
-
-def layoutcolorbargridspec(parents, cax, shrink, aspect, location, pad=0.05):
-    """
-    Do the layout for a colorbar, to not overly pollute colorbar.py
-
-    *pad* is in fraction of the original axis size.
-    """
-
-    gs = parents[0].get_subplotspec().get_gridspec()
-    # parent layout box....
-    gslb = gs._layoutbox
-
-    lb = layoutbox.LayoutBox(parent=gslb.parent,
-                             name=gslb.parent.name + '.cbar',
-                             artist=cax)
-    # figure out the row and column extent of the parents.
-    (minrow, maxrow, minax_row, maxax_row,
-     mincol, maxcol, minax_col, maxax_col) = _getmaxminrowcolumn(parents)
-
-    if location in ('left', 'right'):
-        lbpos = layoutbox.LayoutBox(
-                parent=lb,
-                name=lb.name + '.pos',
-                tightwidth=False,
-                pos=True,
-                subplot=False,
-                artist=cax)
-        for ax in parents:
-            if location == 'right':
-                order = [ax._layoutbox, lb]
-            else:
-                order = [lb, ax._layoutbox]
-            layoutbox.hstack(order, padding=pad * gslb.width,
-                         strength='strong')
-        # constrain the height and center...
-        # This isn't quite right.  We'd like the colorbar
-        # pos to line up w/ the axes poss, not the size of the
-        # gs.
-
-        # Horizontal Layout: need to check all the axes in this gridspec
-        for ch in gslb.children:
-            subspec = ch.artist
-            nrows, ncols, row_start, row_stop, col_start, col_stop = \
-                subspec.get_rows_columns()
-            if location == 'right':
-                if col_stop <= maxcol:
-                    order = [subspec._layoutbox, lb]
-                    # arrange to right of the parents
-                if col_start > maxcol:
-                    order = [lb, subspec._layoutbox]
-            elif location == 'left':
-                if col_start >= mincol:
-                    order = [lb, subspec._layoutbox]
-                if col_stop < mincol:
-                    order = [subspec._layoutbox, lb]
-            layoutbox.hstack(order, padding=pad * gslb.width,
-                             strength='strong')
-
-        # Vertical layout:
-        maxposlb = minax_row._poslayoutbox
-        minposlb = maxax_row._poslayoutbox
-        # now we want the height of the colorbar pos to be
-        # set by the top and bottom of the min/max axes...
-        # bottom            top
-        #     b             t
-        # h = (top-bottom)*shrink
-        # b = bottom + (top-bottom - h) / 2.
-        lbpos.constrain_height(
-                (maxposlb.top - minposlb.bottom) *
-                shrink, strength='strong')
-        lbpos.constrain_bottom(
-                (maxposlb.top - minposlb.bottom) *
-                (1 - shrink)/2 + minposlb.bottom,
-                strength='strong')
-
-        # set the width of the pos box
-        lbpos.constrain_width(lbpos.height * (shrink / aspect),
-                              strength='strong')
-    elif location in ('bottom', 'top'):
-        lbpos = layoutbox.LayoutBox(
-                parent=lb,
-                name=lb.name + '.pos',
-                tightheight=True,
-                pos=True,
-                subplot=False,
-                artist=cax)
-
-        for ax in parents:
-            if location == 'bottom':
-                order = [ax._layoutbox, lb]
-            else:
-                order = [lb, ax._layoutbox]
-            layoutbox.vstack(order, padding=pad * gslb.width,
-                         strength='strong')
-
-        # Vertical Layout: need to check all the axes in this gridspec
-        for ch in gslb.children:
-            subspec = ch.artist
-            nrows, ncols, row_start, row_stop, col_start, col_stop = \
-                subspec.get_rows_columns()
-            if location == 'bottom':
-                if row_stop <= minrow:
-                    order = [subspec._layoutbox, lb]
-                if row_start > maxrow:
-                    order = [lb, subspec._layoutbox]
-            elif location == 'top':
-                if row_stop < minrow:
-                    order = [subspec._layoutbox, lb]
-                if row_start >= maxrow:
-                    order = [lb, subspec._layoutbox]
-            layoutbox.vstack(order, padding=pad * gslb.width,
-                             strength='strong')
-
-        # Do horizontal layout...
-        maxposlb = maxax_col._poslayoutbox
-        minposlb = minax_col._poslayoutbox
-        lbpos.constrain_width((maxposlb.right - minposlb.left) *
-                              shrink)
-        lbpos.constrain_left(
-                (maxposlb.right - minposlb.left) *
-                (1-shrink)/2 + minposlb.left)
-        # set the height of the pos box
-        lbpos.constrain_height(lbpos.width * shrink * aspect,
-                               strength='medium')
-
-    return lb, lbpos

BIN
venv/lib/python3.8/site-packages/matplotlib/_contour.cpython-38-x86_64-linux-gnu.so


BIN
venv/lib/python3.8/site-packages/matplotlib/_image.cpython-38-x86_64-linux-gnu.so


+ 0 - 711
venv/lib/python3.8/site-packages/matplotlib/_layoutbox.py

@@ -1,711 +0,0 @@
-"""
-
-Conventions:
-
-"constrain_x" means to constrain the variable with either
-another kiwisolver variable, or a float.  i.e. `constrain_width(0.2)`
-will set a constraint that the width has to be 0.2 and this constraint is
-permanent - i.e. it will not be removed if it becomes obsolete.
-
-"edit_x" means to set x to a value (just a float), and that this value can
-change.  So `edit_width(0.2)` will set width to be 0.2, but `edit_width(0.3)`
-will allow it to change to 0.3 later.  Note that these values are still just
-"suggestions" in `kiwisolver` parlance, and could be over-ridden by
-other constrains.
-
-"""
-
-import itertools
-import kiwisolver as kiwi
-import logging
-import numpy as np
-
-
-_log = logging.getLogger(__name__)
-
-
-# renderers can be complicated
-def get_renderer(fig):
-    if fig._cachedRenderer:
-        renderer = fig._cachedRenderer
-    else:
-        canvas = fig.canvas
-        if canvas and hasattr(canvas, "get_renderer"):
-            renderer = canvas.get_renderer()
-        else:
-            # not sure if this can happen
-            # seems to with PDF...
-            _log.info("constrained_layout : falling back to Agg renderer")
-            from matplotlib.backends.backend_agg import FigureCanvasAgg
-            canvas = FigureCanvasAgg(fig)
-            renderer = canvas.get_renderer()
-
-    return renderer
-
-
-class LayoutBox:
-    """
-    Basic rectangle representation using kiwi solver variables
-    """
-
-    def __init__(self, parent=None, name='', tightwidth=False,
-                 tightheight=False, artist=None,
-                 lower_left=(0, 0), upper_right=(1, 1), pos=False,
-                 subplot=False, h_pad=None, w_pad=None):
-        Variable = kiwi.Variable
-        self.parent = parent
-        self.name = name
-        sn = self.name + '_'
-        if parent is None:
-            self.solver = kiwi.Solver()
-            self.constrained_layout_called = 0
-        else:
-            self.solver = parent.solver
-            self.constrained_layout_called = None
-            # parent wants to know about this child!
-            parent.add_child(self)
-        # keep track of artist associated w/ this layout.  Can be none
-        self.artist = artist
-        # keep track if this box is supposed to be a pos that is constrained
-        # by the parent.
-        self.pos = pos
-        # keep track of whether we need to match this subplot up with others.
-        self.subplot = subplot
-
-        # we need the str below for Py 2 which complains the string is unicode
-        self.top = Variable(str(sn + 'top'))
-        self.bottom = Variable(str(sn + 'bottom'))
-        self.left = Variable(str(sn + 'left'))
-        self.right = Variable(str(sn + 'right'))
-
-        self.width = Variable(str(sn + 'width'))
-        self.height = Variable(str(sn + 'height'))
-        self.h_center = Variable(str(sn + 'h_center'))
-        self.v_center = Variable(str(sn + 'v_center'))
-
-        self.min_width = Variable(str(sn + 'min_width'))
-        self.min_height = Variable(str(sn + 'min_height'))
-        self.pref_width = Variable(str(sn + 'pref_width'))
-        self.pref_height = Variable(str(sn + 'pref_height'))
-        # margins are only used for axes-position layout boxes.  maybe should
-        # be a separate subclass:
-        self.left_margin = Variable(str(sn + 'left_margin'))
-        self.right_margin = Variable(str(sn + 'right_margin'))
-        self.bottom_margin = Variable(str(sn + 'bottom_margin'))
-        self.top_margin = Variable(str(sn + 'top_margin'))
-        # mins
-        self.left_margin_min = Variable(str(sn + 'left_margin_min'))
-        self.right_margin_min = Variable(str(sn + 'right_margin_min'))
-        self.bottom_margin_min = Variable(str(sn + 'bottom_margin_min'))
-        self.top_margin_min = Variable(str(sn + 'top_margin_min'))
-
-        right, top = upper_right
-        left, bottom = lower_left
-        self.tightheight = tightheight
-        self.tightwidth = tightwidth
-        self.add_constraints()
-        self.children = []
-        self.subplotspec = None
-        if self.pos:
-            self.constrain_margins()
-        self.h_pad = h_pad
-        self.w_pad = w_pad
-
-    def constrain_margins(self):
-        """
-        Only do this for pos.  This sets a variable distance
-        margin between the position of the axes and the outer edge of
-        the axes.
-
-        Margins are variable because they change with the figure size.
-
-        Margin minimums are set to make room for axes decorations.  However,
-        the margins can be larger if we are mathicng the position size to
-        other axes.
-        """
-        sol = self.solver
-
-        # left
-        if not sol.hasEditVariable(self.left_margin_min):
-            sol.addEditVariable(self.left_margin_min, 'strong')
-            sol.suggestValue(self.left_margin_min, 0.0001)
-        c = (self.left_margin == self.left - self.parent.left)
-        self.solver.addConstraint(c | 'required')
-        c = (self.left_margin >= self.left_margin_min)
-        self.solver.addConstraint(c | 'strong')
-
-        # right
-        if not sol.hasEditVariable(self.right_margin_min):
-            sol.addEditVariable(self.right_margin_min, 'strong')
-            sol.suggestValue(self.right_margin_min, 0.0001)
-        c = (self.right_margin == self.parent.right - self.right)
-        self.solver.addConstraint(c | 'required')
-        c = (self.right_margin >= self.right_margin_min)
-        self.solver.addConstraint(c | 'required')
-        # bottom
-        if not sol.hasEditVariable(self.bottom_margin_min):
-            sol.addEditVariable(self.bottom_margin_min, 'strong')
-            sol.suggestValue(self.bottom_margin_min, 0.0001)
-        c = (self.bottom_margin == self.bottom - self.parent.bottom)
-        self.solver.addConstraint(c | 'required')
-        c = (self.bottom_margin >= self.bottom_margin_min)
-        self.solver.addConstraint(c | 'required')
-        # top
-        if not sol.hasEditVariable(self.top_margin_min):
-            sol.addEditVariable(self.top_margin_min, 'strong')
-            sol.suggestValue(self.top_margin_min, 0.0001)
-        c = (self.top_margin == self.parent.top - self.top)
-        self.solver.addConstraint(c | 'required')
-        c = (self.top_margin >= self.top_margin_min)
-        self.solver.addConstraint(c | 'required')
-
-    def add_child(self, child):
-        self.children += [child]
-
-    def remove_child(self, child):
-        try:
-            self.children.remove(child)
-        except ValueError:
-            _log.info("Tried to remove child that doesn't belong to parent")
-
-    def add_constraints(self):
-        sol = self.solver
-        # never let width and height go negative.
-        for i in [self.min_width, self.min_height]:
-            sol.addEditVariable(i, 1e9)
-            sol.suggestValue(i, 0.0)
-        # define relation ships between things thing width and right and left
-        self.hard_constraints()
-        # self.soft_constraints()
-        if self.parent:
-            self.parent_constrain()
-        # sol.updateVariables()
-
-    def parent_constrain(self):
-        parent = self.parent
-        hc = [self.left >= parent.left,
-              self.bottom >= parent.bottom,
-              self.top <= parent.top,
-              self.right <= parent.right]
-        for c in hc:
-            self.solver.addConstraint(c | 'required')
-
-    def hard_constraints(self):
-        hc = [self.width == self.right - self.left,
-              self.height == self.top - self.bottom,
-              self.h_center == (self.left + self.right) * 0.5,
-              self.v_center == (self.top + self.bottom) * 0.5,
-              self.width >= self.min_width,
-              self.height >= self.min_height]
-        for c in hc:
-            self.solver.addConstraint(c | 'required')
-
-    def soft_constraints(self):
-        sol = self.solver
-        if self.tightwidth:
-            suggest = 0.
-        else:
-            suggest = 20.
-        c = (self.pref_width == suggest)
-        for i in c:
-            sol.addConstraint(i | 'required')
-        if self.tightheight:
-            suggest = 0.
-        else:
-            suggest = 20.
-        c = (self.pref_height == suggest)
-        for i in c:
-            sol.addConstraint(i | 'required')
-
-        c = [(self.width >= suggest),
-             (self.height >= suggest)]
-        for i in c:
-            sol.addConstraint(i | 150000)
-
-    def set_parent(self, parent):
-        """Replace the parent of this with the new parent."""
-        self.parent = parent
-        self.parent_constrain()
-
-    def constrain_geometry(self, left, bottom, right, top, strength='strong'):
-        hc = [self.left == left,
-              self.right == right,
-              self.bottom == bottom,
-              self.top == top]
-        for c in hc:
-            self.solver.addConstraint(c | strength)
-        # self.solver.updateVariables()
-
-    def constrain_same(self, other, strength='strong'):
-        """
-        Make the layoutbox have same position as other layoutbox
-        """
-        hc = [self.left == other.left,
-              self.right == other.right,
-              self.bottom == other.bottom,
-              self.top == other.top]
-        for c in hc:
-            self.solver.addConstraint(c | strength)
-
-    def constrain_left_margin(self, margin, strength='strong'):
-        c = (self.left == self.parent.left + margin)
-        self.solver.addConstraint(c | strength)
-
-    def edit_left_margin_min(self, margin):
-        self.solver.suggestValue(self.left_margin_min, margin)
-
-    def constrain_right_margin(self, margin, strength='strong'):
-        c = (self.right == self.parent.right - margin)
-        self.solver.addConstraint(c | strength)
-
-    def edit_right_margin_min(self, margin):
-        self.solver.suggestValue(self.right_margin_min, margin)
-
-    def constrain_bottom_margin(self, margin, strength='strong'):
-        c = (self.bottom == self.parent.bottom + margin)
-        self.solver.addConstraint(c | strength)
-
-    def edit_bottom_margin_min(self, margin):
-        self.solver.suggestValue(self.bottom_margin_min, margin)
-
-    def constrain_top_margin(self, margin, strength='strong'):
-        c = (self.top == self.parent.top - margin)
-        self.solver.addConstraint(c | strength)
-
-    def edit_top_margin_min(self, margin):
-        self.solver.suggestValue(self.top_margin_min, margin)
-
-    def get_rect(self):
-        return (self.left.value(), self.bottom.value(),
-                self.width.value(), self.height.value())
-
-    def update_variables(self):
-        '''
-        Update *all* the variables that are part of the solver this LayoutBox
-        is created with
-        '''
-        self.solver.updateVariables()
-
-    def edit_height(self, height, strength='strong'):
-        '''
-        Set the height of the layout box.
-
-        This is done as an editable variable so that the value can change
-        due to resizing.
-        '''
-        sol = self.solver
-        for i in [self.height]:
-            if not sol.hasEditVariable(i):
-                sol.addEditVariable(i, strength)
-        sol.suggestValue(self.height, height)
-
-    def constrain_height(self, height, strength='strong'):
-        '''
-        Constrain the height of the layout box.  height is
-        either a float or a layoutbox.height.
-        '''
-        c = (self.height == height)
-        self.solver.addConstraint(c | strength)
-
-    def constrain_height_min(self, height, strength='strong'):
-        c = (self.height >= height)
-        self.solver.addConstraint(c | strength)
-
-    def edit_width(self, width, strength='strong'):
-        sol = self.solver
-        for i in [self.width]:
-            if not sol.hasEditVariable(i):
-                sol.addEditVariable(i, strength)
-        sol.suggestValue(self.width, width)
-
-    def constrain_width(self, width, strength='strong'):
-        """
-        Constrain the width of the layout box.  *width* is
-        either a float or a layoutbox.width.
-        """
-        c = (self.width == width)
-        self.solver.addConstraint(c | strength)
-
-    def constrain_width_min(self, width, strength='strong'):
-        c = (self.width >= width)
-        self.solver.addConstraint(c | strength)
-
-    def constrain_left(self, left,  strength='strong'):
-        c = (self.left == left)
-        self.solver.addConstraint(c | strength)
-
-    def constrain_bottom(self, bottom, strength='strong'):
-        c = (self.bottom == bottom)
-        self.solver.addConstraint(c | strength)
-
-    def constrain_right(self, right, strength='strong'):
-        c = (self.right == right)
-        self.solver.addConstraint(c | strength)
-
-    def constrain_top(self, top, strength='strong'):
-        c = (self.top == top)
-        self.solver.addConstraint(c | strength)
-
-    def _is_subplotspec_layoutbox(self):
-        '''
-        Helper to check if this layoutbox is the layoutbox of a
-        subplotspec
-        '''
-        name = (self.name).split('.')[-1]
-        return name[:2] == 'ss'
-
-    def _is_gridspec_layoutbox(self):
-        '''
-        Helper to check if this layoutbox is the layoutbox of a
-        gridspec
-        '''
-        name = (self.name).split('.')[-1]
-        return name[:8] == 'gridspec'
-
-    def find_child_subplots(self):
-        '''
-        Find children of this layout box that are subplots.  We want to line
-        poss up, and this is an easy way to find them all.
-        '''
-        if self.subplot:
-            subplots = [self]
-        else:
-            subplots = []
-        for child in self.children:
-            subplots += child.find_child_subplots()
-        return subplots
-
-    def layout_from_subplotspec(self, subspec,
-                                name='', artist=None, pos=False):
-        """
-        Make a layout box from a subplotspec. The layout box is
-        constrained to be a fraction of the width/height of the parent,
-        and be a fraction of the parent width/height from the left/bottom
-        of the parent.  Therefore the parent can move around and the
-        layout for the subplot spec should move with it.
-
-        The parent is *usually* the gridspec that made the subplotspec.??
-        """
-        lb = LayoutBox(parent=self, name=name, artist=artist, pos=pos)
-        gs = subspec.get_gridspec()
-        nrows, ncols = gs.get_geometry()
-        parent = self.parent
-
-        # OK, now, we want to set the position of this subplotspec
-        # based on its subplotspec parameters.  The new gridspec will inherit
-        # from gridspec.  prob should be new method in gridspec
-        left = 0.0
-        right = 1.0
-        bottom = 0.0
-        top = 1.0
-        totWidth = right-left
-        totHeight = top-bottom
-        hspace = 0.
-        wspace = 0.
-
-        # calculate accumulated heights of columns
-        cellH = totHeight / (nrows + hspace * (nrows - 1))
-        sepH = hspace * cellH
-
-        if gs._row_height_ratios is not None:
-            netHeight = cellH * nrows
-            tr = sum(gs._row_height_ratios)
-            cellHeights = [netHeight * r / tr for r in gs._row_height_ratios]
-        else:
-            cellHeights = [cellH] * nrows
-
-        sepHeights = [0] + ([sepH] * (nrows - 1))
-        cellHs = np.cumsum(np.column_stack([sepHeights, cellHeights]).flat)
-
-        # calculate accumulated widths of rows
-        cellW = totWidth / (ncols + wspace * (ncols - 1))
-        sepW = wspace * cellW
-
-        if gs._col_width_ratios is not None:
-            netWidth = cellW * ncols
-            tr = sum(gs._col_width_ratios)
-            cellWidths = [netWidth * r / tr for r in gs._col_width_ratios]
-        else:
-            cellWidths = [cellW] * ncols
-
-        sepWidths = [0] + ([sepW] * (ncols - 1))
-        cellWs = np.cumsum(np.column_stack([sepWidths, cellWidths]).flat)
-
-        figTops = [top - cellHs[2 * rowNum] for rowNum in range(nrows)]
-        figBottoms = [top - cellHs[2 * rowNum + 1] for rowNum in range(nrows)]
-        figLefts = [left + cellWs[2 * colNum] for colNum in range(ncols)]
-        figRights = [left + cellWs[2 * colNum + 1] for colNum in range(ncols)]
-
-        rowNum1, colNum1 = divmod(subspec.num1, ncols)
-        rowNum2, colNum2 = divmod(subspec.num2, ncols)
-        figBottom = min(figBottoms[rowNum1], figBottoms[rowNum2])
-        figTop = max(figTops[rowNum1], figTops[rowNum2])
-        figLeft = min(figLefts[colNum1], figLefts[colNum2])
-        figRight = max(figRights[colNum1], figRights[colNum2])
-
-        # These are numbers relative to (0, 0, 1, 1).  Need to constrain
-        # relative to parent.
-
-        width = figRight - figLeft
-        height = figTop - figBottom
-        parent = self.parent
-        cs = [self.left == parent.left + parent.width * figLeft,
-              self.bottom == parent.bottom + parent.height * figBottom,
-              self.width == parent.width * width,
-              self.height == parent.height * height]
-        for c in cs:
-            self.solver.addConstraint(c | 'required')
-
-        return lb
-
-    def __repr__(self):
-        args = (self.name, self.left.value(), self.bottom.value(),
-                self.right.value(), self.top.value())
-        return ('LayoutBox: %25s, (left: %1.3f) (bot: %1.3f) '
-               '(right: %1.3f)  (top: %1.3f) ') % args
-
-
-# Utility functions that act on layoutboxes...
-def hstack(boxes, padding=0, strength='strong'):
-    '''
-    Stack LayoutBox instances from left to right.
-    *padding* is in figure-relative units.
-    '''
-
-    for i in range(1, len(boxes)):
-        c = (boxes[i-1].right + padding <= boxes[i].left)
-        boxes[i].solver.addConstraint(c | strength)
-
-
-def hpack(boxes, padding=0, strength='strong'):
-    '''
-    Stack LayoutBox instances from left to right.
-    '''
-
-    for i in range(1, len(boxes)):
-        c = (boxes[i-1].right + padding == boxes[i].left)
-        boxes[i].solver.addConstraint(c | strength)
-
-
-def vstack(boxes, padding=0, strength='strong'):
-    '''
-    Stack LayoutBox instances from top to bottom
-    '''
-
-    for i in range(1, len(boxes)):
-        c = (boxes[i-1].bottom - padding >= boxes[i].top)
-        boxes[i].solver.addConstraint(c | strength)
-
-
-def vpack(boxes, padding=0, strength='strong'):
-    '''
-    Stack LayoutBox instances from top to bottom
-    '''
-
-    for i in range(1, len(boxes)):
-        c = (boxes[i-1].bottom - padding >= boxes[i].top)
-        boxes[i].solver.addConstraint(c | strength)
-
-
-def match_heights(boxes, height_ratios=None, strength='medium'):
-    '''
-    Stack LayoutBox instances from top to bottom
-    '''
-
-    if height_ratios is None:
-        height_ratios = np.ones(len(boxes))
-    for i in range(1, len(boxes)):
-        c = (boxes[i-1].height ==
-             boxes[i].height*height_ratios[i-1]/height_ratios[i])
-        boxes[i].solver.addConstraint(c | strength)
-
-
-def match_widths(boxes, width_ratios=None, strength='medium'):
-    '''
-    Stack LayoutBox instances from top to bottom
-    '''
-
-    if width_ratios is None:
-        width_ratios = np.ones(len(boxes))
-    for i in range(1, len(boxes)):
-        c = (boxes[i-1].width ==
-             boxes[i].width*width_ratios[i-1]/width_ratios[i])
-        boxes[i].solver.addConstraint(c | strength)
-
-
-def vstackeq(boxes, padding=0, height_ratios=None):
-    vstack(boxes, padding=padding)
-    match_heights(boxes, height_ratios=height_ratios)
-
-
-def hstackeq(boxes, padding=0, width_ratios=None):
-    hstack(boxes, padding=padding)
-    match_widths(boxes, width_ratios=width_ratios)
-
-
-def align(boxes, attr, strength='strong'):
-    cons = []
-    for box in boxes[1:]:
-        cons = (getattr(boxes[0], attr) == getattr(box, attr))
-        boxes[0].solver.addConstraint(cons | strength)
-
-
-def match_top_margins(boxes, levels=1):
-    box0 = boxes[0]
-    top0 = box0
-    for n in range(levels):
-        top0 = top0.parent
-    for box in boxes[1:]:
-        topb = box
-        for n in range(levels):
-            topb = topb.parent
-        c = (box0.top-top0.top == box.top-topb.top)
-        box0.solver.addConstraint(c | 'strong')
-
-
-def match_bottom_margins(boxes, levels=1):
-    box0 = boxes[0]
-    top0 = box0
-    for n in range(levels):
-        top0 = top0.parent
-    for box in boxes[1:]:
-        topb = box
-        for n in range(levels):
-            topb = topb.parent
-        c = (box0.bottom-top0.bottom == box.bottom-topb.bottom)
-        box0.solver.addConstraint(c | 'strong')
-
-
-def match_left_margins(boxes, levels=1):
-    box0 = boxes[0]
-    top0 = box0
-    for n in range(levels):
-        top0 = top0.parent
-    for box in boxes[1:]:
-        topb = box
-        for n in range(levels):
-            topb = topb.parent
-        c = (box0.left-top0.left == box.left-topb.left)
-        box0.solver.addConstraint(c | 'strong')
-
-
-def match_right_margins(boxes, levels=1):
-    box0 = boxes[0]
-    top0 = box0
-    for n in range(levels):
-        top0 = top0.parent
-    for box in boxes[1:]:
-        topb = box
-        for n in range(levels):
-            topb = topb.parent
-        c = (box0.right-top0.right == box.right-topb.right)
-        box0.solver.addConstraint(c | 'strong')
-
-
-def match_width_margins(boxes, levels=1):
-    match_left_margins(boxes, levels=levels)
-    match_right_margins(boxes, levels=levels)
-
-
-def match_height_margins(boxes, levels=1):
-    match_top_margins(boxes, levels=levels)
-    match_bottom_margins(boxes, levels=levels)
-
-
-def match_margins(boxes, levels=1):
-    match_width_margins(boxes, levels=levels)
-    match_height_margins(boxes, levels=levels)
-
-
-_layoutboxobjnum = itertools.count()
-
-
-def seq_id():
-    """Generate a short sequential id for layoutbox objects."""
-    return '%06d' % next(_layoutboxobjnum)
-
-
-def print_children(lb):
-    """Print the children of the layoutbox."""
-    print(lb)
-    for child in lb.children:
-        print_children(child)
-
-
-def nonetree(lb):
-    """
-    Make all elements in this tree None, signalling not to do any more layout.
-    """
-    if lb is not None:
-        if lb.parent is None:
-            # Clear the solver.  Hopefully this garbage collects.
-            lb.solver.reset()
-            nonechildren(lb)
-        else:
-            nonetree(lb.parent)
-
-
-def nonechildren(lb):
-    for child in lb.children:
-        nonechildren(child)
-    lb.artist._layoutbox = None
-    lb = None
-
-
-def print_tree(lb):
-    '''
-    Print the tree of layoutboxes
-    '''
-
-    if lb.parent is None:
-        print('LayoutBox Tree\n')
-        print('==============\n')
-        print_children(lb)
-        print('\n')
-    else:
-        print_tree(lb.parent)
-
-
-def plot_children(fig, box, level=0, printit=True):
-    '''
-    Simple plotting to show where boxes are
-    '''
-    import matplotlib
-    import matplotlib.pyplot as plt
-
-    if isinstance(fig, matplotlib.figure.Figure):
-        ax = fig.add_axes([0., 0., 1., 1.])
-        ax.set_facecolor([1., 1., 1., 0.7])
-        ax.set_alpha(0.3)
-        fig.draw(fig.canvas.get_renderer())
-    else:
-        ax = fig
-
-    import matplotlib.patches as patches
-    colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
-    if printit:
-        print("Level:", level)
-    for child in box.children:
-        if printit:
-            print(child)
-        ax.add_patch(
-            patches.Rectangle(
-                (child.left.value(), child.bottom.value()),  # (x, y)
-                child.width.value(),  # width
-                child.height.value(),  # height
-                fc='none',
-                alpha=0.8,
-                ec=colors[level]
-            )
-        )
-        if level > 0:
-            name = child.name.split('.')[-1]
-            if level % 2 == 0:
-                ax.text(child.left.value(), child.bottom.value(), name,
-                        size=12-level, color=colors[level])
-            else:
-                ax.text(child.right.value(), child.top.value(), name,
-                        ha='right', va='top', size=12-level,
-                        color=colors[level])
-
-        plot_children(ax, child, level=level+1, printit=printit)

+ 0 - 2544
venv/lib/python3.8/site-packages/matplotlib/_mathtext_data.py

@@ -1,2544 +0,0 @@
-"""
-font data tables for truetype and afm computer modern fonts
-"""
-
-latex_to_bakoma = {
-    '\\__sqrt__'                 : ('cmex10', 0x70),
-    '\\bigcap'                   : ('cmex10', 0x5c),
-    '\\bigcup'                   : ('cmex10', 0x5b),
-    '\\bigodot'                  : ('cmex10', 0x4b),
-    '\\bigoplus'                 : ('cmex10', 0x4d),
-    '\\bigotimes'                : ('cmex10', 0x4f),
-    '\\biguplus'                 : ('cmex10', 0x5d),
-    '\\bigvee'                   : ('cmex10', 0x5f),
-    '\\bigwedge'                 : ('cmex10', 0x5e),
-    '\\coprod'                   : ('cmex10', 0x61),
-    '\\int'                      : ('cmex10', 0x5a),
-    '\\langle'                   : ('cmex10', 0xad),
-    '\\leftangle'                : ('cmex10', 0xad),
-    '\\leftbrace'                : ('cmex10', 0xa9),
-    '\\oint'                     : ('cmex10', 0x49),
-    '\\prod'                     : ('cmex10', 0x59),
-    '\\rangle'                   : ('cmex10', 0xae),
-    '\\rightangle'               : ('cmex10', 0xae),
-    '\\rightbrace'               : ('cmex10', 0xaa),
-    '\\sum'                      : ('cmex10', 0x58),
-    '\\widehat'                  : ('cmex10', 0x62),
-    '\\widetilde'                : ('cmex10', 0x65),
-    '\\{'                        : ('cmex10', 0xa9),
-    '\\}'                        : ('cmex10', 0xaa),
-    '{'                          : ('cmex10', 0xa9),
-    '}'                          : ('cmex10', 0xaa),
-
-    ','                          : ('cmmi10', 0x3b),
-    '.'                          : ('cmmi10', 0x3a),
-    '/'                          : ('cmmi10', 0x3d),
-    '<'                          : ('cmmi10', 0x3c),
-    '>'                          : ('cmmi10', 0x3e),
-    '\\alpha'                    : ('cmmi10', 0xae),
-    '\\beta'                     : ('cmmi10', 0xaf),
-    '\\chi'                      : ('cmmi10', 0xc2),
-    '\\combiningrightarrowabove' : ('cmmi10', 0x7e),
-    '\\delta'                    : ('cmmi10', 0xb1),
-    '\\ell'                      : ('cmmi10', 0x60),
-    '\\epsilon'                  : ('cmmi10', 0xb2),
-    '\\eta'                      : ('cmmi10', 0xb4),
-    '\\flat'                     : ('cmmi10', 0x5b),
-    '\\frown'                    : ('cmmi10', 0x5f),
-    '\\gamma'                    : ('cmmi10', 0xb0),
-    '\\imath'                    : ('cmmi10', 0x7b),
-    '\\iota'                     : ('cmmi10', 0xb6),
-    '\\jmath'                    : ('cmmi10', 0x7c),
-    '\\kappa'                    : ('cmmi10', 0x2219),
-    '\\lambda'                   : ('cmmi10', 0xb8),
-    '\\leftharpoondown'          : ('cmmi10', 0x29),
-    '\\leftharpoonup'            : ('cmmi10', 0x28),
-    '\\mu'                       : ('cmmi10', 0xb9),
-    '\\natural'                  : ('cmmi10', 0x5c),
-    '\\nu'                       : ('cmmi10', 0xba),
-    '\\omega'                    : ('cmmi10', 0x21),
-    '\\phi'                      : ('cmmi10', 0xc1),
-    '\\pi'                       : ('cmmi10', 0xbc),
-    '\\psi'                      : ('cmmi10', 0xc3),
-    '\\rho'                      : ('cmmi10', 0xbd),
-    '\\rightharpoondown'         : ('cmmi10', 0x2b),
-    '\\rightharpoonup'           : ('cmmi10', 0x2a),
-    '\\sharp'                    : ('cmmi10', 0x5d),
-    '\\sigma'                    : ('cmmi10', 0xbe),
-    '\\smile'                    : ('cmmi10', 0x5e),
-    '\\tau'                      : ('cmmi10', 0xbf),
-    '\\theta'                    : ('cmmi10', 0xb5),
-    '\\triangleleft'             : ('cmmi10', 0x2f),
-    '\\triangleright'            : ('cmmi10', 0x2e),
-    '\\upsilon'                  : ('cmmi10', 0xc0),
-    '\\varepsilon'               : ('cmmi10', 0x22),
-    '\\varphi'                   : ('cmmi10', 0x27),
-    '\\varrho'                   : ('cmmi10', 0x25),
-    '\\varsigma'                 : ('cmmi10', 0x26),
-    '\\vartheta'                 : ('cmmi10', 0x23),
-    '\\wp'                       : ('cmmi10', 0x7d),
-    '\\xi'                       : ('cmmi10', 0xbb),
-    '\\zeta'                     : ('cmmi10', 0xb3),
-
-    '!'                          : ('cmr10', 0x21),
-    '%'                          : ('cmr10', 0x25),
-    '&'                          : ('cmr10', 0x26),
-    '('                          : ('cmr10', 0x28),
-    ')'                          : ('cmr10', 0x29),
-    '+'                          : ('cmr10', 0x2b),
-    '0'                          : ('cmr10', 0x30),
-    '1'                          : ('cmr10', 0x31),
-    '2'                          : ('cmr10', 0x32),
-    '3'                          : ('cmr10', 0x33),
-    '4'                          : ('cmr10', 0x34),
-    '5'                          : ('cmr10', 0x35),
-    '6'                          : ('cmr10', 0x36),
-    '7'                          : ('cmr10', 0x37),
-    '8'                          : ('cmr10', 0x38),
-    '9'                          : ('cmr10', 0x39),
-    ':'                          : ('cmr10', 0x3a),
-    ';'                          : ('cmr10', 0x3b),
-    '='                          : ('cmr10', 0x3d),
-    '?'                          : ('cmr10', 0x3f),
-    '@'                          : ('cmr10', 0x40),
-    '['                          : ('cmr10', 0x5b),
-    '\\#'                        : ('cmr10', 0x23),
-    '\\$'                        : ('cmr10', 0x24),
-    '\\%'                        : ('cmr10', 0x25),
-    '\\Delta'                    : ('cmr10', 0xa2),
-    '\\Gamma'                    : ('cmr10', 0xa1),
-    '\\Lambda'                   : ('cmr10', 0xa4),
-    '\\Omega'                    : ('cmr10', 0xad),
-    '\\Phi'                      : ('cmr10', 0xa9),
-    '\\Pi'                       : ('cmr10', 0xa6),
-    '\\Psi'                      : ('cmr10', 0xaa),
-    '\\Sigma'                    : ('cmr10', 0xa7),
-    '\\Theta'                    : ('cmr10', 0xa3),
-    '\\Upsilon'                  : ('cmr10', 0xa8),
-    '\\Xi'                       : ('cmr10', 0xa5),
-    '\\circumflexaccent'         : ('cmr10', 0x5e),
-    '\\combiningacuteaccent'     : ('cmr10', 0xb6),
-    '\\combiningbreve'           : ('cmr10', 0xb8),
-    '\\combiningdiaeresis'       : ('cmr10', 0xc4),
-    '\\combiningdotabove'        : ('cmr10', 0x5f),
-    '\\combininggraveaccent'     : ('cmr10', 0xb5),
-    '\\combiningoverline'        : ('cmr10', 0xb9),
-    '\\combiningtilde'           : ('cmr10', 0x7e),
-    '\\leftbracket'              : ('cmr10', 0x5b),
-    '\\leftparen'                : ('cmr10', 0x28),
-    '\\rightbracket'             : ('cmr10', 0x5d),
-    '\\rightparen'               : ('cmr10', 0x29),
-    '\\widebar'                  : ('cmr10', 0xb9),
-    ']'                          : ('cmr10', 0x5d),
-
-    '*'                          : ('cmsy10', 0xa4),
-    '-'                          : ('cmsy10', 0xa1),
-    '\\Downarrow'                : ('cmsy10', 0x2b),
-    '\\Im'                       : ('cmsy10', 0x3d),
-    '\\Leftarrow'                : ('cmsy10', 0x28),
-    '\\Leftrightarrow'           : ('cmsy10', 0x2c),
-    '\\P'                        : ('cmsy10', 0x7b),
-    '\\Re'                       : ('cmsy10', 0x3c),
-    '\\Rightarrow'               : ('cmsy10', 0x29),
-    '\\S'                        : ('cmsy10', 0x78),
-    '\\Uparrow'                  : ('cmsy10', 0x2a),
-    '\\Updownarrow'              : ('cmsy10', 0x6d),
-    '\\Vert'                     : ('cmsy10', 0x6b),
-    '\\aleph'                    : ('cmsy10', 0x40),
-    '\\approx'                   : ('cmsy10', 0xbc),
-    '\\ast'                      : ('cmsy10', 0xa4),
-    '\\asymp'                    : ('cmsy10', 0xb3),
-    '\\backslash'                : ('cmsy10', 0x6e),
-    '\\bigcirc'                  : ('cmsy10', 0xb0),
-    '\\bigtriangledown'          : ('cmsy10', 0x35),
-    '\\bigtriangleup'            : ('cmsy10', 0x34),
-    '\\bot'                      : ('cmsy10', 0x3f),
-    '\\bullet'                   : ('cmsy10', 0xb2),
-    '\\cap'                      : ('cmsy10', 0x5c),
-    '\\cdot'                     : ('cmsy10', 0xa2),
-    '\\circ'                     : ('cmsy10', 0xb1),
-    '\\clubsuit'                 : ('cmsy10', 0x7c),
-    '\\cup'                      : ('cmsy10', 0x5b),
-    '\\dag'                      : ('cmsy10', 0x79),
-    '\\dashv'                    : ('cmsy10', 0x61),
-    '\\ddag'                     : ('cmsy10', 0x7a),
-    '\\diamond'                  : ('cmsy10', 0xa6),
-    '\\diamondsuit'              : ('cmsy10', 0x7d),
-    '\\div'                      : ('cmsy10', 0xa5),
-    '\\downarrow'                : ('cmsy10', 0x23),
-    '\\emptyset'                 : ('cmsy10', 0x3b),
-    '\\equiv'                    : ('cmsy10', 0xb4),
-    '\\exists'                   : ('cmsy10', 0x39),
-    '\\forall'                   : ('cmsy10', 0x38),
-    '\\geq'                      : ('cmsy10', 0xb8),
-    '\\gg'                       : ('cmsy10', 0xc0),
-    '\\heartsuit'                : ('cmsy10', 0x7e),
-    '\\in'                       : ('cmsy10', 0x32),
-    '\\infty'                    : ('cmsy10', 0x31),
-    '\\lbrace'                   : ('cmsy10', 0x66),
-    '\\lceil'                    : ('cmsy10', 0x64),
-    '\\leftarrow'                : ('cmsy10', 0xc3),
-    '\\leftrightarrow'           : ('cmsy10', 0x24),
-    '\\leq'                      : ('cmsy10', 0x2219),
-    '\\lfloor'                   : ('cmsy10', 0x62),
-    '\\ll'                       : ('cmsy10', 0xbf),
-    '\\mid'                      : ('cmsy10', 0x6a),
-    '\\mp'                       : ('cmsy10', 0xa8),
-    '\\nabla'                    : ('cmsy10', 0x72),
-    '\\nearrow'                  : ('cmsy10', 0x25),
-    '\\neg'                      : ('cmsy10', 0x3a),
-    '\\ni'                       : ('cmsy10', 0x33),
-    '\\nwarrow'                  : ('cmsy10', 0x2d),
-    '\\odot'                     : ('cmsy10', 0xaf),
-    '\\ominus'                   : ('cmsy10', 0xaa),
-    '\\oplus'                    : ('cmsy10', 0xa9),
-    '\\oslash'                   : ('cmsy10', 0xae),
-    '\\otimes'                   : ('cmsy10', 0xad),
-    '\\pm'                       : ('cmsy10', 0xa7),
-    '\\prec'                     : ('cmsy10', 0xc1),
-    '\\preceq'                   : ('cmsy10', 0xb9),
-    '\\prime'                    : ('cmsy10', 0x30),
-    '\\propto'                   : ('cmsy10', 0x2f),
-    '\\rbrace'                   : ('cmsy10', 0x67),
-    '\\rceil'                    : ('cmsy10', 0x65),
-    '\\rfloor'                   : ('cmsy10', 0x63),
-    '\\rightarrow'               : ('cmsy10', 0x21),
-    '\\searrow'                  : ('cmsy10', 0x26),
-    '\\sim'                      : ('cmsy10', 0xbb),
-    '\\simeq'                    : ('cmsy10', 0x27),
-    '\\slash'                    : ('cmsy10', 0x36),
-    '\\spadesuit'                : ('cmsy10', 0xc4),
-    '\\sqcap'                    : ('cmsy10', 0x75),
-    '\\sqcup'                    : ('cmsy10', 0x74),
-    '\\sqsubseteq'               : ('cmsy10', 0x76),
-    '\\sqsupseteq'               : ('cmsy10', 0x77),
-    '\\subset'                   : ('cmsy10', 0xbd),
-    '\\subseteq'                 : ('cmsy10', 0xb5),
-    '\\succ'                     : ('cmsy10', 0xc2),
-    '\\succeq'                   : ('cmsy10', 0xba),
-    '\\supset'                   : ('cmsy10', 0xbe),
-    '\\supseteq'                 : ('cmsy10', 0xb6),
-    '\\swarrow'                  : ('cmsy10', 0x2e),
-    '\\times'                    : ('cmsy10', 0xa3),
-    '\\to'                       : ('cmsy10', 0x21),
-    '\\top'                      : ('cmsy10', 0x3e),
-    '\\uparrow'                  : ('cmsy10', 0x22),
-    '\\updownarrow'              : ('cmsy10', 0x6c),
-    '\\uplus'                    : ('cmsy10', 0x5d),
-    '\\vdash'                    : ('cmsy10', 0x60),
-    '\\vee'                      : ('cmsy10', 0x5f),
-    '\\vert'                     : ('cmsy10', 0x6a),
-    '\\wedge'                    : ('cmsy10', 0x5e),
-    '\\wr'                       : ('cmsy10', 0x6f),
-    '\\|'                        : ('cmsy10', 0x6b),
-    '|'                          : ('cmsy10', 0x6a),
-
-    '\\_'                        : ('cmtt10', 0x5f)
-}
-
-latex_to_cmex = {
-    r'\__sqrt__'   : 112,
-    r'\bigcap'     : 92,
-    r'\bigcup'     : 91,
-    r'\bigodot'    : 75,
-    r'\bigoplus'   : 77,
-    r'\bigotimes'  : 79,
-    r'\biguplus'   : 93,
-    r'\bigvee'     : 95,
-    r'\bigwedge'   : 94,
-    r'\coprod'     : 97,
-    r'\int'        : 90,
-    r'\leftangle'  : 173,
-    r'\leftbrace'  : 169,
-    r'\oint'       : 73,
-    r'\prod'       : 89,
-    r'\rightangle' : 174,
-    r'\rightbrace' : 170,
-    r'\sum'        : 88,
-    r'\widehat'    : 98,
-    r'\widetilde'  : 101,
-}
-
-latex_to_standard = {
-    r'\cong'                     : ('psyr', 64),
-    r'\Delta'                    : ('psyr', 68),
-    r'\Phi'                      : ('psyr', 70),
-    r'\Gamma'                    : ('psyr', 89),
-    r'\alpha'                    : ('psyr', 97),
-    r'\beta'                     : ('psyr', 98),
-    r'\chi'                      : ('psyr', 99),
-    r'\delta'                    : ('psyr', 100),
-    r'\varepsilon'               : ('psyr', 101),
-    r'\phi'                      : ('psyr', 102),
-    r'\gamma'                    : ('psyr', 103),
-    r'\eta'                      : ('psyr', 104),
-    r'\iota'                     : ('psyr', 105),
-    r'\varpsi'                   : ('psyr', 106),
-    r'\kappa'                    : ('psyr', 108),
-    r'\nu'                       : ('psyr', 110),
-    r'\pi'                       : ('psyr', 112),
-    r'\theta'                    : ('psyr', 113),
-    r'\rho'                      : ('psyr', 114),
-    r'\sigma'                    : ('psyr', 115),
-    r'\tau'                      : ('psyr', 116),
-    r'\upsilon'                  : ('psyr', 117),
-    r'\varpi'                    : ('psyr', 118),
-    r'\omega'                    : ('psyr', 119),
-    r'\xi'                       : ('psyr', 120),
-    r'\psi'                      : ('psyr', 121),
-    r'\zeta'                     : ('psyr', 122),
-    r'\sim'                      : ('psyr', 126),
-    r'\leq'                      : ('psyr', 163),
-    r'\infty'                    : ('psyr', 165),
-    r'\clubsuit'                 : ('psyr', 167),
-    r'\diamondsuit'              : ('psyr', 168),
-    r'\heartsuit'                : ('psyr', 169),
-    r'\spadesuit'                : ('psyr', 170),
-    r'\leftrightarrow'           : ('psyr', 171),
-    r'\leftarrow'                : ('psyr', 172),
-    r'\uparrow'                  : ('psyr', 173),
-    r'\rightarrow'               : ('psyr', 174),
-    r'\downarrow'                : ('psyr', 175),
-    r'\pm'                       : ('psyr', 176),
-    r'\geq'                      : ('psyr', 179),
-    r'\times'                    : ('psyr', 180),
-    r'\propto'                   : ('psyr', 181),
-    r'\partial'                  : ('psyr', 182),
-    r'\bullet'                   : ('psyr', 183),
-    r'\div'                      : ('psyr', 184),
-    r'\neq'                      : ('psyr', 185),
-    r'\equiv'                    : ('psyr', 186),
-    r'\approx'                   : ('psyr', 187),
-    r'\ldots'                    : ('psyr', 188),
-    r'\aleph'                    : ('psyr', 192),
-    r'\Im'                       : ('psyr', 193),
-    r'\Re'                       : ('psyr', 194),
-    r'\wp'                       : ('psyr', 195),
-    r'\otimes'                   : ('psyr', 196),
-    r'\oplus'                    : ('psyr', 197),
-    r'\oslash'                   : ('psyr', 198),
-    r'\cap'                      : ('psyr', 199),
-    r'\cup'                      : ('psyr', 200),
-    r'\supset'                   : ('psyr', 201),
-    r'\supseteq'                 : ('psyr', 202),
-    r'\subset'                   : ('psyr', 204),
-    r'\subseteq'                 : ('psyr', 205),
-    r'\in'                       : ('psyr', 206),
-    r'\notin'                    : ('psyr', 207),
-    r'\angle'                    : ('psyr', 208),
-    r'\nabla'                    : ('psyr', 209),
-    r'\textregistered'           : ('psyr', 210),
-    r'\copyright'                : ('psyr', 211),
-    r'\texttrademark'            : ('psyr', 212),
-    r'\Pi'                       : ('psyr', 213),
-    r'\prod'                     : ('psyr', 213),
-    r'\surd'                     : ('psyr', 214),
-    r'\__sqrt__'                 : ('psyr', 214),
-    r'\cdot'                     : ('psyr', 215),
-    r'\urcorner'                 : ('psyr', 216),
-    r'\vee'                      : ('psyr', 217),
-    r'\wedge'                    : ('psyr', 218),
-    r'\Leftrightarrow'           : ('psyr', 219),
-    r'\Leftarrow'                : ('psyr', 220),
-    r'\Uparrow'                  : ('psyr', 221),
-    r'\Rightarrow'               : ('psyr', 222),
-    r'\Downarrow'                : ('psyr', 223),
-    r'\Diamond'                  : ('psyr', 224),
-    r'\Sigma'                    : ('psyr', 229),
-    r'\sum'                      : ('psyr', 229),
-    r'\forall'                   : ('psyr',  34),
-    r'\exists'                   : ('psyr',  36),
-    r'\lceil'                    : ('psyr', 233),
-    r'\lbrace'                   : ('psyr', 123),
-    r'\Psi'                      : ('psyr',  89),
-    r'\bot'                      : ('psyr', 0o136),
-    r'\Omega'                    : ('psyr', 0o127),
-    r'\leftbracket'              : ('psyr', 0o133),
-    r'\rightbracket'             : ('psyr', 0o135),
-    r'\leftbrace'                : ('psyr', 123),
-    r'\leftparen'                : ('psyr', 0o50),
-    r'\prime'                    : ('psyr', 0o242),
-    r'\sharp'                    : ('psyr', 0o43),
-    r'\slash'                    : ('psyr', 0o57),
-    r'\Lamda'                    : ('psyr', 0o114),
-    r'\neg'                      : ('psyr', 0o330),
-    r'\Upsilon'                  : ('psyr', 0o241),
-    r'\rightbrace'               : ('psyr', 0o175),
-    r'\rfloor'                   : ('psyr', 0o373),
-    r'\lambda'                   : ('psyr', 0o154),
-    r'\to'                       : ('psyr', 0o256),
-    r'\Xi'                       : ('psyr', 0o130),
-    r'\emptyset'                 : ('psyr', 0o306),
-    r'\lfloor'                   : ('psyr', 0o353),
-    r'\rightparen'               : ('psyr', 0o51),
-    r'\rceil'                    : ('psyr', 0o371),
-    r'\ni'                       : ('psyr', 0o47),
-    r'\epsilon'                  : ('psyr', 0o145),
-    r'\Theta'                    : ('psyr', 0o121),
-    r'\langle'                   : ('psyr', 0o341),
-    r'\leftangle'                : ('psyr', 0o341),
-    r'\rangle'                   : ('psyr', 0o361),
-    r'\rightangle'               : ('psyr', 0o361),
-    r'\rbrace'                   : ('psyr', 0o175),
-    r'\circ'                     : ('psyr', 0o260),
-    r'\diamond'                  : ('psyr', 0o340),
-    r'\mu'                       : ('psyr', 0o155),
-    r'\mid'                      : ('psyr', 0o352),
-    r'\imath'                    : ('pncri8a', 105),
-    r'\%'                        : ('pncr8a',  37),
-    r'\$'                        : ('pncr8a',  36),
-    r'\{'                        : ('pncr8a', 123),
-    r'\}'                        : ('pncr8a', 125),
-    r'\backslash'                : ('pncr8a',  92),
-    r'\ast'                      : ('pncr8a',  42),
-    r'\#'                        : ('pncr8a',  35),
-
-    r'\circumflexaccent'         : ('pncri8a',   124), # for \hat
-    r'\combiningbreve'           : ('pncri8a',   81),  # for \breve
-    r'\combininggraveaccent'     : ('pncri8a', 114), # for \grave
-    r'\combiningacuteaccent'     : ('pncri8a', 63), # for \accute
-    r'\combiningdiaeresis'       : ('pncri8a', 91), # for \ddot
-    r'\combiningtilde'           : ('pncri8a', 75), # for \tilde
-    r'\combiningrightarrowabove' : ('pncri8a', 110), # for \vec
-    r'\combiningdotabove'        : ('pncri8a', 26), # for \dot
-}
-
-# Automatically generated.
-
-type12uni = {
-    'uni24C8'        : 9416,
-    'aring'          : 229,
-    'uni22A0'        : 8864,
-    'uni2292'        : 8850,
-    'quotedblright'  : 8221,
-    'uni03D2'        : 978,
-    'uni2215'        : 8725,
-    'uni03D0'        : 976,
-    'V'              : 86,
-    'dollar'         : 36,
-    'uni301E'        : 12318,
-    'uni03D5'        : 981,
-    'four'           : 52,
-    'uni25A0'        : 9632,
-    'uni013C'        : 316,
-    'uni013B'        : 315,
-    'uni013E'        : 318,
-    'Yacute'         : 221,
-    'uni25DE'        : 9694,
-    'uni013F'        : 319,
-    'uni255A'        : 9562,
-    'uni2606'        : 9734,
-    'uni0180'        : 384,
-    'uni22B7'        : 8887,
-    'uni044F'        : 1103,
-    'uni22B5'        : 8885,
-    'uni22B4'        : 8884,
-    'uni22AE'        : 8878,
-    'uni22B2'        : 8882,
-    'uni22B1'        : 8881,
-    'uni22B0'        : 8880,
-    'uni25CD'        : 9677,
-    'uni03CE'        : 974,
-    'uni03CD'        : 973,
-    'uni03CC'        : 972,
-    'uni03CB'        : 971,
-    'uni03CA'        : 970,
-    'uni22B8'        : 8888,
-    'uni22C9'        : 8905,
-    'uni0449'        : 1097,
-    'uni20DD'        : 8413,
-    'uni20DC'        : 8412,
-    'uni20DB'        : 8411,
-    'uni2231'        : 8753,
-    'uni25CF'        : 9679,
-    'uni306E'        : 12398,
-    'uni03D1'        : 977,
-    'uni01A1'        : 417,
-    'uni20D7'        : 8407,
-    'uni03D6'        : 982,
-    'uni2233'        : 8755,
-    'uni20D2'        : 8402,
-    'uni20D1'        : 8401,
-    'uni20D0'        : 8400,
-    'P'              : 80,
-    'uni22BE'        : 8894,
-    'uni22BD'        : 8893,
-    'uni22BC'        : 8892,
-    'uni22BB'        : 8891,
-    'underscore'     : 95,
-    'uni03C8'        : 968,
-    'uni03C7'        : 967,
-    'uni0328'        : 808,
-    'uni03C5'        : 965,
-    'uni03C4'        : 964,
-    'uni03C3'        : 963,
-    'uni03C2'        : 962,
-    'uni03C1'        : 961,
-    'uni03C0'        : 960,
-    'uni2010'        : 8208,
-    'uni0130'        : 304,
-    'uni0133'        : 307,
-    'uni0132'        : 306,
-    'uni0135'        : 309,
-    'uni0134'        : 308,
-    'uni0137'        : 311,
-    'uni0136'        : 310,
-    'uni0139'        : 313,
-    'uni0138'        : 312,
-    'uni2244'        : 8772,
-    'uni229A'        : 8858,
-    'uni2571'        : 9585,
-    'uni0278'        : 632,
-    'uni2239'        : 8761,
-    'p'              : 112,
-    'uni3019'        : 12313,
-    'uni25CB'        : 9675,
-    'uni03DB'        : 987,
-    'uni03DC'        : 988,
-    'uni03DA'        : 986,
-    'uni03DF'        : 991,
-    'uni03DD'        : 989,
-    'uni013D'        : 317,
-    'uni220A'        : 8714,
-    'uni220C'        : 8716,
-    'uni220B'        : 8715,
-    'uni220E'        : 8718,
-    'uni220D'        : 8717,
-    'uni220F'        : 8719,
-    'uni22CC'        : 8908,
-    'Otilde'         : 213,
-    'uni25E5'        : 9701,
-    'uni2736'        : 10038,
-    'perthousand'    : 8240,
-    'zero'           : 48,
-    'uni279B'        : 10139,
-    'dotlessi'       : 305,
-    'uni2279'        : 8825,
-    'Scaron'         : 352,
-    'zcaron'         : 382,
-    'uni21D8'        : 8664,
-    'egrave'         : 232,
-    'uni0271'        : 625,
-    'uni01AA'        : 426,
-    'uni2332'        : 9010,
-    'section'        : 167,
-    'uni25E4'        : 9700,
-    'Icircumflex'    : 206,
-    'ntilde'         : 241,
-    'uni041E'        : 1054,
-    'ampersand'      : 38,
-    'uni041C'        : 1052,
-    'uni041A'        : 1050,
-    'uni22AB'        : 8875,
-    'uni21DB'        : 8667,
-    'dotaccent'      : 729,
-    'uni0416'        : 1046,
-    'uni0417'        : 1047,
-    'uni0414'        : 1044,
-    'uni0415'        : 1045,
-    'uni0412'        : 1042,
-    'uni0413'        : 1043,
-    'degree'         : 176,
-    'uni0411'        : 1041,
-    'K'              : 75,
-    'uni25EB'        : 9707,
-    'uni25EF'        : 9711,
-    'uni0418'        : 1048,
-    'uni0419'        : 1049,
-    'uni2263'        : 8803,
-    'uni226E'        : 8814,
-    'uni2251'        : 8785,
-    'uni02C8'        : 712,
-    'uni2262'        : 8802,
-    'acircumflex'    : 226,
-    'uni22B3'        : 8883,
-    'uni2261'        : 8801,
-    'uni2394'        : 9108,
-    'Aring'          : 197,
-    'uni2260'        : 8800,
-    'uni2254'        : 8788,
-    'uni0436'        : 1078,
-    'uni2267'        : 8807,
-    'k'              : 107,
-    'uni22C8'        : 8904,
-    'uni226A'        : 8810,
-    'uni231F'        : 8991,
-    'smalltilde'     : 732,
-    'uni2201'        : 8705,
-    'uni2200'        : 8704,
-    'uni2203'        : 8707,
-    'uni02BD'        : 701,
-    'uni2205'        : 8709,
-    'uni2204'        : 8708,
-    'Agrave'         : 192,
-    'uni2206'        : 8710,
-    'uni2209'        : 8713,
-    'uni2208'        : 8712,
-    'uni226D'        : 8813,
-    'uni2264'        : 8804,
-    'uni263D'        : 9789,
-    'uni2258'        : 8792,
-    'uni02D3'        : 723,
-    'uni02D2'        : 722,
-    'uni02D1'        : 721,
-    'uni02D0'        : 720,
-    'uni25E1'        : 9697,
-    'divide'         : 247,
-    'uni02D5'        : 725,
-    'uni02D4'        : 724,
-    'ocircumflex'    : 244,
-    'uni2524'        : 9508,
-    'uni043A'        : 1082,
-    'uni24CC'        : 9420,
-    'asciitilde'     : 126,
-    'uni22B9'        : 8889,
-    'uni24D2'        : 9426,
-    'uni211E'        : 8478,
-    'uni211D'        : 8477,
-    'uni24DD'        : 9437,
-    'uni211A'        : 8474,
-    'uni211C'        : 8476,
-    'uni211B'        : 8475,
-    'uni25C6'        : 9670,
-    'uni017F'        : 383,
-    'uni017A'        : 378,
-    'uni017C'        : 380,
-    'uni017B'        : 379,
-    'uni0346'        : 838,
-    'uni22F1'        : 8945,
-    'uni22F0'        : 8944,
-    'two'            : 50,
-    'uni2298'        : 8856,
-    'uni24D1'        : 9425,
-    'E'              : 69,
-    'uni025D'        : 605,
-    'scaron'         : 353,
-    'uni2322'        : 8994,
-    'uni25E3'        : 9699,
-    'uni22BF'        : 8895,
-    'F'              : 70,
-    'uni0440'        : 1088,
-    'uni255E'        : 9566,
-    'uni22BA'        : 8890,
-    'uni0175'        : 373,
-    'uni0174'        : 372,
-    'uni0177'        : 375,
-    'uni0176'        : 374,
-    'bracketleft'    : 91,
-    'uni0170'        : 368,
-    'uni0173'        : 371,
-    'uni0172'        : 370,
-    'asciicircum'    : 94,
-    'uni0179'        : 377,
-    'uni2590'        : 9616,
-    'uni25E2'        : 9698,
-    'uni2119'        : 8473,
-    'uni2118'        : 8472,
-    'uni25CC'        : 9676,
-    'f'              : 102,
-    'ordmasculine'   : 186,
-    'uni229B'        : 8859,
-    'uni22A1'        : 8865,
-    'uni2111'        : 8465,
-    'uni2110'        : 8464,
-    'uni2113'        : 8467,
-    'uni2112'        : 8466,
-    'mu'             : 181,
-    'uni2281'        : 8833,
-    'paragraph'      : 182,
-    'nine'           : 57,
-    'uni25EC'        : 9708,
-    'v'              : 118,
-    'uni040C'        : 1036,
-    'uni0113'        : 275,
-    'uni22D0'        : 8912,
-    'uni21CC'        : 8652,
-    'uni21CB'        : 8651,
-    'uni21CA'        : 8650,
-    'uni22A5'        : 8869,
-    'uni21CF'        : 8655,
-    'uni21CE'        : 8654,
-    'uni21CD'        : 8653,
-    'guilsinglleft'  : 8249,
-    'backslash'      : 92,
-    'uni2284'        : 8836,
-    'uni224E'        : 8782,
-    'uni224D'        : 8781,
-    'uni224F'        : 8783,
-    'uni224A'        : 8778,
-    'uni2287'        : 8839,
-    'uni224C'        : 8780,
-    'uni224B'        : 8779,
-    'uni21BD'        : 8637,
-    'uni2286'        : 8838,
-    'uni030F'        : 783,
-    'uni030D'        : 781,
-    'uni030E'        : 782,
-    'uni030B'        : 779,
-    'uni030C'        : 780,
-    'uni030A'        : 778,
-    'uni026E'        : 622,
-    'uni026D'        : 621,
-    'six'            : 54,
-    'uni026A'        : 618,
-    'uni026C'        : 620,
-    'uni25C1'        : 9665,
-    'uni20D6'        : 8406,
-    'uni045B'        : 1115,
-    'uni045C'        : 1116,
-    'uni256B'        : 9579,
-    'uni045A'        : 1114,
-    'uni045F'        : 1119,
-    'uni045E'        : 1118,
-    'A'              : 65,
-    'uni2569'        : 9577,
-    'uni0458'        : 1112,
-    'uni0459'        : 1113,
-    'uni0452'        : 1106,
-    'uni0453'        : 1107,
-    'uni2562'        : 9570,
-    'uni0451'        : 1105,
-    'uni0456'        : 1110,
-    'uni0457'        : 1111,
-    'uni0454'        : 1108,
-    'uni0455'        : 1109,
-    'icircumflex'    : 238,
-    'uni0307'        : 775,
-    'uni0304'        : 772,
-    'uni0305'        : 773,
-    'uni0269'        : 617,
-    'uni0268'        : 616,
-    'uni0300'        : 768,
-    'uni0301'        : 769,
-    'uni0265'        : 613,
-    'uni0264'        : 612,
-    'uni0267'        : 615,
-    'uni0266'        : 614,
-    'uni0261'        : 609,
-    'uni0260'        : 608,
-    'uni0263'        : 611,
-    'uni0262'        : 610,
-    'a'              : 97,
-    'uni2207'        : 8711,
-    'uni2247'        : 8775,
-    'uni2246'        : 8774,
-    'uni2241'        : 8769,
-    'uni2240'        : 8768,
-    'uni2243'        : 8771,
-    'uni2242'        : 8770,
-    'uni2312'        : 8978,
-    'ogonek'         : 731,
-    'uni2249'        : 8777,
-    'uni2248'        : 8776,
-    'uni3030'        : 12336,
-    'q'              : 113,
-    'uni21C2'        : 8642,
-    'uni21C1'        : 8641,
-    'uni21C0'        : 8640,
-    'uni21C7'        : 8647,
-    'uni21C6'        : 8646,
-    'uni21C5'        : 8645,
-    'uni21C4'        : 8644,
-    'uni225F'        : 8799,
-    'uni212C'        : 8492,
-    'uni21C8'        : 8648,
-    'uni2467'        : 9319,
-    'oacute'         : 243,
-    'uni028F'        : 655,
-    'uni028E'        : 654,
-    'uni026F'        : 623,
-    'uni028C'        : 652,
-    'uni028B'        : 651,
-    'uni028A'        : 650,
-    'uni2510'        : 9488,
-    'ograve'         : 242,
-    'edieresis'      : 235,
-    'uni22CE'        : 8910,
-    'uni22CF'        : 8911,
-    'uni219F'        : 8607,
-    'comma'          : 44,
-    'uni22CA'        : 8906,
-    'uni0429'        : 1065,
-    'uni03C6'        : 966,
-    'uni0427'        : 1063,
-    'uni0426'        : 1062,
-    'uni0425'        : 1061,
-    'uni0424'        : 1060,
-    'uni0423'        : 1059,
-    'uni0422'        : 1058,
-    'uni0421'        : 1057,
-    'uni0420'        : 1056,
-    'uni2465'        : 9317,
-    'uni24D0'        : 9424,
-    'uni2464'        : 9316,
-    'uni0430'        : 1072,
-    'otilde'         : 245,
-    'uni2661'        : 9825,
-    'uni24D6'        : 9430,
-    'uni2466'        : 9318,
-    'uni24D5'        : 9429,
-    'uni219A'        : 8602,
-    'uni2518'        : 9496,
-    'uni22B6'        : 8886,
-    'uni2461'        : 9313,
-    'uni24D4'        : 9428,
-    'uni2460'        : 9312,
-    'uni24EA'        : 9450,
-    'guillemotright' : 187,
-    'ecircumflex'    : 234,
-    'greater'        : 62,
-    'uni2011'        : 8209,
-    'uacute'         : 250,
-    'uni2462'        : 9314,
-    'L'              : 76,
-    'bullet'         : 8226,
-    'uni02A4'        : 676,
-    'uni02A7'        : 679,
-    'cedilla'        : 184,
-    'uni02A2'        : 674,
-    'uni2015'        : 8213,
-    'uni22C4'        : 8900,
-    'uni22C5'        : 8901,
-    'uni22AD'        : 8877,
-    'uni22C7'        : 8903,
-    'uni22C0'        : 8896,
-    'uni2016'        : 8214,
-    'uni22C2'        : 8898,
-    'uni22C3'        : 8899,
-    'uni24CF'        : 9423,
-    'uni042F'        : 1071,
-    'uni042E'        : 1070,
-    'uni042D'        : 1069,
-    'ydieresis'      : 255,
-    'l'              : 108,
-    'logicalnot'     : 172,
-    'uni24CA'        : 9418,
-    'uni0287'        : 647,
-    'uni0286'        : 646,
-    'uni0285'        : 645,
-    'uni0284'        : 644,
-    'uni0283'        : 643,
-    'uni0282'        : 642,
-    'uni0281'        : 641,
-    'uni027C'        : 636,
-    'uni2664'        : 9828,
-    'exclamdown'     : 161,
-    'uni25C4'        : 9668,
-    'uni0289'        : 649,
-    'uni0288'        : 648,
-    'uni039A'        : 922,
-    'endash'         : 8211,
-    'uni2640'        : 9792,
-    'uni20E4'        : 8420,
-    'uni0473'        : 1139,
-    'uni20E1'        : 8417,
-    'uni2642'        : 9794,
-    'uni03B8'        : 952,
-    'uni03B9'        : 953,
-    'agrave'         : 224,
-    'uni03B4'        : 948,
-    'uni03B5'        : 949,
-    'uni03B6'        : 950,
-    'uni03B7'        : 951,
-    'uni03B0'        : 944,
-    'uni03B1'        : 945,
-    'uni03B2'        : 946,
-    'uni03B3'        : 947,
-    'uni2555'        : 9557,
-    'Adieresis'      : 196,
-    'germandbls'     : 223,
-    'Odieresis'      : 214,
-    'space'          : 32,
-    'uni0126'        : 294,
-    'uni0127'        : 295,
-    'uni0124'        : 292,
-    'uni0125'        : 293,
-    'uni0122'        : 290,
-    'uni0123'        : 291,
-    'uni0120'        : 288,
-    'uni0121'        : 289,
-    'quoteright'     : 8217,
-    'uni2560'        : 9568,
-    'uni2556'        : 9558,
-    'ucircumflex'    : 251,
-    'uni2561'        : 9569,
-    'uni2551'        : 9553,
-    'uni25B2'        : 9650,
-    'uni2550'        : 9552,
-    'uni2563'        : 9571,
-    'uni2553'        : 9555,
-    'G'              : 71,
-    'uni2564'        : 9572,
-    'uni2552'        : 9554,
-    'quoteleft'      : 8216,
-    'uni2565'        : 9573,
-    'uni2572'        : 9586,
-    'uni2568'        : 9576,
-    'uni2566'        : 9574,
-    'W'              : 87,
-    'uni214A'        : 8522,
-    'uni012F'        : 303,
-    'uni012D'        : 301,
-    'uni012E'        : 302,
-    'uni012B'        : 299,
-    'uni012C'        : 300,
-    'uni255C'        : 9564,
-    'uni012A'        : 298,
-    'uni2289'        : 8841,
-    'Q'              : 81,
-    'uni2320'        : 8992,
-    'uni2321'        : 8993,
-    'g'              : 103,
-    'uni03BD'        : 957,
-    'uni03BE'        : 958,
-    'uni03BF'        : 959,
-    'uni2282'        : 8834,
-    'uni2285'        : 8837,
-    'uni03BA'        : 954,
-    'uni03BB'        : 955,
-    'uni03BC'        : 956,
-    'uni2128'        : 8488,
-    'uni25B7'        : 9655,
-    'w'              : 119,
-    'uni0302'        : 770,
-    'uni03DE'        : 990,
-    'uni25DA'        : 9690,
-    'uni0303'        : 771,
-    'uni0463'        : 1123,
-    'uni0462'        : 1122,
-    'uni3018'        : 12312,
-    'uni2514'        : 9492,
-    'question'       : 63,
-    'uni25B3'        : 9651,
-    'uni24E1'        : 9441,
-    'one'            : 49,
-    'uni200A'        : 8202,
-    'uni2278'        : 8824,
-    'ring'           : 730,
-    'uni0195'        : 405,
-    'figuredash'     : 8210,
-    'uni22EC'        : 8940,
-    'uni0339'        : 825,
-    'uni0338'        : 824,
-    'uni0337'        : 823,
-    'uni0336'        : 822,
-    'uni0335'        : 821,
-    'uni0333'        : 819,
-    'uni0332'        : 818,
-    'uni0331'        : 817,
-    'uni0330'        : 816,
-    'uni01C1'        : 449,
-    'uni01C0'        : 448,
-    'uni01C3'        : 451,
-    'uni01C2'        : 450,
-    'uni2353'        : 9043,
-    'uni0308'        : 776,
-    'uni2218'        : 8728,
-    'uni2219'        : 8729,
-    'uni2216'        : 8726,
-    'uni2217'        : 8727,
-    'uni2214'        : 8724,
-    'uni0309'        : 777,
-    'uni2609'        : 9737,
-    'uni2213'        : 8723,
-    'uni2210'        : 8720,
-    'uni2211'        : 8721,
-    'uni2245'        : 8773,
-    'B'              : 66,
-    'uni25D6'        : 9686,
-    'iacute'         : 237,
-    'uni02E6'        : 742,
-    'uni02E7'        : 743,
-    'uni02E8'        : 744,
-    'uni02E9'        : 745,
-    'uni221D'        : 8733,
-    'uni221E'        : 8734,
-    'Ydieresis'      : 376,
-    'uni221C'        : 8732,
-    'uni22D7'        : 8919,
-    'uni221A'        : 8730,
-    'R'              : 82,
-    'uni24DC'        : 9436,
-    'uni033F'        : 831,
-    'uni033E'        : 830,
-    'uni033C'        : 828,
-    'uni033B'        : 827,
-    'uni033A'        : 826,
-    'b'              : 98,
-    'uni228A'        : 8842,
-    'uni22DB'        : 8923,
-    'uni2554'        : 9556,
-    'uni046B'        : 1131,
-    'uni046A'        : 1130,
-    'r'              : 114,
-    'uni24DB'        : 9435,
-    'Ccedilla'       : 199,
-    'minus'          : 8722,
-    'uni24DA'        : 9434,
-    'uni03F0'        : 1008,
-    'uni03F1'        : 1009,
-    'uni20AC'        : 8364,
-    'uni2276'        : 8822,
-    'uni24C0'        : 9408,
-    'uni0162'        : 354,
-    'uni0163'        : 355,
-    'uni011E'        : 286,
-    'uni011D'        : 285,
-    'uni011C'        : 284,
-    'uni011B'        : 283,
-    'uni0164'        : 356,
-    'uni0165'        : 357,
-    'Lslash'         : 321,
-    'uni0168'        : 360,
-    'uni0169'        : 361,
-    'uni25C9'        : 9673,
-    'uni02E5'        : 741,
-    'uni21C3'        : 8643,
-    'uni24C4'        : 9412,
-    'uni24E2'        : 9442,
-    'uni2277'        : 8823,
-    'uni013A'        : 314,
-    'uni2102'        : 8450,
-    'Uacute'         : 218,
-    'uni2317'        : 8983,
-    'uni2107'        : 8455,
-    'uni221F'        : 8735,
-    'yacute'         : 253,
-    'uni3012'        : 12306,
-    'Ucircumflex'    : 219,
-    'uni015D'        : 349,
-    'quotedbl'       : 34,
-    'uni25D9'        : 9689,
-    'uni2280'        : 8832,
-    'uni22AF'        : 8879,
-    'onehalf'        : 189,
-    'uni221B'        : 8731,
-    'Thorn'          : 222,
-    'uni2226'        : 8742,
-    'M'              : 77,
-    'uni25BA'        : 9658,
-    'uni2463'        : 9315,
-    'uni2336'        : 9014,
-    'eight'          : 56,
-    'uni2236'        : 8758,
-    'multiply'       : 215,
-    'uni210C'        : 8460,
-    'uni210A'        : 8458,
-    'uni21C9'        : 8649,
-    'grave'          : 96,
-    'uni210E'        : 8462,
-    'uni0117'        : 279,
-    'uni016C'        : 364,
-    'uni0115'        : 277,
-    'uni016A'        : 362,
-    'uni016F'        : 367,
-    'uni0112'        : 274,
-    'uni016D'        : 365,
-    'uni016E'        : 366,
-    'Ocircumflex'    : 212,
-    'uni2305'        : 8965,
-    'm'              : 109,
-    'uni24DF'        : 9439,
-    'uni0119'        : 281,
-    'uni0118'        : 280,
-    'uni20A3'        : 8355,
-    'uni20A4'        : 8356,
-    'uni20A7'        : 8359,
-    'uni2288'        : 8840,
-    'uni24C3'        : 9411,
-    'uni251C'        : 9500,
-    'uni228D'        : 8845,
-    'uni222F'        : 8751,
-    'uni222E'        : 8750,
-    'uni222D'        : 8749,
-    'uni222C'        : 8748,
-    'uni222B'        : 8747,
-    'uni222A'        : 8746,
-    'uni255B'        : 9563,
-    'Ugrave'         : 217,
-    'uni24DE'        : 9438,
-    'guilsinglright' : 8250,
-    'uni250A'        : 9482,
-    'Ntilde'         : 209,
-    'uni0279'        : 633,
-    'questiondown'   : 191,
-    'uni256C'        : 9580,
-    'Atilde'         : 195,
-    'uni0272'        : 626,
-    'uni0273'        : 627,
-    'uni0270'        : 624,
-    'ccedilla'       : 231,
-    'uni0276'        : 630,
-    'uni0277'        : 631,
-    'uni0274'        : 628,
-    'uni0275'        : 629,
-    'uni2252'        : 8786,
-    'uni041F'        : 1055,
-    'uni2250'        : 8784,
-    'Z'              : 90,
-    'uni2256'        : 8790,
-    'uni2257'        : 8791,
-    'copyright'      : 169,
-    'uni2255'        : 8789,
-    'uni043D'        : 1085,
-    'uni043E'        : 1086,
-    'uni043F'        : 1087,
-    'yen'            : 165,
-    'uni041D'        : 1053,
-    'uni043B'        : 1083,
-    'uni043C'        : 1084,
-    'uni21B0'        : 8624,
-    'uni21B1'        : 8625,
-    'uni21B2'        : 8626,
-    'uni21B3'        : 8627,
-    'uni21B4'        : 8628,
-    'uni21B5'        : 8629,
-    'uni21B6'        : 8630,
-    'uni21B7'        : 8631,
-    'uni21B8'        : 8632,
-    'Eacute'         : 201,
-    'uni2311'        : 8977,
-    'uni2310'        : 8976,
-    'uni228F'        : 8847,
-    'uni25DB'        : 9691,
-    'uni21BA'        : 8634,
-    'uni21BB'        : 8635,
-    'uni21BC'        : 8636,
-    'uni2017'        : 8215,
-    'uni21BE'        : 8638,
-    'uni21BF'        : 8639,
-    'uni231C'        : 8988,
-    'H'              : 72,
-    'uni0293'        : 659,
-    'uni2202'        : 8706,
-    'uni22A4'        : 8868,
-    'uni231E'        : 8990,
-    'uni2232'        : 8754,
-    'uni225B'        : 8795,
-    'uni225C'        : 8796,
-    'uni24D9'        : 9433,
-    'uni225A'        : 8794,
-    'uni0438'        : 1080,
-    'uni0439'        : 1081,
-    'uni225D'        : 8797,
-    'uni225E'        : 8798,
-    'uni0434'        : 1076,
-    'X'              : 88,
-    'uni007F'        : 127,
-    'uni0437'        : 1079,
-    'Idieresis'      : 207,
-    'uni0431'        : 1073,
-    'uni0432'        : 1074,
-    'uni0433'        : 1075,
-    'uni22AC'        : 8876,
-    'uni22CD'        : 8909,
-    'uni25A3'        : 9635,
-    'bar'            : 124,
-    'uni24BB'        : 9403,
-    'uni037E'        : 894,
-    'uni027B'        : 635,
-    'h'              : 104,
-    'uni027A'        : 634,
-    'uni027F'        : 639,
-    'uni027D'        : 637,
-    'uni027E'        : 638,
-    'uni2227'        : 8743,
-    'uni2004'        : 8196,
-    'uni2225'        : 8741,
-    'uni2224'        : 8740,
-    'uni2223'        : 8739,
-    'uni2222'        : 8738,
-    'uni2221'        : 8737,
-    'uni2220'        : 8736,
-    'x'              : 120,
-    'uni2323'        : 8995,
-    'uni2559'        : 9561,
-    'uni2558'        : 9560,
-    'uni2229'        : 8745,
-    'uni2228'        : 8744,
-    'udieresis'      : 252,
-    'uni029D'        : 669,
-    'ordfeminine'    : 170,
-    'uni22CB'        : 8907,
-    'uni233D'        : 9021,
-    'uni0428'        : 1064,
-    'uni24C6'        : 9414,
-    'uni22DD'        : 8925,
-    'uni24C7'        : 9415,
-    'uni015C'        : 348,
-    'uni015B'        : 347,
-    'uni015A'        : 346,
-    'uni22AA'        : 8874,
-    'uni015F'        : 351,
-    'uni015E'        : 350,
-    'braceleft'      : 123,
-    'uni24C5'        : 9413,
-    'uni0410'        : 1040,
-    'uni03AA'        : 938,
-    'uni24C2'        : 9410,
-    'uni03AC'        : 940,
-    'uni03AB'        : 939,
-    'macron'         : 175,
-    'uni03AD'        : 941,
-    'uni03AF'        : 943,
-    'uni0294'        : 660,
-    'uni0295'        : 661,
-    'uni0296'        : 662,
-    'uni0297'        : 663,
-    'uni0290'        : 656,
-    'uni0291'        : 657,
-    'uni0292'        : 658,
-    'atilde'         : 227,
-    'Acircumflex'    : 194,
-    'uni2370'        : 9072,
-    'uni24C1'        : 9409,
-    'uni0298'        : 664,
-    'uni0299'        : 665,
-    'Oslash'         : 216,
-    'uni029E'        : 670,
-    'C'              : 67,
-    'quotedblleft'   : 8220,
-    'uni029B'        : 667,
-    'uni029C'        : 668,
-    'uni03A9'        : 937,
-    'uni03A8'        : 936,
-    'S'              : 83,
-    'uni24C9'        : 9417,
-    'uni03A1'        : 929,
-    'uni03A0'        : 928,
-    'exclam'         : 33,
-    'uni03A5'        : 933,
-    'uni03A4'        : 932,
-    'uni03A7'        : 935,
-    'Zcaron'         : 381,
-    'uni2133'        : 8499,
-    'uni2132'        : 8498,
-    'uni0159'        : 345,
-    'uni0158'        : 344,
-    'uni2137'        : 8503,
-    'uni2005'        : 8197,
-    'uni2135'        : 8501,
-    'uni2134'        : 8500,
-    'uni02BA'        : 698,
-    'uni2033'        : 8243,
-    'uni0151'        : 337,
-    'uni0150'        : 336,
-    'uni0157'        : 343,
-    'equal'          : 61,
-    'uni0155'        : 341,
-    'uni0154'        : 340,
-    's'              : 115,
-    'uni233F'        : 9023,
-    'eth'            : 240,
-    'uni24BE'        : 9406,
-    'uni21E9'        : 8681,
-    'uni2060'        : 8288,
-    'Egrave'         : 200,
-    'uni255D'        : 9565,
-    'uni24CD'        : 9421,
-    'uni21E1'        : 8673,
-    'uni21B9'        : 8633,
-    'hyphen'         : 45,
-    'uni01BE'        : 446,
-    'uni01BB'        : 443,
-    'period'         : 46,
-    'igrave'         : 236,
-    'uni01BA'        : 442,
-    'uni2296'        : 8854,
-    'uni2297'        : 8855,
-    'uni2294'        : 8852,
-    'uni2295'        : 8853,
-    'colon'          : 58,
-    'uni2293'        : 8851,
-    'uni2290'        : 8848,
-    'uni2291'        : 8849,
-    'uni032D'        : 813,
-    'uni032E'        : 814,
-    'uni032F'        : 815,
-    'uni032A'        : 810,
-    'uni032B'        : 811,
-    'uni032C'        : 812,
-    'uni231D'        : 8989,
-    'Ecircumflex'    : 202,
-    'uni24D7'        : 9431,
-    'uni25DD'        : 9693,
-    'trademark'      : 8482,
-    'Aacute'         : 193,
-    'cent'           : 162,
-    'uni0445'        : 1093,
-    'uni266E'        : 9838,
-    'uni266D'        : 9837,
-    'uni266B'        : 9835,
-    'uni03C9'        : 969,
-    'uni2003'        : 8195,
-    'uni2047'        : 8263,
-    'lslash'         : 322,
-    'uni03A6'        : 934,
-    'uni2043'        : 8259,
-    'uni250C'        : 9484,
-    'uni2040'        : 8256,
-    'uni255F'        : 9567,
-    'uni24CB'        : 9419,
-    'uni0472'        : 1138,
-    'uni0446'        : 1094,
-    'uni0474'        : 1140,
-    'uni0475'        : 1141,
-    'uni2508'        : 9480,
-    'uni2660'        : 9824,
-    'uni2506'        : 9478,
-    'uni2502'        : 9474,
-    'c'              : 99,
-    'uni2500'        : 9472,
-    'N'              : 78,
-    'uni22A6'        : 8870,
-    'uni21E7'        : 8679,
-    'uni2130'        : 8496,
-    'uni2002'        : 8194,
-    'breve'          : 728,
-    'uni0442'        : 1090,
-    'Oacute'         : 211,
-    'uni229F'        : 8863,
-    'uni25C7'        : 9671,
-    'uni229D'        : 8861,
-    'uni229E'        : 8862,
-    'guillemotleft'  : 171,
-    'uni0329'        : 809,
-    'uni24E5'        : 9445,
-    'uni011F'        : 287,
-    'uni0324'        : 804,
-    'uni0325'        : 805,
-    'uni0326'        : 806,
-    'uni0327'        : 807,
-    'uni0321'        : 801,
-    'uni0322'        : 802,
-    'n'              : 110,
-    'uni2032'        : 8242,
-    'uni2269'        : 8809,
-    'uni2268'        : 8808,
-    'uni0306'        : 774,
-    'uni226B'        : 8811,
-    'uni21EA'        : 8682,
-    'uni0166'        : 358,
-    'uni203B'        : 8251,
-    'uni01B5'        : 437,
-    'idieresis'      : 239,
-    'uni02BC'        : 700,
-    'uni01B0'        : 432,
-    'braceright'     : 125,
-    'seven'          : 55,
-    'uni02BB'        : 699,
-    'uni011A'        : 282,
-    'uni29FB'        : 10747,
-    'brokenbar'      : 166,
-    'uni2036'        : 8246,
-    'uni25C0'        : 9664,
-    'uni0156'        : 342,
-    'uni22D5'        : 8917,
-    'uni0258'        : 600,
-    'ugrave'         : 249,
-    'uni22D6'        : 8918,
-    'uni22D1'        : 8913,
-    'uni2034'        : 8244,
-    'uni22D3'        : 8915,
-    'uni22D2'        : 8914,
-    'uni203C'        : 8252,
-    'uni223E'        : 8766,
-    'uni02BF'        : 703,
-    'uni22D9'        : 8921,
-    'uni22D8'        : 8920,
-    'uni25BD'        : 9661,
-    'uni25BE'        : 9662,
-    'uni25BF'        : 9663,
-    'uni041B'        : 1051,
-    'periodcentered' : 183,
-    'uni25BC'        : 9660,
-    'uni019E'        : 414,
-    'uni019B'        : 411,
-    'uni019A'        : 410,
-    'uni2007'        : 8199,
-    'uni0391'        : 913,
-    'uni0390'        : 912,
-    'uni0393'        : 915,
-    'uni0392'        : 914,
-    'uni0395'        : 917,
-    'uni0394'        : 916,
-    'uni0397'        : 919,
-    'uni0396'        : 918,
-    'uni0399'        : 921,
-    'uni0398'        : 920,
-    'uni25C8'        : 9672,
-    'uni2468'        : 9320,
-    'sterling'       : 163,
-    'uni22EB'        : 8939,
-    'uni039C'        : 924,
-    'uni039B'        : 923,
-    'uni039E'        : 926,
-    'uni039D'        : 925,
-    'uni039F'        : 927,
-    'I'              : 73,
-    'uni03E1'        : 993,
-    'uni03E0'        : 992,
-    'uni2319'        : 8985,
-    'uni228B'        : 8843,
-    'uni25B5'        : 9653,
-    'uni25B6'        : 9654,
-    'uni22EA'        : 8938,
-    'uni24B9'        : 9401,
-    'uni044E'        : 1102,
-    'uni0199'        : 409,
-    'uni2266'        : 8806,
-    'Y'              : 89,
-    'uni22A2'        : 8866,
-    'Eth'            : 208,
-    'uni266F'        : 9839,
-    'emdash'         : 8212,
-    'uni263B'        : 9787,
-    'uni24BD'        : 9405,
-    'uni22DE'        : 8926,
-    'uni0360'        : 864,
-    'uni2557'        : 9559,
-    'uni22DF'        : 8927,
-    'uni22DA'        : 8922,
-    'uni22DC'        : 8924,
-    'uni0361'        : 865,
-    'i'              : 105,
-    'uni24BF'        : 9407,
-    'uni0362'        : 866,
-    'uni263E'        : 9790,
-    'uni028D'        : 653,
-    'uni2259'        : 8793,
-    'uni0323'        : 803,
-    'uni2265'        : 8805,
-    'daggerdbl'      : 8225,
-    'y'              : 121,
-    'uni010A'        : 266,
-    'plusminus'      : 177,
-    'less'           : 60,
-    'uni21AE'        : 8622,
-    'uni0315'        : 789,
-    'uni230B'        : 8971,
-    'uni21AF'        : 8623,
-    'uni21AA'        : 8618,
-    'uni21AC'        : 8620,
-    'uni21AB'        : 8619,
-    'uni01FB'        : 507,
-    'uni01FC'        : 508,
-    'uni223A'        : 8762,
-    'uni01FA'        : 506,
-    'uni01FF'        : 511,
-    'uni01FD'        : 509,
-    'uni01FE'        : 510,
-    'uni2567'        : 9575,
-    'uni25E0'        : 9696,
-    'uni0104'        : 260,
-    'uni0105'        : 261,
-    'uni0106'        : 262,
-    'uni0107'        : 263,
-    'uni0100'        : 256,
-    'uni0101'        : 257,
-    'uni0102'        : 258,
-    'uni0103'        : 259,
-    'uni2038'        : 8248,
-    'uni2009'        : 8201,
-    'uni2008'        : 8200,
-    'uni0108'        : 264,
-    'uni0109'        : 265,
-    'uni02A1'        : 673,
-    'uni223B'        : 8763,
-    'uni226C'        : 8812,
-    'uni25AC'        : 9644,
-    'uni24D3'        : 9427,
-    'uni21E0'        : 8672,
-    'uni21E3'        : 8675,
-    'Udieresis'      : 220,
-    'uni21E2'        : 8674,
-    'D'              : 68,
-    'uni21E5'        : 8677,
-    'uni2621'        : 9761,
-    'uni21D1'        : 8657,
-    'uni203E'        : 8254,
-    'uni22C6'        : 8902,
-    'uni21E4'        : 8676,
-    'uni010D'        : 269,
-    'uni010E'        : 270,
-    'uni010F'        : 271,
-    'five'           : 53,
-    'T'              : 84,
-    'uni010B'        : 267,
-    'uni010C'        : 268,
-    'uni2605'        : 9733,
-    'uni2663'        : 9827,
-    'uni21E6'        : 8678,
-    'uni24B6'        : 9398,
-    'uni22C1'        : 8897,
-    'oslash'         : 248,
-    'acute'          : 180,
-    'uni01F0'        : 496,
-    'd'              : 100,
-    'OE'             : 338,
-    'uni22E3'        : 8931,
-    'Igrave'         : 204,
-    'uni2308'        : 8968,
-    'uni2309'        : 8969,
-    'uni21A9'        : 8617,
-    't'              : 116,
-    'uni2313'        : 8979,
-    'uni03A3'        : 931,
-    'uni21A4'        : 8612,
-    'uni21A7'        : 8615,
-    'uni21A6'        : 8614,
-    'uni21A1'        : 8609,
-    'uni21A0'        : 8608,
-    'uni21A3'        : 8611,
-    'uni21A2'        : 8610,
-    'parenright'     : 41,
-    'uni256A'        : 9578,
-    'uni25DC'        : 9692,
-    'uni24CE'        : 9422,
-    'uni042C'        : 1068,
-    'uni24E0'        : 9440,
-    'uni042B'        : 1067,
-    'uni0409'        : 1033,
-    'uni0408'        : 1032,
-    'uni24E7'        : 9447,
-    'uni25B4'        : 9652,
-    'uni042A'        : 1066,
-    'uni228E'        : 8846,
-    'uni0401'        : 1025,
-    'adieresis'      : 228,
-    'uni0403'        : 1027,
-    'quotesingle'    : 39,
-    'uni0405'        : 1029,
-    'uni0404'        : 1028,
-    'uni0407'        : 1031,
-    'uni0406'        : 1030,
-    'uni229C'        : 8860,
-    'uni2306'        : 8966,
-    'uni2253'        : 8787,
-    'twodotenleader' : 8229,
-    'uni2131'        : 8497,
-    'uni21DA'        : 8666,
-    'uni2234'        : 8756,
-    'uni2235'        : 8757,
-    'uni01A5'        : 421,
-    'uni2237'        : 8759,
-    'uni2230'        : 8752,
-    'uni02CC'        : 716,
-    'slash'          : 47,
-    'uni01A0'        : 416,
-    'ellipsis'       : 8230,
-    'uni2299'        : 8857,
-    'uni2238'        : 8760,
-    'numbersign'     : 35,
-    'uni21A8'        : 8616,
-    'uni223D'        : 8765,
-    'uni01AF'        : 431,
-    'uni223F'        : 8767,
-    'uni01AD'        : 429,
-    'uni01AB'        : 427,
-    'odieresis'      : 246,
-    'uni223C'        : 8764,
-    'uni227D'        : 8829,
-    'uni0280'        : 640,
-    'O'              : 79,
-    'uni227E'        : 8830,
-    'uni21A5'        : 8613,
-    'uni22D4'        : 8916,
-    'uni25D4'        : 9684,
-    'uni227F'        : 8831,
-    'uni0435'        : 1077,
-    'uni2302'        : 8962,
-    'uni2669'        : 9833,
-    'uni24E3'        : 9443,
-    'uni2720'        : 10016,
-    'uni22A8'        : 8872,
-    'uni22A9'        : 8873,
-    'uni040A'        : 1034,
-    'uni22A7'        : 8871,
-    'oe'             : 339,
-    'uni040B'        : 1035,
-    'uni040E'        : 1038,
-    'uni22A3'        : 8867,
-    'o'              : 111,
-    'uni040F'        : 1039,
-    'Edieresis'      : 203,
-    'uni25D5'        : 9685,
-    'plus'           : 43,
-    'uni044D'        : 1101,
-    'uni263C'        : 9788,
-    'uni22E6'        : 8934,
-    'uni2283'        : 8835,
-    'uni258C'        : 9612,
-    'uni219E'        : 8606,
-    'uni24E4'        : 9444,
-    'uni2136'        : 8502,
-    'dagger'         : 8224,
-    'uni24B7'        : 9399,
-    'uni219B'        : 8603,
-    'uni22E5'        : 8933,
-    'three'          : 51,
-    'uni210B'        : 8459,
-    'uni2534'        : 9524,
-    'uni24B8'        : 9400,
-    'uni230A'        : 8970,
-    'hungarumlaut'   : 733,
-    'parenleft'      : 40,
-    'uni0148'        : 328,
-    'uni0149'        : 329,
-    'uni2124'        : 8484,
-    'uni2125'        : 8485,
-    'uni2126'        : 8486,
-    'uni2127'        : 8487,
-    'uni0140'        : 320,
-    'uni2129'        : 8489,
-    'uni25C5'        : 9669,
-    'uni0143'        : 323,
-    'uni0144'        : 324,
-    'uni0145'        : 325,
-    'uni0146'        : 326,
-    'uni0147'        : 327,
-    'uni210D'        : 8461,
-    'fraction'       : 8260,
-    'uni2031'        : 8241,
-    'uni2196'        : 8598,
-    'uni2035'        : 8245,
-    'uni24E6'        : 9446,
-    'uni016B'        : 363,
-    'uni24BA'        : 9402,
-    'uni266A'        : 9834,
-    'uni0116'        : 278,
-    'uni2115'        : 8469,
-    'registered'     : 174,
-    'J'              : 74,
-    'uni25DF'        : 9695,
-    'uni25CE'        : 9678,
-    'uni273D'        : 10045,
-    'dieresis'       : 168,
-    'uni212B'        : 8491,
-    'uni0114'        : 276,
-    'uni212D'        : 8493,
-    'uni212E'        : 8494,
-    'uni212F'        : 8495,
-    'uni014A'        : 330,
-    'uni014B'        : 331,
-    'uni014C'        : 332,
-    'uni014D'        : 333,
-    'uni014E'        : 334,
-    'uni014F'        : 335,
-    'uni025E'        : 606,
-    'uni24E8'        : 9448,
-    'uni0111'        : 273,
-    'uni24E9'        : 9449,
-    'Ograve'         : 210,
-    'j'              : 106,
-    'uni2195'        : 8597,
-    'uni2194'        : 8596,
-    'uni2197'        : 8599,
-    'uni2037'        : 8247,
-    'uni2191'        : 8593,
-    'uni2190'        : 8592,
-    'uni2193'        : 8595,
-    'uni2192'        : 8594,
-    'uni29FA'        : 10746,
-    'uni2713'        : 10003,
-    'z'              : 122,
-    'uni2199'        : 8601,
-    'uni2198'        : 8600,
-    'uni2667'        : 9831,
-    'ae'             : 230,
-    'uni0448'        : 1096,
-    'semicolon'      : 59,
-    'uni2666'        : 9830,
-    'uni038F'        : 911,
-    'uni0444'        : 1092,
-    'uni0447'        : 1095,
-    'uni038E'        : 910,
-    'uni0441'        : 1089,
-    'uni038C'        : 908,
-    'uni0443'        : 1091,
-    'uni038A'        : 906,
-    'uni0250'        : 592,
-    'uni0251'        : 593,
-    'uni0252'        : 594,
-    'uni0253'        : 595,
-    'uni0254'        : 596,
-    'at'             : 64,
-    'uni0256'        : 598,
-    'uni0257'        : 599,
-    'uni0167'        : 359,
-    'uni0259'        : 601,
-    'uni228C'        : 8844,
-    'uni2662'        : 9826,
-    'uni0319'        : 793,
-    'uni0318'        : 792,
-    'uni24BC'        : 9404,
-    'uni0402'        : 1026,
-    'uni22EF'        : 8943,
-    'Iacute'         : 205,
-    'uni22ED'        : 8941,
-    'uni22EE'        : 8942,
-    'uni0311'        : 785,
-    'uni0310'        : 784,
-    'uni21E8'        : 8680,
-    'uni0312'        : 786,
-    'percent'        : 37,
-    'uni0317'        : 791,
-    'uni0316'        : 790,
-    'uni21D6'        : 8662,
-    'uni21D7'        : 8663,
-    'uni21D4'        : 8660,
-    'uni21D5'        : 8661,
-    'uni21D2'        : 8658,
-    'uni21D3'        : 8659,
-    'uni21D0'        : 8656,
-    'uni2138'        : 8504,
-    'uni2270'        : 8816,
-    'uni2271'        : 8817,
-    'uni2272'        : 8818,
-    'uni2273'        : 8819,
-    'uni2274'        : 8820,
-    'uni2275'        : 8821,
-    'bracketright'   : 93,
-    'uni21D9'        : 8665,
-    'uni21DF'        : 8671,
-    'uni21DD'        : 8669,
-    'uni21DE'        : 8670,
-    'AE'             : 198,
-    'uni03AE'        : 942,
-    'uni227A'        : 8826,
-    'uni227B'        : 8827,
-    'uni227C'        : 8828,
-    'asterisk'       : 42,
-    'aacute'         : 225,
-    'uni226F'        : 8815,
-    'uni22E2'        : 8930,
-    'uni0386'        : 902,
-    'uni22E0'        : 8928,
-    'uni22E1'        : 8929,
-    'U'              : 85,
-    'uni22E7'        : 8935,
-    'uni22E4'        : 8932,
-    'uni0387'        : 903,
-    'uni031A'        : 794,
-    'eacute'         : 233,
-    'uni22E8'        : 8936,
-    'uni22E9'        : 8937,
-    'uni24D8'        : 9432,
-    'uni025A'        : 602,
-    'uni025B'        : 603,
-    'uni025C'        : 604,
-    'e'              : 101,
-    'uni0128'        : 296,
-    'uni025F'        : 607,
-    'uni2665'        : 9829,
-    'thorn'          : 254,
-    'uni0129'        : 297,
-    'uni253C'        : 9532,
-    'uni25D7'        : 9687,
-    'u'              : 117,
-    'uni0388'        : 904,
-    'uni0389'        : 905,
-    'uni0255'        : 597,
-    'uni0171'        : 369,
-    'uni0384'        : 900,
-    'uni0385'        : 901,
-    'uni044A'        : 1098,
-    'uni252C'        : 9516,
-    'uni044C'        : 1100,
-    'uni044B'        : 1099
-}
-
-uni2type1 = {v: k for k, v in type12uni.items()}
-
-tex2uni = {
-    'widehat'                  : 0x0302,
-    'widetilde'                : 0x0303,
-    'widebar'                  : 0x0305,
-    'langle'                   : 0x27e8,
-    'rangle'                   : 0x27e9,
-    'perp'                     : 0x27c2,
-    'neq'                      : 0x2260,
-    'Join'                     : 0x2a1d,
-    'leqslant'                 : 0x2a7d,
-    'geqslant'                 : 0x2a7e,
-    'lessapprox'               : 0x2a85,
-    'gtrapprox'                : 0x2a86,
-    'lesseqqgtr'               : 0x2a8b,
-    'gtreqqless'               : 0x2a8c,
-    'triangleeq'               : 0x225c,
-    'eqslantless'              : 0x2a95,
-    'eqslantgtr'               : 0x2a96,
-    'backepsilon'              : 0x03f6,
-    'precapprox'               : 0x2ab7,
-    'succapprox'               : 0x2ab8,
-    'fallingdotseq'            : 0x2252,
-    'subseteqq'                : 0x2ac5,
-    'supseteqq'                : 0x2ac6,
-    'varpropto'                : 0x221d,
-    'precnapprox'              : 0x2ab9,
-    'succnapprox'              : 0x2aba,
-    'subsetneqq'               : 0x2acb,
-    'supsetneqq'               : 0x2acc,
-    'lnapprox'                 : 0x2ab9,
-    'gnapprox'                 : 0x2aba,
-    'longleftarrow'            : 0x27f5,
-    'longrightarrow'           : 0x27f6,
-    'longleftrightarrow'       : 0x27f7,
-    'Longleftarrow'            : 0x27f8,
-    'Longrightarrow'           : 0x27f9,
-    'Longleftrightarrow'       : 0x27fa,
-    'longmapsto'               : 0x27fc,
-    'leadsto'                  : 0x21dd,
-    'dashleftarrow'            : 0x290e,
-    'dashrightarrow'           : 0x290f,
-    'circlearrowleft'          : 0x21ba,
-    'circlearrowright'         : 0x21bb,
-    'leftrightsquigarrow'      : 0x21ad,
-    'leftsquigarrow'           : 0x219c,
-    'rightsquigarrow'          : 0x219d,
-    'Game'                     : 0x2141,
-    'hbar'                     : 0x0127,
-    'hslash'                   : 0x210f,
-    'ldots'                    : 0x2026,
-    'vdots'                    : 0x22ee,
-    'doteqdot'                 : 0x2251,
-    'doteq'                    : 8784,
-    'partial'                  : 8706,
-    'gg'                       : 8811,
-    'asymp'                    : 8781,
-    'blacktriangledown'        : 9662,
-    'otimes'                   : 8855,
-    'nearrow'                  : 8599,
-    'varpi'                    : 982,
-    'vee'                      : 8744,
-    'vec'                      : 8407,
-    'smile'                    : 8995,
-    'succnsim'                 : 8937,
-    'gimel'                    : 8503,
-    'vert'                     : 124,
-    '|'                        : 124,
-    'varrho'                   : 1009,
-    'P'                        : 182,
-    'approxident'              : 8779,
-    'Swarrow'                  : 8665,
-    'textasciicircum'          : 94,
-    'imageof'                  : 8887,
-    'ntriangleleft'            : 8938,
-    'nleq'                     : 8816,
-    'div'                      : 247,
-    'nparallel'                : 8742,
-    'Leftarrow'                : 8656,
-    'lll'                      : 8920,
-    'oiint'                    : 8751,
-    'ngeq'                     : 8817,
-    'Theta'                    : 920,
-    'origof'                   : 8886,
-    'blacksquare'              : 9632,
-    'solbar'                   : 9023,
-    'neg'                      : 172,
-    'sum'                      : 8721,
-    'Vdash'                    : 8873,
-    'coloneq'                  : 8788,
-    'degree'                   : 176,
-    'bowtie'                   : 8904,
-    'blacktriangleright'       : 9654,
-    'varsigma'                 : 962,
-    'leq'                      : 8804,
-    'ggg'                      : 8921,
-    'lneqq'                    : 8808,
-    'scurel'                   : 8881,
-    'stareq'                   : 8795,
-    'BbbN'                     : 8469,
-    'nLeftarrow'               : 8653,
-    'nLeftrightarrow'          : 8654,
-    'k'                        : 808,
-    'bot'                      : 8869,
-    'BbbC'                     : 8450,
-    'Lsh'                      : 8624,
-    'leftleftarrows'           : 8647,
-    'BbbZ'                     : 8484,
-    'digamma'                  : 989,
-    'BbbR'                     : 8477,
-    'BbbP'                     : 8473,
-    'BbbQ'                     : 8474,
-    'vartriangleright'         : 8883,
-    'succsim'                  : 8831,
-    'wedge'                    : 8743,
-    'lessgtr'                  : 8822,
-    'veebar'                   : 8891,
-    'mapsdown'                 : 8615,
-    'Rsh'                      : 8625,
-    'chi'                      : 967,
-    'prec'                     : 8826,
-    'nsubseteq'                : 8840,
-    'therefore'                : 8756,
-    'eqcirc'                   : 8790,
-    'textexclamdown'           : 161,
-    'nRightarrow'              : 8655,
-    'flat'                     : 9837,
-    'notin'                    : 8713,
-    'llcorner'                 : 8990,
-    'varepsilon'               : 949,
-    'bigtriangleup'            : 9651,
-    'aleph'                    : 8501,
-    'dotminus'                 : 8760,
-    'upsilon'                  : 965,
-    'Lambda'                   : 923,
-    'cap'                      : 8745,
-    'barleftarrow'             : 8676,
-    'mu'                       : 956,
-    'boxplus'                  : 8862,
-    'mp'                       : 8723,
-    'circledast'               : 8859,
-    'tau'                      : 964,
-    'in'                       : 8712,
-    'backslash'                : 92,
-    'varnothing'               : 8709,
-    'sharp'                    : 9839,
-    'eqsim'                    : 8770,
-    'gnsim'                    : 8935,
-    'Searrow'                  : 8664,
-    'updownarrows'             : 8645,
-    'heartsuit'                : 9825,
-    'trianglelefteq'           : 8884,
-    'ddag'                     : 8225,
-    'sqsubseteq'               : 8849,
-    'mapsfrom'                 : 8612,
-    'boxbar'                   : 9707,
-    'sim'                      : 8764,
-    'Nwarrow'                  : 8662,
-    'nequiv'                   : 8802,
-    'succ'                     : 8827,
-    'vdash'                    : 8866,
-    'Leftrightarrow'           : 8660,
-    'parallel'                 : 8741,
-    'invnot'                   : 8976,
-    'natural'                  : 9838,
-    'ss'                       : 223,
-    'uparrow'                  : 8593,
-    'nsim'                     : 8769,
-    'hookrightarrow'           : 8618,
-    'Equiv'                    : 8803,
-    'approx'                   : 8776,
-    'Vvdash'                   : 8874,
-    'nsucc'                    : 8833,
-    'leftrightharpoons'        : 8651,
-    'Re'                       : 8476,
-    'boxminus'                 : 8863,
-    'equiv'                    : 8801,
-    'Lleftarrow'               : 8666,
-    'll'                       : 8810,
-    'Cup'                      : 8915,
-    'measeq'                   : 8798,
-    'upharpoonleft'            : 8639,
-    'lq'                       : 8216,
-    'Upsilon'                  : 933,
-    'subsetneq'                : 8842,
-    'greater'                  : 62,
-    'supsetneq'                : 8843,
-    'Cap'                      : 8914,
-    'L'                        : 321,
-    'spadesuit'                : 9824,
-    'lrcorner'                 : 8991,
-    'not'                      : 824,
-    'bar'                      : 772,
-    'rightharpoonaccent'       : 8401,
-    'boxdot'                   : 8865,
-    'l'                        : 322,
-    'leftharpoondown'          : 8637,
-    'bigcup'                   : 8899,
-    'iint'                     : 8748,
-    'bigwedge'                 : 8896,
-    'downharpoonleft'          : 8643,
-    'textasciitilde'           : 126,
-    'subset'                   : 8834,
-    'leqq'                     : 8806,
-    'mapsup'                   : 8613,
-    'nvDash'                   : 8877,
-    'looparrowleft'            : 8619,
-    'nless'                    : 8814,
-    'rightarrowbar'            : 8677,
-    'Vert'                     : 8214,
-    'downdownarrows'           : 8650,
-    'uplus'                    : 8846,
-    'simeq'                    : 8771,
-    'napprox'                  : 8777,
-    'ast'                      : 8727,
-    'twoheaduparrow'           : 8607,
-    'doublebarwedge'           : 8966,
-    'Sigma'                    : 931,
-    'leftharpoonaccent'        : 8400,
-    'ntrianglelefteq'          : 8940,
-    'nexists'                  : 8708,
-    'times'                    : 215,
-    'measuredangle'            : 8737,
-    'bumpeq'                   : 8783,
-    'carriagereturn'           : 8629,
-    'adots'                    : 8944,
-    'checkmark'                : 10003,
-    'lambda'                   : 955,
-    'xi'                       : 958,
-    'rbrace'                   : 125,
-    'rbrack'                   : 93,
-    'Nearrow'                  : 8663,
-    'maltese'                  : 10016,
-    'clubsuit'                 : 9827,
-    'top'                      : 8868,
-    'overarc'                  : 785,
-    'varphi'                   : 966,
-    'Delta'                    : 916,
-    'iota'                     : 953,
-    'nleftarrow'               : 8602,
-    'candra'                   : 784,
-    'supset'                   : 8835,
-    'triangleleft'             : 9665,
-    'gtreqless'                : 8923,
-    'ntrianglerighteq'         : 8941,
-    'quad'                     : 8195,
-    'Xi'                       : 926,
-    'gtrdot'                   : 8919,
-    'leftthreetimes'           : 8907,
-    'minus'                    : 8722,
-    'preccurlyeq'              : 8828,
-    'nleftrightarrow'          : 8622,
-    'lambdabar'                : 411,
-    'blacktriangle'            : 9652,
-    'kernelcontraction'        : 8763,
-    'Phi'                      : 934,
-    'angle'                    : 8736,
-    'spadesuitopen'            : 9828,
-    'eqless'                   : 8924,
-    'mid'                      : 8739,
-    'varkappa'                 : 1008,
-    'Ldsh'                     : 8626,
-    'updownarrow'              : 8597,
-    'beta'                     : 946,
-    'textquotedblleft'         : 8220,
-    'rho'                      : 961,
-    'alpha'                    : 945,
-    'intercal'                 : 8890,
-    'beth'                     : 8502,
-    'grave'                    : 768,
-    'acwopencirclearrow'       : 8634,
-    'nmid'                     : 8740,
-    'nsupset'                  : 8837,
-    'sigma'                    : 963,
-    'dot'                      : 775,
-    'Rightarrow'               : 8658,
-    'turnednot'                : 8985,
-    'backsimeq'                : 8909,
-    'leftarrowtail'            : 8610,
-    'approxeq'                 : 8778,
-    'curlyeqsucc'              : 8927,
-    'rightarrowtail'           : 8611,
-    'Psi'                      : 936,
-    'copyright'                : 169,
-    'yen'                      : 165,
-    'vartriangleleft'          : 8882,
-    'rasp'                     : 700,
-    'triangleright'            : 9655,
-    'precsim'                  : 8830,
-    'infty'                    : 8734,
-    'geq'                      : 8805,
-    'updownarrowbar'           : 8616,
-    'precnsim'                 : 8936,
-    'H'                        : 779,
-    'ulcorner'                 : 8988,
-    'looparrowright'           : 8620,
-    'ncong'                    : 8775,
-    'downarrow'                : 8595,
-    'circeq'                   : 8791,
-    'subseteq'                 : 8838,
-    'bigstar'                  : 9733,
-    'prime'                    : 8242,
-    'lceil'                    : 8968,
-    'Rrightarrow'              : 8667,
-    'oiiint'                   : 8752,
-    'curlywedge'               : 8911,
-    'vDash'                    : 8872,
-    'lfloor'                   : 8970,
-    'ddots'                    : 8945,
-    'exists'                   : 8707,
-    'underbar'                 : 817,
-    'Pi'                       : 928,
-    'leftrightarrows'          : 8646,
-    'sphericalangle'           : 8738,
-    'coprod'                   : 8720,
-    'circledcirc'              : 8858,
-    'gtrsim'                   : 8819,
-    'gneqq'                    : 8809,
-    'between'                  : 8812,
-    'theta'                    : 952,
-    'complement'               : 8705,
-    'arceq'                    : 8792,
-    'nVdash'                   : 8878,
-    'S'                        : 167,
-    'wr'                       : 8768,
-    'wp'                       : 8472,
-    'backcong'                 : 8780,
-    'lasp'                     : 701,
-    'c'                        : 807,
-    'nabla'                    : 8711,
-    'dotplus'                  : 8724,
-    'eta'                      : 951,
-    'forall'                   : 8704,
-    'eth'                      : 240,
-    'colon'                    : 58,
-    'sqcup'                    : 8852,
-    'rightrightarrows'         : 8649,
-    'sqsupset'                 : 8848,
-    'mapsto'                   : 8614,
-    'bigtriangledown'          : 9661,
-    'sqsupseteq'               : 8850,
-    'propto'                   : 8733,
-    'pi'                       : 960,
-    'pm'                       : 177,
-    'dots'                     : 0x2026,
-    'nrightarrow'              : 8603,
-    'textasciiacute'           : 180,
-    'Doteq'                    : 8785,
-    'breve'                    : 774,
-    'sqcap'                    : 8851,
-    'twoheadrightarrow'        : 8608,
-    'kappa'                    : 954,
-    'vartriangle'              : 9653,
-    'diamondsuit'              : 9826,
-    'pitchfork'                : 8916,
-    'blacktriangleleft'        : 9664,
-    'nprec'                    : 8832,
-    'curvearrowright'          : 8631,
-    'barwedge'                 : 8892,
-    'multimap'                 : 8888,
-    'textquestiondown'         : 191,
-    'cong'                     : 8773,
-    'rtimes'                   : 8906,
-    'rightzigzagarrow'         : 8669,
-    'rightarrow'               : 8594,
-    'leftarrow'                : 8592,
-    '__sqrt__'                 : 8730,
-    'twoheaddownarrow'         : 8609,
-    'oint'                     : 8750,
-    'bigvee'                   : 8897,
-    'eqdef'                    : 8797,
-    'sterling'                 : 163,
-    'phi'                      : 981,
-    'Updownarrow'              : 8661,
-    'backprime'                : 8245,
-    'emdash'                   : 8212,
-    'Gamma'                    : 915,
-    'i'                        : 305,
-    'rceil'                    : 8969,
-    'leftharpoonup'            : 8636,
-    'Im'                       : 8465,
-    'curvearrowleft'           : 8630,
-    'wedgeq'                   : 8793,
-    'curlyeqprec'              : 8926,
-    'questeq'                  : 8799,
-    'less'                     : 60,
-    'upuparrows'               : 8648,
-    'tilde'                    : 771,
-    'textasciigrave'           : 96,
-    'smallsetminus'            : 8726,
-    'ell'                      : 8467,
-    'cup'                      : 8746,
-    'danger'                   : 9761,
-    'nVDash'                   : 8879,
-    'cdotp'                    : 183,
-    'cdots'                    : 8943,
-    'hat'                      : 770,
-    'eqgtr'                    : 8925,
-    'psi'                      : 968,
-    'frown'                    : 8994,
-    'acute'                    : 769,
-    'downzigzagarrow'          : 8623,
-    'ntriangleright'           : 8939,
-    'cupdot'                   : 8845,
-    'circleddash'              : 8861,
-    'oslash'                   : 8856,
-    'mho'                      : 8487,
-    'd'                        : 803,
-    'sqsubset'                 : 8847,
-    'cdot'                     : 8901,
-    'Omega'                    : 937,
-    'OE'                       : 338,
-    'veeeq'                    : 8794,
-    'Finv'                     : 8498,
-    't'                        : 865,
-    'leftrightarrow'           : 8596,
-    'swarrow'                  : 8601,
-    'rightthreetimes'          : 8908,
-    'rightleftharpoons'        : 8652,
-    'lesssim'                  : 8818,
-    'searrow'                  : 8600,
-    'because'                  : 8757,
-    'gtrless'                  : 8823,
-    'star'                     : 8902,
-    'nsubset'                  : 8836,
-    'zeta'                     : 950,
-    'dddot'                    : 8411,
-    'bigcirc'                  : 9675,
-    'Supset'                   : 8913,
-    'circ'                     : 8728,
-    'slash'                    : 8725,
-    'ocirc'                    : 778,
-    'prod'                     : 8719,
-    'twoheadleftarrow'         : 8606,
-    'daleth'                   : 8504,
-    'upharpoonright'           : 8638,
-    'odot'                     : 8857,
-    'Uparrow'                  : 8657,
-    'O'                        : 216,
-    'hookleftarrow'            : 8617,
-    'trianglerighteq'          : 8885,
-    'nsime'                    : 8772,
-    'oe'                       : 339,
-    'nwarrow'                  : 8598,
-    'o'                        : 248,
-    'ddddot'                   : 8412,
-    'downharpoonright'         : 8642,
-    'succcurlyeq'              : 8829,
-    'gamma'                    : 947,
-    'scrR'                     : 8475,
-    'dag'                      : 8224,
-    'thickspace'               : 8197,
-    'frakZ'                    : 8488,
-    'lessdot'                  : 8918,
-    'triangledown'             : 9663,
-    'ltimes'                   : 8905,
-    'scrB'                     : 8492,
-    'endash'                   : 8211,
-    'scrE'                     : 8496,
-    'scrF'                     : 8497,
-    'scrH'                     : 8459,
-    'scrI'                     : 8464,
-    'rightharpoondown'         : 8641,
-    'scrL'                     : 8466,
-    'scrM'                     : 8499,
-    'frakC'                    : 8493,
-    'nsupseteq'                : 8841,
-    'circledR'                 : 174,
-    'circledS'                 : 9416,
-    'ngtr'                     : 8815,
-    'bigcap'                   : 8898,
-    'scre'                     : 8495,
-    'Downarrow'                : 8659,
-    'scrg'                     : 8458,
-    'overleftrightarrow'       : 8417,
-    'scro'                     : 8500,
-    'lnsim'                    : 8934,
-    'eqcolon'                  : 8789,
-    'curlyvee'                 : 8910,
-    'urcorner'                 : 8989,
-    'lbrace'                   : 123,
-    'Bumpeq'                   : 8782,
-    'delta'                    : 948,
-    'boxtimes'                 : 8864,
-    'overleftarrow'            : 8406,
-    'prurel'                   : 8880,
-    'clubsuitopen'             : 9831,
-    'cwopencirclearrow'        : 8635,
-    'geqq'                     : 8807,
-    'rightleftarrows'          : 8644,
-    'ac'                       : 8766,
-    'ae'                       : 230,
-    'int'                      : 8747,
-    'rfloor'                   : 8971,
-    'risingdotseq'             : 8787,
-    'nvdash'                   : 8876,
-    'diamond'                  : 8900,
-    'ddot'                     : 776,
-    'backsim'                  : 8765,
-    'oplus'                    : 8853,
-    'triangleq'                : 8796,
-    'check'                    : 780,
-    'ni'                       : 8715,
-    'iiint'                    : 8749,
-    'ne'                       : 8800,
-    'lesseqgtr'                : 8922,
-    'obar'                     : 9021,
-    'supseteq'                 : 8839,
-    'nu'                       : 957,
-    'AA'                       : 197,
-    'AE'                       : 198,
-    'models'                   : 8871,
-    'ominus'                   : 8854,
-    'dashv'                    : 8867,
-    'omega'                    : 969,
-    'rq'                       : 8217,
-    'Subset'                   : 8912,
-    'rightharpoonup'           : 8640,
-    'Rdsh'                     : 8627,
-    'bullet'                   : 8729,
-    'divideontimes'            : 8903,
-    'lbrack'                   : 91,
-    'textquotedblright'        : 8221,
-    'Colon'                    : 8759,
-    '%'                        : 37,
-    '$'                        : 36,
-    '{'                        : 123,
-    '}'                        : 125,
-    '_'                        : 95,
-    '#'                        : 35,
-    'imath'                    : 0x131,
-    'circumflexaccent'         : 770,
-    'combiningbreve'           : 774,
-    'combiningoverline'        : 772,
-    'combininggraveaccent'     : 768,
-    'combiningacuteaccent'     : 769,
-    'combiningdiaeresis'       : 776,
-    'combiningtilde'           : 771,
-    'combiningrightarrowabove' : 8407,
-    'combiningdotabove'        : 775,
-    'to'                       : 8594,
-    'succeq'                   : 8829,
-    'emptyset'                 : 8709,
-    'leftparen'                : 40,
-    'rightparen'               : 41,
-    'bigoplus'                 : 10753,
-    'leftangle'                : 10216,
-    'rightangle'               : 10217,
-    'leftbrace'                : 124,
-    'rightbrace'               : 125,
-    'jmath'                    : 567,
-    'bigodot'                  : 10752,
-    'preceq'                   : 8828,
-    'biguplus'                 : 10756,
-    'epsilon'                  : 949,
-    'vartheta'                 : 977,
-    'bigotimes'                : 10754,
-    'guillemotleft'            : 171,
-    'ring'                     : 730,
-    'Thorn'                    : 222,
-    'guilsinglright'           : 8250,
-    'perthousand'              : 8240,
-    'macron'                   : 175,
-    'cent'                     : 162,
-    'guillemotright'           : 187,
-    'equal'                    : 61,
-    'asterisk'                 : 42,
-    'guilsinglleft'            : 8249,
-    'plus'                     : 43,
-    'thorn'                    : 254,
-    'dagger'                   : 8224
-}
-
-# Each element is a 4-tuple of the form:
-#   src_start, src_end, dst_font, dst_start
-#
-stix_virtual_fonts = {
-    'bb':
-        {
-        'rm':
-            [
-            (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9
-            (0x0041, 0x0042, 'rm', 0x1d538), # A-B
-            (0x0043, 0x0043, 'rm', 0x2102),  # C
-            (0x0044, 0x0047, 'rm', 0x1d53b), # D-G
-            (0x0048, 0x0048, 'rm', 0x210d),  # H
-            (0x0049, 0x004d, 'rm', 0x1d540), # I-M
-            (0x004e, 0x004e, 'rm', 0x2115),  # N
-            (0x004f, 0x004f, 'rm', 0x1d546), # O
-            (0x0050, 0x0051, 'rm', 0x2119),  # P-Q
-            (0x0052, 0x0052, 'rm', 0x211d),  # R
-            (0x0053, 0x0059, 'rm', 0x1d54a), # S-Y
-            (0x005a, 0x005a, 'rm', 0x2124),  # Z
-            (0x0061, 0x007a, 'rm', 0x1d552), # a-z
-            (0x0393, 0x0393, 'rm', 0x213e),  # \Gamma
-            (0x03a0, 0x03a0, 'rm', 0x213f),  # \Pi
-            (0x03a3, 0x03a3, 'rm', 0x2140),  # \Sigma
-            (0x03b3, 0x03b3, 'rm', 0x213d),  # \gamma
-            (0x03c0, 0x03c0, 'rm', 0x213c),  # \pi
-            ],
-        'it':
-            [
-            (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9
-            (0x0041, 0x0042, 'it', 0xe154),  # A-B
-            (0x0043, 0x0043, 'it', 0x2102),  # C
-            (0x0044, 0x0044, 'it', 0x2145),  # D
-            (0x0045, 0x0047, 'it', 0xe156),  # E-G
-            (0x0048, 0x0048, 'it', 0x210d),  # H
-            (0x0049, 0x004d, 'it', 0xe159),  # I-M
-            (0x004e, 0x004e, 'it', 0x2115),  # N
-            (0x004f, 0x004f, 'it', 0xe15e),  # O
-            (0x0050, 0x0051, 'it', 0x2119),  # P-Q
-            (0x0052, 0x0052, 'it', 0x211d),  # R
-            (0x0053, 0x0059, 'it', 0xe15f),  # S-Y
-            (0x005a, 0x005a, 'it', 0x2124),  # Z
-            (0x0061, 0x0063, 'it', 0xe166),  # a-c
-            (0x0064, 0x0065, 'it', 0x2146),  # d-e
-            (0x0066, 0x0068, 'it', 0xe169),  # f-h
-            (0x0069, 0x006a, 'it', 0x2148),  # i-j
-            (0x006b, 0x007a, 'it', 0xe16c),  # k-z
-            (0x0393, 0x0393, 'it', 0x213e),  # \Gamma (not in beta STIX fonts)
-            (0x03a0, 0x03a0, 'it', 0x213f),  # \Pi
-            (0x03a3, 0x03a3, 'it', 0x2140),  # \Sigma (not in beta STIX fonts)
-            (0x03b3, 0x03b3, 'it', 0x213d),  # \gamma (not in beta STIX fonts)
-            (0x03c0, 0x03c0, 'it', 0x213c),  # \pi
-            ],
-        'bf':
-            [
-            (0x0030, 0x0039, 'rm', 0x1d7d8), # 0-9
-            (0x0041, 0x0042, 'bf', 0xe38a),  # A-B
-            (0x0043, 0x0043, 'bf', 0x2102),  # C
-            (0x0044, 0x0044, 'bf', 0x2145),  # D
-            (0x0045, 0x0047, 'bf', 0xe38d),  # E-G
-            (0x0048, 0x0048, 'bf', 0x210d),  # H
-            (0x0049, 0x004d, 'bf', 0xe390),  # I-M
-            (0x004e, 0x004e, 'bf', 0x2115),  # N
-            (0x004f, 0x004f, 'bf', 0xe395),  # O
-            (0x0050, 0x0051, 'bf', 0x2119),  # P-Q
-            (0x0052, 0x0052, 'bf', 0x211d),  # R
-            (0x0053, 0x0059, 'bf', 0xe396),  # S-Y
-            (0x005a, 0x005a, 'bf', 0x2124),  # Z
-            (0x0061, 0x0063, 'bf', 0xe39d),  # a-c
-            (0x0064, 0x0065, 'bf', 0x2146),  # d-e
-            (0x0066, 0x0068, 'bf', 0xe3a2),  # f-h
-            (0x0069, 0x006a, 'bf', 0x2148),  # i-j
-            (0x006b, 0x007a, 'bf', 0xe3a7),  # k-z
-            (0x0393, 0x0393, 'bf', 0x213e),  # \Gamma
-            (0x03a0, 0x03a0, 'bf', 0x213f),  # \Pi
-            (0x03a3, 0x03a3, 'bf', 0x2140),  # \Sigma
-            (0x03b3, 0x03b3, 'bf', 0x213d),  # \gamma
-            (0x03c0, 0x03c0, 'bf', 0x213c),  # \pi
-            ],
-        },
-    'cal':
-        [
-        (0x0041, 0x005a, 'it', 0xe22d), # A-Z
-        ],
-    'circled':
-        {
-        'rm':
-            [
-            (0x0030, 0x0030, 'rm', 0x24ea), # 0
-            (0x0031, 0x0039, 'rm', 0x2460), # 1-9
-            (0x0041, 0x005a, 'rm', 0x24b6), # A-Z
-            (0x0061, 0x007a, 'rm', 0x24d0)  # a-z
-            ],
-        'it':
-            [
-            (0x0030, 0x0030, 'rm', 0x24ea), # 0
-            (0x0031, 0x0039, 'rm', 0x2460), # 1-9
-            (0x0041, 0x005a, 'it', 0x24b6), # A-Z
-            (0x0061, 0x007a, 'it', 0x24d0)  # a-z
-            ],
-        'bf':
-            [
-            (0x0030, 0x0030, 'bf', 0x24ea), # 0
-            (0x0031, 0x0039, 'bf', 0x2460), # 1-9
-            (0x0041, 0x005a, 'bf', 0x24b6), # A-Z
-            (0x0061, 0x007a, 'bf', 0x24d0)  # a-z
-            ],
-        },
-    'frak':
-        {
-        'rm':
-            [
-            (0x0041, 0x0042, 'rm', 0x1d504), # A-B
-            (0x0043, 0x0043, 'rm', 0x212d),  # C
-            (0x0044, 0x0047, 'rm', 0x1d507), # D-G
-            (0x0048, 0x0048, 'rm', 0x210c),  # H
-            (0x0049, 0x0049, 'rm', 0x2111),  # I
-            (0x004a, 0x0051, 'rm', 0x1d50d), # J-Q
-            (0x0052, 0x0052, 'rm', 0x211c),  # R
-            (0x0053, 0x0059, 'rm', 0x1d516), # S-Y
-            (0x005a, 0x005a, 'rm', 0x2128),  # Z
-            (0x0061, 0x007a, 'rm', 0x1d51e), # a-z
-            ],
-        'it':
-            [
-            (0x0041, 0x0042, 'rm', 0x1d504), # A-B
-            (0x0043, 0x0043, 'rm', 0x212d),  # C
-            (0x0044, 0x0047, 'rm', 0x1d507), # D-G
-            (0x0048, 0x0048, 'rm', 0x210c),  # H
-            (0x0049, 0x0049, 'rm', 0x2111),  # I
-            (0x004a, 0x0051, 'rm', 0x1d50d), # J-Q
-            (0x0052, 0x0052, 'rm', 0x211c),  # R
-            (0x0053, 0x0059, 'rm', 0x1d516), # S-Y
-            (0x005a, 0x005a, 'rm', 0x2128),  # Z
-            (0x0061, 0x007a, 'rm', 0x1d51e), # a-z
-            ],
-        'bf':
-            [
-            (0x0041, 0x005a, 'bf', 0x1d56c), # A-Z
-            (0x0061, 0x007a, 'bf', 0x1d586), # a-z
-            ],
-        },
-    'scr':
-        [
-        (0x0041, 0x0041, 'it', 0x1d49c), # A
-        (0x0042, 0x0042, 'it', 0x212c),  # B
-        (0x0043, 0x0044, 'it', 0x1d49e), # C-D
-        (0x0045, 0x0046, 'it', 0x2130),  # E-F
-        (0x0047, 0x0047, 'it', 0x1d4a2), # G
-        (0x0048, 0x0048, 'it', 0x210b),  # H
-        (0x0049, 0x0049, 'it', 0x2110),  # I
-        (0x004a, 0x004b, 'it', 0x1d4a5), # J-K
-        (0x004c, 0x004c, 'it', 0x2112),  # L
-        (0x004d, 0x004d, 'it', 0x2133),  # M
-        (0x004e, 0x0051, 'it', 0x1d4a9), # N-Q
-        (0x0052, 0x0052, 'it', 0x211b),  # R
-        (0x0053, 0x005a, 'it', 0x1d4ae), # S-Z
-        (0x0061, 0x0064, 'it', 0x1d4b6), # a-d
-        (0x0065, 0x0065, 'it', 0x212f),  # e
-        (0x0066, 0x0066, 'it', 0x1d4bb), # f
-        (0x0067, 0x0067, 'it', 0x210a),  # g
-        (0x0068, 0x006e, 'it', 0x1d4bd), # h-n
-        (0x006f, 0x006f, 'it', 0x2134),  # o
-        (0x0070, 0x007a, 'it', 0x1d4c5), # p-z
-        ],
-    'sf':
-        {
-        'rm':
-            [
-            (0x0030, 0x0039, 'rm', 0x1d7e2), # 0-9
-            (0x0041, 0x005a, 'rm', 0x1d5a0), # A-Z
-            (0x0061, 0x007a, 'rm', 0x1d5ba), # a-z
-            (0x0391, 0x03a9, 'rm', 0xe17d),  # \Alpha-\Omega
-            (0x03b1, 0x03c9, 'rm', 0xe196),  # \alpha-\omega
-            (0x03d1, 0x03d1, 'rm', 0xe1b0),  # theta variant
-            (0x03d5, 0x03d5, 'rm', 0xe1b1),  # phi variant
-            (0x03d6, 0x03d6, 'rm', 0xe1b3),  # pi variant
-            (0x03f1, 0x03f1, 'rm', 0xe1b2),  # rho variant
-            (0x03f5, 0x03f5, 'rm', 0xe1af),  # lunate epsilon
-            (0x2202, 0x2202, 'rm', 0xe17c),  # partial differential
-            ],
-        'it':
-            [
-            # These numerals are actually upright.  We don't actually
-            # want italic numerals ever.
-            (0x0030, 0x0039, 'rm', 0x1d7e2), # 0-9
-            (0x0041, 0x005a, 'it', 0x1d608), # A-Z
-            (0x0061, 0x007a, 'it', 0x1d622), # a-z
-            (0x0391, 0x03a9, 'rm', 0xe17d),  # \Alpha-\Omega
-            (0x03b1, 0x03c9, 'it', 0xe1d8),  # \alpha-\omega
-            (0x03d1, 0x03d1, 'it', 0xe1f2),  # theta variant
-            (0x03d5, 0x03d5, 'it', 0xe1f3),  # phi variant
-            (0x03d6, 0x03d6, 'it', 0xe1f5),  # pi variant
-            (0x03f1, 0x03f1, 'it', 0xe1f4),  # rho variant
-            (0x03f5, 0x03f5, 'it', 0xe1f1),  # lunate epsilon
-            ],
-        'bf':
-            [
-            (0x0030, 0x0039, 'bf', 0x1d7ec), # 0-9
-            (0x0041, 0x005a, 'bf', 0x1d5d4), # A-Z
-            (0x0061, 0x007a, 'bf', 0x1d5ee), # a-z
-            (0x0391, 0x03a9, 'bf', 0x1d756), # \Alpha-\Omega
-            (0x03b1, 0x03c9, 'bf', 0x1d770), # \alpha-\omega
-            (0x03d1, 0x03d1, 'bf', 0x1d78b), # theta variant
-            (0x03d5, 0x03d5, 'bf', 0x1d78d), # phi variant
-            (0x03d6, 0x03d6, 'bf', 0x1d78f), # pi variant
-            (0x03f0, 0x03f0, 'bf', 0x1d78c), # kappa variant
-            (0x03f1, 0x03f1, 'bf', 0x1d78e), # rho variant
-            (0x03f5, 0x03f5, 'bf', 0x1d78a), # lunate epsilon
-            (0x2202, 0x2202, 'bf', 0x1d789), # partial differential
-            (0x2207, 0x2207, 'bf', 0x1d76f), # \Nabla
-            ],
-        },
-    'tt':
-        [
-        (0x0030, 0x0039, 'rm', 0x1d7f6), # 0-9
-        (0x0041, 0x005a, 'rm', 0x1d670), # A-Z
-        (0x0061, 0x007a, 'rm', 0x1d68a)  # a-z
-        ],
-    }

BIN
venv/lib/python3.8/site-packages/matplotlib/_path.cpython-38-x86_64-linux-gnu.so


BIN
venv/lib/python3.8/site-packages/matplotlib/_png.cpython-38-x86_64-linux-gnu.so


+ 0 - 129
venv/lib/python3.8/site-packages/matplotlib/_pylab_helpers.py

@@ -1,129 +0,0 @@
-"""
-Manage figures for pyplot interface.
-"""
-
-import atexit
-import gc
-
-
-class Gcf:
-    """
-    Singleton to manage a set of integer-numbered figures.
-
-    This class is never instantiated; it consists of two class
-    attributes (a list and a dictionary), and a set of static
-    methods that operate on those attributes, accessing them
-    directly as class attributes.
-
-    Attributes
-    ----------
-    figs
-          dictionary of the form {*num*: *manager*, ...}
-    _activeQue
-          list of *managers*, with active one at the end
-
-    """
-    _activeQue = []
-    figs = {}
-
-    @classmethod
-    def get_fig_manager(cls, num):
-        """
-        If figure manager *num* exists, make it the active
-        figure and return the manager; otherwise return *None*.
-        """
-        manager = cls.figs.get(num, None)
-        if manager is not None:
-            cls.set_active(manager)
-        return manager
-
-    @classmethod
-    def destroy(cls, num):
-        """
-        Try to remove all traces of figure *num*.
-
-        In the interactive backends, this is bound to the
-        window "destroy" and "delete" events.
-        """
-        if not cls.has_fignum(num):
-            return
-        manager = cls.figs[num]
-        manager.canvas.mpl_disconnect(manager._cidgcf)
-        cls._activeQue.remove(manager)
-        del cls.figs[num]
-        manager.destroy()
-        gc.collect(1)
-
-    @classmethod
-    def destroy_fig(cls, fig):
-        "*fig* is a Figure instance"
-        num = next((manager.num for manager in cls.figs.values()
-                    if manager.canvas.figure == fig), None)
-        if num is not None:
-            cls.destroy(num)
-
-    @classmethod
-    def destroy_all(cls):
-        # this is need to ensure that gc is available in corner cases
-        # where modules are being torn down after install with easy_install
-        import gc  # noqa
-        for manager in list(cls.figs.values()):
-            manager.canvas.mpl_disconnect(manager._cidgcf)
-            manager.destroy()
-
-        cls._activeQue = []
-        cls.figs.clear()
-        gc.collect(1)
-
-    @classmethod
-    def has_fignum(cls, num):
-        """
-        Return *True* if figure *num* exists.
-        """
-        return num in cls.figs
-
-    @classmethod
-    def get_all_fig_managers(cls):
-        """
-        Return a list of figure managers.
-        """
-        return list(cls.figs.values())
-
-    @classmethod
-    def get_num_fig_managers(cls):
-        """
-        Return the number of figures being managed.
-        """
-        return len(cls.figs)
-
-    @classmethod
-    def get_active(cls):
-        """
-        Return the manager of the active figure, or *None*.
-        """
-        if len(cls._activeQue) == 0:
-            return None
-        else:
-            return cls._activeQue[-1]
-
-    @classmethod
-    def set_active(cls, manager):
-        """
-        Make the figure corresponding to *manager* the active one.
-        """
-        oldQue = cls._activeQue[:]
-        cls._activeQue = [m for m in oldQue if m != manager]
-        cls._activeQue.append(manager)
-        cls.figs[manager.num] = manager
-
-    @classmethod
-    def draw_all(cls, force=False):
-        """
-        Redraw all figures registered with the pyplot
-        state machine.
-        """
-        for f_mgr in cls.get_all_fig_managers():
-            if force or f_mgr.canvas.figure.stale:
-                f_mgr.canvas.draw_idle()
-
-atexit.register(Gcf.destroy_all)

BIN
venv/lib/python3.8/site-packages/matplotlib/_qhull.cpython-38-x86_64-linux-gnu.so


+ 0 - 38
venv/lib/python3.8/site-packages/matplotlib/_text_layout.py

@@ -1,38 +0,0 @@
-"""
-Text layouting utilities.
-"""
-
-from .ft2font import KERNING_DEFAULT, LOAD_NO_HINTING
-
-
-def layout(string, font, *, kern_mode=KERNING_DEFAULT):
-    """
-    Render *string* with *font*.  For each character in *string*, yield a
-    (glyph-index, x-position) pair.  When such a pair is yielded, the font's
-    glyph is set to the corresponding character.
-
-    Parameters
-    ----------
-    string : str
-        The string to be rendered.
-    font : FT2Font
-        The font.
-    kern_mode : int
-        A FreeType kerning mode.
-
-    Yields
-    ------
-    glyph_index : int
-    x_position : float
-    """
-    x = 0
-    last_glyph_idx = None
-    for char in string:
-        glyph_idx = font.get_char_index(ord(char))
-        kern = (font.get_kerning(last_glyph_idx, glyph_idx, kern_mode)
-                if last_glyph_idx is not None else 0) / 64
-        x += kern
-        glyph = font.load_glyph(glyph_idx, flags=LOAD_NO_HINTING)
-        yield glyph_idx, x
-        x += glyph.linearHoriAdvance / 65536
-        last_glyph_idx = glyph_idx

BIN
venv/lib/python3.8/site-packages/matplotlib/_tri.cpython-38-x86_64-linux-gnu.so


+ 0 - 21
venv/lib/python3.8/site-packages/matplotlib/_version.py

@@ -1,21 +0,0 @@
-
-# This file was generated by 'versioneer.py' (0.15) from
-# revision-control system data, or from the parent directory name of an
-# unpacked source archive. Distribution tarballs contain a pre-generated copy
-# of this file.
-
-import json
-import sys
-
-version_json = '''
-{
- "dirty": false,
- "error": null,
- "full-revisionid": "ca3d653536dec38a0c1ac3b80413961ca1bcdda6",
- "version": "3.2.1"
-}
-'''  # END VERSION_JSON
-
-
-def get_versions():
-    return json.loads(version_json)

+ 0 - 530
venv/lib/python3.8/site-packages/matplotlib/afm.py

@@ -1,530 +0,0 @@
-"""
-This is a python interface to Adobe Font Metrics Files.  Although a
-number of other python implementations exist, and may be more complete
-than this, it was decided not to go with them because they were either:
-
-1) copyrighted or used a non-BSD compatible license
-2) had too many dependencies and a free standing lib was needed
-3) did more than needed and it was easier to write afresh rather than
-   figure out how to get just what was needed.
-
-It is pretty easy to use, and requires only built-in python libs:
-
->>> import matplotlib as mpl
->>> from pathlib import Path
->>> afm_path = Path(mpl.get_data_path(), 'fonts', 'afm', 'ptmr8a.afm')
->>>
->>> from matplotlib.afm import AFM
->>> with afm_path.open('rb') as fh:
-...     afm = AFM(fh)
->>> afm.string_width_height('What the heck?')
-(6220.0, 694)
->>> afm.get_fontname()
-'Times-Roman'
->>> afm.get_kern_dist('A', 'f')
-0
->>> afm.get_kern_dist('A', 'y')
--92.0
->>> afm.get_bbox_char('!')
-[130, -9, 238, 676]
-
-As in the Adobe Font Metrics File Format Specification, all dimensions
-are given in units of 1/1000 of the scale factor (point size) of the font
-being used.
-"""
-
-from collections import namedtuple
-import logging
-import re
-
-
-from ._mathtext_data import uni2type1
-from matplotlib.cbook import deprecated
-
-
-_log = logging.getLogger(__name__)
-
-
-def _to_int(x):
-    # Some AFM files have floats where we are expecting ints -- there is
-    # probably a better way to handle this (support floats, round rather than
-    # truncate).  But I don't know what the best approach is now and this
-    # change to _to_int should at least prevent Matplotlib from crashing on
-    # these.  JDH (2009-11-06)
-    return int(float(x))
-
-
-def _to_float(x):
-    # Some AFM files use "," instead of "." as decimal separator -- this
-    # shouldn't be ambiguous (unless someone is wicked enough to use "," as
-    # thousands separator...).
-    if isinstance(x, bytes):
-        # Encoding doesn't really matter -- if we have codepoints >127 the call
-        # to float() will error anyways.
-        x = x.decode('latin-1')
-    return float(x.replace(',', '.'))
-
-
-def _to_str(x):
-    return x.decode('utf8')
-
-
-def _to_list_of_ints(s):
-    s = s.replace(b',', b' ')
-    return [_to_int(val) for val in s.split()]
-
-
-def _to_list_of_floats(s):
-    return [_to_float(val) for val in s.split()]
-
-
-def _to_bool(s):
-    if s.lower().strip() in (b'false', b'0', b'no'):
-        return False
-    else:
-        return True
-
-
-def _parse_header(fh):
-    """
-    Reads the font metrics header (up to the char metrics) and returns
-    a dictionary mapping *key* to *val*.  *val* will be converted to the
-    appropriate python type as necessary; e.g.:
-
-        * 'False'->False
-        * '0'->0
-        * '-168 -218 1000 898'-> [-168, -218, 1000, 898]
-
-    Dictionary keys are
-
-      StartFontMetrics, FontName, FullName, FamilyName, Weight,
-      ItalicAngle, IsFixedPitch, FontBBox, UnderlinePosition,
-      UnderlineThickness, Version, Notice, EncodingScheme, CapHeight,
-      XHeight, Ascender, Descender, StartCharMetrics
-
-    """
-    header_converters = {
-        b'StartFontMetrics': _to_float,
-        b'FontName': _to_str,
-        b'FullName': _to_str,
-        b'FamilyName': _to_str,
-        b'Weight': _to_str,
-        b'ItalicAngle': _to_float,
-        b'IsFixedPitch': _to_bool,
-        b'FontBBox': _to_list_of_ints,
-        b'UnderlinePosition': _to_float,
-        b'UnderlineThickness': _to_float,
-        b'Version': _to_str,
-        # Some AFM files have non-ASCII characters (which are not allowed by
-        # the spec).  Given that there is actually no public API to even access
-        # this field, just return it as straight bytes.
-        b'Notice': lambda x: x,
-        b'EncodingScheme': _to_str,
-        b'CapHeight': _to_float,  # Is the second version a mistake, or
-        b'Capheight': _to_float,  # do some AFM files contain 'Capheight'? -JKS
-        b'XHeight': _to_float,
-        b'Ascender': _to_float,
-        b'Descender': _to_float,
-        b'StdHW': _to_float,
-        b'StdVW': _to_float,
-        b'StartCharMetrics': _to_int,
-        b'CharacterSet': _to_str,
-        b'Characters': _to_int,
-        }
-
-    d = {}
-    first_line = True
-    for line in fh:
-        line = line.rstrip()
-        if line.startswith(b'Comment'):
-            continue
-        lst = line.split(b' ', 1)
-        key = lst[0]
-        if first_line:
-            # AFM spec, Section 4: The StartFontMetrics keyword
-            # [followed by a version number] must be the first line in
-            # the file, and the EndFontMetrics keyword must be the
-            # last non-empty line in the file.  We just check the
-            # first header entry.
-            if key != b'StartFontMetrics':
-                raise RuntimeError('Not an AFM file')
-            first_line = False
-        if len(lst) == 2:
-            val = lst[1]
-        else:
-            val = b''
-        try:
-            converter = header_converters[key]
-        except KeyError:
-            _log.error('Found an unknown keyword in AFM header (was %r)' % key)
-            continue
-        try:
-            d[key] = converter(val)
-        except ValueError:
-            _log.error('Value error parsing header in AFM: %s, %s', key, val)
-            continue
-        if key == b'StartCharMetrics':
-            break
-    else:
-        raise RuntimeError('Bad parse')
-    return d
-
-
-CharMetrics = namedtuple('CharMetrics', 'width, name, bbox')
-CharMetrics.__doc__ = """
-    Represents the character metrics of a single character.
-
-    Notes
-    -----
-    The fields do currently only describe a subset of character metrics
-    information defined in the AFM standard.
-    """
-CharMetrics.width.__doc__ = """The character width (WX)."""
-CharMetrics.name.__doc__ = """The character name (N)."""
-CharMetrics.bbox.__doc__ = """
-    The bbox of the character (B) as a tuple (*llx*, *lly*, *urx*, *ury*)."""
-
-
-def _parse_char_metrics(fh):
-    """
-    Parse the given filehandle for character metrics information and return
-    the information as dicts.
-
-    It is assumed that the file cursor is on the line behind
-    'StartCharMetrics'.
-
-    Returns
-    -------
-    ascii_d : dict
-         A mapping "ASCII num of the character" to `.CharMetrics`.
-    name_d : dict
-         A mapping "character name" to `.CharMetrics`.
-
-    Notes
-    -----
-    This function is incomplete per the standard, but thus far parses
-    all the sample afm files tried.
-    """
-    required_keys = {'C', 'WX', 'N', 'B'}
-
-    ascii_d = {}
-    name_d = {}
-    for line in fh:
-        # We are defensively letting values be utf8. The spec requires
-        # ascii, but there are non-compliant fonts in circulation
-        line = _to_str(line.rstrip())  # Convert from byte-literal
-        if line.startswith('EndCharMetrics'):
-            return ascii_d, name_d
-        # Split the metric line into a dictionary, keyed by metric identifiers
-        vals = dict(s.strip().split(' ', 1) for s in line.split(';') if s)
-        # There may be other metrics present, but only these are needed
-        if not required_keys.issubset(vals):
-            raise RuntimeError('Bad char metrics line: %s' % line)
-        num = _to_int(vals['C'])
-        wx = _to_float(vals['WX'])
-        name = vals['N']
-        bbox = _to_list_of_floats(vals['B'])
-        bbox = list(map(int, bbox))
-        metrics = CharMetrics(wx, name, bbox)
-        # Workaround: If the character name is 'Euro', give it the
-        # corresponding character code, according to WinAnsiEncoding (see PDF
-        # Reference).
-        if name == 'Euro':
-            num = 128
-        elif name == 'minus':
-            num = ord("\N{MINUS SIGN}")  # 0x2212
-        if num != -1:
-            ascii_d[num] = metrics
-        name_d[name] = metrics
-    raise RuntimeError('Bad parse')
-
-
-def _parse_kern_pairs(fh):
-    """
-    Return a kern pairs dictionary; keys are (*char1*, *char2*) tuples and
-    values are the kern pair value.  For example, a kern pairs line like
-    ``KPX A y -50``
-
-    will be represented as::
-
-      d[ ('A', 'y') ] = -50
-
-    """
-
-    line = next(fh)
-    if not line.startswith(b'StartKernPairs'):
-        raise RuntimeError('Bad start of kern pairs data: %s' % line)
-
-    d = {}
-    for line in fh:
-        line = line.rstrip()
-        if not line:
-            continue
-        if line.startswith(b'EndKernPairs'):
-            next(fh)  # EndKernData
-            return d
-        vals = line.split()
-        if len(vals) != 4 or vals[0] != b'KPX':
-            raise RuntimeError('Bad kern pairs line: %s' % line)
-        c1, c2, val = _to_str(vals[1]), _to_str(vals[2]), _to_float(vals[3])
-        d[(c1, c2)] = val
-    raise RuntimeError('Bad kern pairs parse')
-
-
-CompositePart = namedtuple('CompositePart', 'name, dx, dy')
-CompositePart.__doc__ = """
-    Represents the information on a composite element of a composite char."""
-CompositePart.name.__doc__ = """Name of the part, e.g. 'acute'."""
-CompositePart.dx.__doc__ = """x-displacement of the part from the origin."""
-CompositePart.dy.__doc__ = """y-displacement of the part from the origin."""
-
-
-def _parse_composites(fh):
-    """
-    Parse the given filehandle for composites information return them as a
-    dict.
-
-    It is assumed that the file cursor is on the line behind 'StartComposites'.
-
-    Returns
-    -------
-    composites : dict
-        A dict mapping composite character names to a parts list. The parts
-        list is a list of `.CompositePart` entries describing the parts of
-        the composite.
-
-    Example
-    -------
-    A composite definition line::
-
-      CC Aacute 2 ; PCC A 0 0 ; PCC acute 160 170 ;
-
-    will be represented as::
-
-      composites['Aacute'] = [CompositePart(name='A', dx=0, dy=0),
-                              CompositePart(name='acute', dx=160, dy=170)]
-
-    """
-    composites = {}
-    for line in fh:
-        line = line.rstrip()
-        if not line:
-            continue
-        if line.startswith(b'EndComposites'):
-            return composites
-        vals = line.split(b';')
-        cc = vals[0].split()
-        name, numParts = cc[1], _to_int(cc[2])
-        pccParts = []
-        for s in vals[1:-1]:
-            pcc = s.split()
-            part = CompositePart(pcc[1], _to_float(pcc[2]), _to_float(pcc[3]))
-            pccParts.append(part)
-        composites[name] = pccParts
-
-    raise RuntimeError('Bad composites parse')
-
-
-def _parse_optional(fh):
-    """
-    Parse the optional fields for kern pair data and composites.
-
-    Returns
-    -------
-    kern_data : dict
-        A dict containing kerning information. May be empty.
-        See `._parse_kern_pairs`.
-    composites : dict
-        A dict containing composite information. May be empty.
-        See `._parse_composites`.
-    """
-    optional = {
-        b'StartKernData': _parse_kern_pairs,
-        b'StartComposites':  _parse_composites,
-        }
-
-    d = {b'StartKernData': {},
-         b'StartComposites': {}}
-    for line in fh:
-        line = line.rstrip()
-        if not line:
-            continue
-        key = line.split()[0]
-
-        if key in optional:
-            d[key] = optional[key](fh)
-
-    return d[b'StartKernData'], d[b'StartComposites']
-
-
-class AFM:
-
-    def __init__(self, fh):
-        """Parse the AFM file in file object *fh*."""
-        self._header = _parse_header(fh)
-        self._metrics, self._metrics_by_name = _parse_char_metrics(fh)
-        self._kern, self._composite = _parse_optional(fh)
-
-    def get_bbox_char(self, c, isord=False):
-        if not isord:
-            c = ord(c)
-        return self._metrics[c].bbox
-
-    def string_width_height(self, s):
-        """
-        Return the string width (including kerning) and string height
-        as a (*w*, *h*) tuple.
-        """
-        if not len(s):
-            return 0, 0
-        total_width = 0
-        namelast = None
-        miny = 1e9
-        maxy = 0
-        for c in s:
-            if c == '\n':
-                continue
-            wx, name, bbox = self._metrics[ord(c)]
-
-            total_width += wx + self._kern.get((namelast, name), 0)
-            l, b, w, h = bbox
-            miny = min(miny, b)
-            maxy = max(maxy, b + h)
-
-            namelast = name
-
-        return total_width, maxy - miny
-
-    def get_str_bbox_and_descent(self, s):
-        """Return the string bounding box and the maximal descent."""
-        if not len(s):
-            return 0, 0, 0, 0, 0
-        total_width = 0
-        namelast = None
-        miny = 1e9
-        maxy = 0
-        left = 0
-        if not isinstance(s, str):
-            s = _to_str(s)
-        for c in s:
-            if c == '\n':
-                continue
-            name = uni2type1.get(ord(c), 'question')
-            try:
-                wx, _, bbox = self._metrics_by_name[name]
-            except KeyError:
-                name = 'question'
-                wx, _, bbox = self._metrics_by_name[name]
-            total_width += wx + self._kern.get((namelast, name), 0)
-            l, b, w, h = bbox
-            left = min(left, l)
-            miny = min(miny, b)
-            maxy = max(maxy, b + h)
-
-            namelast = name
-
-        return left, miny, total_width, maxy - miny, -miny
-
-    def get_str_bbox(self, s):
-        """Return the string bounding box."""
-        return self.get_str_bbox_and_descent(s)[:4]
-
-    def get_name_char(self, c, isord=False):
-        """Get the name of the character, i.e., ';' is 'semicolon'."""
-        if not isord:
-            c = ord(c)
-        return self._metrics[c].name
-
-    def get_width_char(self, c, isord=False):
-        """
-        Get the width of the character from the character metric WX field.
-        """
-        if not isord:
-            c = ord(c)
-        return self._metrics[c].width
-
-    def get_width_from_char_name(self, name):
-        """Get the width of the character from a type1 character name."""
-        return self._metrics_by_name[name].width
-
-    def get_height_char(self, c, isord=False):
-        """Get the bounding box (ink) height of character *c* (space is 0)."""
-        if not isord:
-            c = ord(c)
-        return self._metrics[c].bbox[-1]
-
-    def get_kern_dist(self, c1, c2):
-        """
-        Return the kerning pair distance (possibly 0) for chars *c1* and *c2*.
-        """
-        name1, name2 = self.get_name_char(c1), self.get_name_char(c2)
-        return self.get_kern_dist_from_name(name1, name2)
-
-    def get_kern_dist_from_name(self, name1, name2):
-        """
-        Return the kerning pair distance (possibly 0) for chars
-        *name1* and *name2*.
-        """
-        return self._kern.get((name1, name2), 0)
-
-    def get_fontname(self):
-        """Return the font name, e.g., 'Times-Roman'."""
-        return self._header[b'FontName']
-
-    def get_fullname(self):
-        """Return the font full name, e.g., 'Times-Roman'."""
-        name = self._header.get(b'FullName')
-        if name is None:  # use FontName as a substitute
-            name = self._header[b'FontName']
-        return name
-
-    def get_familyname(self):
-        """Return the font family name, e.g., 'Times'."""
-        name = self._header.get(b'FamilyName')
-        if name is not None:
-            return name
-
-        # FamilyName not specified so we'll make a guess
-        name = self.get_fullname()
-        extras = (r'(?i)([ -](regular|plain|italic|oblique|bold|semibold|'
-                  r'light|ultralight|extra|condensed))+$')
-        return re.sub(extras, '', name)
-
-    @property
-    def family_name(self):
-        """The font family name, e.g., 'Times'."""
-        return self.get_familyname()
-
-    def get_weight(self):
-        """Return the font weight, e.g., 'Bold' or 'Roman'."""
-        return self._header[b'Weight']
-
-    def get_angle(self):
-        """Return the fontangle as float."""
-        return self._header[b'ItalicAngle']
-
-    def get_capheight(self):
-        """Return the cap height as float."""
-        return self._header[b'CapHeight']
-
-    def get_xheight(self):
-        """Return the xheight as float."""
-        return self._header[b'XHeight']
-
-    def get_underline_thickness(self):
-        """Return the underline thickness as float."""
-        return self._header[b'UnderlineThickness']
-
-    def get_horizontal_stem_width(self):
-        """
-        Return the standard horizontal stem width as float, or *None* if
-        not specified in AFM file.
-        """
-        return self._header.get(b'StdHW', None)
-
-    def get_vertical_stem_width(self):
-        """
-        Return the standard vertical stem width as float, or *None* if
-        not specified in AFM file.
-        """
-        return self._header.get(b'StdVW', None)

+ 0 - 1775
venv/lib/python3.8/site-packages/matplotlib/animation.py

@@ -1,1775 +0,0 @@
-# TODO:
-# * Documentation -- this will need a new section of the User's Guide.
-#      Both for Animations and just timers.
-#   - Also need to update http://www.scipy.org/Cookbook/Matplotlib/Animations
-# * Blit
-#   * Currently broken with Qt4 for widgets that don't start on screen
-#   * Still a few edge cases that aren't working correctly
-#   * Can this integrate better with existing matplotlib animation artist flag?
-#     - If animated removes from default draw(), perhaps we could use this to
-#       simplify initial draw.
-# * Example
-#   * Frameless animation - pure procedural with no loop
-#   * Need example that uses something like inotify or subprocess
-#   * Complex syncing examples
-# * Movies
-#   * Can blit be enabled for movies?
-# * Need to consider event sources to allow clicking through multiple figures
-
-import abc
-import base64
-import contextlib
-from io import BytesIO, TextIOWrapper
-import itertools
-import logging
-from pathlib import Path
-import shutil
-import subprocess
-import sys
-from tempfile import TemporaryDirectory
-import uuid
-
-import numpy as np
-
-import matplotlib as mpl
-from matplotlib._animation_data import (
-    DISPLAY_TEMPLATE, INCLUDED_FRAMES, JS_INCLUDE, STYLE_INCLUDE)
-from matplotlib import cbook, rcParams, rc_context
-
-
-_log = logging.getLogger(__name__)
-
-# Process creation flag for subprocess to prevent it raising a terminal
-# window. See for example:
-# https://stackoverflow.com/questions/24130623/using-python-subprocess-popen-cant-prevent-exe-stopped-working-prompt
-if sys.platform == 'win32':
-    subprocess_creation_flags = CREATE_NO_WINDOW = 0x08000000
-else:
-    # Apparently None won't work here
-    subprocess_creation_flags = 0
-
-# Other potential writing methods:
-# * http://pymedia.org/
-# * libming (produces swf) python wrappers: https://github.com/libming/libming
-# * Wrap x264 API:
-
-# (http://stackoverflow.com/questions/2940671/
-# how-to-encode-series-of-images-into-h264-using-x264-api-c-c )
-
-
-def adjusted_figsize(w, h, dpi, n):
-    '''Compute figure size so that pixels are a multiple of n
-
-    Parameters
-    ----------
-    w, h : float
-        Size in inches
-
-    dpi : float
-        The dpi
-
-    n : int
-        The target multiple
-
-    Returns
-    -------
-    wnew, hnew : float
-        The new figure size in inches.
-    '''
-
-    # this maybe simplified if / when we adopt consistent rounding for
-    # pixel size across the whole library
-    def correct_roundoff(x, dpi, n):
-        if int(x*dpi) % n != 0:
-            if int(np.nextafter(x, np.inf)*dpi) % n == 0:
-                x = np.nextafter(x, np.inf)
-            elif int(np.nextafter(x, -np.inf)*dpi) % n == 0:
-                x = np.nextafter(x, -np.inf)
-        return x
-
-    wnew = int(w * dpi / n) * n / dpi
-    hnew = int(h * dpi / n) * n / dpi
-    return (correct_roundoff(wnew, dpi, n), correct_roundoff(hnew, dpi, n))
-
-
-# A registry for available MovieWriter classes
-class MovieWriterRegistry:
-    '''Registry of available writer classes by human readable name.'''
-    def __init__(self):
-        self._registered = dict()
-
-    @cbook.deprecated("3.2")
-    def set_dirty(self):
-        """Sets a flag to re-setup the writers."""
-
-    def register(self, name):
-        """Decorator for registering a class under a name.
-
-        Example use::
-
-            @registry.register(name)
-            class Foo:
-                pass
-        """
-        def wrapper(writer_cls):
-            self._registered[name] = writer_cls
-            return writer_cls
-        return wrapper
-
-    @cbook.deprecated("3.2")
-    def ensure_not_dirty(self):
-        """If dirty, reasks the writers if they are available"""
-
-    @cbook.deprecated("3.2")
-    def reset_available_writers(self):
-        """Reset the available state of all registered writers"""
-
-    @cbook.deprecated("3.2")
-    @property
-    def avail(self):
-        return {name: self._registered[name] for name in self.list()}
-
-    def is_available(self, name):
-        """
-        Check if given writer is available by name.
-
-        Parameters
-        ----------
-        name : str
-
-        Returns
-        -------
-        available : bool
-        """
-        try:
-            cls = self._registered[name]
-        except KeyError:
-            return False
-        return cls.isAvailable()
-
-    def __iter__(self):
-        """Iterate over names of available writer class."""
-        for name in self._registered:
-            if self.is_available(name):
-                yield name
-
-    def list(self):
-        """Get a list of available MovieWriters."""
-        return [*self]
-
-    def __getitem__(self, name):
-        """Get an available writer class from its name."""
-        if self.is_available(name):
-            return self._registered[name]
-        raise RuntimeError(f"Requested MovieWriter ({name}) not available")
-
-
-writers = MovieWriterRegistry()
-
-
-class AbstractMovieWriter(abc.ABC):
-    '''
-    Abstract base class for writing movies. Fundamentally, what a MovieWriter
-    does is provide is a way to grab frames by calling grab_frame().
-
-    setup() is called to start the process and finish() is called afterwards.
-
-    This class is set up to provide for writing movie frame data to a pipe.
-    saving() is provided as a context manager to facilitate this process as::
-
-        with moviewriter.saving(fig, outfile='myfile.mp4', dpi=100):
-            # Iterate over frames
-            moviewriter.grab_frame(**savefig_kwargs)
-
-    The use of the context manager ensures that setup() and finish() are
-    performed as necessary.
-
-    An instance of a concrete subclass of this class can be given as the
-    ``writer`` argument of `Animation.save()`.
-    '''
-
-    @abc.abstractmethod
-    def setup(self, fig, outfile, dpi=None):
-        '''
-        Perform setup for writing the movie file.
-
-        Parameters
-        ----------
-        fig : `~matplotlib.figure.Figure`
-            The figure object that contains the information for frames
-        outfile : str
-            The filename of the resulting movie file
-        dpi : int, optional
-            The DPI (or resolution) for the file.  This controls the size
-            in pixels of the resulting movie file. Default is ``fig.dpi``.
-        '''
-
-    @abc.abstractmethod
-    def grab_frame(self, **savefig_kwargs):
-        '''
-        Grab the image information from the figure and save as a movie frame.
-
-        All keyword arguments in savefig_kwargs are passed on to the `savefig`
-        command that saves the figure.
-        '''
-
-    @abc.abstractmethod
-    def finish(self):
-        '''Finish any processing for writing the movie.'''
-
-    @contextlib.contextmanager
-    def saving(self, fig, outfile, dpi, *args, **kwargs):
-        '''
-        Context manager to facilitate writing the movie file.
-
-        ``*args, **kw`` are any parameters that should be passed to `setup`.
-        '''
-        # This particular sequence is what contextlib.contextmanager wants
-        self.setup(fig, outfile, dpi, *args, **kwargs)
-        try:
-            yield self
-        finally:
-            self.finish()
-
-
-class MovieWriter(AbstractMovieWriter):
-    """
-    Base class for writing movies.
-
-    This is a base class for MovieWriter subclasses that write a movie frame
-    data to a pipe. You cannot instantiate this class directly.
-    See examples for how to use its subclasses.
-
-    Attributes
-    ----------
-    frame_format : str
-        The format used in writing frame data, defaults to 'rgba'.
-    fig : `~matplotlib.figure.Figure`
-        The figure to capture data from.
-        This must be provided by the sub-classes.
-
-    """
-
-    def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,
-                 metadata=None):
-        """
-        Parameters
-        ----------
-        fps : int
-            Framerate for movie.
-        codec : str or None, optional
-            The codec to use. If ``None`` (the default) :rc:`animation.codec`
-            is used.
-        bitrate : int or None, optional
-            The bitrate for the saved movie file, which is one way to control
-            the output file size and quality. The default value is ``None``,
-            which uses :rc:`animation.bitrate`.  A value of -1 implies that
-            the bitrate should be determined automatically by the underlying
-            utility.
-        extra_args : list of str or None, optional
-            A list of extra string arguments to be passed to the underlying
-            movie utility. The default is ``None``, which passes the additional
-            arguments in :rc:`animation.extra_args`.
-        metadata : Dict[str, str] or None
-            A dictionary of keys and values for metadata to include in the
-            output file. Some keys that may be of use include:
-            title, artist, genre, subject, copyright, srcform, comment.
-        """
-        if self.__class__ is MovieWriter:
-            # TODO MovieWriter is still an abstract class and needs to be
-            #      extended with a mixin. This should be clearer in naming
-            #      and description. For now, just give a reasonable error
-            #      message to users.
-            raise TypeError(
-                'MovieWriter cannot be instantiated directly. Please use one '
-                'of its subclasses.')
-
-        self.fps = fps
-        self.frame_format = 'rgba'
-
-        if codec is None:
-            self.codec = rcParams['animation.codec']
-        else:
-            self.codec = codec
-
-        if bitrate is None:
-            self.bitrate = rcParams['animation.bitrate']
-        else:
-            self.bitrate = bitrate
-
-        if extra_args is None:
-            self.extra_args = list(rcParams[self.args_key])
-        else:
-            self.extra_args = extra_args
-
-        if metadata is None:
-            self.metadata = dict()
-        else:
-            self.metadata = metadata
-
-    @property
-    def frame_size(self):
-        '''A tuple ``(width, height)`` in pixels of a movie frame.'''
-        w, h = self.fig.get_size_inches()
-        return int(w * self.dpi), int(h * self.dpi)
-
-    def _adjust_frame_size(self):
-        if self.codec == 'h264':
-            wo, ho = self.fig.get_size_inches()
-            w, h = adjusted_figsize(wo, ho, self.dpi, 2)
-            if (wo, ho) != (w, h):
-                self.fig.set_size_inches(w, h, forward=True)
-                _log.info('figure size in inches has been adjusted '
-                          'from %s x %s to %s x %s', wo, ho, w, h)
-        else:
-            w, h = self.fig.get_size_inches()
-        _log.debug('frame size in pixels is %s x %s', *self.frame_size)
-        return w, h
-
-    def setup(self, fig, outfile, dpi=None):
-        '''
-        Perform setup for writing the movie file.
-
-        Parameters
-        ----------
-        fig : `~matplotlib.figure.Figure`
-            The figure object that contains the information for frames
-        outfile : str
-            The filename of the resulting movie file
-        dpi : int, optional
-            The DPI (or resolution) for the file.  This controls the size
-            in pixels of the resulting movie file. Default is fig.dpi.
-        '''
-        self.outfile = outfile
-        self.fig = fig
-        if dpi is None:
-            dpi = self.fig.dpi
-        self.dpi = dpi
-        self._w, self._h = self._adjust_frame_size()
-
-        # Run here so that grab_frame() can write the data to a pipe. This
-        # eliminates the need for temp files.
-        self._run()
-
-    def _run(self):
-        # Uses subprocess to call the program for assembling frames into a
-        # movie file.  *args* returns the sequence of command line arguments
-        # from a few configuration options.
-        command = self._args()
-        _log.info('MovieWriter._run: running command: %s',
-                  cbook._pformat_subprocess(command))
-        PIPE = subprocess.PIPE
-        self._proc = subprocess.Popen(
-            command, stdin=PIPE, stdout=PIPE, stderr=PIPE,
-            creationflags=subprocess_creation_flags)
-
-    def finish(self):
-        '''Finish any processing for writing the movie.'''
-        self.cleanup()
-
-    def grab_frame(self, **savefig_kwargs):
-        '''
-        Grab the image information from the figure and save as a movie frame.
-
-        All keyword arguments in savefig_kwargs are passed on to the `savefig`
-        command that saves the figure.
-        '''
-        _log.debug('MovieWriter.grab_frame: Grabbing frame.')
-        # re-adjust the figure size in case it has been changed by the
-        # user.  We must ensure that every frame is the same size or
-        # the movie will not save correctly.
-        self.fig.set_size_inches(self._w, self._h)
-        # Tell the figure to save its data to the sink, using the
-        # frame format and dpi.
-        self.fig.savefig(self._frame_sink(), format=self.frame_format,
-                         dpi=self.dpi, **savefig_kwargs)
-
-    def _frame_sink(self):
-        '''Return the place to which frames should be written.'''
-        return self._proc.stdin
-
-    def _args(self):
-        '''Assemble list of utility-specific command-line arguments.'''
-        return NotImplementedError("args needs to be implemented by subclass.")
-
-    def cleanup(self):
-        '''Clean-up and collect the process used to write the movie file.'''
-        out, err = self._proc.communicate()
-        self._frame_sink().close()
-        # Use the encoding/errors that universal_newlines would use.
-        out = TextIOWrapper(BytesIO(out)).read()
-        err = TextIOWrapper(BytesIO(err)).read()
-        if out:
-            _log.log(
-                logging.WARNING if self._proc.returncode else logging.DEBUG,
-                "MovieWriter stdout:\n%s", out)
-        if err:
-            _log.log(
-                logging.WARNING if self._proc.returncode else logging.DEBUG,
-                "MovieWriter stderr:\n%s", err)
-        if self._proc.returncode:
-            raise subprocess.CalledProcessError(
-                self._proc.returncode, self._proc.args, out, err)
-
-    @classmethod
-    def bin_path(cls):
-        '''
-        Return the binary path to the commandline tool used by a specific
-        subclass. This is a class method so that the tool can be looked for
-        before making a particular MovieWriter subclass available.
-        '''
-        return str(rcParams[cls.exec_key])
-
-    @classmethod
-    def isAvailable(cls):
-        '''
-        Check to see if a MovieWriter subclass is actually available.
-        '''
-        return shutil.which(cls.bin_path()) is not None
-
-
-class FileMovieWriter(MovieWriter):
-    '''`MovieWriter` for writing to individual files and stitching at the end.
-
-    This must be sub-classed to be useful.
-    '''
-    def __init__(self, *args, **kwargs):
-        MovieWriter.__init__(self, *args, **kwargs)
-        self.frame_format = rcParams['animation.frame_format']
-
-    def setup(self, fig, outfile, dpi=None, frame_prefix='_tmp',
-              clear_temp=True):
-        '''Perform setup for writing the movie file.
-
-        Parameters
-        ----------
-        fig : `~matplotlib.figure.Figure`
-            The figure to grab the rendered frames from.
-        outfile : str
-            The filename of the resulting movie file.
-        dpi : number, optional
-            The dpi of the output file. This, with the figure size,
-            controls the size in pixels of the resulting movie file.
-            Default is fig.dpi.
-        frame_prefix : str, optional
-            The filename prefix to use for temporary files.  Defaults to
-            ``'_tmp'``.
-        clear_temp : bool, optional
-            If the temporary files should be deleted after stitching
-            the final result.  Setting this to ``False`` can be useful for
-            debugging.  Defaults to ``True``.
-
-        '''
-        self.fig = fig
-        self.outfile = outfile
-        if dpi is None:
-            dpi = self.fig.dpi
-        self.dpi = dpi
-        self._adjust_frame_size()
-
-        self.clear_temp = clear_temp
-        self.temp_prefix = frame_prefix
-        self._frame_counter = 0  # used for generating sequential file names
-        self._temp_paths = list()
-        self.fname_format_str = '%s%%07d.%s'
-
-    @property
-    def frame_format(self):
-        '''
-        Format (png, jpeg, etc.) to use for saving the frames, which can be
-        decided by the individual subclasses.
-        '''
-        return self._frame_format
-
-    @frame_format.setter
-    def frame_format(self, frame_format):
-        if frame_format in self.supported_formats:
-            self._frame_format = frame_format
-        else:
-            self._frame_format = self.supported_formats[0]
-
-    def _base_temp_name(self):
-        # Generates a template name (without number) given the frame format
-        # for extension and the prefix.
-        return self.fname_format_str % (self.temp_prefix, self.frame_format)
-
-    def _frame_sink(self):
-        # Creates a filename for saving using the basename and the current
-        # counter.
-        path = Path(self._base_temp_name() % self._frame_counter)
-
-        # Save the filename so we can delete it later if necessary
-        self._temp_paths.append(path)
-        _log.debug('FileMovieWriter.frame_sink: saving frame %d to path=%s',
-                   self._frame_counter, path)
-        self._frame_counter += 1  # Ensures each created name is 'unique'
-
-        # This file returned here will be closed once it's used by savefig()
-        # because it will no longer be referenced and will be gc-ed.
-        return open(path, 'wb')
-
-    def grab_frame(self, **savefig_kwargs):
-        '''
-        Grab the image information from the figure and save as a movie frame.
-        All keyword arguments in savefig_kwargs are passed on to the `savefig`
-        command that saves the figure.
-        '''
-        # Overloaded to explicitly close temp file.
-        _log.debug('MovieWriter.grab_frame: Grabbing frame.')
-        # Tell the figure to save its data to the sink, using the
-        # frame format and dpi.
-        with self._frame_sink() as myframesink:
-            self.fig.savefig(myframesink, format=self.frame_format,
-                             dpi=self.dpi, **savefig_kwargs)
-
-    def finish(self):
-        # Call run here now that all frame grabbing is done. All temp files
-        # are available to be assembled.
-        self._run()
-        MovieWriter.finish(self)  # Will call clean-up
-
-    def cleanup(self):
-        MovieWriter.cleanup(self)
-
-        # Delete temporary files
-        if self.clear_temp:
-            _log.debug('MovieWriter: clearing temporary paths=%s',
-                       self._temp_paths)
-            for path in self._temp_paths:
-                path.unlink()
-
-
-@writers.register('pillow')
-class PillowWriter(MovieWriter):
-    @classmethod
-    def isAvailable(cls):
-        try:
-            import PIL
-        except ImportError:
-            return False
-        return True
-
-    def __init__(self, *args, **kwargs):
-        if kwargs.get("extra_args") is None:
-            kwargs["extra_args"] = ()
-        super().__init__(*args, **kwargs)
-
-    def setup(self, fig, outfile, dpi=None):
-        self._frames = []
-        self._outfile = outfile
-        self._dpi = dpi
-        self._fig = fig
-
-    def grab_frame(self, **savefig_kwargs):
-        from PIL import Image
-        buf = BytesIO()
-        self._fig.savefig(buf, **dict(savefig_kwargs, format="rgba"))
-        renderer = self._fig.canvas.get_renderer()
-        self._frames.append(Image.frombuffer(
-            "RGBA",
-            (int(renderer.width), int(renderer.height)), buf.getbuffer(),
-            "raw", "RGBA", 0, 1))
-
-    def finish(self):
-        self._frames[0].save(
-            self._outfile, save_all=True, append_images=self._frames[1:],
-            duration=int(1000 / self.fps), loop=0)
-
-
-# Base class of ffmpeg information. Has the config keys and the common set
-# of arguments that controls the *output* side of things.
-class FFMpegBase:
-    '''Mixin class for FFMpeg output.
-
-    To be useful this must be multiply-inherited from with a
-    `MovieWriterBase` sub-class.
-    '''
-
-    exec_key = 'animation.ffmpeg_path'
-    args_key = 'animation.ffmpeg_args'
-
-    @property
-    def output_args(self):
-        args = ['-vcodec', self.codec]
-        # For h264, the default format is yuv444p, which is not compatible
-        # with quicktime (and others). Specifying yuv420p fixes playback on
-        # iOS, as well as HTML5 video in firefox and safari (on both Win and
-        # OSX). Also fixes internet explorer. This is as of 2015/10/29.
-        if self.codec == 'h264' and '-pix_fmt' not in self.extra_args:
-            args.extend(['-pix_fmt', 'yuv420p'])
-        # The %dk adds 'k' as a suffix so that ffmpeg treats our bitrate as in
-        # kbps
-        if self.bitrate > 0:
-            args.extend(['-b', '%dk' % self.bitrate])
-        if self.extra_args:
-            args.extend(self.extra_args)
-        for k, v in self.metadata.items():
-            args.extend(['-metadata', '%s=%s' % (k, v)])
-
-        return args + ['-y', self.outfile]
-
-    @classmethod
-    def isAvailable(cls):
-        return (
-            super().isAvailable()
-            # Ubuntu 12.04 ships a broken ffmpeg binary which we shouldn't use.
-            # NOTE: when removed, remove the same method in AVConvBase.
-            and b'LibAv' not in subprocess.run(
-                [cls.bin_path()], creationflags=subprocess_creation_flags,
-                stdout=subprocess.DEVNULL, stderr=subprocess.PIPE).stderr)
-
-
-# Combine FFMpeg options with pipe-based writing
-@writers.register('ffmpeg')
-class FFMpegWriter(FFMpegBase, MovieWriter):
-    '''Pipe-based ffmpeg writer.
-
-    Frames are streamed directly to ffmpeg via a pipe and written in a single
-    pass.
-    '''
-    def _args(self):
-        # Returns the command line parameters for subprocess to use
-        # ffmpeg to create a movie using a pipe.
-        args = [self.bin_path(), '-f', 'rawvideo', '-vcodec', 'rawvideo',
-                '-s', '%dx%d' % self.frame_size, '-pix_fmt', self.frame_format,
-                '-r', str(self.fps)]
-        # Logging is quieted because subprocess.PIPE has limited buffer size.
-        # If you have a lot of frames in your animation and set logging to
-        # DEBUG, you will have a buffer overrun.
-        if _log.getEffectiveLevel() > logging.DEBUG:
-            args += ['-loglevel', 'error']
-        args += ['-i', 'pipe:'] + self.output_args
-        return args
-
-
-# Combine FFMpeg options with temp file-based writing
-@writers.register('ffmpeg_file')
-class FFMpegFileWriter(FFMpegBase, FileMovieWriter):
-    '''File-based ffmpeg writer.
-
-    Frames are written to temporary files on disk and then stitched
-    together at the end.
-
-    '''
-    supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp',
-                         'pbm', 'raw', 'rgba']
-
-    def _args(self):
-        # Returns the command line parameters for subprocess to use
-        # ffmpeg to create a movie using a collection of temp images
-        return [self.bin_path(), '-r', str(self.fps),
-                '-i', self._base_temp_name(),
-                '-vframes', str(self._frame_counter)] + self.output_args
-
-
-# Base class of avconv information.  AVConv has identical arguments to FFMpeg.
-class AVConvBase(FFMpegBase):
-    '''Mixin class for avconv output.
-
-    To be useful this must be multiply-inherited from with a
-    `MovieWriterBase` sub-class.
-    '''
-
-    exec_key = 'animation.avconv_path'
-    args_key = 'animation.avconv_args'
-
-    # NOTE : should be removed when the same method is removed in FFMpegBase.
-    isAvailable = classmethod(MovieWriter.isAvailable.__func__)
-
-
-# Combine AVConv options with pipe-based writing
-@writers.register('avconv')
-class AVConvWriter(AVConvBase, FFMpegWriter):
-    '''Pipe-based avconv writer.
-
-    Frames are streamed directly to avconv via a pipe and written in a single
-    pass.
-    '''
-
-
-# Combine AVConv options with file-based writing
-@writers.register('avconv_file')
-class AVConvFileWriter(AVConvBase, FFMpegFileWriter):
-    '''File-based avconv writer.
-
-    Frames are written to temporary files on disk and then stitched
-    together at the end.
-    '''
-
-
-# Base class for animated GIFs with ImageMagick
-class ImageMagickBase:
-    '''Mixin class for ImageMagick output.
-
-    To be useful this must be multiply-inherited from with a
-    `MovieWriterBase` sub-class.
-    '''
-
-    exec_key = 'animation.convert_path'
-    args_key = 'animation.convert_args'
-
-    @property
-    def delay(self):
-        return 100. / self.fps
-
-    @property
-    def output_args(self):
-        return [self.outfile]
-
-    @classmethod
-    def bin_path(cls):
-        binpath = super().bin_path()
-        if binpath == 'convert':
-            binpath = mpl._get_executable_info('magick').executable
-        return binpath
-
-    @classmethod
-    def isAvailable(cls):
-        try:
-            return super().isAvailable()
-        except mpl.ExecutableNotFoundError as _enf:
-            # May be raised by get_executable_info.
-            _log.debug('ImageMagick unavailable due to: %s', _enf)
-            return False
-
-
-# Combine ImageMagick options with pipe-based writing
-@writers.register('imagemagick')
-class ImageMagickWriter(ImageMagickBase, MovieWriter):
-    '''Pipe-based animated gif.
-
-    Frames are streamed directly to ImageMagick via a pipe and written
-    in a single pass.
-
-    '''
-    def _args(self):
-        return ([self.bin_path(),
-                 '-size', '%ix%i' % self.frame_size, '-depth', '8',
-                 '-delay', str(self.delay), '-loop', '0',
-                 '%s:-' % self.frame_format]
-                + self.output_args)
-
-
-# Combine ImageMagick options with temp file-based writing
-@writers.register('imagemagick_file')
-class ImageMagickFileWriter(ImageMagickBase, FileMovieWriter):
-    '''File-based animated gif writer.
-
-    Frames are written to temporary files on disk and then stitched
-    together at the end.
-
-    '''
-
-    supported_formats = ['png', 'jpeg', 'ppm', 'tiff', 'sgi', 'bmp',
-                         'pbm', 'raw', 'rgba']
-
-    def _args(self):
-        return ([self.bin_path(), '-delay', str(self.delay), '-loop', '0',
-                 '%s*.%s' % (self.temp_prefix, self.frame_format)]
-                + self.output_args)
-
-
-# Taken directly from jakevdp's JSAnimation package at
-# http://github.com/jakevdp/JSAnimation
-def _included_frames(paths, frame_format):
-    """paths should be a list of Paths"""
-    return INCLUDED_FRAMES.format(Nframes=len(paths),
-                                  frame_dir=paths[0].parent,
-                                  frame_format=frame_format)
-
-
-def _embedded_frames(frame_list, frame_format):
-    """frame_list should be a list of base64-encoded png files"""
-    template = '  frames[{0}] = "data:image/{1};base64,{2}"\n'
-    return "\n" + "".join(
-        template.format(i, frame_format, frame_data.replace('\n', '\\\n'))
-        for i, frame_data in enumerate(frame_list))
-
-
-@writers.register('html')
-class HTMLWriter(FileMovieWriter):
-    supported_formats = ['png', 'jpeg', 'tiff', 'svg']
-    args_key = 'animation.html_args'
-
-    @classmethod
-    def isAvailable(cls):
-        return True
-
-    def __init__(self, fps=30, codec=None, bitrate=None, extra_args=None,
-                 metadata=None, embed_frames=False, default_mode='loop',
-                 embed_limit=None):
-        self.embed_frames = embed_frames
-        self.default_mode = default_mode.lower()
-
-        # Save embed limit, which is given in MB
-        if embed_limit is None:
-            self._bytes_limit = rcParams['animation.embed_limit']
-        else:
-            self._bytes_limit = embed_limit
-
-        # Convert from MB to bytes
-        self._bytes_limit *= 1024 * 1024
-
-        cbook._check_in_list(['loop', 'once', 'reflect'],
-                             default_mode=self.default_mode)
-
-        super().__init__(fps, codec, bitrate, extra_args, metadata)
-
-    def setup(self, fig, outfile, dpi, frame_dir=None):
-        outfile = Path(outfile)
-        cbook._check_in_list(['.html', '.htm'],
-                             outfile_extension=outfile.suffix)
-
-        self._saved_frames = []
-        self._total_bytes = 0
-        self._hit_limit = False
-
-        if not self.embed_frames:
-            if frame_dir is None:
-                frame_dir = outfile.with_name(outfile.stem + '_frames')
-            frame_dir.mkdir(parents=True, exist_ok=True)
-            frame_prefix = frame_dir / 'frame'
-        else:
-            frame_prefix = None
-
-        super().setup(fig, outfile, dpi, frame_prefix, clear_temp=False)
-
-    def grab_frame(self, **savefig_kwargs):
-        if self.embed_frames:
-            # Just stop processing if we hit the limit
-            if self._hit_limit:
-                return
-            f = BytesIO()
-            self.fig.savefig(f, format=self.frame_format,
-                             dpi=self.dpi, **savefig_kwargs)
-            imgdata64 = base64.encodebytes(f.getvalue()).decode('ascii')
-            self._total_bytes += len(imgdata64)
-            if self._total_bytes >= self._bytes_limit:
-                _log.warning(
-                    "Animation size has reached %s bytes, exceeding the limit "
-                    "of %s. If you're sure you want a larger animation "
-                    "embedded, set the animation.embed_limit rc parameter to "
-                    "a larger value (in MB). This and further frames will be "
-                    "dropped.", self._total_bytes, self._bytes_limit)
-                self._hit_limit = True
-            else:
-                self._saved_frames.append(imgdata64)
-        else:
-            return super().grab_frame(**savefig_kwargs)
-
-    def finish(self):
-        # save the frames to an html file
-        if self.embed_frames:
-            fill_frames = _embedded_frames(self._saved_frames,
-                                           self.frame_format)
-            Nframes = len(self._saved_frames)
-        else:
-            # temp names is filled by FileMovieWriter
-            fill_frames = _included_frames(self._temp_paths, self.frame_format)
-            Nframes = len(self._temp_paths)
-        mode_dict = dict(once_checked='',
-                         loop_checked='',
-                         reflect_checked='')
-        mode_dict[self.default_mode + '_checked'] = 'checked'
-
-        interval = 1000 // self.fps
-
-        with open(self.outfile, 'w') as of:
-            of.write(JS_INCLUDE + STYLE_INCLUDE)
-            of.write(DISPLAY_TEMPLATE.format(id=uuid.uuid4().hex,
-                                             Nframes=Nframes,
-                                             fill_frames=fill_frames,
-                                             interval=interval,
-                                             **mode_dict))
-
-
-class Animation:
-    '''This class wraps the creation of an animation using matplotlib.
-
-    It is only a base class which should be subclassed to provide
-    needed behavior.
-
-    This class is not typically used directly.
-
-    Parameters
-    ----------
-    fig : `~matplotlib.figure.Figure`
-       The figure object that is used to get draw, resize, and any
-       other needed events.
-
-    event_source : object, optional
-       A class that can run a callback when desired events
-       are generated, as well as be stopped and started.
-
-       Examples include timers (see :class:`TimedAnimation`) and file
-       system notifications.
-
-    blit : bool, optional
-       controls whether blitting is used to optimize drawing.  Defaults
-       to ``False``.
-
-    See Also
-    --------
-    FuncAnimation,  ArtistAnimation
-
-    '''
-    def __init__(self, fig, event_source=None, blit=False):
-        self._fig = fig
-        # Disables blitting for backends that don't support it.  This
-        # allows users to request it if available, but still have a
-        # fallback that works if it is not.
-        self._blit = blit and fig.canvas.supports_blit
-
-        # These are the basics of the animation.  The frame sequence represents
-        # information for each frame of the animation and depends on how the
-        # drawing is handled by the subclasses. The event source fires events
-        # that cause the frame sequence to be iterated.
-        self.frame_seq = self.new_frame_seq()
-        self.event_source = event_source
-
-        # Instead of starting the event source now, we connect to the figure's
-        # draw_event, so that we only start once the figure has been drawn.
-        self._first_draw_id = fig.canvas.mpl_connect('draw_event', self._start)
-
-        # Connect to the figure's close_event so that we don't continue to
-        # fire events and try to draw to a deleted figure.
-        self._close_id = self._fig.canvas.mpl_connect('close_event',
-                                                      self._stop)
-        if self._blit:
-            self._setup_blit()
-
-    def _start(self, *args):
-        '''
-        Starts interactive animation. Adds the draw frame command to the GUI
-        handler, calls show to start the event loop.
-        '''
-        # First disconnect our draw event handler
-        self._fig.canvas.mpl_disconnect(self._first_draw_id)
-        self._first_draw_id = None  # So we can check on save
-
-        # Now do any initial draw
-        self._init_draw()
-
-        # Add our callback for stepping the animation and
-        # actually start the event_source.
-        self.event_source.add_callback(self._step)
-        self.event_source.start()
-
-    def _stop(self, *args):
-        # On stop we disconnect all of our events.
-        if self._blit:
-            self._fig.canvas.mpl_disconnect(self._resize_id)
-        self._fig.canvas.mpl_disconnect(self._close_id)
-        self.event_source.remove_callback(self._step)
-        self.event_source = None
-
-    def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
-             bitrate=None, extra_args=None, metadata=None, extra_anim=None,
-             savefig_kwargs=None, *, progress_callback=None):
-        """
-        Save the animation as a movie file by drawing every frame.
-
-        Parameters
-        ----------
-        filename : str
-            The output filename, e.g., :file:`mymovie.mp4`.
-
-        writer : :class:`MovieWriter` or str, optional
-            A `MovieWriter` instance to use or a key that identifies a
-            class to use, such as 'ffmpeg'. If ``None``, defaults to
-            :rc:`animation.writer` = 'ffmpeg'.
-
-        fps : number, optional
-           Frames per second in the movie. Defaults to ``None``, which will use
-           the animation's specified interval to set the frames per second.
-
-        dpi : number, optional
-           Controls the dots per inch for the movie frames.  This combined with
-           the figure's size in inches controls the size of the movie.  If
-           ``None``, defaults to :rc:`savefig.dpi`.
-
-        codec : str, optional
-           The video codec to be used. Not all codecs are supported
-           by a given :class:`MovieWriter`. If ``None``, default to
-           :rc:`animation.codec` = 'h264'.
-
-        bitrate : number, optional
-           Specifies the number of bits used per second in the compressed
-           movie, in kilobits per second. A higher number means a higher
-           quality movie, but at the cost of increased file size. If ``None``,
-           defaults to :rc:`animation.bitrate` = -1.
-
-        extra_args : list, optional
-           List of extra string arguments to be passed to the underlying movie
-           utility. If ``None``, defaults to :rc:`animation.extra_args`.
-
-        metadata : Dict[str, str], optional
-           Dictionary of keys and values for metadata to include in
-           the output file. Some keys that may be of use include:
-           title, artist, genre, subject, copyright, srcform, comment.
-
-        extra_anim : list, optional
-           Additional `Animation` objects that should be included
-           in the saved movie file. These need to be from the same
-           `matplotlib.figure.Figure` instance. Also, animation frames will
-           just be simply combined, so there should be a 1:1 correspondence
-           between the frames from the different animations.
-
-        savefig_kwargs : dict, optional
-           Is a dictionary containing keyword arguments to be passed
-           on to the `savefig` command which is called repeatedly to
-           save the individual frames.
-
-        progress_callback : function, optional
-            A callback function that will be called for every frame to notify
-            the saving progress. It must have the signature ::
-
-                def func(current_frame: int, total_frames: int) -> Any
-
-            where *current_frame* is the current frame number and
-            *total_frames* is the total number of frames to be saved.
-            *total_frames* is set to None, if the total number of frames can
-            not be determined. Return values may exist but are ignored.
-
-            Example code to write the progress to stdout::
-
-                progress_callback =\
-                    lambda i, n: print(f'Saving frame {i} of {n}')
-
-        Notes
-        -----
-        *fps*, *codec*, *bitrate*, *extra_args* and *metadata* are used to
-        construct a `.MovieWriter` instance and can only be passed if
-        *writer* is a string.  If they are passed as non-*None* and *writer*
-        is a `.MovieWriter`, a `RuntimeError` will be raised.
-
-        """
-        # If the writer is None, use the rc param to find the name of the one
-        # to use
-        if writer is None:
-            writer = rcParams['animation.writer']
-        elif (not isinstance(writer, str) and
-              any(arg is not None
-                  for arg in (fps, codec, bitrate, extra_args, metadata))):
-            raise RuntimeError('Passing in values for arguments '
-                               'fps, codec, bitrate, extra_args, or metadata '
-                               'is not supported when writer is an existing '
-                               'MovieWriter instance. These should instead be '
-                               'passed as arguments when creating the '
-                               'MovieWriter instance.')
-
-        if savefig_kwargs is None:
-            savefig_kwargs = {}
-
-        # Need to disconnect the first draw callback, since we'll be doing
-        # draws. Otherwise, we'll end up starting the animation.
-        if self._first_draw_id is not None:
-            self._fig.canvas.mpl_disconnect(self._first_draw_id)
-            reconnect_first_draw = True
-        else:
-            reconnect_first_draw = False
-
-        if fps is None and hasattr(self, '_interval'):
-            # Convert interval in ms to frames per second
-            fps = 1000. / self._interval
-
-        # Re-use the savefig DPI for ours if none is given
-        if dpi is None:
-            dpi = rcParams['savefig.dpi']
-        if dpi == 'figure':
-            dpi = self._fig.dpi
-
-        if codec is None:
-            codec = rcParams['animation.codec']
-
-        if bitrate is None:
-            bitrate = rcParams['animation.bitrate']
-
-        all_anim = [self]
-        if extra_anim is not None:
-            all_anim.extend(anim
-                            for anim
-                            in extra_anim if anim._fig is self._fig)
-
-        # If we have the name of a writer, instantiate an instance of the
-        # registered class.
-        if isinstance(writer, str):
-            if writers.is_available(writer):
-                writer = writers[writer](fps, codec, bitrate,
-                                         extra_args=extra_args,
-                                         metadata=metadata)
-            else:
-                alt_writer = next(writers, None)
-                if alt_writer is None:
-                    raise ValueError("Cannot save animation: no writers are "
-                                     "available. Please install ffmpeg to "
-                                     "save animations.")
-                _log.warning("MovieWriter %s unavailable; trying to use %s "
-                             "instead.", writer, alt_writer)
-                writer = alt_writer(
-                    fps, codec, bitrate,
-                    extra_args=extra_args, metadata=metadata)
-        _log.info('Animation.save using %s', type(writer))
-
-        if 'bbox_inches' in savefig_kwargs:
-            _log.warning("Warning: discarding the 'bbox_inches' argument in "
-                         "'savefig_kwargs' as it may cause frame size "
-                         "to vary, which is inappropriate for animation.")
-            savefig_kwargs.pop('bbox_inches')
-
-        # Create a new sequence of frames for saved data. This is different
-        # from new_frame_seq() to give the ability to save 'live' generated
-        # frame information to be saved later.
-        # TODO: Right now, after closing the figure, saving a movie won't work
-        # since GUI widgets are gone. Either need to remove extra code to
-        # allow for this non-existent use case or find a way to make it work.
-        with rc_context():
-            if rcParams['savefig.bbox'] == 'tight':
-                _log.info("Disabling savefig.bbox = 'tight', as it may cause "
-                          "frame size to vary, which is inappropriate for "
-                          "animation.")
-                rcParams['savefig.bbox'] = None
-            with writer.saving(self._fig, filename, dpi):
-                for anim in all_anim:
-                    # Clear the initial frame
-                    anim._init_draw()
-                frame_number = 0
-                # TODO: Currently only FuncAnimation has a save_count
-                #       attribute. Can we generalize this to all Animations?
-                save_count_list = [getattr(a, 'save_count', None)
-                                   for a in all_anim]
-                if None in save_count_list:
-                    total_frames = None
-                else:
-                    total_frames = sum(save_count_list)
-                for data in zip(*[a.new_saved_frame_seq() for a in all_anim]):
-                    for anim, d in zip(all_anim, data):
-                        # TODO: See if turning off blit is really necessary
-                        anim._draw_next_frame(d, blit=False)
-                        if progress_callback is not None:
-                            progress_callback(frame_number, total_frames)
-                            frame_number += 1
-                    writer.grab_frame(**savefig_kwargs)
-
-        # Reconnect signal for first draw if necessary
-        if reconnect_first_draw:
-            self._first_draw_id = self._fig.canvas.mpl_connect('draw_event',
-                                                               self._start)
-
-    def _step(self, *args):
-        '''
-        Handler for getting events. By default, gets the next frame in the
-        sequence and hands the data off to be drawn.
-        '''
-        # Returns True to indicate that the event source should continue to
-        # call _step, until the frame sequence reaches the end of iteration,
-        # at which point False will be returned.
-        try:
-            framedata = next(self.frame_seq)
-            self._draw_next_frame(framedata, self._blit)
-            return True
-        except StopIteration:
-            return False
-
-    def new_frame_seq(self):
-        """Return a new sequence of frame information."""
-        # Default implementation is just an iterator over self._framedata
-        return iter(self._framedata)
-
-    def new_saved_frame_seq(self):
-        """Return a new sequence of saved/cached frame information."""
-        # Default is the same as the regular frame sequence
-        return self.new_frame_seq()
-
-    def _draw_next_frame(self, framedata, blit):
-        # Breaks down the drawing of the next frame into steps of pre- and
-        # post- draw, as well as the drawing of the frame itself.
-        self._pre_draw(framedata, blit)
-        self._draw_frame(framedata)
-        self._post_draw(framedata, blit)
-
-    def _init_draw(self):
-        # Initial draw to clear the frame. Also used by the blitting code
-        # when a clean base is required.
-        pass
-
-    def _pre_draw(self, framedata, blit):
-        # Perform any cleaning or whatnot before the drawing of the frame.
-        # This default implementation allows blit to clear the frame.
-        if blit:
-            self._blit_clear(self._drawn_artists, self._blit_cache)
-
-    def _draw_frame(self, framedata):
-        # Performs actual drawing of the frame.
-        raise NotImplementedError('Needs to be implemented by subclasses to'
-                                  ' actually make an animation.')
-
-    def _post_draw(self, framedata, blit):
-        # After the frame is rendered, this handles the actual flushing of
-        # the draw, which can be a direct draw_idle() or make use of the
-        # blitting.
-        if blit and self._drawn_artists:
-            self._blit_draw(self._drawn_artists, self._blit_cache)
-        else:
-            self._fig.canvas.draw_idle()
-
-    # The rest of the code in this class is to facilitate easy blitting
-    def _blit_draw(self, artists, bg_cache):
-        # Handles blitted drawing, which renders only the artists given instead
-        # of the entire figure.
-        updated_ax = []
-
-        # Enumerate artists to cache axes' backgrounds. We do not draw
-        # artists yet to not cache foreground from plots with shared axes
-        for a in artists:
-            # If we haven't cached the background for this axes object, do
-            # so now. This might not always be reliable, but it's an attempt
-            # to automate the process.
-            if a.axes not in bg_cache:
-                bg_cache[a.axes] = a.figure.canvas.copy_from_bbox(a.axes.bbox)
-
-        # Make a separate pass to draw foreground
-        for a in artists:
-            a.axes.draw_artist(a)
-            updated_ax.append(a.axes)
-
-        # After rendering all the needed artists, blit each axes individually.
-        for ax in set(updated_ax):
-            ax.figure.canvas.blit(ax.bbox)
-
-    def _blit_clear(self, artists, bg_cache):
-        # Get a list of the axes that need clearing from the artists that
-        # have been drawn. Grab the appropriate saved background from the
-        # cache and restore.
-        axes = {a.axes for a in artists}
-        for a in axes:
-            if a in bg_cache:
-                a.figure.canvas.restore_region(bg_cache[a])
-
-    def _setup_blit(self):
-        # Setting up the blit requires: a cache of the background for the
-        # axes
-        self._blit_cache = dict()
-        self._drawn_artists = []
-        for ax in self._fig.axes:
-            ax.callbacks.connect('xlim_changed',
-                                 lambda ax: self._blit_cache.pop(ax, None))
-            ax.callbacks.connect('ylim_changed',
-                                 lambda ax: self._blit_cache.pop(ax, None))
-        self._resize_id = self._fig.canvas.mpl_connect('resize_event',
-                                                       self._handle_resize)
-        self._post_draw(None, self._blit)
-
-    def _handle_resize(self, *args):
-        # On resize, we need to disable the resize event handling so we don't
-        # get too many events. Also stop the animation events, so that
-        # we're paused. Reset the cache and re-init. Set up an event handler
-        # to catch once the draw has actually taken place.
-        self._fig.canvas.mpl_disconnect(self._resize_id)
-        self.event_source.stop()
-        self._blit_cache.clear()
-        self._init_draw()
-        self._resize_id = self._fig.canvas.mpl_connect('draw_event',
-                                                       self._end_redraw)
-
-    def _end_redraw(self, evt):
-        # Now that the redraw has happened, do the post draw flushing and
-        # blit handling. Then re-enable all of the original events.
-        self._post_draw(None, False)
-        self.event_source.start()
-        self._fig.canvas.mpl_disconnect(self._resize_id)
-        self._resize_id = self._fig.canvas.mpl_connect('resize_event',
-                                                       self._handle_resize)
-
-    def to_html5_video(self, embed_limit=None):
-        """
-        Convert the animation to an HTML5 ``<video>`` tag.
-
-        This saves the animation as an h264 video, encoded in base64
-        directly into the HTML5 video tag. This respects the rc parameters
-        for the writer as well as the bitrate. This also makes use of the
-        ``interval`` to control the speed, and uses the ``repeat``
-        parameter to decide whether to loop.
-
-        Parameters
-        ----------
-        embed_limit : float, optional
-            Limit, in MB, of the returned animation. No animation is created
-            if the limit is exceeded.
-            Defaults to :rc:`animation.embed_limit` = 20.0.
-
-        Returns
-        -------
-        video_tag : str
-            An HTML5 video tag with the animation embedded as base64 encoded
-            h264 video.
-            If the *embed_limit* is exceeded, this returns the string
-            "Video too large to embed."
-        """
-        VIDEO_TAG = r'''<video {size} {options}>
-  <source type="video/mp4" src="data:video/mp4;base64,{video}">
-  Your browser does not support the video tag.
-</video>'''
-        # Cache the rendering of the video as HTML
-        if not hasattr(self, '_base64_video'):
-            # Save embed limit, which is given in MB
-            if embed_limit is None:
-                embed_limit = rcParams['animation.embed_limit']
-
-            # Convert from MB to bytes
-            embed_limit *= 1024 * 1024
-
-            # Can't open a NamedTemporaryFile twice on Windows, so use a
-            # TemporaryDirectory instead.
-            with TemporaryDirectory() as tmpdir:
-                path = Path(tmpdir, "temp.m4v")
-                # We create a writer manually so that we can get the
-                # appropriate size for the tag
-                Writer = writers[rcParams['animation.writer']]
-                writer = Writer(codec='h264',
-                                bitrate=rcParams['animation.bitrate'],
-                                fps=1000. / self._interval)
-                self.save(str(path), writer=writer)
-                # Now open and base64 encode.
-                vid64 = base64.encodebytes(path.read_bytes())
-
-            vid_len = len(vid64)
-            if vid_len >= embed_limit:
-                _log.warning(
-                    "Animation movie is %s bytes, exceeding the limit of %s. "
-                    "If you're sure you want a large animation embedded, set "
-                    "the animation.embed_limit rc parameter to a larger value "
-                    "(in MB).", vid_len, embed_limit)
-            else:
-                self._base64_video = vid64.decode('ascii')
-                self._video_size = 'width="{}" height="{}"'.format(
-                        *writer.frame_size)
-
-        # If we exceeded the size, this attribute won't exist
-        if hasattr(self, '_base64_video'):
-            # Default HTML5 options are to autoplay and display video controls
-            options = ['controls', 'autoplay']
-
-            # If we're set to repeat, make it loop
-            if hasattr(self, 'repeat') and self.repeat:
-                options.append('loop')
-
-            return VIDEO_TAG.format(video=self._base64_video,
-                                    size=self._video_size,
-                                    options=' '.join(options))
-        else:
-            return 'Video too large to embed.'
-
-    def to_jshtml(self, fps=None, embed_frames=True, default_mode=None):
-        """Generate HTML representation of the animation"""
-        if fps is None and hasattr(self, '_interval'):
-            # Convert interval in ms to frames per second
-            fps = 1000 / self._interval
-
-        # If we're not given a default mode, choose one base on the value of
-        # the repeat attribute
-        if default_mode is None:
-            default_mode = 'loop' if self.repeat else 'once'
-
-        if not hasattr(self, "_html_representation"):
-            # Can't open a NamedTemporaryFile twice on Windows, so use a
-            # TemporaryDirectory instead.
-            with TemporaryDirectory() as tmpdir:
-                path = Path(tmpdir, "temp.html")
-                writer = HTMLWriter(fps=fps,
-                                    embed_frames=embed_frames,
-                                    default_mode=default_mode)
-                self.save(str(path), writer=writer)
-                self._html_representation = path.read_text()
-
-        return self._html_representation
-
-    def _repr_html_(self):
-        '''IPython display hook for rendering.'''
-        fmt = rcParams['animation.html']
-        if fmt == 'html5':
-            return self.to_html5_video()
-        elif fmt == 'jshtml':
-            return self.to_jshtml()
-
-
-class TimedAnimation(Animation):
-    ''':class:`Animation` subclass for time-based animation.
-
-    A new frame is drawn every *interval* milliseconds.
-
-    Parameters
-    ----------
-    fig : `~matplotlib.figure.Figure`
-       The figure object that is used to get draw, resize, and any
-       other needed events.
-
-    interval : number, optional
-       Delay between frames in milliseconds.  Defaults to 200.
-
-    repeat_delay : number, optional
-        If the animation in repeated, adds a delay in milliseconds
-        before repeating the animation.  Defaults to ``None``.
-
-    repeat : bool, optional
-        Controls whether the animation should repeat when the sequence
-        of frames is completed.  Defaults to ``True``.
-
-    blit : bool, optional
-        Controls whether blitting is used to optimize drawing.  Defaults
-        to ``False``.
-
-    '''
-    def __init__(self, fig, interval=200, repeat_delay=None, repeat=True,
-                 event_source=None, *args, **kwargs):
-        # Store the timing information
-        self._interval = interval
-        self._repeat_delay = repeat_delay
-        self.repeat = repeat
-
-        # If we're not given an event source, create a new timer. This permits
-        # sharing timers between animation objects for syncing animations.
-        if event_source is None:
-            event_source = fig.canvas.new_timer()
-            event_source.interval = self._interval
-
-        Animation.__init__(self, fig, event_source=event_source,
-                           *args, **kwargs)
-
-    def _step(self, *args):
-        '''
-        Handler for getting events.
-        '''
-        # Extends the _step() method for the Animation class.  If
-        # Animation._step signals that it reached the end and we want to
-        # repeat, we refresh the frame sequence and return True. If
-        # _repeat_delay is set, change the event_source's interval to our loop
-        # delay and set the callback to one which will then set the interval
-        # back.
-        still_going = Animation._step(self, *args)
-        if not still_going and self.repeat:
-            self._init_draw()
-            self.frame_seq = self.new_frame_seq()
-            if self._repeat_delay:
-                self.event_source.remove_callback(self._step)
-                self.event_source.add_callback(self._loop_delay)
-                self.event_source.interval = self._repeat_delay
-                return True
-            else:
-                return Animation._step(self, *args)
-        else:
-            return still_going
-
-    def _stop(self, *args):
-        # If we stop in the middle of a loop delay (which is relatively likely
-        # given the potential pause here, remove the loop_delay callback as
-        # well.
-        self.event_source.remove_callback(self._loop_delay)
-        Animation._stop(self)
-
-    def _loop_delay(self, *args):
-        # Reset the interval and change callbacks after the delay.
-        self.event_source.remove_callback(self._loop_delay)
-        self.event_source.interval = self._interval
-        self.event_source.add_callback(self._step)
-        Animation._step(self)
-
-
-class ArtistAnimation(TimedAnimation):
-    '''Animation using a fixed set of `Artist` objects.
-
-    Before creating an instance, all plotting should have taken place
-    and the relevant artists saved.
-
-    Parameters
-    ----------
-    fig : `~matplotlib.figure.Figure`
-       The figure object that is used to get draw, resize, and any
-       other needed events.
-
-    artists : list
-        Each list entry a collection of artists that represent what
-        needs to be enabled on each frame. These will be disabled for
-        other frames.
-
-    interval : number, optional
-       Delay between frames in milliseconds.  Defaults to 200.
-
-    repeat_delay : number, optional
-        If the animation in repeated, adds a delay in milliseconds
-        before repeating the animation.  Defaults to ``None``.
-
-    repeat : bool, optional
-        Controls whether the animation should repeat when the sequence
-        of frames is completed. Defaults to ``True``.
-
-    blit : bool, optional
-        Controls whether blitting is used to optimize drawing.  Defaults
-        to ``False``.
-
-    '''
-    def __init__(self, fig, artists, *args, **kwargs):
-        # Internal list of artists drawn in the most recent frame.
-        self._drawn_artists = []
-
-        # Use the list of artists as the framedata, which will be iterated
-        # over by the machinery.
-        self._framedata = artists
-        TimedAnimation.__init__(self, fig, *args, **kwargs)
-
-    def _init_draw(self):
-        # Make all the artists involved in *any* frame invisible
-        figs = set()
-        for f in self.new_frame_seq():
-            for artist in f:
-                artist.set_visible(False)
-                artist.set_animated(self._blit)
-                # Assemble a list of unique figures that need flushing
-                if artist.get_figure() not in figs:
-                    figs.add(artist.get_figure())
-
-        # Flush the needed figures
-        for fig in figs:
-            fig.canvas.draw_idle()
-
-    def _pre_draw(self, framedata, blit):
-        '''
-        Clears artists from the last frame.
-        '''
-        if blit:
-            # Let blit handle clearing
-            self._blit_clear(self._drawn_artists, self._blit_cache)
-        else:
-            # Otherwise, make all the artists from the previous frame invisible
-            for artist in self._drawn_artists:
-                artist.set_visible(False)
-
-    def _draw_frame(self, artists):
-        # Save the artists that were passed in as framedata for the other
-        # steps (esp. blitting) to use.
-        self._drawn_artists = artists
-
-        # Make all the artists from the current frame visible
-        for artist in artists:
-            artist.set_visible(True)
-
-
-class FuncAnimation(TimedAnimation):
-    """
-    Makes an animation by repeatedly calling a function *func*.
-
-    Parameters
-    ----------
-    fig : `~matplotlib.figure.Figure`
-       The figure object that is used to get draw, resize, and any
-       other needed events.
-
-    func : callable
-       The function to call at each frame.  The first argument will
-       be the next value in *frames*.   Any additional positional
-       arguments can be supplied via the *fargs* parameter.
-
-       The required signature is::
-
-          def func(frame, *fargs) -> iterable_of_artists
-
-       If ``blit == True``, *func* must return an iterable of all artists
-       that were modified or created. This information is used by the blitting
-       algorithm to determine which parts of the figure have to be updated.
-       The return value is unused if ``blit == False`` and may be omitted in
-       that case.
-
-    frames : iterable, int, generator function, or None, optional
-        Source of data to pass *func* and each frame of the animation
-
-        - If an iterable, then simply use the values provided.  If the
-          iterable has a length, it will override the *save_count* kwarg.
-
-        - If an integer, then equivalent to passing ``range(frames)``
-
-        - If a generator function, then must have the signature::
-
-             def gen_function() -> obj
-
-        - If *None*, then equivalent to passing ``itertools.count``.
-
-        In all of these cases, the values in *frames* is simply passed through
-        to the user-supplied *func* and thus can be of any type.
-
-    init_func : callable, optional
-       A function used to draw a clear frame. If not given, the
-       results of drawing from the first item in the frames sequence
-       will be used. This function will be called once before the
-       first frame.
-
-       The required signature is::
-
-          def init_func() -> iterable_of_artists
-
-       If ``blit == True``, *init_func* must return an iterable of artists
-       to be re-drawn. This information is used by the blitting
-       algorithm to determine which parts of the figure have to be updated.
-       The return value is unused if ``blit == False`` and may be omitted in
-       that case.
-
-    fargs : tuple or None, optional
-       Additional arguments to pass to each call to *func*.
-
-    save_count : int, default: 100
-        Fallback for the number of values from *frames* to cache. This is
-        only used if the number of frames cannot be inferred from *frames*,
-        i.e. when it's an iterator without length or a generator.
-
-    interval : number, optional
-       Delay between frames in milliseconds.  Defaults to 200.
-
-    repeat_delay : number, optional
-       If the animation in repeated, adds a delay in milliseconds
-       before repeating the animation.  Defaults to *None*.
-
-    repeat : bool, optional
-       Controls whether the animation should repeat when the sequence
-       of frames is completed.  Defaults to *True*.
-
-    blit : bool, optional
-       Controls whether blitting is used to optimize drawing. Note: when using
-       blitting any animated artists will be drawn according to their zorder.
-       However, they will be drawn on top of any previous artists, regardless
-       of their zorder.  Defaults to *False*.
-
-    cache_frame_data : bool, optional
-       Controls whether frame data is cached. Defaults to *True*.
-       Disabling cache might be helpful when frames contain large objects.
-    """
-
-    def __init__(self, fig, func, frames=None, init_func=None, fargs=None,
-                 save_count=None, *, cache_frame_data=True, **kwargs):
-        if fargs:
-            self._args = fargs
-        else:
-            self._args = ()
-        self._func = func
-        self._init_func = init_func
-
-        # Amount of framedata to keep around for saving movies. This is only
-        # used if we don't know how many frames there will be: in the case
-        # of no generator or in the case of a callable.
-        self.save_count = save_count
-        # Set up a function that creates a new iterable when needed. If nothing
-        # is passed in for frames, just use itertools.count, which will just
-        # keep counting from 0. A callable passed in for frames is assumed to
-        # be a generator. An iterable will be used as is, and anything else
-        # will be treated as a number of frames.
-        if frames is None:
-            self._iter_gen = itertools.count
-        elif callable(frames):
-            self._iter_gen = frames
-        elif np.iterable(frames):
-            if kwargs.get('repeat', True):
-                def iter_frames(frames=frames):
-                    while True:
-                        this, frames = itertools.tee(frames, 2)
-                        yield from this
-                self._iter_gen = iter_frames
-            else:
-                self._iter_gen = lambda: iter(frames)
-            if hasattr(frames, '__len__'):
-                self.save_count = len(frames)
-        else:
-            self._iter_gen = lambda: iter(range(frames))
-            self.save_count = frames
-
-        if self.save_count is None:
-            # If we're passed in and using the default, set save_count to 100.
-            self.save_count = 100
-        else:
-            # itertools.islice returns an error when passed a numpy int instead
-            # of a native python int (http://bugs.python.org/issue30537).
-            # As a workaround, convert save_count to a native python int.
-            self.save_count = int(self.save_count)
-
-        self._cache_frame_data = cache_frame_data
-
-        # Needs to be initialized so the draw functions work without checking
-        self._save_seq = []
-
-        TimedAnimation.__init__(self, fig, **kwargs)
-
-        # Need to reset the saved seq, since right now it will contain data
-        # for a single frame from init, which is not what we want.
-        self._save_seq = []
-
-    def new_frame_seq(self):
-        # Use the generating function to generate a new frame sequence
-        return self._iter_gen()
-
-    def new_saved_frame_seq(self):
-        # Generate an iterator for the sequence of saved data. If there are
-        # no saved frames, generate a new frame sequence and take the first
-        # save_count entries in it.
-        if self._save_seq:
-            # While iterating we are going to update _save_seq
-            # so make a copy to safely iterate over
-            self._old_saved_seq = list(self._save_seq)
-            return iter(self._old_saved_seq)
-        else:
-            if self.save_count is not None:
-                return itertools.islice(self.new_frame_seq(), self.save_count)
-
-            else:
-                frame_seq = self.new_frame_seq()
-
-                def gen():
-                    try:
-                        for _ in range(100):
-                            yield next(frame_seq)
-                    except StopIteration:
-                        pass
-                    else:
-                        cbook.warn_deprecated(
-                            "2.2", message="FuncAnimation.save has truncated "
-                            "your animation to 100 frames.  In the future, no "
-                            "such truncation will occur; please pass "
-                            "'save_count' accordingly.")
-
-                return gen()
-
-    def _init_draw(self):
-        # Initialize the drawing either using the given init_func or by
-        # calling the draw function with the first item of the frame sequence.
-        # For blitting, the init_func should return a sequence of modified
-        # artists.
-        if self._init_func is None:
-            self._draw_frame(next(self.new_frame_seq()))
-
-        else:
-            self._drawn_artists = self._init_func()
-            if self._blit:
-                if self._drawn_artists is None:
-                    raise RuntimeError('The init_func must return a '
-                                       'sequence of Artist objects.')
-                for a in self._drawn_artists:
-                    a.set_animated(self._blit)
-        self._save_seq = []
-
-    def _draw_frame(self, framedata):
-        if self._cache_frame_data:
-            # Save the data for potential saving of movies.
-            self._save_seq.append(framedata)
-
-        # Make sure to respect save_count (keep only the last save_count
-        # around)
-        self._save_seq = self._save_seq[-self.save_count:]
-
-        # Call the func with framedata and args. If blitting is desired,
-        # func needs to return a sequence of any artists that were modified.
-        self._drawn_artists = self._func(framedata, *self._args)
-        if self._blit:
-            if self._drawn_artists is None:
-                raise RuntimeError('The animation function must return a '
-                                   'sequence of Artist objects.')
-            self._drawn_artists = sorted(self._drawn_artists,
-                                         key=lambda x: x.get_zorder())
-
-            for a in self._drawn_artists:
-                a.set_animated(self._blit)

+ 0 - 1633
venv/lib/python3.8/site-packages/matplotlib/artist.py

@@ -1,1633 +0,0 @@
-from collections import OrderedDict, namedtuple
-from functools import wraps
-import inspect
-import logging
-from numbers import Number
-import re
-import warnings
-
-import numpy as np
-
-import matplotlib
-from . import cbook, docstring, rcParams
-from .path import Path
-from .transforms import (Bbox, IdentityTransform, Transform, TransformedBbox,
-                         TransformedPatchPath, TransformedPath)
-
-_log = logging.getLogger(__name__)
-
-
-def allow_rasterization(draw):
-    """
-    Decorator for Artist.draw method. Provides routines
-    that run before and after the draw call. The before and after functions
-    are useful for changing artist-dependent renderer attributes or making
-    other setup function calls, such as starting and flushing a mixed-mode
-    renderer.
-    """
-
-    # the axes class has a second argument inframe for its draw method.
-    @wraps(draw)
-    def draw_wrapper(artist, renderer, *args, **kwargs):
-        try:
-            if artist.get_rasterized():
-                renderer.start_rasterizing()
-            if artist.get_agg_filter() is not None:
-                renderer.start_filter()
-
-            return draw(artist, renderer, *args, **kwargs)
-        finally:
-            if artist.get_agg_filter() is not None:
-                renderer.stop_filter(artist.get_agg_filter())
-            if artist.get_rasterized():
-                renderer.stop_rasterizing()
-
-    draw_wrapper._supports_rasterization = True
-    return draw_wrapper
-
-
-def _stale_axes_callback(self, val):
-    if self.axes:
-        self.axes.stale = val
-
-
-_XYPair = namedtuple("_XYPair", "x y")
-
-
-class Artist:
-    """
-    Abstract base class for objects that render into a FigureCanvas.
-
-    Typically, all visible elements in a figure are subclasses of Artist.
-    """
-    @cbook.deprecated("3.1")
-    @property
-    def aname(self):
-        return 'Artist'
-
-    zorder = 0
-    # order of precedence when bulk setting/updating properties
-    # via update.  The keys should be property names and the values
-    # integers
-    _prop_order = dict(color=-1)
-
-    def __init__(self):
-        self._stale = True
-        self.stale_callback = None
-        self._axes = None
-        self.figure = None
-
-        self._transform = None
-        self._transformSet = False
-        self._visible = True
-        self._animated = False
-        self._alpha = None
-        self.clipbox = None
-        self._clippath = None
-        self._clipon = True
-        self._label = ''
-        self._picker = None
-        self._contains = None
-        self._rasterized = None
-        self._agg_filter = None
-        self._mouseover = False
-        self.eventson = False  # fire events only if eventson
-        self._oid = 0  # an observer id
-        self._propobservers = {}  # a dict from oids to funcs
-        try:
-            self.axes = None
-        except AttributeError:
-            # Handle self.axes as a read-only property, as in Figure.
-            pass
-        self._remove_method = None
-        self._url = None
-        self._gid = None
-        self._snap = None
-        self._sketch = rcParams['path.sketch']
-        self._path_effects = rcParams['path.effects']
-        self._sticky_edges = _XYPair([], [])
-        self._in_layout = True
-
-    def __getstate__(self):
-        d = self.__dict__.copy()
-        # remove the unpicklable remove method, this will get re-added on load
-        # (by the axes) if the artist lives on an axes.
-        d['stale_callback'] = None
-        return d
-
-    def remove(self):
-        """
-        Remove the artist from the figure if possible.
-
-        The effect will not be visible until the figure is redrawn, e.g.,
-        with `.FigureCanvasBase.draw_idle`.  Call `~.axes.Axes.relim` to
-        update the axes limits if desired.
-
-        Note: `~.axes.Axes.relim` will not see collections even if the
-        collection was added to the axes with *autolim* = True.
-
-        Note: there is no support for removing the artist's legend entry.
-        """
-
-        # There is no method to set the callback.  Instead the parent should
-        # set the _remove_method attribute directly.  This would be a
-        # protected attribute if Python supported that sort of thing.  The
-        # callback has one parameter, which is the child to be removed.
-        if self._remove_method is not None:
-            self._remove_method(self)
-            # clear stale callback
-            self.stale_callback = None
-            _ax_flag = False
-            if hasattr(self, 'axes') and self.axes:
-                # remove from the mouse hit list
-                self.axes._mouseover_set.discard(self)
-                # mark the axes as stale
-                self.axes.stale = True
-                # decouple the artist from the axes
-                self.axes = None
-                _ax_flag = True
-
-            if self.figure:
-                self.figure = None
-                if not _ax_flag:
-                    self.figure = True
-
-        else:
-            raise NotImplementedError('cannot remove artist')
-        # TODO: the fix for the collections relim problem is to move the
-        # limits calculation into the artist itself, including the property of
-        # whether or not the artist should affect the limits.  Then there will
-        # be no distinction between axes.add_line, axes.add_patch, etc.
-        # TODO: add legend support
-
-    def have_units(self):
-        """Return *True* if units are set on any axis."""
-        ax = self.axes
-        return ax and any(axis.have_units() for axis in ax._get_axis_list())
-
-    def convert_xunits(self, x):
-        """
-        Convert *x* using the unit type of the xaxis.
-
-        If the artist is not in contained in an Axes or if the xaxis does not
-        have units, *x* itself is returned.
-        """
-        ax = getattr(self, 'axes', None)
-        if ax is None or ax.xaxis is None:
-            return x
-        return ax.xaxis.convert_units(x)
-
-    def convert_yunits(self, y):
-        """
-        Convert *y* using the unit type of the yaxis.
-
-        If the artist is not in contained in an Axes or if the yaxis does not
-        have units, *y* itself is returned.
-        """
-        ax = getattr(self, 'axes', None)
-        if ax is None or ax.yaxis is None:
-            return y
-        return ax.yaxis.convert_units(y)
-
-    @property
-    def axes(self):
-        """The `~.axes.Axes` instance the artist resides in, or *None*."""
-        return self._axes
-
-    @axes.setter
-    def axes(self, new_axes):
-        if (new_axes is not None and self._axes is not None
-                and new_axes != self._axes):
-            raise ValueError("Can not reset the axes.  You are probably "
-                             "trying to re-use an artist in more than one "
-                             "Axes which is not supported")
-        self._axes = new_axes
-        if new_axes is not None and new_axes is not self:
-            self.stale_callback = _stale_axes_callback
-        return new_axes
-
-    @property
-    def stale(self):
-        """
-        Whether the artist is 'stale' and needs to be re-drawn for the output
-        to match the internal state of the artist.
-        """
-        return self._stale
-
-    @stale.setter
-    def stale(self, val):
-        self._stale = val
-
-        # if the artist is animated it does not take normal part in the
-        # draw stack and is not expected to be drawn as part of the normal
-        # draw loop (when not saving) so do not propagate this change
-        if self.get_animated():
-            return
-
-        if val and self.stale_callback is not None:
-            self.stale_callback(self, val)
-
-    def get_window_extent(self, renderer):
-        """
-        Get the axes bounding box in display space.
-
-        The bounding box' width and height are nonnegative.
-
-        Subclasses should override for inclusion in the bounding box
-        "tight" calculation. Default is to return an empty bounding
-        box at 0, 0.
-
-        Be careful when using this function, the results will not update
-        if the artist window extent of the artist changes.  The extent
-        can change due to any changes in the transform stack, such as
-        changing the axes limits, the figure size, or the canvas used
-        (as is done when saving a figure).  This can lead to unexpected
-        behavior where interactive figures will look fine on the screen,
-        but will save incorrectly.
-        """
-        return Bbox([[0, 0], [0, 0]])
-
-    def _get_clipping_extent_bbox(self):
-        """
-        Return a bbox with the extents of the intersection of the clip_path
-        and clip_box for this artist, or None if both of these are
-        None, or ``get_clip_on`` is False.
-        """
-        bbox = None
-        if self.get_clip_on():
-            clip_box = self.get_clip_box()
-            if clip_box is not None:
-                bbox = clip_box
-            clip_path = self.get_clip_path()
-            if clip_path is not None and bbox is not None:
-                clip_path = clip_path.get_fully_transformed_path()
-                bbox = Bbox.intersection(bbox, clip_path.get_extents())
-        return bbox
-
-    def get_tightbbox(self, renderer):
-        """
-        Like `Artist.get_window_extent`, but includes any clipping.
-
-        Parameters
-        ----------
-        renderer : `.RendererBase` instance
-            renderer that will be used to draw the figures (i.e.
-            ``fig.canvas.get_renderer()``)
-
-        Returns
-        -------
-        bbox : `.Bbox`
-            The enclosing bounding box (in figure pixel co-ordinates).
-        """
-        bbox = self.get_window_extent(renderer)
-        if self.get_clip_on():
-            clip_box = self.get_clip_box()
-            if clip_box is not None:
-                bbox = Bbox.intersection(bbox, clip_box)
-            clip_path = self.get_clip_path()
-            if clip_path is not None and bbox is not None:
-                clip_path = clip_path.get_fully_transformed_path()
-                bbox = Bbox.intersection(bbox, clip_path.get_extents())
-        return bbox
-
-    def add_callback(self, func):
-        """
-        Add a callback function that will be called whenever one of the
-        `.Artist`'s properties changes.
-
-        Parameters
-        ----------
-        func : callable
-            The callback function. It must have the signature::
-
-                def func(artist: Artist) -> Any
-
-            where *artist* is the calling `.Artist`. Return values may exist
-            but are ignored.
-
-        Returns
-        -------
-        oid : int
-            The observer id associated with the callback. This id can be
-            used for removing the callback with `.remove_callback` later.
-
-        See Also
-        --------
-        remove_callback
-        """
-        oid = self._oid
-        self._propobservers[oid] = func
-        self._oid += 1
-        return oid
-
-    def remove_callback(self, oid):
-        """
-        Remove a callback based on its observer id.
-
-        See Also
-        --------
-        add_callback
-        """
-        try:
-            del self._propobservers[oid]
-        except KeyError:
-            pass
-
-    def pchanged(self):
-        """
-        Call all of the registered callbacks.
-
-        This function is triggered internally when a property is changed.
-
-        See Also
-        --------
-        add_callback
-        remove_callback
-        """
-        for oid, func in self._propobservers.items():
-            func(self)
-
-    def is_transform_set(self):
-        """
-        Return whether the Artist has an explicitly set transform.
-
-        This is *True* after `.set_transform` has been called.
-        """
-        return self._transformSet
-
-    def set_transform(self, t):
-        """
-        Set the artist transform.
-
-        Parameters
-        ----------
-        t : `.Transform`
-        """
-        self._transform = t
-        self._transformSet = True
-        self.pchanged()
-        self.stale = True
-
-    def get_transform(self):
-        """Return the `.Transform` instance used by this artist."""
-        if self._transform is None:
-            self._transform = IdentityTransform()
-        elif (not isinstance(self._transform, Transform)
-              and hasattr(self._transform, '_as_mpl_transform')):
-            self._transform = self._transform._as_mpl_transform(self.axes)
-        return self._transform
-
-    def get_children(self):
-        r"""Return a list of the child `.Artist`\s of this `.Artist`."""
-        return []
-
-    def _default_contains(self, mouseevent, figure=None):
-        """
-        Base impl. for checking whether a mouseevent happened in an artist.
-
-        1. If the artist defines a custom checker, use it.
-        2. If the artist figure is known and the event did not occur in that
-           figure (by checking its ``canvas`` attribute), reject it.
-        3. Otherwise, return `None, {}`, indicating that the subclass'
-           implementation should be used.
-
-        Subclasses should start their definition of `contains` as follows:
-
-            inside, info = self._default_contains(mouseevent)
-            if inside is not None:
-                return inside, info
-            # subclass-specific implementation follows
-
-        The `canvas` kwarg is provided for the implementation of
-        `Figure.contains`.
-        """
-        if callable(self._contains):
-            return self._contains(self, mouseevent)
-        if figure is not None and mouseevent.canvas is not figure.canvas:
-            return False, {}
-        return None, {}
-
-    def contains(self, mouseevent):
-        """Test whether the artist contains the mouse event.
-
-        Parameters
-        ----------
-        mouseevent : `matplotlib.backend_bases.MouseEvent`
-
-        Returns
-        -------
-        contains : bool
-            Whether any values are within the radius.
-        details : dict
-            An artist-specific dictionary of details of the event context,
-            such as which points are contained in the pick radius. See the
-            individual Artist subclasses for details.
-
-        See Also
-        --------
-        set_contains, get_contains
-        """
-        inside, info = self._default_contains(mouseevent)
-        if inside is not None:
-            return inside, info
-        _log.warning("%r needs 'contains' method", self.__class__.__name__)
-        return False, {}
-
-    def set_contains(self, picker):
-        """
-        Define a custom contains test for the artist.
-
-        The provided callable replaces the default `.contains` method
-        of the artist.
-
-        Parameters
-        ----------
-        picker : callable
-            A custom picker function to evaluate if an event is within the
-            artist. The function must have the signature::
-
-                def contains(artist: Artist, event: MouseEvent) -> bool, dict
-
-            that returns:
-
-            - a bool indicating if the event is within the artist
-            - a dict of additional information. The dict should at least
-              return the same information as the default ``contains()``
-              implementation of the respective artist, but may provide
-              additional information.
-        """
-        if not callable(picker):
-            raise TypeError("picker is not a callable")
-        self._contains = picker
-
-    def get_contains(self):
-        """
-        Return the custom contains function of the artist if set, or *None*.
-
-        See Also
-        --------
-        set_contains
-        """
-        return self._contains
-
-    def pickable(self):
-        """
-        Return whether the artist is pickable.
-
-        See Also
-        --------
-        set_picker, get_picker, pick
-        """
-        return self.figure is not None and self._picker is not None
-
-    def pick(self, mouseevent):
-        """
-        Process a pick event.
-
-        Each child artist will fire a pick event if *mouseevent* is over
-        the artist and the artist has picker set.
-
-        See Also
-        --------
-        set_picker, get_picker, pickable
-        """
-        # Pick self
-        if self.pickable():
-            picker = self.get_picker()
-            if callable(picker):
-                inside, prop = picker(self, mouseevent)
-            else:
-                inside, prop = self.contains(mouseevent)
-            if inside:
-                self.figure.canvas.pick_event(mouseevent, self, **prop)
-
-        # Pick children
-        for a in self.get_children():
-            # make sure the event happened in the same axes
-            ax = getattr(a, 'axes', None)
-            if (mouseevent.inaxes is None or ax is None
-                    or mouseevent.inaxes == ax):
-                # we need to check if mouseevent.inaxes is None
-                # because some objects associated with an axes (e.g., a
-                # tick label) can be outside the bounding box of the
-                # axes and inaxes will be None
-                # also check that ax is None so that it traverse objects
-                # which do no have an axes property but children might
-                a.pick(mouseevent)
-
-    def set_picker(self, picker):
-        """
-        Define the picking behavior of the artist.
-
-        Parameters
-        ----------
-        picker : None or bool or float or callable
-            This can be one of the following:
-
-            - *None*: Picking is disabled for this artist (default).
-
-            - A boolean: If *True* then picking will be enabled and the
-              artist will fire a pick event if the mouse event is over
-              the artist.
-
-            - A float: If picker is a number it is interpreted as an
-              epsilon tolerance in points and the artist will fire
-              off an event if it's data is within epsilon of the mouse
-              event.  For some artists like lines and patch collections,
-              the artist may provide additional data to the pick event
-              that is generated, e.g., the indices of the data within
-              epsilon of the pick event
-
-            - A function: If picker is callable, it is a user supplied
-              function which determines whether the artist is hit by the
-              mouse event::
-
-                hit, props = picker(artist, mouseevent)
-
-              to determine the hit test.  if the mouse event is over the
-              artist, return *hit=True* and props is a dictionary of
-              properties you want added to the PickEvent attributes.
-
-        """
-        self._picker = picker
-
-    def get_picker(self):
-        """
-        Return the picking behavior of the artist.
-
-        The possible values are described in `.set_picker`.
-
-        See Also
-        --------
-        set_picker, pickable, pick
-        """
-        return self._picker
-
-    def get_url(self):
-        """Return the url."""
-        return self._url
-
-    def set_url(self, url):
-        """
-        Set the url for the artist.
-
-        Parameters
-        ----------
-        url : str
-        """
-        self._url = url
-
-    def get_gid(self):
-        """Return the group id."""
-        return self._gid
-
-    def set_gid(self, gid):
-        """
-        Set the (group) id for the artist.
-
-        Parameters
-        ----------
-        gid : str
-        """
-        self._gid = gid
-
-    def get_snap(self):
-        """
-        Returns the snap setting.
-
-        See `.set_snap` for details.
-        """
-        if rcParams['path.snap']:
-            return self._snap
-        else:
-            return False
-
-    def set_snap(self, snap):
-        """
-        Set the snapping behavior.
-
-        Snapping aligns positions with the pixel grid, which results in
-        clearer images. For example, if a black line of 1px width was
-        defined at a position in between two pixels, the resulting image
-        would contain the interpolated value of that line in the pixel grid,
-        which would be a grey value on both adjacent pixel positions. In
-        contrast, snapping will move the line to the nearest integer pixel
-        value, so that the resulting image will really contain a 1px wide
-        black line.
-
-        Snapping is currently only supported by the Agg and MacOSX backends.
-
-        Parameters
-        ----------
-        snap : bool or None
-            Possible values:
-
-            - *True*: Snap vertices to the nearest pixel center.
-            - *False*: Do not modify vertex positions.
-            - *None*: (auto) If the path contains only rectilinear line
-              segments, round to the nearest pixel center.
-        """
-        self._snap = snap
-        self.stale = True
-
-    def get_sketch_params(self):
-        """
-        Returns the sketch parameters for the artist.
-
-        Returns
-        -------
-        sketch_params : tuple or None
-
-            A 3-tuple with the following elements:
-
-            - *scale*: The amplitude of the wiggle perpendicular to the
-              source line.
-            - *length*: The length of the wiggle along the line.
-            - *randomness*: The scale factor by which the length is
-              shrunken or expanded.
-
-            Returns *None* if no sketch parameters were set.
-        """
-        return self._sketch
-
-    def set_sketch_params(self, scale=None, length=None, randomness=None):
-        """
-        Sets the sketch parameters.
-
-        Parameters
-        ----------
-        scale : float, optional
-            The amplitude of the wiggle perpendicular to the source
-            line, in pixels.  If scale is `None`, or not provided, no
-            sketch filter will be provided.
-        length : float, optional
-             The length of the wiggle along the line, in pixels
-             (default 128.0)
-        randomness : float, optional
-            The scale factor by which the length is shrunken or
-            expanded (default 16.0)
-
-            .. ACCEPTS: (scale: float, length: float, randomness: float)
-        """
-        if scale is None:
-            self._sketch = None
-        else:
-            self._sketch = (scale, length or 128.0, randomness or 16.0)
-        self.stale = True
-
-    def set_path_effects(self, path_effects):
-        """Set the path effects.
-
-        Parameters
-        ----------
-        path_effects : `.AbstractPathEffect`
-        """
-        self._path_effects = path_effects
-        self.stale = True
-
-    def get_path_effects(self):
-        return self._path_effects
-
-    def get_figure(self):
-        """Return the `.Figure` instance the artist belongs to."""
-        return self.figure
-
-    def set_figure(self, fig):
-        """
-        Set the `.Figure` instance the artist belongs to.
-
-        Parameters
-        ----------
-        fig : `.Figure`
-        """
-        # if this is a no-op just return
-        if self.figure is fig:
-            return
-        # if we currently have a figure (the case of both `self.figure`
-        # and *fig* being none is taken care of above) we then user is
-        # trying to change the figure an artist is associated with which
-        # is not allowed for the same reason as adding the same instance
-        # to more than one Axes
-        if self.figure is not None:
-            raise RuntimeError("Can not put single artist in "
-                               "more than one figure")
-        self.figure = fig
-        if self.figure and self.figure is not self:
-            self.pchanged()
-        self.stale = True
-
-    def set_clip_box(self, clipbox):
-        """
-        Set the artist's clip `.Bbox`.
-
-        Parameters
-        ----------
-        clipbox : `.Bbox`
-        """
-        self.clipbox = clipbox
-        self.pchanged()
-        self.stale = True
-
-    def set_clip_path(self, path, transform=None):
-        """
-        Set the artist's clip path.
-
-        Parameters
-        ----------
-        path : `.Patch` or `.Path` or `.TransformedPath` or None
-            The clip path. If given a `.Path`, *transform* must be provided as
-            well. If *None*, a previously set clip path is removed.
-        transform : `~matplotlib.transforms.Transform`, optional
-            Only used if *path* is a `.Path`, in which case the given `.Path`
-            is converted to a `.TransformedPath` using *transform*.
-
-        Notes
-        -----
-        For efficiency, if *path* is a `.Rectangle` this method will set the
-        clipping box to the corresponding rectangle and set the clipping path
-        to ``None``.
-
-        For technical reasons (support of ``setp``), a tuple
-        (*path*, *transform*) is also accepted as a single positional
-        parameter.
-
-        .. ACCEPTS: Patch or (Path, Transform) or None
-        """
-        from matplotlib.patches import Patch, Rectangle
-
-        success = False
-        if transform is None:
-            if isinstance(path, Rectangle):
-                self.clipbox = TransformedBbox(Bbox.unit(),
-                                               path.get_transform())
-                self._clippath = None
-                success = True
-            elif isinstance(path, Patch):
-                self._clippath = TransformedPatchPath(path)
-                success = True
-            elif isinstance(path, tuple):
-                path, transform = path
-
-        if path is None:
-            self._clippath = None
-            success = True
-        elif isinstance(path, Path):
-            self._clippath = TransformedPath(path, transform)
-            success = True
-        elif isinstance(path, TransformedPatchPath):
-            self._clippath = path
-            success = True
-        elif isinstance(path, TransformedPath):
-            self._clippath = path
-            success = True
-
-        if not success:
-            raise TypeError(
-                "Invalid arguments to set_clip_path, of type {} and {}"
-                .format(type(path).__name__, type(transform).__name__))
-        # This may result in the callbacks being hit twice, but guarantees they
-        # will be hit at least once.
-        self.pchanged()
-        self.stale = True
-
-    def get_alpha(self):
-        """
-        Return the alpha value used for blending - not supported on all
-        backends
-        """
-        return self._alpha
-
-    def get_visible(self):
-        """Return the visibility."""
-        return self._visible
-
-    def get_animated(self):
-        """Return the animated state."""
-        return self._animated
-
-    def get_in_layout(self):
-        """
-        Return boolean flag, ``True`` if artist is included in layout
-        calculations.
-
-        E.g. :doc:`/tutorials/intermediate/constrainedlayout_guide`,
-        `.Figure.tight_layout()`, and
-        ``fig.savefig(fname, bbox_inches='tight')``.
-        """
-        return self._in_layout
-
-    def get_clip_on(self):
-        """Return whether the artist uses clipping."""
-        return self._clipon
-
-    def get_clip_box(self):
-        """Return the clipbox."""
-        return self.clipbox
-
-    def get_clip_path(self):
-        """Return the clip path."""
-        return self._clippath
-
-    def get_transformed_clip_path_and_affine(self):
-        '''
-        Return the clip path with the non-affine part of its
-        transformation applied, and the remaining affine part of its
-        transformation.
-        '''
-        if self._clippath is not None:
-            return self._clippath.get_transformed_path_and_affine()
-        return None, None
-
-    def set_clip_on(self, b):
-        """
-        Set whether the artist uses clipping.
-
-        When False artists will be visible out side of the axes which
-        can lead to unexpected results.
-
-        Parameters
-        ----------
-        b : bool
-        """
-        self._clipon = b
-        # This may result in the callbacks being hit twice, but ensures they
-        # are hit at least once
-        self.pchanged()
-        self.stale = True
-
-    def _set_gc_clip(self, gc):
-        'Set the clip properly for the gc'
-        if self._clipon:
-            if self.clipbox is not None:
-                gc.set_clip_rectangle(self.clipbox)
-            gc.set_clip_path(self._clippath)
-        else:
-            gc.set_clip_rectangle(None)
-            gc.set_clip_path(None)
-
-    def get_rasterized(self):
-        """Return whether the artist is to be rasterized."""
-        return self._rasterized
-
-    def set_rasterized(self, rasterized):
-        """
-        Force rasterized (bitmap) drawing in vector backend output.
-
-        Defaults to None, which implies the backend's default behavior.
-
-        Parameters
-        ----------
-        rasterized : bool or None
-        """
-        if rasterized and not hasattr(self.draw, "_supports_rasterization"):
-            cbook._warn_external(
-                "Rasterization of '%s' will be ignored" % self)
-
-        self._rasterized = rasterized
-
-    def get_agg_filter(self):
-        """Return filter function to be used for agg filter."""
-        return self._agg_filter
-
-    def set_agg_filter(self, filter_func):
-        """Set the agg filter.
-
-        Parameters
-        ----------
-        filter_func : callable
-            A filter function, which takes a (m, n, 3) float array and a dpi
-            value, and returns a (m, n, 3) array.
-
-            .. ACCEPTS: a filter function, which takes a (m, n, 3) float array
-                and a dpi value, and returns a (m, n, 3) array
-        """
-        self._agg_filter = filter_func
-        self.stale = True
-
-    def draw(self, renderer, *args, **kwargs):
-        """
-        Draw the Artist using the given renderer.
-
-        This method will be overridden in the Artist subclasses. Typically,
-        it is implemented to not have any effect if the Artist is not visible
-        (`.Artist.get_visible` is *False*).
-
-        Parameters
-        ----------
-        renderer : `.RendererBase` subclass.
-        """
-        if not self.get_visible():
-            return
-        self.stale = False
-
-    def set_alpha(self, alpha):
-        """
-        Set the alpha value used for blending - not supported on all backends.
-
-        Parameters
-        ----------
-        alpha : float or None
-        """
-        if alpha is not None and not isinstance(alpha, Number):
-            raise TypeError('alpha must be a float or None')
-        self._alpha = alpha
-        self.pchanged()
-        self.stale = True
-
-    def set_visible(self, b):
-        """
-        Set the artist's visibility.
-
-        Parameters
-        ----------
-        b : bool
-        """
-        self._visible = b
-        self.pchanged()
-        self.stale = True
-
-    def set_animated(self, b):
-        """
-        Set the artist's animation state.
-
-        Parameters
-        ----------
-        b : bool
-        """
-        if self._animated != b:
-            self._animated = b
-            self.pchanged()
-
-    def set_in_layout(self, in_layout):
-        """
-        Set if artist is to be included in layout calculations,
-        E.g. :doc:`/tutorials/intermediate/constrainedlayout_guide`,
-        `.Figure.tight_layout()`, and
-        ``fig.savefig(fname, bbox_inches='tight')``.
-
-        Parameters
-        ----------
-        in_layout : bool
-        """
-        self._in_layout = in_layout
-
-    def update(self, props):
-        """
-        Update this artist's properties from the dictionary *props*.
-        """
-        def _update_property(self, k, v):
-            """Sorting out how to update property (setter or setattr).
-
-            Parameters
-            ----------
-            k : str
-                The name of property to update
-            v : obj
-                The value to assign to the property
-
-            Returns
-            -------
-            ret : obj or None
-                If using a `set_*` method return it's return, else None.
-            """
-            k = k.lower()
-            # white list attributes we want to be able to update through
-            # art.update, art.set, setp
-            if k in {'axes'}:
-                return setattr(self, k, v)
-            else:
-                func = getattr(self, 'set_' + k, None)
-                if not callable(func):
-                    raise AttributeError('{!r} object has no property {!r}'
-                                         .format(type(self).__name__, k))
-                return func(v)
-
-        with cbook._setattr_cm(self, eventson=False):
-            ret = [_update_property(self, k, v) for k, v in props.items()]
-
-        if len(ret):
-            self.pchanged()
-            self.stale = True
-        return ret
-
-    def get_label(self):
-        """Return the label used for this artist in the legend."""
-        return self._label
-
-    def set_label(self, s):
-        """
-        Set a label that will be displayed in the legend.
-
-        Parameters
-        ----------
-        s : object
-            *s* will be converted to a string by calling `str`.
-        """
-        if s is not None:
-            self._label = str(s)
-        else:
-            self._label = None
-        self.pchanged()
-        self.stale = True
-
-    def get_zorder(self):
-        """Return the artist's zorder."""
-        return self.zorder
-
-    def set_zorder(self, level):
-        """
-        Set the zorder for the artist.  Artists with lower zorder
-        values are drawn first.
-
-        Parameters
-        ----------
-        level : float
-        """
-        if level is None:
-            level = self.__class__.zorder
-        self.zorder = level
-        self.pchanged()
-        self.stale = True
-
-    @property
-    def sticky_edges(self):
-        """
-        ``x`` and ``y`` sticky edge lists for autoscaling.
-
-        When performing autoscaling, if a data limit coincides with a value in
-        the corresponding sticky_edges list, then no margin will be added--the
-        view limit "sticks" to the edge. A typical use case is histograms,
-        where one usually expects no margin on the bottom edge (0) of the
-        histogram.
-
-        This attribute cannot be assigned to; however, the ``x`` and ``y``
-        lists can be modified in place as needed.
-
-        Examples
-        --------
-        >>> artist.sticky_edges.x[:] = (xmin, xmax)
-        >>> artist.sticky_edges.y[:] = (ymin, ymax)
-
-        """
-        return self._sticky_edges
-
-    def update_from(self, other):
-        'Copy properties from *other* to *self*.'
-        self._transform = other._transform
-        self._transformSet = other._transformSet
-        self._visible = other._visible
-        self._alpha = other._alpha
-        self.clipbox = other.clipbox
-        self._clipon = other._clipon
-        self._clippath = other._clippath
-        self._label = other._label
-        self._sketch = other._sketch
-        self._path_effects = other._path_effects
-        self.sticky_edges.x[:] = other.sticky_edges.x[:]
-        self.sticky_edges.y[:] = other.sticky_edges.y[:]
-        self.pchanged()
-        self.stale = True
-
-    def properties(self):
-        """Return a dictionary of all the properties of the artist."""
-        return ArtistInspector(self).properties()
-
-    def set(self, **kwargs):
-        """A property batch setter.  Pass *kwargs* to set properties."""
-        kwargs = cbook.normalize_kwargs(kwargs, self)
-        props = OrderedDict(
-            sorted(kwargs.items(), reverse=True,
-                   key=lambda x: (self._prop_order.get(x[0], 0), x[0])))
-        return self.update(props)
-
-    def findobj(self, match=None, include_self=True):
-        """
-        Find artist objects.
-
-        Recursively find all `.Artist` instances contained in the artist.
-
-        Parameters
-        ----------
-        match
-            A filter criterion for the matches. This can be
-
-            - *None*: Return all objects contained in artist.
-            - A function with signature ``def match(artist: Artist) -> bool``.
-              The result will only contain artists for which the function
-              returns *True*.
-            - A class instance: e.g., `.Line2D`. The result will only contain
-              artists of this class or its subclasses (``isinstance`` check).
-
-        include_self : bool
-            Include *self* in the list to be checked for a match.
-
-        Returns
-        -------
-        artists : list of `.Artist`
-
-        """
-        if match is None:  # always return True
-            def matchfunc(x):
-                return True
-        elif isinstance(match, type) and issubclass(match, Artist):
-            def matchfunc(x):
-                return isinstance(x, match)
-        elif callable(match):
-            matchfunc = match
-        else:
-            raise ValueError('match must be None, a matplotlib.artist.Artist '
-                             'subclass, or a callable')
-
-        artists = sum([c.findobj(matchfunc) for c in self.get_children()], [])
-        if include_self and matchfunc(self):
-            artists.append(self)
-        return artists
-
-    def get_cursor_data(self, event):
-        """
-        Return the cursor data for a given event.
-
-        .. note::
-            This method is intended to be overridden by artist subclasses.
-            As an end-user of Matplotlib you will most likely not call this
-            method yourself.
-
-        Cursor data can be used by Artists to provide additional context
-        information for a given event. The default implementation just returns
-        *None*.
-
-        Subclasses can override the method and return arbitrary data. However,
-        when doing so, they must ensure that `.format_cursor_data` can convert
-        the data to a string representation.
-
-        The only current use case is displaying the z-value of an `.AxesImage`
-        in the status bar of a plot window, while moving the mouse.
-
-        Parameters
-        ----------
-        event : `matplotlib.backend_bases.MouseEvent`
-
-        See Also
-        --------
-        format_cursor_data
-
-        """
-        return None
-
-    def format_cursor_data(self, data):
-        """
-        Return a string representation of *data*.
-
-        .. note::
-            This method is intended to be overridden by artist subclasses.
-            As an end-user of Matplotlib you will most likely not call this
-            method yourself.
-
-        The default implementation converts ints and floats and arrays of ints
-        and floats into a comma-separated string enclosed in square brackets.
-
-        See Also
-        --------
-        get_cursor_data
-        """
-        try:
-            data[0]
-        except (TypeError, IndexError):
-            data = [data]
-        data_str = ', '.join('{:0.3g}'.format(item) for item in data
-                             if isinstance(item, Number))
-        return "[" + data_str + "]"
-
-    @property
-    def mouseover(self):
-        """
-        If this property is set to *True*, the artist will be queried for
-        custom context information when the mouse cursor moves over it.
-
-        See also :meth:`get_cursor_data`, :class:`.ToolCursorPosition` and
-        :class:`.NavigationToolbar2`.
-        """
-        return self._mouseover
-
-    @mouseover.setter
-    def mouseover(self, val):
-        val = bool(val)
-        self._mouseover = val
-        ax = self.axes
-        if ax:
-            if val:
-                ax._mouseover_set.add(self)
-            else:
-                ax._mouseover_set.discard(self)
-
-
-class ArtistInspector:
-    """
-    A helper class to inspect an `~matplotlib.artist.Artist` and return
-    information about its settable properties and their current values.
-    """
-
-    def __init__(self, o):
-        r"""
-        Initialize the artist inspector with an `Artist` or an iterable of
-        `Artist`\s.  If an iterable is used, we assume it is a homogeneous
-        sequence (all `Artists` are of the same type) and it is your
-        responsibility to make sure this is so.
-        """
-        if not isinstance(o, Artist):
-            if np.iterable(o):
-                o = list(o)
-                if len(o):
-                    o = o[0]
-
-        self.oorig = o
-        if not isinstance(o, type):
-            o = type(o)
-        self.o = o
-
-        self.aliasd = self.get_aliases()
-
-    def get_aliases(self):
-        """
-        Get a dict mapping property fullnames to sets of aliases for each alias
-        in the :class:`~matplotlib.artist.ArtistInspector`.
-
-        e.g., for lines::
-
-          {'markerfacecolor': {'mfc'},
-           'linewidth'      : {'lw'},
-          }
-        """
-        names = [name for name in dir(self.o)
-                 if name.startswith(('set_', 'get_'))
-                    and callable(getattr(self.o, name))]
-        aliases = {}
-        for name in names:
-            func = getattr(self.o, name)
-            if not self.is_alias(func):
-                continue
-            propname = re.search("`({}.*)`".format(name[:4]),  # get_.*/set_.*
-                                 inspect.getdoc(func)).group(1)
-            aliases.setdefault(propname[4:], set()).add(name[4:])
-        return aliases
-
-    _get_valid_values_regex = re.compile(
-        r"\n\s*(?:\.\.\s+)?ACCEPTS:\s*((?:.|\n)*?)(?:$|(?:\n\n))"
-    )
-
-    def get_valid_values(self, attr):
-        """
-        Get the legal arguments for the setter associated with *attr*.
-
-        This is done by querying the docstring of the setter for a line that
-        begins with "ACCEPTS:" or ".. ACCEPTS:", and then by looking for a
-        numpydoc-style documentation for the setter's first argument.
-        """
-
-        name = 'set_%s' % attr
-        if not hasattr(self.o, name):
-            raise AttributeError('%s has no function %s' % (self.o, name))
-        func = getattr(self.o, name)
-
-        docstring = inspect.getdoc(func)
-        if docstring is None:
-            return 'unknown'
-
-        if docstring.startswith('Alias for '):
-            return None
-
-        match = self._get_valid_values_regex.search(docstring)
-        if match is not None:
-            return re.sub("\n *", " ", match.group(1))
-
-        # Much faster than list(inspect.signature(func).parameters)[1],
-        # although barely relevant wrt. matplotlib's total import time.
-        param_name = func.__code__.co_varnames[1]
-        # We could set the presence * based on whether the parameter is a
-        # varargs (it can't be a varkwargs) but it's not really worth the it.
-        match = re.search(r"(?m)^ *\*?{} : (.+)".format(param_name), docstring)
-        if match:
-            return match.group(1)
-
-        return 'unknown'
-
-    def _get_setters_and_targets(self):
-        """
-        Get the attribute strings and a full path to where the setter
-        is defined for all setters in an object.
-        """
-        setters = []
-        for name in dir(self.o):
-            if not name.startswith('set_'):
-                continue
-            func = getattr(self.o, name)
-            if (not callable(func)
-                    or len(inspect.signature(func).parameters) < 2
-                    or self.is_alias(func)):
-                continue
-            setters.append(
-                (name[4:], f"{func.__module__}.{func.__qualname__}"))
-        return setters
-
-    def _replace_path(self, source_class):
-        """
-        Changes the full path to the public API path that is used
-        in sphinx. This is needed for links to work.
-        """
-        replace_dict = {'_base._AxesBase': 'Axes',
-                        '_axes.Axes': 'Axes'}
-        for key, value in replace_dict.items():
-            source_class = source_class.replace(key, value)
-        return source_class
-
-    def get_setters(self):
-        """
-        Get the attribute strings with setters for object.  e.g., for a line,
-        return ``['markerfacecolor', 'linewidth', ....]``.
-        """
-        return [prop for prop, target in self._get_setters_and_targets()]
-
-    def is_alias(self, o):
-        """Return whether method object *o* is an alias for another method."""
-        ds = inspect.getdoc(o)
-        if ds is None:
-            return False
-        return ds.startswith('Alias for ')
-
-    def aliased_name(self, s):
-        """
-        Return 'PROPNAME or alias' if *s* has an alias, else return 'PROPNAME'.
-
-        e.g., for the line markerfacecolor property, which has an
-        alias, return 'markerfacecolor or mfc' and for the transform
-        property, which does not, return 'transform'.
-        """
-        aliases = ''.join(' or %s' % x for x in sorted(self.aliasd.get(s, [])))
-        return s + aliases
-
-    def aliased_name_rest(self, s, target):
-        """
-        Return 'PROPNAME or alias' if *s* has an alias, else return 'PROPNAME',
-        formatted for ReST.
-
-        e.g., for the line markerfacecolor property, which has an
-        alias, return 'markerfacecolor or mfc' and for the transform
-        property, which does not, return 'transform'.
-        """
-        aliases = ''.join(' or %s' % x for x in sorted(self.aliasd.get(s, [])))
-        return ':meth:`%s <%s>`%s' % (s, target, aliases)
-
-    def pprint_setters(self, prop=None, leadingspace=2):
-        """
-        If *prop* is *None*, return a list of strings of all settable
-        properties and their valid values.
-
-        If *prop* is not *None*, it is a valid property name and that
-        property will be returned as a string of property : valid
-        values.
-        """
-        if leadingspace:
-            pad = ' ' * leadingspace
-        else:
-            pad = ''
-        if prop is not None:
-            accepts = self.get_valid_values(prop)
-            return '%s%s: %s' % (pad, prop, accepts)
-
-        attrs = self._get_setters_and_targets()
-        attrs.sort()
-        lines = []
-
-        for prop, path in attrs:
-            accepts = self.get_valid_values(prop)
-            name = self.aliased_name(prop)
-
-            lines.append('%s%s: %s' % (pad, name, accepts))
-        return lines
-
-    def pprint_setters_rest(self, prop=None, leadingspace=4):
-        """
-        If *prop* is *None*, return a list of strings of all settable
-        properties and their valid values.  Format the output for ReST
-
-        If *prop* is not *None*, it is a valid property name and that
-        property will be returned as a string of property : valid
-        values.
-        """
-        if leadingspace:
-            pad = ' ' * leadingspace
-        else:
-            pad = ''
-        if prop is not None:
-            accepts = self.get_valid_values(prop)
-            return '%s%s: %s' % (pad, prop, accepts)
-
-        attrs = sorted(self._get_setters_and_targets())
-
-        names = [self.aliased_name_rest(prop, target).replace(
-            '_base._AxesBase', 'Axes').replace(
-            '_axes.Axes', 'Axes')
-                 for prop, target in attrs]
-        accepts = [self.get_valid_values(prop) for prop, target in attrs]
-
-        col0_len = max(len(n) for n in names)
-        col1_len = max(len(a) for a in accepts)
-        table_formatstr = pad + '   ' + '=' * col0_len + '   ' + '=' * col1_len
-
-        return [
-            '',
-            pad + '.. table::',
-            pad + '   :class: property-table',
-            '',
-            table_formatstr,
-            pad + '   ' + 'Property'.ljust(col0_len)
-            + '   ' + 'Description'.ljust(col1_len),
-            table_formatstr,
-            *[pad + '   ' + n.ljust(col0_len) + '   ' + a.ljust(col1_len)
-              for n, a in zip(names, accepts)],
-            table_formatstr,
-            '',
-        ]
-
-    def properties(self):
-        """Return a dictionary mapping property name -> value."""
-        o = self.oorig
-        getters = [name for name in dir(o)
-                   if name.startswith('get_') and callable(getattr(o, name))]
-        getters.sort()
-        d = {}
-        for name in getters:
-            func = getattr(o, name)
-            if self.is_alias(func):
-                continue
-            try:
-                with warnings.catch_warnings():
-                    warnings.simplefilter('ignore')
-                    val = func()
-            except Exception:
-                continue
-            else:
-                d[name[4:]] = val
-        return d
-
-    def pprint_getters(self):
-        """Return the getters and actual values as list of strings."""
-        lines = []
-        for name, val in sorted(self.properties().items()):
-            if getattr(val, 'shape', ()) != () and len(val) > 6:
-                s = str(val[:6]) + '...'
-            else:
-                s = str(val)
-            s = s.replace('\n', ' ')
-            if len(s) > 50:
-                s = s[:50] + '...'
-            name = self.aliased_name(name)
-            lines.append('    %s = %s' % (name, s))
-        return lines
-
-
-def getp(obj, property=None):
-    """
-    Return the value of object's property.  *property* is an optional string
-    for the property you want to return
-
-    Example usage::
-
-        getp(obj)  # get all the object properties
-        getp(obj, 'linestyle')  # get the linestyle property
-
-    *obj* is a :class:`Artist` instance, e.g.,
-    :class:`~matplotlib.lines.Line2D` or an instance of a
-    :class:`~matplotlib.axes.Axes` or :class:`matplotlib.text.Text`.
-    If the *property* is 'somename', this function returns
-
-      obj.get_somename()
-
-    :func:`getp` can be used to query all the gettable properties with
-    ``getp(obj)``. Many properties have aliases for shorter typing, e.g.
-    'lw' is an alias for 'linewidth'.  In the output, aliases and full
-    property names will be listed as:
-
-      property or alias = value
-
-    e.g.:
-
-      linewidth or lw = 2
-    """
-    if property is None:
-        insp = ArtistInspector(obj)
-        ret = insp.pprint_getters()
-        print('\n'.join(ret))
-        return
-
-    func = getattr(obj, 'get_' + property)
-    return func()
-
-# alias
-get = getp
-
-
-def setp(obj, *args, **kwargs):
-    """
-    Set a property on an artist object.
-
-    matplotlib supports the use of :func:`setp` ("set property") and
-    :func:`getp` to set and get object properties, as well as to do
-    introspection on the object.  For example, to set the linestyle of a
-    line to be dashed, you can do::
-
-      >>> line, = plot([1, 2, 3])
-      >>> setp(line, linestyle='--')
-
-    If you want to know the valid types of arguments, you can provide
-    the name of the property you want to set without a value::
-
-      >>> setp(line, 'linestyle')
-          linestyle: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...}
-
-    If you want to see all the properties that can be set, and their
-    possible values, you can do::
-
-      >>> setp(line)
-          ... long output listing omitted
-
-    You may specify another output file to `setp` if `sys.stdout` is not
-    acceptable for some reason using the *file* keyword-only argument::
-
-      >>> with fopen('output.log') as f:
-      >>>     setp(line, file=f)
-
-    :func:`setp` operates on a single instance or a iterable of
-    instances. If you are in query mode introspecting the possible
-    values, only the first instance in the sequence is used. When
-    actually setting values, all the instances will be set.  e.g.,
-    suppose you have a list of two lines, the following will make both
-    lines thicker and red::
-
-      >>> x = arange(0, 1, 0.01)
-      >>> y1 = sin(2*pi*x)
-      >>> y2 = sin(4*pi*x)
-      >>> lines = plot(x, y1, x, y2)
-      >>> setp(lines, linewidth=2, color='r')
-
-    :func:`setp` works with the MATLAB style string/value pairs or
-    with python kwargs.  For example, the following are equivalent::
-
-      >>> setp(lines, 'linewidth', 2, 'color', 'r')  # MATLAB style
-      >>> setp(lines, linewidth=2, color='r')        # python style
-    """
-
-    if isinstance(obj, Artist):
-        objs = [obj]
-    else:
-        objs = list(cbook.flatten(obj))
-
-    if not objs:
-        return
-
-    insp = ArtistInspector(objs[0])
-
-    # file has to be popped before checking if kwargs is empty
-    printArgs = {}
-    if 'file' in kwargs:
-        printArgs['file'] = kwargs.pop('file')
-
-    if not kwargs and len(args) < 2:
-        if args:
-            print(insp.pprint_setters(prop=args[0]), **printArgs)
-        else:
-            print('\n'.join(insp.pprint_setters()), **printArgs)
-        return
-
-    if len(args) % 2:
-        raise ValueError('The set args must be string, value pairs')
-
-    # put args into ordereddict to maintain order
-    funcvals = OrderedDict((k, v) for k, v in zip(args[::2], args[1::2]))
-    ret = [o.update(funcvals) for o in objs] + [o.set(**kwargs) for o in objs]
-    return list(cbook.flatten(ret))
-
-
-def kwdoc(artist):
-    r"""
-    Inspect an `~matplotlib.artist.Artist` class (using `.ArtistInspector`) and
-    return information about its settable properties and their current values.
-
-    Parameters
-    ----------
-    artist : `~matplotlib.artist.Artist` or an iterable of `Artist`\s
-
-    Returns
-    -------
-    string
-        The settable properties of *artist*, as plain text if
-        :rc:`docstring.hardcopy` is False and as a rst table (intended for
-        use in Sphinx) if it is True.
-    """
-    ai = ArtistInspector(artist)
-    return ('\n'.join(ai.pprint_setters_rest(leadingspace=4))
-            if matplotlib.rcParams['docstring.hardcopy'] else
-            'Properties:\n' + '\n'.join(ai.pprint_setters(leadingspace=4)))
-
-
-docstring.interpd.update(Artist=kwdoc(Artist))

+ 0 - 2
venv/lib/python3.8/site-packages/matplotlib/axes/__init__.py

@@ -1,2 +0,0 @@
-from ._subplots import *
-from ._axes import *

+ 0 - 8098
venv/lib/python3.8/site-packages/matplotlib/axes/_axes.py

@@ -1,8098 +0,0 @@
-import collections.abc
-import functools
-import itertools
-import logging
-import math
-from numbers import Number
-
-import numpy as np
-from numpy import ma
-
-import matplotlib.category as _  # <-registers a category unit converter
-import matplotlib.cbook as cbook
-import matplotlib.collections as mcoll
-import matplotlib.colors as mcolors
-import matplotlib.contour as mcontour
-import matplotlib.dates as _  # <-registers a date unit converter
-import matplotlib.docstring as docstring
-import matplotlib.image as mimage
-import matplotlib.legend as mlegend
-import matplotlib.lines as mlines
-import matplotlib.markers as mmarkers
-import matplotlib.mlab as mlab
-import matplotlib.patches as mpatches
-import matplotlib.path as mpath
-import matplotlib.quiver as mquiver
-import matplotlib.stackplot as mstack
-import matplotlib.streamplot as mstream
-import matplotlib.table as mtable
-import matplotlib.text as mtext
-import matplotlib.ticker as mticker
-import matplotlib.transforms as mtransforms
-import matplotlib.tri as mtri
-from matplotlib import _preprocess_data, rcParams
-from matplotlib.axes._base import _AxesBase, _process_plot_format
-from matplotlib.axes._secondary_axes import SecondaryAxis
-from matplotlib.container import BarContainer, ErrorbarContainer, StemContainer
-
-try:
-    from numpy.lib.histograms import (
-        histogram_bin_edges as _histogram_bin_edges)
-except ImportError:
-    # this function is new in np 1.15
-    def _histogram_bin_edges(arr, bins, range=None, weights=None):
-        # this in True for 1D arrays, and False for None and str
-        if np.ndim(bins) == 1:
-            return bins
-
-        if isinstance(bins, str):
-            # rather than backporting the internals, just do the full
-            # computation.  If this is too slow for users, they can
-            # update numpy, or pick a manual number of bins
-            return np.histogram(arr, bins, range, weights)[1]
-        else:
-            if bins is None:
-                # hard-code numpy's default
-                bins = 10
-            if range is None:
-                range = np.min(arr), np.max(arr)
-
-            return np.linspace(*range, bins + 1)
-
-
-_log = logging.getLogger(__name__)
-
-
-def _make_inset_locator(bounds, trans, parent):
-    """
-    Helper function to locate inset axes, used in
-    `.Axes.inset_axes`.
-
-    A locator gets used in `Axes.set_aspect` to override the default
-    locations...  It is a function that takes an axes object and
-    a renderer and tells `set_aspect` where it is to be placed.
-
-    Here *rect* is a rectangle [l, b, w, h] that specifies the
-    location for the axes in the transform given by *trans* on the
-    *parent*.
-    """
-    _bounds = mtransforms.Bbox.from_bounds(*bounds)
-    _trans = trans
-    _parent = parent
-
-    def inset_locator(ax, renderer):
-        bbox = _bounds
-        bb = mtransforms.TransformedBbox(bbox, _trans)
-        tr = _parent.figure.transFigure.inverted()
-        bb = mtransforms.TransformedBbox(bb, tr)
-        return bb
-
-    return inset_locator
-
-
-# The axes module contains all the wrappers to plotting functions.
-# All the other methods should go in the _AxesBase class.
-
-
-class Axes(_AxesBase):
-    """
-    The `Axes` contains most of the figure elements: `~.axis.Axis`,
-    `~.axis.Tick`, `~.lines.Line2D`, `~.text.Text`, `~.patches.Polygon`, etc.,
-    and sets the coordinate system.
-
-    The `Axes` instance supports callbacks through a callbacks attribute which
-    is a `~.cbook.CallbackRegistry` instance.  The events you can connect to
-    are 'xlim_changed' and 'ylim_changed' and the callback will be called with
-    func(*ax*) where *ax* is the `Axes` instance.
-
-    Attributes
-    ----------
-    dataLim : `.Bbox`
-        The bounding box enclosing all data displayed in the Axes.
-    viewLim : `.Bbox`
-        The view limits in data coordinates.
-
-    """
-    ### Labelling, legend and texts
-
-    @cbook.deprecated("3.1")
-    @property
-    def aname(self):
-        return 'Axes'
-
-    def get_title(self, loc="center"):
-        """
-        Get an axes title.
-
-        Get one of the three available axes titles. The available titles
-        are positioned above the axes in the center, flush with the left
-        edge, and flush with the right edge.
-
-        Parameters
-        ----------
-        loc : {'center', 'left', 'right'}, str, optional
-            Which title to get, defaults to 'center'.
-
-        Returns
-        -------
-        title : str
-            The title text string.
-
-        """
-        titles = {'left': self._left_title,
-                  'center': self.title,
-                  'right': self._right_title}
-        title = cbook._check_getitem(titles, loc=loc.lower())
-        return title.get_text()
-
-    def set_title(self, label, fontdict=None, loc=None, pad=None,
-                    **kwargs):
-        """
-        Set a title for the axes.
-
-        Set one of the three available axes titles. The available titles
-        are positioned above the axes in the center, flush with the left
-        edge, and flush with the right edge.
-
-        Parameters
-        ----------
-        label : str
-            Text to use for the title
-
-        fontdict : dict
-            A dictionary controlling the appearance of the title text,
-            the default *fontdict* is::
-
-               {'fontsize': rcParams['axes.titlesize'],
-                'fontweight' : rcParams['axes.titleweight'],
-                'color' : rcParams['axes.titlecolor'],
-                'verticalalignment': 'baseline',
-                'horizontalalignment': loc}
-
-        loc : {'center', 'left', 'right'}, str, optional
-            Which title to set.
-            If *None*, defaults to :rc:`axes.titlelocation`.
-
-        pad : float
-            The offset of the title from the top of the axes, in points.
-            If *None*, defaults to :rc:`axes.titlepad`.
-
-        Returns
-        -------
-        text : :class:`~matplotlib.text.Text`
-            The matplotlib text instance representing the title
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.text.Text` properties
-            Other keyword arguments are text properties, see
-            :class:`~matplotlib.text.Text` for a list of valid text
-            properties.
-        """
-        if loc is None:
-            loc = rcParams['axes.titlelocation']
-
-        titles = {'left': self._left_title,
-                  'center': self.title,
-                  'right': self._right_title}
-        title = cbook._check_getitem(titles, loc=loc.lower())
-        default = {
-            'fontsize': rcParams['axes.titlesize'],
-            'fontweight': rcParams['axes.titleweight'],
-            'verticalalignment': 'baseline',
-            'horizontalalignment': loc.lower()}
-        titlecolor = rcParams['axes.titlecolor']
-        if not cbook._str_lower_equal(titlecolor, 'auto'):
-            default["color"] = titlecolor
-        if pad is None:
-            pad = rcParams['axes.titlepad']
-        self._set_title_offset_trans(float(pad))
-        title.set_text(label)
-        title.update(default)
-        if fontdict is not None:
-            title.update(fontdict)
-        title.update(kwargs)
-        return title
-
-    def get_xlabel(self):
-        """
-        Get the xlabel text string.
-        """
-        label = self.xaxis.get_label()
-        return label.get_text()
-
-    def set_xlabel(self, xlabel, fontdict=None, labelpad=None, **kwargs):
-        """
-        Set the label for the x-axis.
-
-        Parameters
-        ----------
-        xlabel : str
-            The label text.
-
-        labelpad : scalar, optional, default: None
-            Spacing in points from the axes bounding box including ticks
-            and tick labels.
-
-        Other Parameters
-        ----------------
-        **kwargs : `.Text` properties
-            `.Text` properties control the appearance of the label.
-
-        See also
-        --------
-        text : for information on how override and the optional args work
-        """
-        if labelpad is not None:
-            self.xaxis.labelpad = labelpad
-        return self.xaxis.set_label_text(xlabel, fontdict, **kwargs)
-
-    def get_ylabel(self):
-        """
-        Get the ylabel text string.
-        """
-        label = self.yaxis.get_label()
-        return label.get_text()
-
-    def set_ylabel(self, ylabel, fontdict=None, labelpad=None, **kwargs):
-        """
-        Set the label for the y-axis.
-
-        Parameters
-        ----------
-        ylabel : str
-            The label text.
-
-        labelpad : scalar, optional, default: None
-            Spacing in points from the axes bounding box including ticks
-            and tick labels.
-
-        Other Parameters
-        ----------------
-        **kwargs : `.Text` properties
-            `.Text` properties control the appearance of the label.
-
-        See also
-        --------
-        text : for information on how override and the optional args work
-
-        """
-        if labelpad is not None:
-            self.yaxis.labelpad = labelpad
-        return self.yaxis.set_label_text(ylabel, fontdict, **kwargs)
-
-    def get_legend_handles_labels(self, legend_handler_map=None):
-        """
-        Return handles and labels for legend
-
-        ``ax.legend()`` is equivalent to ::
-
-          h, l = ax.get_legend_handles_labels()
-          ax.legend(h, l)
-
-        """
-
-        # pass through to legend.
-        handles, labels = mlegend._get_legend_handles_labels([self],
-                legend_handler_map)
-        return handles, labels
-
-    @docstring.dedent_interpd
-    def legend(self, *args, **kwargs):
-        """
-        Place a legend on the axes.
-
-        Call signatures::
-
-            legend()
-            legend(labels)
-            legend(handles, labels)
-
-        The call signatures correspond to three different ways how to use
-        this method.
-
-        **1. Automatic detection of elements to be shown in the legend**
-
-        The elements to be added to the legend are automatically determined,
-        when you do not pass in any extra arguments.
-
-        In this case, the labels are taken from the artist. You can specify
-        them either at artist creation or by calling the
-        :meth:`~.Artist.set_label` method on the artist::
-
-            line, = ax.plot([1, 2, 3], label='Inline label')
-            ax.legend()
-
-        or::
-
-            line, = ax.plot([1, 2, 3])
-            line.set_label('Label via method')
-            ax.legend()
-
-        Specific lines can be excluded from the automatic legend element
-        selection by defining a label starting with an underscore.
-        This is default for all artists, so calling `Axes.legend` without
-        any arguments and without setting the labels manually will result in
-        no legend being drawn.
-
-
-        **2. Labeling existing plot elements**
-
-        To make a legend for lines which already exist on the axes
-        (via plot for instance), simply call this function with an iterable
-        of strings, one for each legend item. For example::
-
-            ax.plot([1, 2, 3])
-            ax.legend(['A simple line'])
-
-        Note: This way of using is discouraged, because the relation between
-        plot elements and labels is only implicit by their order and can
-        easily be mixed up.
-
-
-        **3. Explicitly defining the elements in the legend**
-
-        For full control of which artists have a legend entry, it is possible
-        to pass an iterable of legend artists followed by an iterable of
-        legend labels respectively::
-
-            legend((line1, line2, line3), ('label1', 'label2', 'label3'))
-
-        Parameters
-        ----------
-        handles : sequence of `.Artist`, optional
-            A list of Artists (lines, patches) to be added to the legend.
-            Use this together with *labels*, if you need full control on what
-            is shown in the legend and the automatic mechanism described above
-            is not sufficient.
-
-            The length of handles and labels should be the same in this
-            case. If they are not, they are truncated to the smaller length.
-
-        labels : list of str, optional
-            A list of labels to show next to the artists.
-            Use this together with *handles*, if you need full control on what
-            is shown in the legend and the automatic mechanism described above
-            is not sufficient.
-
-        Other Parameters
-        ----------------
-        %(_legend_kw_doc)s
-
-        Returns
-        -------
-        legend : `~matplotlib.legend.Legend`
-
-        Notes
-        -----
-        Not all kinds of artist are supported by the legend command. See
-        :doc:`/tutorials/intermediate/legend_guide` for details.
-
-        Examples
-        --------
-        .. plot:: gallery/text_labels_and_annotations/legend.py
-        """
-        handles, labels, extra_args, kwargs = mlegend._parse_legend_args(
-                [self],
-                *args,
-                **kwargs)
-        if len(extra_args):
-            raise TypeError('legend only accepts two non-keyword arguments')
-        self.legend_ = mlegend.Legend(self, handles, labels, **kwargs)
-        self.legend_._remove_method = self._remove_legend
-        return self.legend_
-
-    def _remove_legend(self, legend):
-        self.legend_ = None
-
-    def inset_axes(self, bounds, *, transform=None, zorder=5,
-            **kwargs):
-        """
-        Add a child inset axes to this existing axes.
-
-        Warnings
-        --------
-        This method is experimental as of 3.0, and the API may change.
-
-        Parameters
-        ----------
-        bounds : [x0, y0, width, height]
-            Lower-left corner of inset axes, and its width and height.
-
-        transform : `.Transform`
-            Defaults to `ax.transAxes`, i.e. the units of *rect* are in
-            axes-relative coordinates.
-
-        zorder : number
-            Defaults to 5 (same as `.Axes.legend`).  Adjust higher or lower
-            to change whether it is above or below data plotted on the
-            parent axes.
-
-        **kwargs
-            Other keyword arguments are passed on to the `.Axes` child axes.
-
-        Returns
-        -------
-        ax
-            The created `~.axes.Axes` instance.
-
-        Examples
-        --------
-        This example makes two inset axes, the first is in axes-relative
-        coordinates, and the second in data-coordinates::
-
-            fig, ax = plt.subplots()
-            ax.plot(range(10))
-            axin1 = ax.inset_axes([0.8, 0.1, 0.15, 0.15])
-            axin2 = ax.inset_axes(
-                    [5, 7, 2.3, 2.3], transform=ax.transData)
-
-        """
-        if transform is None:
-            transform = self.transAxes
-        label = kwargs.pop('label', 'inset_axes')
-
-        # This puts the rectangle into figure-relative coordinates.
-        inset_locator = _make_inset_locator(bounds, transform, self)
-        bb = inset_locator(None, None)
-
-        inset_ax = Axes(self.figure, bb.bounds, zorder=zorder,
-                label=label, **kwargs)
-
-        # this locator lets the axes move if in data coordinates.
-        # it gets called in `ax.apply_aspect() (of all places)
-        inset_ax.set_axes_locator(inset_locator)
-
-        self.add_child_axes(inset_ax)
-
-        return inset_ax
-
-    def indicate_inset(self, bounds, inset_ax=None, *, transform=None,
-            facecolor='none', edgecolor='0.5', alpha=0.5,
-            zorder=4.99, **kwargs):
-        """
-        Add an inset indicator to the axes.  This is a rectangle on the plot
-        at the position indicated by *bounds* that optionally has lines that
-        connect the rectangle to an inset axes (`.Axes.inset_axes`).
-
-        Warnings
-        --------
-        This method is experimental as of 3.0, and the API may change.
-
-
-        Parameters
-        ----------
-        bounds : [x0, y0, width, height]
-            Lower-left corner of rectangle to be marked, and its width
-            and height.
-
-        inset_ax : `.Axes`
-            An optional inset axes to draw connecting lines to.  Two lines are
-            drawn connecting the indicator box to the inset axes on corners
-            chosen so as to not overlap with the indicator box.
-
-        transform : `.Transform`
-            Transform for the rectangle co-ordinates. Defaults to
-            `ax.transAxes`, i.e. the units of *rect* are in axes-relative
-            coordinates.
-
-        facecolor : Matplotlib color
-            Facecolor of the rectangle (default 'none').
-
-        edgecolor : Matplotlib color
-            Color of the rectangle and color of the connecting lines.  Default
-            is '0.5'.
-
-        alpha : float
-            Transparency of the rectangle and connector lines.  Default is 0.5.
-
-        zorder : float
-            Drawing order of the rectangle and connector lines. Default is 4.99
-            (just below the default level of inset axes).
-
-        **kwargs
-            Other keyword arguments are passed on to the rectangle patch.
-
-        Returns
-        -------
-        rectangle_patch : `.patches.Rectangle`
-             The indicator frame.
-
-        connector_lines : 4-tuple of `.patches.ConnectionPatch`
-            The four connector lines connecting to (lower_left, upper_left,
-            lower_right upper_right) corners of *inset_ax*. Two lines are
-            set with visibility to *False*,  but the user can set the
-            visibility to True if the automatic choice is not deemed correct.
-
-        """
-        # to make the axes connectors work, we need to apply the aspect to
-        # the parent axes.
-        self.apply_aspect()
-
-        if transform is None:
-            transform = self.transData
-        label = kwargs.pop('label', 'indicate_inset')
-
-        x, y, width, height = bounds
-        rectangle_patch = mpatches.Rectangle(
-            (x, y), width, height,
-            facecolor=facecolor, edgecolor=edgecolor, alpha=alpha,
-            zorder=zorder,  label=label, transform=transform, **kwargs)
-        self.add_patch(rectangle_patch)
-
-        connects = []
-
-        if inset_ax is not None:
-            # connect the inset_axes to the rectangle
-            for xy_inset_ax in [(0, 0), (0, 1), (1, 0), (1, 1)]:
-                # inset_ax positions are in axes coordinates
-                # The 0, 1 values define the four edges if the inset_ax
-                # lower_left, upper_left, lower_right upper_right.
-                ex, ey = xy_inset_ax
-                if self.xaxis.get_inverted():
-                    ex = 1 - ex
-                if self.yaxis.get_inverted():
-                    ey = 1 - ey
-                xy_data = x + ex * width, y + ey * height
-                p = mpatches.ConnectionPatch(
-                    xyA=xy_inset_ax, coordsA=inset_ax.transAxes,
-                    xyB=xy_data, coordsB=self.transData,
-                    arrowstyle="-", zorder=zorder,
-                    edgecolor=edgecolor, alpha=alpha)
-                connects.append(p)
-                self.add_patch(p)
-
-            # decide which two of the lines to keep visible....
-            pos = inset_ax.get_position()
-            bboxins = pos.transformed(self.figure.transFigure)
-            rectbbox = mtransforms.Bbox.from_bounds(
-                *bounds
-            ).transformed(transform)
-            x0 = rectbbox.x0 < bboxins.x0
-            x1 = rectbbox.x1 < bboxins.x1
-            y0 = rectbbox.y0 < bboxins.y0
-            y1 = rectbbox.y1 < bboxins.y1
-            connects[0].set_visible(x0 ^ y0)
-            connects[1].set_visible(x0 == y1)
-            connects[2].set_visible(x1 == y0)
-            connects[3].set_visible(x1 ^ y1)
-
-        return rectangle_patch, tuple(connects) if connects else None
-
-    def indicate_inset_zoom(self, inset_ax, **kwargs):
-        """
-        Add an inset indicator rectangle to the axes based on the axis
-        limits for an *inset_ax* and draw connectors between *inset_ax*
-        and the rectangle.
-
-        Warnings
-        --------
-        This method is experimental as of 3.0, and the API may change.
-
-        Parameters
-        ----------
-        inset_ax : `.Axes`
-            Inset axes to draw connecting lines to.  Two lines are
-            drawn connecting the indicator box to the inset axes on corners
-            chosen so as to not overlap with the indicator box.
-
-        **kwargs
-            Other keyword arguments are passed on to `.Axes.indicate_inset`
-
-        Returns
-        -------
-        rectangle_patch : `.Patches.Rectangle`
-             Rectangle artist.
-
-        connector_lines : 4-tuple of `.Patches.ConnectionPatch`
-            Each of four connector lines coming from the rectangle drawn on
-            this axis, in the order lower left, upper left, lower right,
-            upper right.
-            Two are set with visibility to *False*,  but the user can
-            set the visibility to *True* if the automatic choice is not deemed
-            correct.
-        """
-
-        xlim = inset_ax.get_xlim()
-        ylim = inset_ax.get_ylim()
-        rect = (xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0])
-        return self.indicate_inset(rect, inset_ax, **kwargs)
-
-    @docstring.dedent_interpd
-    def secondary_xaxis(self, location, *, functions=None, **kwargs):
-        """
-        Add a second x-axis to this axes.
-
-        For example if we want to have a second scale for the data plotted on
-        the xaxis.
-
-        %(_secax_docstring)s
-
-        Examples
-        --------
-        The main axis shows frequency, and the secondary axis shows period.
-
-        .. plot::
-
-            fig, ax = plt.subplots()
-            ax.loglog(range(1, 360, 5), range(1, 360, 5))
-            ax.set_xlabel('frequency [Hz]')
-
-            def invert(x):
-                return 1 / x
-
-            secax = ax.secondary_xaxis('top', functions=(invert, invert))
-            secax.set_xlabel('Period [s]')
-            plt.show()
-        """
-        if (location in ['top', 'bottom'] or isinstance(location, Number)):
-            secondary_ax = SecondaryAxis(self, 'x', location, functions,
-                                         **kwargs)
-            self.add_child_axes(secondary_ax)
-            return secondary_ax
-        else:
-            raise ValueError('secondary_xaxis location must be either '
-                             'a float or "top"/"bottom"')
-
-    def secondary_yaxis(self, location, *, functions=None, **kwargs):
-        """
-        Add a second y-axis to this axes.
-
-        For example if we want to have a second scale for the data plotted on
-        the yaxis.
-
-        %(_secax_docstring)s
-
-        Examples
-        --------
-        Add a secondary axes that converts from radians to degrees
-
-        .. plot::
-
-            fig, ax = plt.subplots()
-            ax.plot(range(1, 360, 5), range(1, 360, 5))
-            ax.set_ylabel('degrees')
-            secax = ax.secondary_yaxis('right', functions=(np.deg2rad,
-                                                           np.rad2deg))
-            secax.set_ylabel('radians')
-        """
-        if location in ['left', 'right'] or isinstance(location, Number):
-            secondary_ax = SecondaryAxis(self, 'y', location,
-                                         functions, **kwargs)
-            self.add_child_axes(secondary_ax)
-            return secondary_ax
-        else:
-            raise ValueError('secondary_yaxis location must be either '
-                             'a float or "left"/"right"')
-
-    @cbook._delete_parameter("3.1", "withdash")
-    def text(self, x, y, s, fontdict=None, withdash=False, **kwargs):
-        """
-        Add text to the axes.
-
-        Add the text *s* to the axes at location *x*, *y* in data coordinates.
-
-        Parameters
-        ----------
-        x, y : scalars
-            The position to place the text. By default, this is in data
-            coordinates. The coordinate system can be changed using the
-            *transform* parameter.
-
-        s : str
-            The text.
-
-        fontdict : dictionary, optional, default: None
-            A dictionary to override the default text properties. If fontdict
-            is None, the defaults are determined by your rc parameters.
-
-        withdash : boolean, optional, default: False
-            Creates a `~matplotlib.text.TextWithDash` instance instead of a
-            `~matplotlib.text.Text` instance.
-
-        Returns
-        -------
-        text : `.Text`
-            The created `.Text` instance.
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.text.Text` properties.
-            Other miscellaneous text parameters.
-
-        Examples
-        --------
-        Individual keyword arguments can be used to override any given
-        parameter::
-
-            >>> text(x, y, s, fontsize=12)
-
-        The default transform specifies that text is in data coords,
-        alternatively, you can specify text in axis coords ((0, 0) is
-        lower-left and (1, 1) is upper-right).  The example below places
-        text in the center of the axes::
-
-            >>> text(0.5, 0.5, 'matplotlib', horizontalalignment='center',
-            ...      verticalalignment='center', transform=ax.transAxes)
-
-        You can put a rectangular box around the text instance (e.g., to
-        set a background color) by using the keyword *bbox*.  *bbox* is
-        a dictionary of `~matplotlib.patches.Rectangle`
-        properties.  For example::
-
-            >>> text(x, y, s, bbox=dict(facecolor='red', alpha=0.5))
-        """
-        if fontdict is None:
-            fontdict = {}
-
-        effective_kwargs = {
-            'verticalalignment': 'baseline',
-            'horizontalalignment': 'left',
-            'transform': self.transData,
-            'clip_on': False,
-            **fontdict,
-            **kwargs,
-        }
-
-        # At some point if we feel confident that TextWithDash
-        # is robust as a drop-in replacement for Text and that
-        # the performance impact of the heavier-weight class
-        # isn't too significant, it may make sense to eliminate
-        # the withdash kwarg and simply delegate whether there's
-        # a dash to TextWithDash and dashlength.
-
-        if (withdash
-                and withdash is not cbook.deprecation._deprecated_parameter):
-            t = mtext.TextWithDash(x, y, text=s)
-        else:
-            t = mtext.Text(x, y, text=s)
-        t.update(effective_kwargs)
-
-        t.set_clip_path(self.patch)
-        self._add_text(t)
-        return t
-
-    @docstring.dedent_interpd
-    def annotate(self, s, xy, *args, **kwargs):
-        a = mtext.Annotation(s, xy, *args, **kwargs)
-        a.set_transform(mtransforms.IdentityTransform())
-        if 'clip_on' in kwargs:
-            a.set_clip_path(self.patch)
-        self._add_text(a)
-        return a
-    annotate.__doc__ = mtext.Annotation.__init__.__doc__
-    #### Lines and spans
-
-    @docstring.dedent_interpd
-    def axhline(self, y=0, xmin=0, xmax=1, **kwargs):
-        """
-        Add a horizontal line across the axis.
-
-        Parameters
-        ----------
-        y : scalar, optional, default: 0
-            y position in data coordinates of the horizontal line.
-
-        xmin : scalar, optional, default: 0
-            Should be between 0 and 1, 0 being the far left of the plot, 1 the
-            far right of the plot.
-
-        xmax : scalar, optional, default: 1
-            Should be between 0 and 1, 0 being the far left of the plot, 1 the
-            far right of the plot.
-
-        Returns
-        -------
-        line : `~matplotlib.lines.Line2D`
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Valid keyword arguments are `.Line2D` properties, with the
-            exception of 'transform':
-
-            %(_Line2D_docstr)s
-
-        See also
-        --------
-        hlines : Add horizontal lines in data coordinates.
-        axhspan : Add a horizontal span (rectangle) across the axis.
-
-        Examples
-        --------
-        * draw a thick red hline at 'y' = 0 that spans the xrange::
-
-            >>> axhline(linewidth=4, color='r')
-
-        * draw a default hline at 'y' = 1 that spans the xrange::
-
-            >>> axhline(y=1)
-
-        * draw a default hline at 'y' = .5 that spans the middle half of
-          the xrange::
-
-            >>> axhline(y=.5, xmin=0.25, xmax=0.75)
-        """
-        if "transform" in kwargs:
-            raise ValueError(
-                "'transform' is not allowed as a kwarg;"
-                + "axhline generates its own transform.")
-        ymin, ymax = self.get_ybound()
-
-        # We need to strip away the units for comparison with
-        # non-unitized bounds
-        self._process_unit_info(ydata=y, kwargs=kwargs)
-        yy = self.convert_yunits(y)
-        scaley = (yy < ymin) or (yy > ymax)
-
-        trans = self.get_yaxis_transform(which='grid')
-        l = mlines.Line2D([xmin, xmax], [y, y], transform=trans, **kwargs)
-        self.add_line(l)
-        self._request_autoscale_view(scalex=False, scaley=scaley)
-        return l
-
-    @docstring.dedent_interpd
-    def axvline(self, x=0, ymin=0, ymax=1, **kwargs):
-        """
-        Add a vertical line across the axes.
-
-        Parameters
-        ----------
-        x : scalar, optional, default: 0
-            x position in data coordinates of the vertical line.
-
-        ymin : scalar, optional, default: 0
-            Should be between 0 and 1, 0 being the bottom of the plot, 1 the
-            top of the plot.
-
-        ymax : scalar, optional, default: 1
-            Should be between 0 and 1, 0 being the bottom of the plot, 1 the
-            top of the plot.
-
-        Returns
-        -------
-        line : `~matplotlib.lines.Line2D`
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Valid keyword arguments are `.Line2D` properties, with the
-            exception of 'transform':
-
-            %(_Line2D_docstr)s
-
-        Examples
-        --------
-        * draw a thick red vline at *x* = 0 that spans the yrange::
-
-            >>> axvline(linewidth=4, color='r')
-
-        * draw a default vline at *x* = 1 that spans the yrange::
-
-            >>> axvline(x=1)
-
-        * draw a default vline at *x* = .5 that spans the middle half of
-          the yrange::
-
-            >>> axvline(x=.5, ymin=0.25, ymax=0.75)
-
-        See also
-        --------
-        vlines : Add vertical lines in data coordinates.
-        axvspan : Add a vertical span (rectangle) across the axis.
-        """
-
-        if "transform" in kwargs:
-            raise ValueError(
-                "'transform' is not allowed as a kwarg;"
-                + "axvline generates its own transform.")
-        xmin, xmax = self.get_xbound()
-
-        # We need to strip away the units for comparison with
-        # non-unitized bounds
-        self._process_unit_info(xdata=x, kwargs=kwargs)
-        xx = self.convert_xunits(x)
-        scalex = (xx < xmin) or (xx > xmax)
-
-        trans = self.get_xaxis_transform(which='grid')
-        l = mlines.Line2D([x, x], [ymin, ymax], transform=trans, **kwargs)
-        self.add_line(l)
-        self._request_autoscale_view(scalex=scalex, scaley=False)
-        return l
-
-    @docstring.dedent_interpd
-    def axhspan(self, ymin, ymax, xmin=0, xmax=1, **kwargs):
-        """
-        Add a horizontal span (rectangle) across the axis.
-
-        Draw a horizontal span (rectangle) from *ymin* to *ymax*.
-        With the default values of *xmin* = 0 and *xmax* = 1, this
-        always spans the xrange, regardless of the xlim settings, even
-        if you change them, e.g., with the :meth:`set_xlim` command.
-        That is, the horizontal extent is in axes coords: 0=left,
-        0.5=middle, 1.0=right but the *y* location is in data
-        coordinates.
-
-        Parameters
-        ----------
-        ymin : float
-               Lower limit of the horizontal span in data units.
-        ymax : float
-               Upper limit of the horizontal span in data units.
-        xmin : float, optional, default: 0
-               Lower limit of the vertical span in axes (relative
-               0-1) units.
-        xmax : float, optional, default: 1
-               Upper limit of the vertical span in axes (relative
-               0-1) units.
-
-        Returns
-        -------
-        Polygon : `~matplotlib.patches.Polygon`
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.patches.Polygon` properties.
-
-        %(Polygon)s
-
-        See Also
-        --------
-        axvspan : Add a vertical span across the axes.
-        """
-        trans = self.get_yaxis_transform(which='grid')
-
-        # process the unit information
-        self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs)
-
-        # first we need to strip away the units
-        xmin, xmax = self.convert_xunits([xmin, xmax])
-        ymin, ymax = self.convert_yunits([ymin, ymax])
-
-        verts = (xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)
-        p = mpatches.Polygon(verts, **kwargs)
-        p.set_transform(trans)
-        self.add_patch(p)
-        self._request_autoscale_view(scalex=False)
-        return p
-
-    def axvspan(self, xmin, xmax, ymin=0, ymax=1, **kwargs):
-        """
-        Add a vertical span (rectangle) across the axes.
-
-        Draw a vertical span (rectangle) from *xmin* to *xmax*.  With
-        the default values of *ymin* = 0 and *ymax* = 1. This always
-        spans the yrange, regardless of the ylim settings, even if you
-        change them, e.g., with the :meth:`set_ylim` command.  That is,
-        the vertical extent is in axes coords: 0=bottom, 0.5=middle,
-        1.0=top but the x location is in data coordinates.
-
-        Parameters
-        ----------
-        xmin : scalar
-            Number indicating the first X-axis coordinate of the vertical
-            span rectangle in data units.
-        xmax : scalar
-            Number indicating the second X-axis coordinate of the vertical
-            span rectangle in data units.
-        ymin : scalar, optional
-            Number indicating the first Y-axis coordinate of the vertical
-            span rectangle in relative Y-axis units (0-1). Default to 0.
-        ymax : scalar, optional
-            Number indicating the second Y-axis coordinate of the vertical
-            span rectangle in relative Y-axis units (0-1). Default to 1.
-
-        Returns
-        -------
-        rectangle : `~matplotlib.patches.Polygon`
-            Vertical span (rectangle) from (xmin, ymin) to (xmax, ymax).
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Optional parameters are properties of the class `.Polygon`.
-
-        See Also
-        --------
-        axhspan : Add a horizontal span across the axes.
-
-        Examples
-        --------
-        Draw a vertical, green, translucent rectangle from x = 1.25 to
-        x = 1.55 that spans the yrange of the axes.
-
-        >>> axvspan(1.25, 1.55, facecolor='g', alpha=0.5)
-
-        """
-        trans = self.get_xaxis_transform(which='grid')
-
-        # process the unit information
-        self._process_unit_info([xmin, xmax], [ymin, ymax], kwargs=kwargs)
-
-        # first we need to strip away the units
-        xmin, xmax = self.convert_xunits([xmin, xmax])
-        ymin, ymax = self.convert_yunits([ymin, ymax])
-
-        verts = [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)]
-        p = mpatches.Polygon(verts, **kwargs)
-        p.set_transform(trans)
-        self.add_patch(p)
-        self._request_autoscale_view(scaley=False)
-        return p
-
-    @_preprocess_data(replace_names=["y", "xmin", "xmax", "colors"],
-                      label_namer="y")
-    def hlines(self, y, xmin, xmax, colors='k', linestyles='solid',
-               label='', **kwargs):
-        """
-        Plot horizontal lines at each *y* from *xmin* to *xmax*.
-
-        Parameters
-        ----------
-        y : scalar or sequence of scalar
-            y-indexes where to plot the lines.
-
-        xmin, xmax : scalar or 1D array-like
-            Respective beginning and end of each line. If scalars are
-            provided, all lines will have same length.
-
-        colors : array-like of colors, optional, default: 'k'
-
-        linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, optional
-
-        label : str, optional, default: ''
-
-        Returns
-        -------
-        lines : `~matplotlib.collections.LineCollection`
-
-        Other Parameters
-        ----------------
-        **kwargs :  `~matplotlib.collections.LineCollection` properties.
-
-        See also
-        --------
-        vlines : vertical lines
-        axhline: horizontal line across the axes
-        """
-
-        # We do the conversion first since not all unitized data is uniform
-        # process the unit information
-        self._process_unit_info([xmin, xmax], y, kwargs=kwargs)
-        y = self.convert_yunits(y)
-        xmin = self.convert_xunits(xmin)
-        xmax = self.convert_xunits(xmax)
-
-        if not np.iterable(y):
-            y = [y]
-        if not np.iterable(xmin):
-            xmin = [xmin]
-        if not np.iterable(xmax):
-            xmax = [xmax]
-
-        y, xmin, xmax = cbook.delete_masked_points(y, xmin, xmax)
-
-        y = np.ravel(y)
-        xmin = np.resize(xmin, y.shape)
-        xmax = np.resize(xmax, y.shape)
-
-        verts = [((thisxmin, thisy), (thisxmax, thisy))
-                 for thisxmin, thisxmax, thisy in zip(xmin, xmax, y)]
-        lines = mcoll.LineCollection(verts, colors=colors,
-                                     linestyles=linestyles, label=label)
-        self.add_collection(lines, autolim=False)
-        lines.update(kwargs)
-
-        if len(y) > 0:
-            minx = min(xmin.min(), xmax.min())
-            maxx = max(xmin.max(), xmax.max())
-            miny = y.min()
-            maxy = y.max()
-
-            corners = (minx, miny), (maxx, maxy)
-
-            self.update_datalim(corners)
-            self._request_autoscale_view()
-
-        return lines
-
-    @_preprocess_data(replace_names=["x", "ymin", "ymax", "colors"],
-                      label_namer="x")
-    def vlines(self, x, ymin, ymax, colors='k', linestyles='solid',
-               label='', **kwargs):
-        """
-        Plot vertical lines.
-
-        Plot vertical lines at each *x* from *ymin* to *ymax*.
-
-        Parameters
-        ----------
-        x : scalar or 1D array-like
-            x-indexes where to plot the lines.
-
-        ymin, ymax : scalar or 1D array-like
-            Respective beginning and end of each line. If scalars are
-            provided, all lines will have same length.
-
-        colors : array-like of colors, optional, default: 'k'
-
-        linestyles : {'solid', 'dashed', 'dashdot', 'dotted'}, optional
-
-        label : str, optional, default: ''
-
-        Returns
-        -------
-        lines : `~matplotlib.collections.LineCollection`
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.collections.LineCollection` properties.
-
-        See also
-        --------
-        hlines : horizontal lines
-        axvline: vertical line across the axes
-        """
-
-        self._process_unit_info(xdata=x, ydata=[ymin, ymax], kwargs=kwargs)
-
-        # We do the conversion first since not all unitized data is uniform
-        x = self.convert_xunits(x)
-        ymin = self.convert_yunits(ymin)
-        ymax = self.convert_yunits(ymax)
-
-        if not np.iterable(x):
-            x = [x]
-        if not np.iterable(ymin):
-            ymin = [ymin]
-        if not np.iterable(ymax):
-            ymax = [ymax]
-
-        x, ymin, ymax = cbook.delete_masked_points(x, ymin, ymax)
-
-        x = np.ravel(x)
-        ymin = np.resize(ymin, x.shape)
-        ymax = np.resize(ymax, x.shape)
-
-        verts = [((thisx, thisymin), (thisx, thisymax))
-                 for thisx, thisymin, thisymax in zip(x, ymin, ymax)]
-        lines = mcoll.LineCollection(verts, colors=colors,
-                                     linestyles=linestyles, label=label)
-        self.add_collection(lines, autolim=False)
-        lines.update(kwargs)
-
-        if len(x) > 0:
-            minx = x.min()
-            maxx = x.max()
-            miny = min(ymin.min(), ymax.min())
-            maxy = max(ymin.max(), ymax.max())
-
-            corners = (minx, miny), (maxx, maxy)
-            self.update_datalim(corners)
-            self._request_autoscale_view()
-
-        return lines
-
-    @_preprocess_data(replace_names=["positions", "lineoffsets",
-                                     "linelengths", "linewidths",
-                                     "colors", "linestyles"])
-    @docstring.dedent_interpd
-    def eventplot(self, positions, orientation='horizontal', lineoffsets=1,
-                  linelengths=1, linewidths=None, colors=None,
-                  linestyles='solid', **kwargs):
-        """
-        Plot identical parallel lines at the given positions.
-
-        *positions* should be a 1D or 2D array-like object, with each row
-        corresponding to a row or column of lines.
-
-        This type of plot is commonly used in neuroscience for representing
-        neural events, where it is usually called a spike raster, dot raster,
-        or raster plot.
-
-        However, it is useful in any situation where you wish to show the
-        timing or position of multiple sets of discrete events, such as the
-        arrival times of people to a business on each day of the month or the
-        date of hurricanes each year of the last century.
-
-        Parameters
-        ----------
-        positions : 1D or 2D array-like object
-            Each value is an event. If *positions* is a 2D array-like, each
-            row corresponds to a row or a column of lines (depending on the
-            *orientation* parameter).
-
-        orientation : {'horizontal', 'vertical'}, optional
-            Controls the direction of the event collections:
-
-                - 'horizontal' : the lines are arranged horizontally in rows,
-                  and are vertical.
-                - 'vertical' : the lines are arranged vertically in columns,
-                  and are horizontal.
-
-        lineoffsets : scalar or sequence of scalars, optional, default: 1
-            The offset of the center of the lines from the origin, in the
-            direction orthogonal to *orientation*.
-
-        linelengths : scalar or sequence of scalars, optional, default: 1
-            The total height of the lines (i.e. the lines stretches from
-            ``lineoffset - linelength/2`` to ``lineoffset + linelength/2``).
-
-        linewidths : scalar, scalar sequence or None, optional, default: None
-            The line width(s) of the event lines, in points. If it is None,
-            defaults to its rcParams setting.
-
-        colors : color, sequence of colors or None, optional, default: None
-            The color(s) of the event lines. If it is None, defaults to its
-            rcParams setting.
-
-        linestyles : str or tuple or a sequence of such values, optional
-            Default is 'solid'. Valid strings are ['solid', 'dashed',
-            'dashdot', 'dotted', '-', '--', '-.', ':']. Dash tuples
-            should be of the form::
-
-                (offset, onoffseq),
-
-            where *onoffseq* is an even length tuple of on and off ink
-            in points.
-
-        **kwargs : optional
-            Other keyword arguments are line collection properties.  See
-            :class:`~matplotlib.collections.LineCollection` for a list of
-            the valid properties.
-
-        Returns
-        -------
-        list : A list of :class:`~.collections.EventCollection` objects.
-            Contains the :class:`~.collections.EventCollection` that
-            were added.
-
-        Notes
-        -----
-        For *linelengths*, *linewidths*, *colors*, and *linestyles*, if only
-        a single value is given, that value is applied to all lines.  If an
-        array-like is given, it must have the same length as *positions*, and
-        each value will be applied to the corresponding row of the array.
-
-        Examples
-        --------
-        .. plot:: gallery/lines_bars_and_markers/eventplot_demo.py
-        """
-        self._process_unit_info(xdata=positions,
-                                ydata=[lineoffsets, linelengths],
-                                kwargs=kwargs)
-
-        # We do the conversion first since not all unitized data is uniform
-        positions = self.convert_xunits(positions)
-        lineoffsets = self.convert_yunits(lineoffsets)
-        linelengths = self.convert_yunits(linelengths)
-
-        if not np.iterable(positions):
-            positions = [positions]
-        elif any(np.iterable(position) for position in positions):
-            positions = [np.asanyarray(position) for position in positions]
-        else:
-            positions = [np.asanyarray(positions)]
-
-        if len(positions) == 0:
-            return []
-
-        # prevent 'singular' keys from **kwargs dict from overriding the effect
-        # of 'plural' keyword arguments (e.g. 'color' overriding 'colors')
-        colors = cbook.local_over_kwdict(colors, kwargs, 'color')
-        linewidths = cbook.local_over_kwdict(linewidths, kwargs, 'linewidth')
-        linestyles = cbook.local_over_kwdict(linestyles, kwargs, 'linestyle')
-
-        if not np.iterable(lineoffsets):
-            lineoffsets = [lineoffsets]
-        if not np.iterable(linelengths):
-            linelengths = [linelengths]
-        if not np.iterable(linewidths):
-            linewidths = [linewidths]
-        if not np.iterable(colors):
-            colors = [colors]
-        if hasattr(linestyles, 'lower') or not np.iterable(linestyles):
-            linestyles = [linestyles]
-
-        lineoffsets = np.asarray(lineoffsets)
-        linelengths = np.asarray(linelengths)
-        linewidths = np.asarray(linewidths)
-
-        if len(lineoffsets) == 0:
-            lineoffsets = [None]
-        if len(linelengths) == 0:
-            linelengths = [None]
-        if len(linewidths) == 0:
-            lineoffsets = [None]
-        if len(linewidths) == 0:
-            lineoffsets = [None]
-        if len(colors) == 0:
-            colors = [None]
-        try:
-            # Early conversion of the colors into RGBA values to take care
-            # of cases like colors='0.5' or colors='C1'.  (Issue #8193)
-            colors = mcolors.to_rgba_array(colors)
-        except ValueError:
-            # Will fail if any element of *colors* is None. But as long
-            # as len(colors) == 1 or len(positions), the rest of the
-            # code should process *colors* properly.
-            pass
-
-        if len(lineoffsets) == 1 and len(positions) != 1:
-            lineoffsets = np.tile(lineoffsets, len(positions))
-            lineoffsets[0] = 0
-            lineoffsets = np.cumsum(lineoffsets)
-        if len(linelengths) == 1:
-            linelengths = np.tile(linelengths, len(positions))
-        if len(linewidths) == 1:
-            linewidths = np.tile(linewidths, len(positions))
-        if len(colors) == 1:
-            colors = list(colors)
-            colors = colors * len(positions)
-        if len(linestyles) == 1:
-            linestyles = [linestyles] * len(positions)
-
-        if len(lineoffsets) != len(positions):
-            raise ValueError('lineoffsets and positions are unequal sized '
-                             'sequences')
-        if len(linelengths) != len(positions):
-            raise ValueError('linelengths and positions are unequal sized '
-                             'sequences')
-        if len(linewidths) != len(positions):
-            raise ValueError('linewidths and positions are unequal sized '
-                             'sequences')
-        if len(colors) != len(positions):
-            raise ValueError('colors and positions are unequal sized '
-                             'sequences')
-        if len(linestyles) != len(positions):
-            raise ValueError('linestyles and positions are unequal sized '
-                             'sequences')
-
-        colls = []
-        for position, lineoffset, linelength, linewidth, color, linestyle in \
-            zip(positions, lineoffsets, linelengths, linewidths,
-                           colors, linestyles):
-            coll = mcoll.EventCollection(position,
-                                         orientation=orientation,
-                                         lineoffset=lineoffset,
-                                         linelength=linelength,
-                                         linewidth=linewidth,
-                                         color=color,
-                                         linestyle=linestyle)
-            self.add_collection(coll, autolim=False)
-            coll.update(kwargs)
-            colls.append(coll)
-
-        if len(positions) > 0:
-            # try to get min/max
-            min_max = [(np.min(_p), np.max(_p)) for _p in positions
-                       if len(_p) > 0]
-            # if we have any non-empty positions, try to autoscale
-            if len(min_max) > 0:
-                mins, maxes = zip(*min_max)
-                minpos = np.min(mins)
-                maxpos = np.max(maxes)
-
-                minline = (lineoffsets - linelengths).min()
-                maxline = (lineoffsets + linelengths).max()
-
-                if (orientation is not None and
-                        orientation.lower() == "vertical"):
-                    corners = (minline, minpos), (maxline, maxpos)
-                else:  # "horizontal", None or "none" (see EventCollection)
-                    corners = (minpos, minline), (maxpos, maxline)
-                self.update_datalim(corners)
-                self._request_autoscale_view()
-
-        return colls
-
-    #### Basic plotting
-
-    # Uses a custom implementation of data-kwarg handling in
-    # _process_plot_var_args.
-    @docstring.dedent_interpd
-    def plot(self, *args, scalex=True, scaley=True, data=None, **kwargs):
-        """
-        Plot y versus x as lines and/or markers.
-
-        Call signatures::
-
-            plot([x], y, [fmt], *, data=None, **kwargs)
-            plot([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
-
-        The coordinates of the points or line nodes are given by *x*, *y*.
-
-        The optional parameter *fmt* is a convenient way for defining basic
-        formatting like color, marker and linestyle. It's a shortcut string
-        notation described in the *Notes* section below.
-
-        >>> plot(x, y)        # plot x and y using default line style and color
-        >>> plot(x, y, 'bo')  # plot x and y using blue circle markers
-        >>> plot(y)           # plot y using x as index array 0..N-1
-        >>> plot(y, 'r+')     # ditto, but with red plusses
-
-        You can use `.Line2D` properties as keyword arguments for more
-        control on the appearance. Line properties and *fmt* can be mixed.
-        The following two calls yield identical results:
-
-        >>> plot(x, y, 'go--', linewidth=2, markersize=12)
-        >>> plot(x, y, color='green', marker='o', linestyle='dashed',
-        ...      linewidth=2, markersize=12)
-
-        When conflicting with *fmt*, keyword arguments take precedence.
-
-
-        **Plotting labelled data**
-
-        There's a convenient way for plotting objects with labelled data (i.e.
-        data that can be accessed by index ``obj['y']``). Instead of giving
-        the data in *x* and *y*, you can provide the object in the *data*
-        parameter and just give the labels for *x* and *y*::
-
-        >>> plot('xlabel', 'ylabel', data=obj)
-
-        All indexable objects are supported. This could e.g. be a `dict`, a
-        `pandas.DataFame` or a structured numpy array.
-
-
-        **Plotting multiple sets of data**
-
-        There are various ways to plot multiple sets of data.
-
-        - The most straight forward way is just to call `plot` multiple times.
-          Example:
-
-          >>> plot(x1, y1, 'bo')
-          >>> plot(x2, y2, 'go')
-
-        - Alternatively, if your data is already a 2d array, you can pass it
-          directly to *x*, *y*. A separate data set will be drawn for every
-          column.
-
-          Example: an array ``a`` where the first column represents the *x*
-          values and the other columns are the *y* columns::
-
-          >>> plot(a[0], a[1:])
-
-        - The third way is to specify multiple sets of *[x]*, *y*, *[fmt]*
-          groups::
-
-          >>> plot(x1, y1, 'g^', x2, y2, 'g-')
-
-          In this case, any additional keyword argument applies to all
-          datasets. Also this syntax cannot be combined with the *data*
-          parameter.
-
-        By default, each line is assigned a different style specified by a
-        'style cycle'. The *fmt* and line property parameters are only
-        necessary if you want explicit deviations from these defaults.
-        Alternatively, you can also change the style cycle using
-        :rc:`axes.prop_cycle`.
-
-
-        Parameters
-        ----------
-        x, y : array-like or scalar
-            The horizontal / vertical coordinates of the data points.
-            *x* values are optional and default to `range(len(y))`.
-
-            Commonly, these parameters are 1D arrays.
-
-            They can also be scalars, or two-dimensional (in that case, the
-            columns represent separate data sets).
-
-            These arguments cannot be passed as keywords.
-
-        fmt : str, optional
-            A format string, e.g. 'ro' for red circles. See the *Notes*
-            section for a full description of the format strings.
-
-            Format strings are just an abbreviation for quickly setting
-            basic line properties. All of these and more can also be
-            controlled by keyword arguments.
-
-            This argument cannot be passed as keyword.
-
-        data : indexable object, optional
-            An object with labelled data. If given, provide the label names to
-            plot in *x* and *y*.
-
-            .. note::
-                Technically there's a slight ambiguity in calls where the
-                second label is a valid *fmt*. `plot('n', 'o', data=obj)`
-                could be `plt(x, y)` or `plt(y, fmt)`. In such cases,
-                the former interpretation is chosen, but a warning is issued.
-                You may suppress the warning by adding an empty format string
-                `plot('n', 'o', '', data=obj)`.
-
-        Other Parameters
-        ----------------
-        scalex, scaley : bool, optional, default: True
-            These parameters determined if the view limits are adapted to
-            the data limits. The values are passed on to `autoscale_view`.
-
-        **kwargs : `.Line2D` properties, optional
-            *kwargs* are used to specify properties like a line label (for
-            auto legends), linewidth, antialiasing, marker face color.
-            Example::
-
-            >>> plot([1, 2, 3], [1, 2, 3], 'go-', label='line 1', linewidth=2)
-            >>> plot([1, 2, 3], [1, 4, 9], 'rs', label='line 2')
-
-            If you make multiple lines with one plot command, the kwargs
-            apply to all those lines.
-
-            Here is a list of available `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        Returns
-        -------
-        lines
-            A list of `.Line2D` objects representing the plotted data.
-
-        See Also
-        --------
-        scatter : XY scatter plot with markers of varying size and/or color (
-            sometimes also called bubble chart).
-
-        Notes
-        -----
-        **Format Strings**
-
-        A format string consists of a part for color, marker and line::
-
-            fmt = '[marker][line][color]'
-
-        Each of them is optional. If not provided, the value from the style
-        cycle is used. Exception: If ``line`` is given, but no ``marker``,
-        the data will be a line without markers.
-
-        Other combinations such as ``[color][marker][line]`` are also
-        supported, but note that their parsing may be ambiguous.
-
-        **Markers**
-
-        =============    ===============================
-        character        description
-        =============    ===============================
-        ``'.'``          point marker
-        ``','``          pixel marker
-        ``'o'``          circle marker
-        ``'v'``          triangle_down marker
-        ``'^'``          triangle_up marker
-        ``'<'``          triangle_left marker
-        ``'>'``          triangle_right marker
-        ``'1'``          tri_down marker
-        ``'2'``          tri_up marker
-        ``'3'``          tri_left marker
-        ``'4'``          tri_right marker
-        ``'s'``          square marker
-        ``'p'``          pentagon marker
-        ``'*'``          star marker
-        ``'h'``          hexagon1 marker
-        ``'H'``          hexagon2 marker
-        ``'+'``          plus marker
-        ``'x'``          x marker
-        ``'D'``          diamond marker
-        ``'d'``          thin_diamond marker
-        ``'|'``          vline marker
-        ``'_'``          hline marker
-        =============    ===============================
-
-        **Line Styles**
-
-        =============    ===============================
-        character        description
-        =============    ===============================
-        ``'-'``          solid line style
-        ``'--'``         dashed line style
-        ``'-.'``         dash-dot line style
-        ``':'``          dotted line style
-        =============    ===============================
-
-        Example format strings::
-
-            'b'    # blue markers with default shape
-            'or'   # red circles
-            '-g'   # green solid line
-            '--'   # dashed line with default color
-            '^k:'  # black triangle_up markers connected by a dotted line
-
-        **Colors**
-
-        The supported color abbreviations are the single letter codes
-
-        =============    ===============================
-        character        color
-        =============    ===============================
-        ``'b'``          blue
-        ``'g'``          green
-        ``'r'``          red
-        ``'c'``          cyan
-        ``'m'``          magenta
-        ``'y'``          yellow
-        ``'k'``          black
-        ``'w'``          white
-        =============    ===============================
-
-        and the ``'CN'`` colors that index into the default property cycle.
-
-        If the color is the only part of the format string, you can
-        additionally use any  `matplotlib.colors` spec, e.g. full names
-        (``'green'``) or hex strings (``'#008000'``).
-        """
-        kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-        lines = [*self._get_lines(*args, data=data, **kwargs)]
-        for line in lines:
-            self.add_line(line)
-        self._request_autoscale_view(scalex=scalex, scaley=scaley)
-        return lines
-
-    @_preprocess_data(replace_names=["x", "y"], label_namer="y")
-    @docstring.dedent_interpd
-    def plot_date(self, x, y, fmt='o', tz=None, xdate=True, ydate=False,
-                  **kwargs):
-        """
-        Plot data that contains dates.
-
-        Similar to `.plot`, this plots *y* vs. *x* as lines or markers.
-        However, the axis labels are formatted as dates depending on *xdate*
-        and *ydate*.
-
-        Parameters
-        ----------
-        x, y : array-like
-            The coordinates of the data points. If *xdate* or *ydate* is
-            *True*, the respective values *x* or *y* are interpreted as
-            :ref:`Matplotlib dates <date-format>`.
-
-        fmt : str, optional
-            The plot format string. For details, see the corresponding
-            parameter in `.plot`.
-
-        tz : timezone string or `tzinfo` or None
-            The time zone to use in labeling dates. If *None*, defaults to
-            :rc:`timezone`.
-
-        xdate : bool, optional, default: True
-            If *True*, the *x*-axis will be interpreted as Matplotlib dates.
-
-        ydate : bool, optional, default: False
-            If *True*, the *y*-axis will be interpreted as Matplotlib dates.
-
-
-        Returns
-        -------
-        lines
-            A list of `.Line2D` objects representing the plotted data.
-
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Keyword arguments control the `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        See Also
-        --------
-        matplotlib.dates : Helper functions on dates.
-        matplotlib.dates.date2num : Convert dates to num.
-        matplotlib.dates.num2date : Convert num to dates.
-        matplotlib.dates.drange : Create an equally spaced sequence of dates.
-
-        Notes
-        -----
-        If you are using custom date tickers and formatters, it may be
-        necessary to set the formatters/locators after the call to
-        `.plot_date`. `.plot_date` will set the default tick locator to
-        `.AutoDateLocator` (if the tick locator is not already set to a
-        `.DateLocator` instance) and the default tick formatter to
-        `.AutoDateFormatter` (if the tick formatter is not already set to a
-        `.DateFormatter` instance).
-        """
-        if xdate:
-            self.xaxis_date(tz)
-        if ydate:
-            self.yaxis_date(tz)
-
-        ret = self.plot(x, y, fmt, **kwargs)
-
-        self._request_autoscale_view()
-
-        return ret
-
-    # @_preprocess_data() # let 'plot' do the unpacking..
-    @docstring.dedent_interpd
-    def loglog(self, *args, **kwargs):
-        """
-        Make a plot with log scaling on both the x and y axis.
-
-        Call signatures::
-
-            loglog([x], y, [fmt], data=None, **kwargs)
-            loglog([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
-
-        This is just a thin wrapper around `.plot` which additionally changes
-        both the x-axis and the y-axis to log scaling. All of the concepts and
-        parameters of plot can be used here as well.
-
-        The additional parameters *basex/y*, *subsx/y* and *nonposx/y* control
-        the x/y-axis properties. They are just forwarded to `.Axes.set_xscale`
-        and `.Axes.set_yscale`.
-
-        Parameters
-        ----------
-        basex, basey : scalar, optional, default 10
-            Base of the x/y logarithm.
-
-        subsx, subsy : sequence, optional
-            The location of the minor x/y ticks. If *None*, reasonable
-            locations are automatically chosen depending on the number of
-            decades in the plot.
-            See `.Axes.set_xscale` / `.Axes.set_yscale` for details.
-
-        nonposx, nonposy : {'mask', 'clip'}, optional, default 'mask'
-            Non-positive values in x or y can be masked as invalid, or clipped
-            to a very small positive number.
-
-        Returns
-        -------
-        lines
-            A list of `.Line2D` objects representing the plotted data.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            All parameters supported by `.plot`.
-        """
-        dx = {k: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx']
-              if k in kwargs}
-        dy = {k: kwargs.pop(k) for k in ['basey', 'subsy', 'nonposy']
-              if k in kwargs}
-
-        self.set_xscale('log', **dx)
-        self.set_yscale('log', **dy)
-
-        l = self.plot(*args, **kwargs)
-        return l
-
-    # @_preprocess_data() # let 'plot' do the unpacking..
-    @docstring.dedent_interpd
-    def semilogx(self, *args, **kwargs):
-        """
-        Make a plot with log scaling on the x axis.
-
-        Call signatures::
-
-            semilogx([x], y, [fmt], data=None, **kwargs)
-            semilogx([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
-
-        This is just a thin wrapper around `.plot` which additionally changes
-        the x-axis to log scaling. All of the concepts and parameters of plot
-        can be used here as well.
-
-        The additional parameters *basex*, *subsx* and *nonposx* control the
-        x-axis properties. They are just forwarded to `.Axes.set_xscale`.
-
-        Parameters
-        ----------
-        basex : scalar, optional, default 10
-            Base of the x logarithm.
-
-        subsx : array-like, optional
-            The location of the minor xticks. If *None*, reasonable locations
-            are automatically chosen depending on the number of decades in the
-            plot. See `.Axes.set_xscale` for details.
-
-        nonposx : {'mask', 'clip'}, optional, default 'mask'
-            Non-positive values in x can be masked as invalid, or clipped to a
-            very small positive number.
-
-        Returns
-        -------
-        lines
-            A list of `.Line2D` objects representing the plotted data.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            All parameters supported by `.plot`.
-        """
-        d = {k: kwargs.pop(k) for k in ['basex', 'subsx', 'nonposx']
-             if k in kwargs}
-
-        self.set_xscale('log', **d)
-        l = self.plot(*args, **kwargs)
-        return l
-
-    # @_preprocess_data() # let 'plot' do the unpacking..
-    @docstring.dedent_interpd
-    def semilogy(self, *args, **kwargs):
-        """
-        Make a plot with log scaling on the y axis.
-
-        Call signatures::
-
-            semilogy([x], y, [fmt], data=None, **kwargs)
-            semilogy([x], y, [fmt], [x2], y2, [fmt2], ..., **kwargs)
-
-        This is just a thin wrapper around `.plot` which additionally changes
-        the y-axis to log scaling. All of the concepts and parameters of plot
-        can be used here as well.
-
-        The additional parameters *basey*, *subsy* and *nonposy* control the
-        y-axis properties. They are just forwarded to `.Axes.set_yscale`.
-
-        Parameters
-        ----------
-        basey : scalar, optional, default 10
-            Base of the y logarithm.
-
-        subsy : array-like, optional
-            The location of the minor yticks. If *None*, reasonable locations
-            are automatically chosen depending on the number of decades in the
-            plot. See `.Axes.set_yscale` for details.
-
-        nonposy : {'mask', 'clip'}, optional, default 'mask'
-            Non-positive values in y can be masked as invalid, or clipped to a
-            very small positive number.
-
-        Returns
-        -------
-        lines
-            A list of `.Line2D` objects representing the plotted data.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            All parameters supported by `.plot`.
-        """
-        d = {k: kwargs.pop(k) for k in ['basey', 'subsy', 'nonposy']
-             if k in kwargs}
-        self.set_yscale('log', **d)
-        l = self.plot(*args, **kwargs)
-
-        return l
-
-    @_preprocess_data(replace_names=["x"], label_namer="x")
-    def acorr(self, x, **kwargs):
-        """
-        Plot the autocorrelation of *x*.
-
-        Parameters
-        ----------
-        x : array-like
-
-        detrend : callable, optional, default: `mlab.detrend_none`
-            *x* is detrended by the *detrend* callable. This must be a
-            function ``x = detrend(x)`` accepting and returning an
-            `numpy.array`. Default is no normalization.
-
-        normed : bool, optional, default: True
-            If ``True``, input vectors are normalised to unit length.
-
-        usevlines : bool, optional, default: True
-            Determines the plot style.
-
-            If ``True``, vertical lines are plotted from 0 to the acorr value
-            using `Axes.vlines`. Additionally, a horizontal line is plotted
-            at y=0 using `Axes.axhline`.
-
-            If ``False``, markers are plotted at the acorr values using
-            `Axes.plot`.
-
-        maxlags : int, optional, default: 10
-            Number of lags to show. If ``None``, will return all
-            ``2 * len(x) - 1`` lags.
-
-        Returns
-        -------
-        lags : array (length ``2*maxlags+1``)
-            The lag vector.
-        c : array  (length ``2*maxlags+1``)
-            The auto correlation vector.
-        line : `.LineCollection` or `.Line2D`
-            `.Artist` added to the axes of the correlation:
-
-            - `.LineCollection` if *usevlines* is True.
-            - `.Line2D` if *usevlines* is False.
-        b : `.Line2D` or None
-            Horizontal line at 0 if *usevlines* is True
-            None *usevlines* is False.
-
-        Other Parameters
-        ----------------
-        linestyle : `.Line2D` property, optional
-            The linestyle for plotting the data points.
-            Only used if *usevlines* is ``False``.
-
-        marker : str, optional, default: 'o'
-            The marker for plotting the data points.
-            Only used if *usevlines* is ``False``.
-
-        Notes
-        -----
-        The cross correlation is performed with :func:`numpy.correlate` with
-        ``mode = "full"``.
-        """
-        return self.xcorr(x, x, **kwargs)
-
-    @_preprocess_data(replace_names=["x", "y"], label_namer="y")
-    def xcorr(self, x, y, normed=True, detrend=mlab.detrend_none,
-              usevlines=True, maxlags=10, **kwargs):
-        r"""
-        Plot the cross correlation between *x* and *y*.
-
-        The correlation with lag k is defined as
-        :math:`\sum_n x[n+k] \cdot y^*[n]`, where :math:`y^*` is the complex
-        conjugate of :math:`y`.
-
-        Parameters
-        ----------
-        x : array-like of length n
-
-        y : array-like of length n
-
-        detrend : callable, optional, default: `mlab.detrend_none`
-            *x* and *y* are detrended by the *detrend* callable. This must be a
-            function ``x = detrend(x)`` accepting and returning an
-            `numpy.array`. Default is no normalization.
-
-        normed : bool, optional, default: True
-            If ``True``, input vectors are normalised to unit length.
-
-        usevlines : bool, optional, default: True
-            Determines the plot style.
-
-            If ``True``, vertical lines are plotted from 0 to the xcorr value
-            using `Axes.vlines`. Additionally, a horizontal line is plotted
-            at y=0 using `Axes.axhline`.
-
-            If ``False``, markers are plotted at the xcorr values using
-            `Axes.plot`.
-
-        maxlags : int, optional, default: 10
-            Number of lags to show. If None, will return all ``2 * len(x) - 1``
-            lags.
-
-        Returns
-        -------
-        lags : array (length ``2*maxlags+1``)
-            The lag vector.
-        c : array  (length ``2*maxlags+1``)
-            The auto correlation vector.
-        line : `.LineCollection` or `.Line2D`
-            `.Artist` added to the axes of the correlation:
-
-            - `.LineCollection` if *usevlines* is True.
-            - `.Line2D` if *usevlines* is False.
-        b : `.Line2D` or None
-            Horizontal line at 0 if *usevlines* is True
-            None *usevlines* is False.
-
-        Other Parameters
-        ----------------
-        linestyle : `.Line2D` property, optional
-            The linestyle for plotting the data points.
-            Only used if *usevlines* is ``False``.
-
-        marker : str, optional, default: 'o'
-            The marker for plotting the data points.
-            Only used if *usevlines* is ``False``.
-
-        Notes
-        -----
-        The cross correlation is performed with :func:`numpy.correlate` with
-        ``mode = "full"``.
-        """
-        Nx = len(x)
-        if Nx != len(y):
-            raise ValueError('x and y must be equal length')
-
-        x = detrend(np.asarray(x))
-        y = detrend(np.asarray(y))
-
-        correls = np.correlate(x, y, mode="full")
-
-        if normed:
-            correls /= np.sqrt(np.dot(x, x) * np.dot(y, y))
-
-        if maxlags is None:
-            maxlags = Nx - 1
-
-        if maxlags >= Nx or maxlags < 1:
-            raise ValueError('maxlags must be None or strictly '
-                             'positive < %d' % Nx)
-
-        lags = np.arange(-maxlags, maxlags + 1)
-        correls = correls[Nx - 1 - maxlags:Nx + maxlags]
-
-        if usevlines:
-            a = self.vlines(lags, [0], correls, **kwargs)
-            # Make label empty so only vertical lines get a legend entry
-            kwargs.pop('label', '')
-            b = self.axhline(**kwargs)
-        else:
-            kwargs.setdefault('marker', 'o')
-            kwargs.setdefault('linestyle', 'None')
-            a, = self.plot(lags, correls, **kwargs)
-            b = None
-        return lags, correls, a, b
-
-    #### Specialized plotting
-
-    # @_preprocess_data() # let 'plot' do the unpacking..
-    def step(self, x, y, *args, where='pre', data=None, **kwargs):
-        """
-        Make a step plot.
-
-        Call signatures::
-
-            step(x, y, [fmt], *, data=None, where='pre', **kwargs)
-            step(x, y, [fmt], x2, y2, [fmt2], ..., *, where='pre', **kwargs)
-
-        This is just a thin wrapper around `.plot` which changes some
-        formatting options. Most of the concepts and parameters of plot can be
-        used here as well.
-
-        Parameters
-        ----------
-        x : array-like
-            1-D sequence of x positions. It is assumed, but not checked, that
-            it is uniformly increasing.
-
-        y : array-like
-            1-D sequence of y levels.
-
-        fmt : str, optional
-            A format string, e.g. 'g' for a green line. See `.plot` for a more
-            detailed description.
-
-            Note: While full format strings are accepted, it is recommended to
-            only specify the color. Line styles are currently ignored (use
-            the keyword argument *linestyle* instead). Markers are accepted
-            and plotted on the given positions, however, this is a rarely
-            needed feature for step plots.
-
-        data : indexable object, optional
-            An object with labelled data. If given, provide the label names to
-            plot in *x* and *y*.
-
-        where : {'pre', 'post', 'mid'}, optional, default 'pre'
-            Define where the steps should be placed:
-
-            - 'pre': The y value is continued constantly to the left from
-              every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the
-              value ``y[i]``.
-            - 'post': The y value is continued constantly to the right from
-              every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the
-              value ``y[i]``.
-            - 'mid': Steps occur half-way between the *x* positions.
-
-        Returns
-        -------
-        lines
-            A list of `.Line2D` objects representing the plotted data.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Additional parameters are the same as those for `.plot`.
-
-        Notes
-        -----
-        .. [notes section required to get data note injection right]
-        """
-        cbook._check_in_list(('pre', 'post', 'mid'), where=where)
-        kwargs['drawstyle'] = 'steps-' + where
-        return self.plot(x, y, *args, data=data, **kwargs)
-
-    @staticmethod
-    def _convert_dx(dx, x0, xconv, convert):
-        """
-        Small helper to do logic of width conversion flexibly.
-
-        *dx* and *x0* have units, but *xconv* has already been converted
-        to unitless (and is an ndarray).  This allows the *dx* to have units
-        that are different from *x0*, but are still accepted by the
-        ``__add__`` operator of *x0*.
-        """
-
-        # x should be an array...
-        assert type(xconv) is np.ndarray
-
-        if xconv.size == 0:
-            # xconv has already been converted, but maybe empty...
-            return convert(dx)
-
-        try:
-            # attempt to add the width to x0; this works for
-            # datetime+timedelta, for instance
-
-            # only use the first element of x and x0.  This saves
-            # having to be sure addition works across the whole
-            # vector.  This is particularly an issue if
-            # x0 and dx are lists so x0 + dx just concatenates the lists.
-            # We can't just cast x0 and dx to numpy arrays because that
-            # removes the units from unit packages like `pint` that
-            # wrap numpy arrays.
-            try:
-                x0 = cbook.safe_first_element(x0)
-            except (TypeError, IndexError, KeyError):
-                x0 = x0
-
-            try:
-                x = cbook.safe_first_element(xconv)
-            except (TypeError, IndexError, KeyError):
-                x = xconv
-
-            delist = False
-            if not np.iterable(dx):
-                dx = [dx]
-                delist = True
-            dx = [convert(x0 + ddx) - x for ddx in dx]
-            if delist:
-                dx = dx[0]
-        except (ValueError, TypeError, AttributeError):
-            # if the above fails (for any reason) just fallback to what
-            # we do by default and convert dx by itself.
-            dx = convert(dx)
-        return dx
-
-    @_preprocess_data()
-    @docstring.dedent_interpd
-    def bar(self, x, height, width=0.8, bottom=None, *, align="center",
-            **kwargs):
-        r"""
-        Make a bar plot.
-
-        The bars are positioned at *x* with the given *align*\ment. Their
-        dimensions are given by *width* and *height*. The vertical baseline
-        is *bottom* (default 0).
-
-        Each of *x*, *height*, *width*, and *bottom* may either be a scalar
-        applying to all bars, or it may be a sequence of length N providing a
-        separate value for each bar.
-
-        Parameters
-        ----------
-        x : sequence of scalars
-            The x coordinates of the bars. See also *align* for the
-            alignment of the bars to the coordinates.
-
-        height : scalar or sequence of scalars
-            The height(s) of the bars.
-
-        width : scalar or array-like, optional
-            The width(s) of the bars (default: 0.8).
-
-        bottom : scalar or array-like, optional
-            The y coordinate(s) of the bars bases (default: 0).
-
-        align : {'center', 'edge'}, optional, default: 'center'
-            Alignment of the bars to the *x* coordinates:
-
-            - 'center': Center the base on the *x* positions.
-            - 'edge': Align the left edges of the bars with the *x* positions.
-
-            To align the bars on the right edge pass a negative *width* and
-            ``align='edge'``.
-
-        Returns
-        -------
-        container : `.BarContainer`
-            Container with all the bars and optionally errorbars.
-
-        Other Parameters
-        ----------------
-        color : scalar or array-like, optional
-            The colors of the bar faces.
-
-        edgecolor : scalar or array-like, optional
-            The colors of the bar edges.
-
-        linewidth : scalar or array-like, optional
-            Width of the bar edge(s). If 0, don't draw edges.
-
-        tick_label : str or array-like, optional
-            The tick labels of the bars.
-            Default: None (Use default numeric labels.)
-
-        xerr, yerr : scalar or array-like of shape(N,) or shape(2, N), optional
-            If not *None*, add horizontal / vertical errorbars to the bar tips.
-            The values are +/- sizes relative to the data:
-
-            - scalar: symmetric +/- values for all bars
-            - shape(N,): symmetric +/- values for each bar
-            - shape(2, N): Separate - and + values for each bar. First row
-              contains the lower errors, the second row contains the upper
-              errors.
-            - *None*: No errorbar. (Default)
-
-            See :doc:`/gallery/statistics/errorbar_features`
-            for an example on the usage of ``xerr`` and ``yerr``.
-
-        ecolor : scalar or array-like, optional, default: 'black'
-            The line color of the errorbars.
-
-        capsize : scalar, optional
-           The length of the error bar caps in points.
-           Default: None, which will take the value from
-           :rc:`errorbar.capsize`.
-
-        error_kw : dict, optional
-            Dictionary of kwargs to be passed to the `~.Axes.errorbar`
-            method. Values of *ecolor* or *capsize* defined here take
-            precedence over the independent kwargs.
-
-        log : bool, optional, default: False
-            If *True*, set the y-axis to be log scale.
-
-        orientation : {'vertical',  'horizontal'}, optional
-            *This is for internal use only.* Please use `barh` for
-            horizontal bar plots. Default: 'vertical'.
-
-        See also
-        --------
-        barh: Plot a horizontal bar plot.
-
-        Notes
-        -----
-        The optional arguments *color*, *edgecolor*, *linewidth*,
-        *xerr*, and *yerr* can be either scalars or sequences of
-        length equal to the number of bars.  This enables you to use
-        bar as the basis for stacked bar charts, or candlestick plots.
-        Detail: *xerr* and *yerr* are passed directly to
-        :meth:`errorbar`, so they can also have shape 2xN for
-        independent specification of lower and upper errors.
-
-        Other optional kwargs:
-
-        %(Rectangle)s
-        """
-        kwargs = cbook.normalize_kwargs(kwargs, mpatches.Patch)
-        color = kwargs.pop('color', None)
-        if color is None:
-            color = self._get_patches_for_fill.get_next_color()
-        edgecolor = kwargs.pop('edgecolor', None)
-        linewidth = kwargs.pop('linewidth', None)
-
-        # Because xerr and yerr will be passed to errorbar, most dimension
-        # checking and processing will be left to the errorbar method.
-        xerr = kwargs.pop('xerr', None)
-        yerr = kwargs.pop('yerr', None)
-        error_kw = kwargs.pop('error_kw', {})
-        ezorder = error_kw.pop('zorder', None)
-        if ezorder is None:
-            ezorder = kwargs.get('zorder', None)
-            if ezorder is not None:
-                # If using the bar zorder, increment slightly to make sure
-                # errorbars are drawn on top of bars
-                ezorder += 0.01
-        error_kw.setdefault('zorder', ezorder)
-        ecolor = kwargs.pop('ecolor', 'k')
-        capsize = kwargs.pop('capsize', rcParams["errorbar.capsize"])
-        error_kw.setdefault('ecolor', ecolor)
-        error_kw.setdefault('capsize', capsize)
-
-        orientation = kwargs.pop('orientation', 'vertical')
-        cbook._check_in_list(['vertical', 'horizontal'],
-                             orientation=orientation)
-        log = kwargs.pop('log', False)
-        label = kwargs.pop('label', '')
-        tick_labels = kwargs.pop('tick_label', None)
-
-        y = bottom  # Matches barh call signature.
-        if orientation == 'vertical':
-            if y is None:
-                y = 0
-        elif orientation == 'horizontal':
-            if x is None:
-                x = 0
-
-        if orientation == 'vertical':
-            self._process_unit_info(xdata=x, ydata=height, kwargs=kwargs)
-            if log:
-                self.set_yscale('log', nonposy='clip')
-        elif orientation == 'horizontal':
-            self._process_unit_info(xdata=width, ydata=y, kwargs=kwargs)
-            if log:
-                self.set_xscale('log', nonposx='clip')
-
-        # lets do some conversions now since some types cannot be
-        # subtracted uniformly
-        if self.xaxis is not None:
-            x0 = x
-            x = np.asarray(self.convert_xunits(x))
-            width = self._convert_dx(width, x0, x, self.convert_xunits)
-            if xerr is not None:
-                xerr = self._convert_dx(xerr, x0, x, self.convert_xunits)
-        if self.yaxis is not None:
-            y0 = y
-            y = np.asarray(self.convert_yunits(y))
-            height = self._convert_dx(height, y0, y, self.convert_yunits)
-            if yerr is not None:
-                yerr = self._convert_dx(yerr, y0, y, self.convert_yunits)
-
-        x, height, width, y, linewidth = np.broadcast_arrays(
-            # Make args iterable too.
-            np.atleast_1d(x), height, width, y, linewidth)
-
-        # Now that units have been converted, set the tick locations.
-        if orientation == 'vertical':
-            tick_label_axis = self.xaxis
-            tick_label_position = x
-        elif orientation == 'horizontal':
-            tick_label_axis = self.yaxis
-            tick_label_position = y
-
-        linewidth = itertools.cycle(np.atleast_1d(linewidth))
-        color = itertools.chain(itertools.cycle(mcolors.to_rgba_array(color)),
-                                # Fallback if color == "none".
-                                itertools.repeat('none'))
-        if edgecolor is None:
-            edgecolor = itertools.repeat(None)
-        else:
-            edgecolor = itertools.chain(
-                itertools.cycle(mcolors.to_rgba_array(edgecolor)),
-                # Fallback if edgecolor == "none".
-                itertools.repeat('none'))
-
-        # We will now resolve the alignment and really have
-        # left, bottom, width, height vectors
-        cbook._check_in_list(['center', 'edge'], align=align)
-        if align == 'center':
-            if orientation == 'vertical':
-                try:
-                    left = x - width / 2
-                except TypeError as e:
-                    raise TypeError(f'the dtypes of parameters x ({x.dtype}) '
-                                    f'and width ({width.dtype}) '
-                                    f'are incompatible') from e
-                bottom = y
-            elif orientation == 'horizontal':
-                try:
-                    bottom = y - height / 2
-                except TypeError as e:
-                    raise TypeError(f'the dtypes of parameters y ({y.dtype}) '
-                                    f'and height ({height.dtype}) '
-                                    f'are incompatible') from e
-                left = x
-        elif align == 'edge':
-            left = x
-            bottom = y
-
-        patches = []
-        args = zip(left, bottom, width, height, color, edgecolor, linewidth)
-        for l, b, w, h, c, e, lw in args:
-            r = mpatches.Rectangle(
-                xy=(l, b), width=w, height=h,
-                facecolor=c,
-                edgecolor=e,
-                linewidth=lw,
-                label='_nolegend_',
-                )
-            r.update(kwargs)
-            r.get_path()._interpolation_steps = 100
-            if orientation == 'vertical':
-                r.sticky_edges.y.append(b)
-            elif orientation == 'horizontal':
-                r.sticky_edges.x.append(l)
-            self.add_patch(r)
-            patches.append(r)
-
-        if xerr is not None or yerr is not None:
-            if orientation == 'vertical':
-                # using list comps rather than arrays to preserve unit info
-                ex = [l + 0.5 * w for l, w in zip(left, width)]
-                ey = [b + h for b, h in zip(bottom, height)]
-
-            elif orientation == 'horizontal':
-                # using list comps rather than arrays to preserve unit info
-                ex = [l + w for l, w in zip(left, width)]
-                ey = [b + 0.5 * h for b, h in zip(bottom, height)]
-
-            error_kw.setdefault("label", '_nolegend_')
-
-            errorbar = self.errorbar(ex, ey,
-                                     yerr=yerr, xerr=xerr,
-                                     fmt='none', **error_kw)
-        else:
-            errorbar = None
-
-        self._request_autoscale_view()
-
-        bar_container = BarContainer(patches, errorbar, label=label)
-        self.add_container(bar_container)
-
-        if tick_labels is not None:
-            tick_labels = np.broadcast_to(tick_labels, len(patches))
-            tick_label_axis.set_ticks(tick_label_position)
-            tick_label_axis.set_ticklabels(tick_labels)
-
-        return bar_container
-
-    @docstring.dedent_interpd
-    def barh(self, y, width, height=0.8, left=None, *, align="center",
-             **kwargs):
-        r"""
-        Make a horizontal bar plot.
-
-        The bars are positioned at *y* with the given *align*\ment. Their
-        dimensions are given by *width* and *height*. The horizontal baseline
-        is *left* (default 0).
-
-        Each of *y*, *width*, *height*, and *left* may either be a scalar
-        applying to all bars, or it may be a sequence of length N providing a
-        separate value for each bar.
-
-        Parameters
-        ----------
-        y : scalar or array-like
-            The y coordinates of the bars. See also *align* for the
-            alignment of the bars to the coordinates.
-
-        width : scalar or array-like
-            The width(s) of the bars.
-
-        height : sequence of scalars, optional, default: 0.8
-            The heights of the bars.
-
-        left : sequence of scalars
-            The x coordinates of the left sides of the bars (default: 0).
-
-        align : {'center', 'edge'}, optional, default: 'center'
-            Alignment of the base to the *y* coordinates*:
-
-            - 'center': Center the bars on the *y* positions.
-            - 'edge': Align the bottom edges of the bars with the *y*
-              positions.
-
-            To align the bars on the top edge pass a negative *height* and
-            ``align='edge'``.
-
-        Returns
-        -------
-        container : `.BarContainer`
-            Container with all the bars and optionally errorbars.
-
-        Other Parameters
-        ----------------
-        color : scalar or array-like, optional
-            The colors of the bar faces.
-
-        edgecolor : scalar or array-like, optional
-            The colors of the bar edges.
-
-        linewidth : scalar or array-like, optional
-            Width of the bar edge(s). If 0, don't draw edges.
-
-        tick_label : str or array-like, optional
-            The tick labels of the bars.
-            Default: None (Use default numeric labels.)
-
-        xerr, yerr : scalar or array-like of shape(N,) or shape(2, N), optional
-            If not ``None``, add horizontal / vertical errorbars to the
-            bar tips. The values are +/- sizes relative to the data:
-
-            - scalar: symmetric +/- values for all bars
-            - shape(N,): symmetric +/- values for each bar
-            - shape(2, N): Separate - and + values for each bar. First row
-              contains the lower errors, the second row contains the upper
-              errors.
-            - *None*: No errorbar. (default)
-
-            See :doc:`/gallery/statistics/errorbar_features`
-            for an example on the usage of ``xerr`` and ``yerr``.
-
-        ecolor : scalar or array-like, optional, default: 'black'
-            The line color of the errorbars.
-
-        capsize : scalar, optional
-           The length of the error bar caps in points.
-           Default: None, which will take the value from
-           :rc:`errorbar.capsize`.
-
-        error_kw : dict, optional
-            Dictionary of kwargs to be passed to the `~.Axes.errorbar`
-            method. Values of *ecolor* or *capsize* defined here take
-            precedence over the independent kwargs.
-
-        log : bool, optional, default: False
-            If ``True``, set the x-axis to be log scale.
-
-        See also
-        --------
-        bar: Plot a vertical bar plot.
-
-        Notes
-        -----
-        The optional arguments *color*, *edgecolor*, *linewidth*,
-        *xerr*, and *yerr* can be either scalars or sequences of
-        length equal to the number of bars.  This enables you to use
-        bar as the basis for stacked bar charts, or candlestick plots.
-        Detail: *xerr* and *yerr* are passed directly to
-        :meth:`errorbar`, so they can also have shape 2xN for
-        independent specification of lower and upper errors.
-
-        Other optional kwargs:
-
-        %(Rectangle)s
-        """
-        kwargs.setdefault('orientation', 'horizontal')
-        patches = self.bar(x=left, height=height, width=width, bottom=y,
-                           align=align, **kwargs)
-        return patches
-
-    @_preprocess_data()
-    @docstring.dedent_interpd
-    def broken_barh(self, xranges, yrange, **kwargs):
-        """
-        Plot a horizontal sequence of rectangles.
-
-        A rectangle is drawn for each element of *xranges*. All rectangles
-        have the same vertical position and size defined by *yrange*.
-
-        This is a convenience function for instantiating a
-        `.BrokenBarHCollection`, adding it to the axes and autoscaling the
-        view.
-
-        Parameters
-        ----------
-        xranges : sequence of tuples (*xmin*, *xwidth*)
-            The x-positions and extends of the rectangles. For each tuple
-            (*xmin*, *xwidth*) a rectangle is drawn from *xmin* to *xmin* +
-            *xwidth*.
-        yrange : (*ymin*, *yheight*)
-            The y-position and extend for all the rectangles.
-
-        Other Parameters
-        ----------------
-        **kwargs : :class:`.BrokenBarHCollection` properties
-
-            Each *kwarg* can be either a single argument applying to all
-            rectangles, e.g.::
-
-                facecolors='black'
-
-            or a sequence of arguments over which is cycled, e.g.::
-
-                facecolors=('black', 'blue')
-
-            would create interleaving black and blue rectangles.
-
-            Supported keywords:
-
-            %(BrokenBarHCollection)s
-
-        Returns
-        -------
-        collection : A :class:`~.collections.BrokenBarHCollection`
-        """
-        # process the unit information
-        if len(xranges):
-            xdata = cbook.safe_first_element(xranges)
-        else:
-            xdata = None
-        if len(yrange):
-            ydata = cbook.safe_first_element(yrange)
-        else:
-            ydata = None
-        self._process_unit_info(xdata=xdata,
-                                ydata=ydata,
-                                kwargs=kwargs)
-        xranges_conv = []
-        for xr in xranges:
-            if len(xr) != 2:
-                raise ValueError('each range in xrange must be a sequence '
-                                 'with two elements (i.e. an Nx2 array)')
-            # convert the absolute values, not the x and dx...
-            x_conv = np.asarray(self.convert_xunits(xr[0]))
-            x1 = self._convert_dx(xr[1], xr[0], x_conv, self.convert_xunits)
-            xranges_conv.append((x_conv, x1))
-
-        yrange_conv = self.convert_yunits(yrange)
-
-        col = mcoll.BrokenBarHCollection(xranges_conv, yrange_conv, **kwargs)
-        self.add_collection(col, autolim=True)
-        self._request_autoscale_view()
-
-        return col
-
-    @_preprocess_data()
-    def stem(self, *args, linefmt=None, markerfmt=None, basefmt=None, bottom=0,
-             label=None, use_line_collection=False):
-        """
-        Create a stem plot.
-
-        A stem plot plots vertical lines at each *x* location from the baseline
-        to *y*, and places a marker there.
-
-        Call signature::
-
-          stem([x,] y, linefmt=None, markerfmt=None, basefmt=None)
-
-        The x-positions are optional. The formats may be provided either as
-        positional or as keyword-arguments.
-
-        Parameters
-        ----------
-        x : array-like, optional
-            The x-positions of the stems. Default: (0, 1, ..., len(y) - 1).
-
-        y : array-like
-            The y-values of the stem heads.
-
-        linefmt : str, optional
-            A string defining the properties of the vertical lines. Usually,
-            this will be a color or a color and a linestyle:
-
-            =========  =============
-            Character  Line Style
-            =========  =============
-            ``'-'``    solid line
-            ``'--'``   dashed line
-            ``'-.'``   dash-dot line
-            ``':'``    dotted line
-            =========  =============
-
-            Default: 'C0-', i.e. solid line with the first color of the color
-            cycle.
-
-            Note: While it is technically possible to specify valid formats
-            other than color or color and linestyle (e.g. 'rx' or '-.'), this
-            is beyond the intention of the method and will most likely not
-            result in a reasonable reasonable plot.
-
-        markerfmt : str, optional
-            A string defining the properties of the markers at the stem heads.
-            Default: 'C0o', i.e. filled circles with the first color of the
-            color cycle.
-
-        basefmt : str, optional
-            A format string defining the properties of the baseline.
-
-            Default: 'C3-' ('C2-' in classic mode).
-
-        bottom : float, optional, default: 0
-            The y-position of the baseline.
-
-        label : str, optional, default: None
-            The label to use for the stems in legends.
-
-        use_line_collection : bool, optional, default: False
-            If ``True``, store and plot the stem lines as a
-            `~.collections.LineCollection` instead of individual lines. This
-            significantly increases performance, and will become the default
-            option in Matplotlib 3.3. If ``False``, defaults to the old
-            behavior of using a list of `.Line2D` objects.
-
-
-        Returns
-        -------
-        container : :class:`~matplotlib.container.StemContainer`
-            The container may be treated like a tuple
-            (*markerline*, *stemlines*, *baseline*)
-
-
-        Notes
-        -----
-        .. seealso::
-            The MATLAB function
-            `stem <http://www.mathworks.com/help/techdoc/ref/stem.html>`_
-            which inspired this method.
-
-        """
-        if not 1 <= len(args) <= 5:
-            raise TypeError('stem expected between 1 and 5 positional '
-                            'arguments, got {}'.format(args))
-
-        if len(args) == 1:
-            y, = args
-            x = np.arange(len(y))
-            args = ()
-        else:
-            x, y, *args = args
-
-        self._process_unit_info(xdata=x, ydata=y)
-        x = self.convert_xunits(x)
-        y = self.convert_yunits(y)
-
-        # defaults for formats
-        if linefmt is None:
-            try:
-                # fallback to positional argument
-                linefmt = args[0]
-            except IndexError:
-                linecolor = 'C0'
-                linemarker = 'None'
-                linestyle = '-'
-            else:
-                linestyle, linemarker, linecolor = \
-                    _process_plot_format(linefmt)
-        else:
-            linestyle, linemarker, linecolor = _process_plot_format(linefmt)
-
-        if markerfmt is None:
-            try:
-                # fallback to positional argument
-                markerfmt = args[1]
-            except IndexError:
-                markercolor = 'C0'
-                markermarker = 'o'
-                markerstyle = 'None'
-            else:
-                markerstyle, markermarker, markercolor = \
-                    _process_plot_format(markerfmt)
-        else:
-            markerstyle, markermarker, markercolor = \
-                _process_plot_format(markerfmt)
-
-        if basefmt is None:
-            try:
-                # fallback to positional argument
-                basefmt = args[2]
-            except IndexError:
-                if rcParams['_internal.classic_mode']:
-                    basecolor = 'C2'
-                else:
-                    basecolor = 'C3'
-                basemarker = 'None'
-                basestyle = '-'
-            else:
-                basestyle, basemarker, basecolor = \
-                    _process_plot_format(basefmt)
-        else:
-            basestyle, basemarker, basecolor = _process_plot_format(basefmt)
-
-        # New behaviour in 3.1 is to use a LineCollection for the stemlines
-        if use_line_collection:
-            stemlines = [((xi, bottom), (xi, yi)) for xi, yi in zip(x, y)]
-            if linestyle is None:
-                linestyle = rcParams['lines.linestyle']
-            stemlines = mcoll.LineCollection(stemlines, linestyles=linestyle,
-                                             colors=linecolor,
-                                             label='_nolegend_')
-            self.add_collection(stemlines)
-        # Old behaviour is to plot each of the lines individually
-        else:
-            cbook._warn_external(
-                'In Matplotlib 3.3 individual lines on a stem plot will be '
-                'added as a LineCollection instead of individual lines. '
-                'This significantly improves the performance of a stem plot. '
-                'To remove this warning and switch to the new behaviour, '
-                'set the "use_line_collection" keyword argument to True.')
-            stemlines = []
-            for xi, yi in zip(x, y):
-                l, = self.plot([xi, xi], [bottom, yi],
-                               color=linecolor, linestyle=linestyle,
-                               marker=linemarker, label="_nolegend_")
-                stemlines.append(l)
-
-        markerline, = self.plot(x, y, color=markercolor, linestyle=markerstyle,
-                                marker=markermarker, label="_nolegend_")
-
-        baseline, = self.plot([np.min(x), np.max(x)], [bottom, bottom],
-                              color=basecolor, linestyle=basestyle,
-                              marker=basemarker, label="_nolegend_")
-
-        stem_container = StemContainer((markerline, stemlines, baseline),
-                                       label=label)
-        self.add_container(stem_container)
-        return stem_container
-
-    @_preprocess_data(replace_names=["x", "explode", "labels", "colors"])
-    def pie(self, x, explode=None, labels=None, colors=None,
-            autopct=None, pctdistance=0.6, shadow=False, labeldistance=1.1,
-            startangle=None, radius=None, counterclock=True,
-            wedgeprops=None, textprops=None, center=(0, 0),
-            frame=False, rotatelabels=False):
-        """
-        Plot a pie chart.
-
-        Make a pie chart of array *x*.  The fractional area of each wedge is
-        given by ``x/sum(x)``.  If ``sum(x) < 1``, then the values of *x* give
-        the fractional area directly and the array will not be normalized. The
-        resulting pie will have an empty wedge of size ``1 - sum(x)``.
-
-        The wedges are plotted counterclockwise, by default starting from the
-        x-axis.
-
-        Parameters
-        ----------
-        x : array-like
-            The wedge sizes.
-
-        explode : array-like, optional, default: None
-            If not *None*, is a ``len(x)`` array which specifies the fraction
-            of the radius with which to offset each wedge.
-
-        labels : list, optional, default: None
-            A sequence of strings providing the labels for each wedge
-
-        colors : array-like, optional, default: None
-            A sequence of matplotlib color args through which the pie chart
-            will cycle.  If *None*, will use the colors in the currently
-            active cycle.
-
-        autopct : None (default), str, or function, optional
-            If not *None*, is a string or function used to label the wedges
-            with their numeric value.  The label will be placed inside the
-            wedge.  If it is a format string, the label will be ``fmt%pct``.
-            If it is a function, it will be called.
-
-        pctdistance : float, optional, default: 0.6
-            The ratio between the center of each pie slice and the start of
-            the text generated by *autopct*.  Ignored if *autopct* is *None*.
-
-        shadow : bool, optional, default: False
-            Draw a shadow beneath the pie.
-
-        labeldistance : float or None, optional, default: 1.1
-            The radial distance at which the pie labels are drawn.
-            If set to ``None``, label are not drawn, but are stored for use in
-            ``legend()``
-
-        startangle : float, optional, default: None
-            If not *None*, rotates the start of the pie chart by *angle*
-            degrees counterclockwise from the x-axis.
-
-        radius : float, optional, default: None
-            The radius of the pie, if *radius* is *None* it will be set to 1.
-
-        counterclock : bool, optional, default: True
-            Specify fractions direction, clockwise or counterclockwise.
-
-        wedgeprops : dict, optional, default: None
-            Dict of arguments passed to the wedge objects making the pie.
-            For example, you can pass in ``wedgeprops = {'linewidth': 3}``
-            to set the width of the wedge border lines equal to 3.
-            For more details, look at the doc/arguments of the wedge object.
-            By default ``clip_on=False``.
-
-        textprops : dict, optional, default: None
-            Dict of arguments to pass to the text objects.
-
-        center :  list of float, optional, default: (0, 0)
-            Center position of the chart. Takes value (0, 0) or is a sequence
-            of 2 scalars.
-
-        frame : bool, optional, default: False
-            Plot axes frame with the chart if true.
-
-        rotatelabels : bool, optional, default: False
-            Rotate each label to the angle of the corresponding slice if true.
-
-        Returns
-        -------
-        patches : list
-            A sequence of :class:`matplotlib.patches.Wedge` instances
-
-        texts : list
-            A list of the label :class:`matplotlib.text.Text` instances.
-
-        autotexts : list
-            A list of :class:`~matplotlib.text.Text` instances for the numeric
-            labels. This will only be returned if the parameter *autopct* is
-            not *None*.
-
-        Notes
-        -----
-        The pie chart will probably look best if the figure and axes are
-        square, or the Axes aspect is equal.
-        This method sets the aspect ratio of the axis to "equal".
-        The axes aspect ratio can be controlled with `Axes.set_aspect`.
-        """
-        self.set_aspect('equal')
-        # The use of float32 is "historical", but can't be changed without
-        # regenerating the test baselines.
-        x = np.asarray(x, np.float32)
-        if x.ndim != 1 and x.squeeze().ndim <= 1:
-            cbook.warn_deprecated(
-                "3.1", message="Non-1D inputs to pie() are currently "
-                "squeeze()d, but this behavior is deprecated since %(since)s "
-                "and will be removed %(removal)s; pass a 1D array instead.")
-            x = np.atleast_1d(x.squeeze())
-
-        sx = x.sum()
-        if sx > 1:
-            x = x / sx
-
-        if labels is None:
-            labels = [''] * len(x)
-        if explode is None:
-            explode = [0] * len(x)
-        if len(x) != len(labels):
-            raise ValueError("'label' must be of length 'x'")
-        if len(x) != len(explode):
-            raise ValueError("'explode' must be of length 'x'")
-        if colors is None:
-            get_next_color = self._get_patches_for_fill.get_next_color
-        else:
-            color_cycle = itertools.cycle(colors)
-
-            def get_next_color():
-                return next(color_cycle)
-
-        if radius is None:
-            radius = 1
-
-        # Starting theta1 is the start fraction of the circle
-        if startangle is None:
-            theta1 = 0
-        else:
-            theta1 = startangle / 360.0
-
-        # set default values in wedge_prop
-        if wedgeprops is None:
-            wedgeprops = {}
-        wedgeprops.setdefault('clip_on', False)
-
-        if textprops is None:
-            textprops = {}
-        textprops.setdefault('clip_on', False)
-
-        texts = []
-        slices = []
-        autotexts = []
-
-        for frac, label, expl in zip(x, labels, explode):
-            x, y = center
-            theta2 = (theta1 + frac) if counterclock else (theta1 - frac)
-            thetam = 2 * np.pi * 0.5 * (theta1 + theta2)
-            x += expl * math.cos(thetam)
-            y += expl * math.sin(thetam)
-
-            w = mpatches.Wedge((x, y), radius, 360. * min(theta1, theta2),
-                               360. * max(theta1, theta2),
-                               facecolor=get_next_color(),
-                               **wedgeprops)
-            slices.append(w)
-            self.add_patch(w)
-            w.set_label(label)
-
-            if shadow:
-                # make sure to add a shadow after the call to
-                # add_patch so the figure and transform props will be
-                # set
-                shad = mpatches.Shadow(w, -0.02, -0.02)
-                shad.set_zorder(0.9 * w.get_zorder())
-                shad.set_label('_nolegend_')
-                self.add_patch(shad)
-
-            if labeldistance is not None:
-                xt = x + labeldistance * radius * math.cos(thetam)
-                yt = y + labeldistance * radius * math.sin(thetam)
-                label_alignment_h = 'left' if xt > 0 else 'right'
-                label_alignment_v = 'center'
-                label_rotation = 'horizontal'
-                if rotatelabels:
-                    label_alignment_v = 'bottom' if yt > 0 else 'top'
-                    label_rotation = (np.rad2deg(thetam)
-                                      + (0 if xt > 0 else 180))
-                props = dict(horizontalalignment=label_alignment_h,
-                             verticalalignment=label_alignment_v,
-                             rotation=label_rotation,
-                             size=rcParams['xtick.labelsize'])
-                props.update(textprops)
-
-                t = self.text(xt, yt, label, **props)
-
-                texts.append(t)
-
-            if autopct is not None:
-                xt = x + pctdistance * radius * math.cos(thetam)
-                yt = y + pctdistance * radius * math.sin(thetam)
-                if isinstance(autopct, str):
-                    s = autopct % (100. * frac)
-                elif callable(autopct):
-                    s = autopct(100. * frac)
-                else:
-                    raise TypeError(
-                        'autopct must be callable or a format string')
-
-                props = dict(horizontalalignment='center',
-                             verticalalignment='center')
-                props.update(textprops)
-                t = self.text(xt, yt, s, **props)
-
-                autotexts.append(t)
-
-            theta1 = theta2
-
-        if not frame:
-            self.set_frame_on(False)
-
-            self.set_xlim((-1.25 + center[0],
-                           1.25 + center[0]))
-            self.set_ylim((-1.25 + center[1],
-                           1.25 + center[1]))
-            self.set_xticks([])
-            self.set_yticks([])
-
-        if autopct is None:
-            return slices, texts
-        else:
-            return slices, texts, autotexts
-
-    @_preprocess_data(replace_names=["x", "y", "xerr", "yerr"],
-                      label_namer="y")
-    @docstring.dedent_interpd
-    def errorbar(self, x, y, yerr=None, xerr=None,
-                 fmt='', ecolor=None, elinewidth=None, capsize=None,
-                 barsabove=False, lolims=False, uplims=False,
-                 xlolims=False, xuplims=False, errorevery=1, capthick=None,
-                 **kwargs):
-        """
-        Plot y versus x as lines and/or markers with attached errorbars.
-
-        *x*, *y* define the data locations, *xerr*, *yerr* define the errorbar
-        sizes. By default, this draws the data markers/lines as well the
-        errorbars. Use fmt='none' to draw errorbars without any data markers.
-
-        Parameters
-        ----------
-        x, y : scalar or array-like
-            The data positions.
-
-        xerr, yerr : scalar or array-like, shape(N,) or shape(2, N), optional
-            The errorbar sizes:
-
-            - scalar: Symmetric +/- values for all data points.
-            - shape(N,): Symmetric +/-values for each data point.
-            - shape(2, N): Separate - and + values for each bar. First row
-              contains the lower errors, the second row contains the upper
-              errors.
-            - *None*: No errorbar.
-
-            Note that all error arrays should have *positive* values.
-
-            See :doc:`/gallery/statistics/errorbar_features`
-            for an example on the usage of ``xerr`` and ``yerr``.
-
-        fmt : str, optional, default: ''
-            The format for the data points / data lines. See `.plot` for
-            details.
-
-            Use 'none' (case insensitive) to plot errorbars without any data
-            markers.
-
-        ecolor : color, optional, default: None
-            The color of the errorbar lines.  If None, use the color of the
-            line connecting the markers.
-
-        elinewidth : scalar, optional, default: None
-            The linewidth of the errorbar lines. If None, the linewidth of
-            the current style is used.
-
-        capsize : scalar, optional, default: None
-            The length of the error bar caps in points. If None, it will take
-            the value from :rc:`errorbar.capsize`.
-
-        capthick : scalar, optional, default: None
-            An alias to the keyword argument *markeredgewidth* (a.k.a. *mew*).
-            This setting is a more sensible name for the property that
-            controls the thickness of the error bar cap in points. For
-            backwards compatibility, if *mew* or *markeredgewidth* are given,
-            then they will over-ride *capthick*. This may change in future
-            releases.
-
-        barsabove : bool, optional, default: False
-            If True, will plot the errorbars above the plot
-            symbols. Default is below.
-
-        lolims, uplims, xlolims, xuplims : bool, optional, default: False
-            These arguments can be used to indicate that a value gives only
-            upper/lower limits. In that case a caret symbol is used to
-            indicate this. *lims*-arguments may be of the same type as *xerr*
-            and *yerr*.  To use limits with inverted axes, :meth:`set_xlim`
-            or :meth:`set_ylim` must be called before :meth:`errorbar`.
-
-        errorevery : int or (int, int), optional, default: 1
-            draws error bars on a subset of the data. *errorevery* =N draws
-            error bars on the points (x[::N], y[::N]).
-            *errorevery* =(start, N) draws error bars on the points
-            (x[start::N], y[start::N]). e.g. errorevery=(6, 3)
-            adds error bars to the data at (x[6], x[9], x[12], x[15], ...).
-            Used to avoid overlapping error bars when two series share x-axis
-            values.
-
-        Returns
-        -------
-        container : :class:`~.container.ErrorbarContainer`
-            The container contains:
-
-            - plotline: `.Line2D` instance of x, y plot markers and/or line.
-            - caplines: A tuple of `.Line2D` instances of the error bar caps.
-            - barlinecols: A tuple of
-              :class:`~matplotlib.collections.LineCollection` with the
-              horizontal and vertical error ranges.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            All other keyword arguments are passed on to the plot
-            command for the markers. For example, this code makes big red
-            squares with thick green edges::
-
-                x, y, yerr = rand(3, 10)
-                errorbar(x, y, yerr, marker='s', mfc='red',
-                         mec='green', ms=20, mew=4)
-
-            where *mfc*, *mec*, *ms* and *mew* are aliases for the longer
-            property names, *markerfacecolor*, *markeredgecolor*, *markersize*
-            and *markeredgewidth*.
-
-            Valid kwargs for the marker properties are `.Lines2D` properties:
-
-            %(_Line2D_docstr)s
-        """
-        kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-        # anything that comes in as 'None', drop so the default thing
-        # happens down stream
-        kwargs = {k: v for k, v in kwargs.items() if v is not None}
-        kwargs.setdefault('zorder', 2)
-
-        try:
-            offset, errorevery = errorevery
-        except TypeError:
-            offset = 0
-
-        if errorevery < 1 or int(errorevery) != errorevery:
-            raise ValueError(
-                'errorevery must be positive integer or tuple of integers')
-        if int(offset) != offset:
-            raise ValueError("errorevery's starting index must be an integer")
-
-        self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
-
-        plot_line = (fmt.lower() != 'none')
-        label = kwargs.pop("label", None)
-
-        if fmt == '':
-            fmt_style_kwargs = {}
-        else:
-            fmt_style_kwargs = {k: v for k, v in
-                                zip(('linestyle', 'marker', 'color'),
-                                    _process_plot_format(fmt))
-                                if v is not None}
-        if fmt == 'none':
-            # Remove alpha=0 color that _process_plot_format returns
-            fmt_style_kwargs.pop('color')
-
-        if ('color' in kwargs or 'color' in fmt_style_kwargs or
-                ecolor is not None):
-            base_style = {}
-            if 'color' in kwargs:
-                base_style['color'] = kwargs.pop('color')
-        else:
-            base_style = next(self._get_lines.prop_cycler)
-
-        base_style['label'] = '_nolegend_'
-        base_style.update(fmt_style_kwargs)
-        if 'color' not in base_style:
-            base_style['color'] = 'C0'
-        if ecolor is None:
-            ecolor = base_style['color']
-        # make sure all the args are iterable; use lists not arrays to
-        # preserve units
-        if not np.iterable(x):
-            x = [x]
-
-        if not np.iterable(y):
-            y = [y]
-
-        if xerr is not None:
-            if not np.iterable(xerr):
-                xerr = [xerr] * len(x)
-
-        if yerr is not None:
-            if not np.iterable(yerr):
-                yerr = [yerr] * len(y)
-
-        # make the style dict for the 'normal' plot line
-        plot_line_style = {
-            **base_style,
-            **kwargs,
-            'zorder': (kwargs['zorder'] - .1 if barsabove else
-                       kwargs['zorder'] + .1),
-        }
-
-        # make the style dict for the line collections (the bars)
-        eb_lines_style = dict(base_style)
-        eb_lines_style.pop('marker', None)
-        eb_lines_style.pop('linestyle', None)
-        eb_lines_style['color'] = ecolor
-
-        if elinewidth:
-            eb_lines_style['linewidth'] = elinewidth
-        elif 'linewidth' in kwargs:
-            eb_lines_style['linewidth'] = kwargs['linewidth']
-
-        for key in ('transform', 'alpha', 'zorder', 'rasterized'):
-            if key in kwargs:
-                eb_lines_style[key] = kwargs[key]
-
-        # set up cap style dictionary
-        eb_cap_style = dict(base_style)
-        # eject any marker information from format string
-        eb_cap_style.pop('marker', None)
-        eb_lines_style.pop('markerfacecolor', None)
-        eb_lines_style.pop('markeredgewidth', None)
-        eb_lines_style.pop('markeredgecolor', None)
-        eb_cap_style.pop('ls', None)
-        eb_cap_style['linestyle'] = 'none'
-        if capsize is None:
-            capsize = rcParams["errorbar.capsize"]
-        if capsize > 0:
-            eb_cap_style['markersize'] = 2. * capsize
-        if capthick is not None:
-            eb_cap_style['markeredgewidth'] = capthick
-
-        # For backwards-compat, allow explicit setting of
-        # 'markeredgewidth' to over-ride capthick.
-        for key in ('markeredgewidth', 'transform', 'alpha',
-                    'zorder', 'rasterized'):
-            if key in kwargs:
-                eb_cap_style[key] = kwargs[key]
-        eb_cap_style['color'] = ecolor
-
-        data_line = None
-        if plot_line:
-            data_line = mlines.Line2D(x, y, **plot_line_style)
-            self.add_line(data_line)
-
-        barcols = []
-        caplines = []
-
-        # arrays fine here, they are booleans and hence not units
-        lolims = np.broadcast_to(lolims, len(x)).astype(bool)
-        uplims = np.broadcast_to(uplims, len(x)).astype(bool)
-        xlolims = np.broadcast_to(xlolims, len(x)).astype(bool)
-        xuplims = np.broadcast_to(xuplims, len(x)).astype(bool)
-
-        everymask = np.zeros(len(x), bool)
-        everymask[offset::errorevery] = True
-
-        def xywhere(xs, ys, mask):
-            """
-            return xs[mask], ys[mask] where mask is True but xs and
-            ys are not arrays
-            """
-            assert len(xs) == len(ys)
-            assert len(xs) == len(mask)
-            xs = [thisx for thisx, b in zip(xs, mask) if b]
-            ys = [thisy for thisy, b in zip(ys, mask) if b]
-            return xs, ys
-
-        def extract_err(err, data):
-            """
-            Private function to parse *err* and subtract/add it to *data*.
-
-            Both *err* and *data* are already iterables at this point.
-            """
-            try:  # Asymmetric error: pair of 1D iterables.
-                a, b = err
-                iter(a)
-                iter(b)
-            except (TypeError, ValueError):
-                a = b = err  # Symmetric error: 1D iterable.
-            # This could just be `np.ndim(a) > 1 and np.ndim(b) > 1`, except
-            # for the (undocumented, but tested) support for (n, 1) arrays.
-            a_sh = np.shape(a)
-            b_sh = np.shape(b)
-            if (len(a_sh) > 2 or (len(a_sh) == 2 and a_sh[1] != 1)
-                    or len(b_sh) > 2 or (len(b_sh) == 2 and b_sh[1] != 1)):
-                raise ValueError(
-                    "err must be a scalar or a 1D or (2, n) array-like")
-            if len(a_sh) == 2 or len(b_sh) == 2:
-                cbook.warn_deprecated(
-                    "3.1", message="Support for passing a (n, 1)-shaped error "
-                    "array to errorbar() is deprecated since Matplotlib "
-                    "%(since)s and will be removed %(removal)s; pass a 1D "
-                    "array instead.")
-            # Using list comprehensions rather than arrays to preserve units.
-            for e in [a, b]:
-                if len(data) != len(e):
-                    raise ValueError(
-                        f"The lengths of the data ({len(data)}) and the "
-                        f"error {len(e)} do not match")
-            low = [v - e for v, e in zip(data, a)]
-            high = [v + e for v, e in zip(data, b)]
-            return low, high
-
-        if xerr is not None:
-            left, right = extract_err(xerr, x)
-            # select points without upper/lower limits in x and
-            # draw normal errorbars for these points
-            noxlims = ~(xlolims | xuplims)
-            if noxlims.any() or len(noxlims) == 0:
-                yo, _ = xywhere(y, right, noxlims & everymask)
-                lo, ro = xywhere(left, right, noxlims & everymask)
-                barcols.append(self.hlines(yo, lo, ro, **eb_lines_style))
-                if capsize > 0:
-                    caplines.append(mlines.Line2D(lo, yo, marker='|',
-                                                  **eb_cap_style))
-                    caplines.append(mlines.Line2D(ro, yo, marker='|',
-                                                  **eb_cap_style))
-
-            if xlolims.any():
-                yo, _ = xywhere(y, right, xlolims & everymask)
-                lo, ro = xywhere(x, right, xlolims & everymask)
-                barcols.append(self.hlines(yo, lo, ro, **eb_lines_style))
-                rightup, yup = xywhere(right, y, xlolims & everymask)
-                if self.xaxis_inverted():
-                    marker = mlines.CARETLEFTBASE
-                else:
-                    marker = mlines.CARETRIGHTBASE
-                caplines.append(
-                    mlines.Line2D(rightup, yup, ls='None', marker=marker,
-                                  **eb_cap_style))
-                if capsize > 0:
-                    xlo, ylo = xywhere(x, y, xlolims & everymask)
-                    caplines.append(mlines.Line2D(xlo, ylo, marker='|',
-                                                  **eb_cap_style))
-
-            if xuplims.any():
-                yo, _ = xywhere(y, right, xuplims & everymask)
-                lo, ro = xywhere(left, x, xuplims & everymask)
-                barcols.append(self.hlines(yo, lo, ro, **eb_lines_style))
-                leftlo, ylo = xywhere(left, y, xuplims & everymask)
-                if self.xaxis_inverted():
-                    marker = mlines.CARETRIGHTBASE
-                else:
-                    marker = mlines.CARETLEFTBASE
-                caplines.append(
-                    mlines.Line2D(leftlo, ylo, ls='None', marker=marker,
-                                  **eb_cap_style))
-                if capsize > 0:
-                    xup, yup = xywhere(x, y, xuplims & everymask)
-                    caplines.append(mlines.Line2D(xup, yup, marker='|',
-                                                  **eb_cap_style))
-
-        if yerr is not None:
-            lower, upper = extract_err(yerr, y)
-            # select points without upper/lower limits in y and
-            # draw normal errorbars for these points
-            noylims = ~(lolims | uplims)
-            if noylims.any() or len(noylims) == 0:
-                xo, _ = xywhere(x, lower, noylims & everymask)
-                lo, uo = xywhere(lower, upper, noylims & everymask)
-                barcols.append(self.vlines(xo, lo, uo, **eb_lines_style))
-                if capsize > 0:
-                    caplines.append(mlines.Line2D(xo, lo, marker='_',
-                                                  **eb_cap_style))
-                    caplines.append(mlines.Line2D(xo, uo, marker='_',
-                                                  **eb_cap_style))
-
-            if lolims.any():
-                xo, _ = xywhere(x, lower, lolims & everymask)
-                lo, uo = xywhere(y, upper, lolims & everymask)
-                barcols.append(self.vlines(xo, lo, uo, **eb_lines_style))
-                xup, upperup = xywhere(x, upper, lolims & everymask)
-                if self.yaxis_inverted():
-                    marker = mlines.CARETDOWNBASE
-                else:
-                    marker = mlines.CARETUPBASE
-                caplines.append(
-                    mlines.Line2D(xup, upperup, ls='None', marker=marker,
-                                  **eb_cap_style))
-                if capsize > 0:
-                    xlo, ylo = xywhere(x, y, lolims & everymask)
-                    caplines.append(mlines.Line2D(xlo, ylo, marker='_',
-                                                  **eb_cap_style))
-
-            if uplims.any():
-                xo, _ = xywhere(x, lower, uplims & everymask)
-                lo, uo = xywhere(lower, y, uplims & everymask)
-                barcols.append(self.vlines(xo, lo, uo, **eb_lines_style))
-                xlo, lowerlo = xywhere(x, lower, uplims & everymask)
-                if self.yaxis_inverted():
-                    marker = mlines.CARETUPBASE
-                else:
-                    marker = mlines.CARETDOWNBASE
-                caplines.append(
-                    mlines.Line2D(xlo, lowerlo, ls='None', marker=marker,
-                                  **eb_cap_style))
-                if capsize > 0:
-                    xup, yup = xywhere(x, y, uplims & everymask)
-                    caplines.append(mlines.Line2D(xup, yup, marker='_',
-                                                  **eb_cap_style))
-        for l in caplines:
-            self.add_line(l)
-
-        self._request_autoscale_view()
-        errorbar_container = ErrorbarContainer((data_line, tuple(caplines),
-                                                tuple(barcols)),
-                                               has_xerr=(xerr is not None),
-                                               has_yerr=(yerr is not None),
-                                               label=label)
-        self.containers.append(errorbar_container)
-
-        return errorbar_container  # (l0, caplines, barcols)
-
-    @cbook._rename_parameter("3.1", "manage_xticks", "manage_ticks")
-    @_preprocess_data()
-    def boxplot(self, x, notch=None, sym=None, vert=None, whis=None,
-                positions=None, widths=None, patch_artist=None,
-                bootstrap=None, usermedians=None, conf_intervals=None,
-                meanline=None, showmeans=None, showcaps=None,
-                showbox=None, showfliers=None, boxprops=None,
-                labels=None, flierprops=None, medianprops=None,
-                meanprops=None, capprops=None, whiskerprops=None,
-                manage_ticks=True, autorange=False, zorder=None):
-        """
-        Make a box and whisker plot.
-
-        Make a box and whisker plot for each column of ``x`` or each
-        vector in sequence ``x``.  The box extends from the lower to
-        upper quartile values of the data, with a line at the median.
-        The whiskers extend from the box to show the range of the
-        data.  Flier points are those past the end of the whiskers.
-
-        Parameters
-        ----------
-        x : Array or a sequence of vectors.
-            The input data.
-
-        notch : bool, optional (False)
-            If `True`, will produce a notched box plot. Otherwise, a
-            rectangular boxplot is produced. The notches represent the
-            confidence interval (CI) around the median. See the entry
-            for the ``bootstrap`` parameter for information regarding
-            how the locations of the notches are computed.
-
-            .. note::
-
-                In cases where the values of the CI are less than the
-                lower quartile or greater than the upper quartile, the
-                notches will extend beyond the box, giving it a
-                distinctive "flipped" appearance. This is expected
-                behavior and consistent with other statistical
-                visualization packages.
-
-        sym : str, optional
-            The default symbol for flier points. Enter an empty string
-            ('') if you don't want to show fliers. If `None`, then the
-            fliers default to 'b+'  If you want more control use the
-            flierprops kwarg.
-
-        vert : bool, optional (True)
-            If `True` (default), makes the boxes vertical. If `False`,
-            everything is drawn horizontally.
-
-        whis : float or (float, float) (default = 1.5)
-            The position of the whiskers.
-
-            If a float, the lower whisker is at the lowest datum above
-            ``Q1 - whis*(Q3-Q1)``, and the upper whisker at the highest datum
-            below ``Q3 + whis*(Q3-Q1)``, where Q1 and Q3 are the first and
-            third quartiles.  The default value of ``whis = 1.5`` corresponds
-            to Tukey's original definition of boxplots.
-
-            If a pair of floats, they indicate the percentiles at which to
-            draw the whiskers (e.g., (5, 95)).  In particular, setting this to
-            (0, 100) results in whiskers covering the whole range of the data.
-            "range" is a deprecated synonym for (0, 100).
-
-            In the edge case where ``Q1 == Q3``, *whis* is automatically set
-            to (0, 100) (cover the whole range of the data) if *autorange* is
-            True.
-
-            Beyond the whiskers, data are considered outliers and are plotted
-            as individual points.
-
-        bootstrap : int, optional
-            Specifies whether to bootstrap the confidence intervals
-            around the median for notched boxplots. If ``bootstrap`` is
-            None, no bootstrapping is performed, and notches are
-            calculated using a Gaussian-based asymptotic approximation
-            (see McGill, R., Tukey, J.W., and Larsen, W.A., 1978, and
-            Kendall and Stuart, 1967). Otherwise, bootstrap specifies
-            the number of times to bootstrap the median to determine its
-            95% confidence intervals. Values between 1000 and 10000 are
-            recommended.
-
-        usermedians : array-like, optional
-            An array or sequence whose first dimension (or length) is
-            compatible with ``x``. This overrides the medians computed
-            by matplotlib for each element of ``usermedians`` that is not
-            `None`. When an element of ``usermedians`` is None, the median
-            will be computed by matplotlib as normal.
-
-        conf_intervals : array-like, optional
-            Array or sequence whose first dimension (or length) is
-            compatible with ``x`` and whose second dimension is 2. When
-            the an element of ``conf_intervals`` is not None, the
-            notch locations computed by matplotlib are overridden
-            (provided ``notch`` is `True`). When an element of
-            ``conf_intervals`` is `None`, the notches are computed by the
-            method specified by the other kwargs (e.g., ``bootstrap``).
-
-        positions : array-like, optional
-            Sets the positions of the boxes. The ticks and limits are
-            automatically set to match the positions. Defaults to
-            `range(1, N+1)` where N is the number of boxes to be drawn.
-
-        widths : scalar or array-like
-            Sets the width of each box either with a scalar or a
-            sequence. The default is 0.5, or ``0.15*(distance between
-            extreme positions)``, if that is smaller.
-
-        patch_artist : bool, optional (False)
-            If `False` produces boxes with the Line2D artist. Otherwise,
-            boxes and drawn with Patch artists.
-
-        labels : sequence, optional
-            Labels for each dataset. Length must be compatible with
-            dimensions of ``x``.
-
-        manage_ticks : bool, optional (True)
-            If True, the tick locations and labels will be adjusted to match
-            the boxplot positions.
-
-        autorange : bool, optional (False)
-            When `True` and the data are distributed such that the 25th and
-            75th percentiles are equal, ``whis`` is set to (0, 100) such
-            that the whisker ends are at the minimum and maximum of the data.
-
-        meanline : bool, optional (False)
-            If `True` (and ``showmeans`` is `True`), will try to render
-            the mean as a line spanning the full width of the box
-            according to ``meanprops`` (see below). Not recommended if
-            ``shownotches`` is also True. Otherwise, means will be shown
-            as points.
-
-        zorder : scalar, optional (None)
-            Sets the zorder of the boxplot.
-
-        Other Parameters
-        ----------------
-        showcaps : bool, optional (True)
-            Show the caps on the ends of whiskers.
-        showbox : bool, optional (True)
-            Show the central box.
-        showfliers : bool, optional (True)
-            Show the outliers beyond the caps.
-        showmeans : bool, optional (False)
-            Show the arithmetic means.
-        capprops : dict, optional (None)
-            Specifies the style of the caps.
-        boxprops : dict, optional (None)
-            Specifies the style of the box.
-        whiskerprops : dict, optional (None)
-            Specifies the style of the whiskers.
-        flierprops : dict, optional (None)
-            Specifies the style of the fliers.
-        medianprops : dict, optional (None)
-            Specifies the style of the median.
-        meanprops : dict, optional (None)
-            Specifies the style of the mean.
-
-        Returns
-        -------
-        result : dict
-          A dictionary mapping each component of the boxplot to a list
-          of the `.Line2D` instances created. That dictionary has the
-          following keys (assuming vertical boxplots):
-
-          - ``boxes``: the main body of the boxplot showing the
-            quartiles and the median's confidence intervals if
-            enabled.
-
-          - ``medians``: horizontal lines at the median of each box.
-
-          - ``whiskers``: the vertical lines extending to the most
-            extreme, non-outlier data points.
-
-          - ``caps``: the horizontal lines at the ends of the
-            whiskers.
-
-          - ``fliers``: points representing data that extend beyond
-            the whiskers (fliers).
-
-          - ``means``: points or lines representing the means.
-
-        """
-
-        # Missing arguments default to rcParams.
-        if whis is None:
-            whis = rcParams['boxplot.whiskers']
-        if bootstrap is None:
-            bootstrap = rcParams['boxplot.bootstrap']
-
-        bxpstats = cbook.boxplot_stats(x, whis=whis, bootstrap=bootstrap,
-                                       labels=labels, autorange=autorange)
-        if notch is None:
-            notch = rcParams['boxplot.notch']
-        if vert is None:
-            vert = rcParams['boxplot.vertical']
-        if patch_artist is None:
-            patch_artist = rcParams['boxplot.patchartist']
-        if meanline is None:
-            meanline = rcParams['boxplot.meanline']
-        if showmeans is None:
-            showmeans = rcParams['boxplot.showmeans']
-        if showcaps is None:
-            showcaps = rcParams['boxplot.showcaps']
-        if showbox is None:
-            showbox = rcParams['boxplot.showbox']
-        if showfliers is None:
-            showfliers = rcParams['boxplot.showfliers']
-
-        if boxprops is None:
-            boxprops = {}
-        if whiskerprops is None:
-            whiskerprops = {}
-        if capprops is None:
-            capprops = {}
-        if medianprops is None:
-            medianprops = {}
-        if meanprops is None:
-            meanprops = {}
-        if flierprops is None:
-            flierprops = {}
-
-        if patch_artist:
-            boxprops['linestyle'] = 'solid'  # Not consistent with bxp.
-            if 'color' in boxprops:
-                boxprops['edgecolor'] = boxprops.pop('color')
-
-        # if non-default sym value, put it into the flier dictionary
-        # the logic for providing the default symbol ('b+') now lives
-        # in bxp in the initial value of final_flierprops
-        # handle all of the *sym* related logic here so we only have to pass
-        # on the flierprops dict.
-        if sym is not None:
-            # no-flier case, which should really be done with
-            # 'showfliers=False' but none-the-less deal with it to keep back
-            # compatibility
-            if sym == '':
-                # blow away existing dict and make one for invisible markers
-                flierprops = dict(linestyle='none', marker='', color='none')
-                # turn the fliers off just to be safe
-                showfliers = False
-            # now process the symbol string
-            else:
-                # process the symbol string
-                # discarded linestyle
-                _, marker, color = _process_plot_format(sym)
-                # if we have a marker, use it
-                if marker is not None:
-                    flierprops['marker'] = marker
-                # if we have a color, use it
-                if color is not None:
-                    # assume that if color is passed in the user want
-                    # filled symbol, if the users want more control use
-                    # flierprops
-                    flierprops['color'] = color
-                    flierprops['markerfacecolor'] = color
-                    flierprops['markeredgecolor'] = color
-
-        # replace medians if necessary:
-        if usermedians is not None:
-            if (len(np.ravel(usermedians)) != len(bxpstats) or
-                    np.shape(usermedians)[0] != len(bxpstats)):
-                raise ValueError('usermedians length not compatible with x')
-            else:
-                # reassign medians as necessary
-                for stats, med in zip(bxpstats, usermedians):
-                    if med is not None:
-                        stats['med'] = med
-
-        if conf_intervals is not None:
-            if np.shape(conf_intervals)[0] != len(bxpstats):
-                err_mess = 'conf_intervals length not compatible with x'
-                raise ValueError(err_mess)
-            else:
-                for stats, ci in zip(bxpstats, conf_intervals):
-                    if ci is not None:
-                        if len(ci) != 2:
-                            raise ValueError('each confidence interval must '
-                                             'have two values')
-                        else:
-                            if ci[0] is not None:
-                                stats['cilo'] = ci[0]
-                            if ci[1] is not None:
-                                stats['cihi'] = ci[1]
-
-        artists = self.bxp(bxpstats, positions=positions, widths=widths,
-                           vert=vert, patch_artist=patch_artist,
-                           shownotches=notch, showmeans=showmeans,
-                           showcaps=showcaps, showbox=showbox,
-                           boxprops=boxprops, flierprops=flierprops,
-                           medianprops=medianprops, meanprops=meanprops,
-                           meanline=meanline, showfliers=showfliers,
-                           capprops=capprops, whiskerprops=whiskerprops,
-                           manage_ticks=manage_ticks, zorder=zorder)
-        return artists
-
-    @cbook._rename_parameter("3.1", "manage_xticks", "manage_ticks")
-    def bxp(self, bxpstats, positions=None, widths=None, vert=True,
-            patch_artist=False, shownotches=False, showmeans=False,
-            showcaps=True, showbox=True, showfliers=True,
-            boxprops=None, whiskerprops=None, flierprops=None,
-            medianprops=None, capprops=None, meanprops=None,
-            meanline=False, manage_ticks=True, zorder=None):
-        """
-        Drawing function for box and whisker plots.
-
-        Make a box and whisker plot for each column of *x* or each
-        vector in sequence *x*.  The box extends from the lower to
-        upper quartile values of the data, with a line at the median.
-        The whiskers extend from the box to show the range of the
-        data.  Flier points are those past the end of the whiskers.
-
-        Parameters
-        ----------
-        bxpstats : list of dicts
-          A list of dictionaries containing stats for each boxplot.
-          Required keys are:
-
-          - ``med``: The median (scalar float).
-
-          - ``q1``: The first quartile (25th percentile) (scalar
-            float).
-
-          - ``q3``: The third quartile (75th percentile) (scalar
-            float).
-
-          - ``whislo``: Lower bound of the lower whisker (scalar
-            float).
-
-          - ``whishi``: Upper bound of the upper whisker (scalar
-            float).
-
-          Optional keys are:
-
-          - ``mean``: The mean (scalar float). Needed if
-            ``showmeans=True``.
-
-          - ``fliers``: Data beyond the whiskers (sequence of floats).
-            Needed if ``showfliers=True``.
-
-          - ``cilo`` & ``cihi``: Lower and upper confidence intervals
-            about the median. Needed if ``shownotches=True``.
-
-          - ``label``: Name of the dataset (string). If available,
-            this will be used a tick label for the boxplot
-
-        positions : array-like, default = [1, 2, ..., n]
-          Sets the positions of the boxes. The ticks and limits
-          are automatically set to match the positions.
-
-        widths : array-like, default = None
-          Either a scalar or a vector and sets the width of each
-          box. The default is ``0.15*(distance between extreme
-          positions)``, clipped to no less than 0.15 and no more than
-          0.5.
-
-        vert : bool, default = True
-          If `True` (default), makes the boxes vertical.  If `False`,
-          makes horizontal boxes.
-
-        patch_artist : bool, default = False
-          If `False` produces boxes with the `.Line2D` artist.
-          If `True` produces boxes with the `~matplotlib.patches.Patch` artist.
-
-        shownotches : bool, default = False
-          If `False` (default), produces a rectangular box plot.
-          If `True`, will produce a notched box plot
-
-        showmeans : bool, default = False
-          If `True`, will toggle on the rendering of the means
-
-        showcaps  : bool, default = True
-          If `True`, will toggle on the rendering of the caps
-
-        showbox  : bool, default = True
-          If `True`, will toggle on the rendering of the box
-
-        showfliers : bool, default = True
-          If `True`, will toggle on the rendering of the fliers
-
-        boxprops : dict or None (default)
-          If provided, will set the plotting style of the boxes
-
-        whiskerprops : dict or None (default)
-          If provided, will set the plotting style of the whiskers
-
-        capprops : dict or None (default)
-          If provided, will set the plotting style of the caps
-
-        flierprops : dict or None (default)
-          If provided will set the plotting style of the fliers
-
-        medianprops : dict or None (default)
-          If provided, will set the plotting style of the medians
-
-        meanprops : dict or None (default)
-          If provided, will set the plotting style of the means
-
-        meanline : bool, default = False
-          If `True` (and *showmeans* is `True`), will try to render the mean
-          as a line spanning the full width of the box according to
-          *meanprops*. Not recommended if *shownotches* is also True.
-          Otherwise, means will be shown as points.
-
-        manage_ticks : bool, default = True
-          If True, the tick locations and labels will be adjusted to match the
-          boxplot positions.
-
-        zorder : scalar, default = None
-          The zorder of the resulting boxplot.
-
-        Returns
-        -------
-        result : dict
-          A dictionary mapping each component of the boxplot to a list
-          of the `.Line2D` instances created. That dictionary has the
-          following keys (assuming vertical boxplots):
-
-          - ``boxes``: the main body of the boxplot showing the
-            quartiles and the median's confidence intervals if
-            enabled.
-
-          - ``medians``: horizontal lines at the median of each box.
-
-          - ``whiskers``: the vertical lines extending to the most
-            extreme, non-outlier data points.
-
-          - ``caps``: the horizontal lines at the ends of the
-            whiskers.
-
-          - ``fliers``: points representing data that extend beyond
-            the whiskers (fliers).
-
-          - ``means``: points or lines representing the means.
-
-        Examples
-        --------
-        .. plot:: gallery/statistics/bxp.py
-
-        """
-        # lists of artists to be output
-        whiskers = []
-        caps = []
-        boxes = []
-        medians = []
-        means = []
-        fliers = []
-
-        # empty list of xticklabels
-        datalabels = []
-
-        # Use default zorder if none specified
-        if zorder is None:
-            zorder = mlines.Line2D.zorder
-
-        zdelta = 0.1
-
-        def line_props_with_rcdefaults(subkey, explicit, zdelta=0):
-            d = {k.split('.')[-1]: v for k, v in rcParams.items()
-                 if k.startswith(f'boxplot.{subkey}')}
-            d['zorder'] = zorder + zdelta
-            if explicit is not None:
-                d.update(
-                    cbook.normalize_kwargs(explicit, mlines.Line2D._alias_map))
-            return d
-
-        # box properties
-        if patch_artist:
-            final_boxprops = dict(
-                linestyle=rcParams['boxplot.boxprops.linestyle'],
-                linewidth=rcParams['boxplot.boxprops.linewidth'],
-                edgecolor=rcParams['boxplot.boxprops.color'],
-                facecolor=('white' if rcParams['_internal.classic_mode'] else
-                           rcParams['patch.facecolor']),
-                zorder=zorder,
-            )
-            if boxprops is not None:
-                final_boxprops.update(
-                    cbook.normalize_kwargs(
-                        boxprops, mpatches.PathPatch._alias_map))
-        else:
-            final_boxprops = line_props_with_rcdefaults('boxprops', boxprops)
-        final_whiskerprops = line_props_with_rcdefaults(
-            'whiskerprops', whiskerprops)
-        final_capprops = line_props_with_rcdefaults(
-            'capprops', capprops)
-        final_flierprops = line_props_with_rcdefaults(
-            'flierprops', flierprops)
-        final_medianprops = line_props_with_rcdefaults(
-            'medianprops', medianprops, zdelta)
-        final_meanprops = line_props_with_rcdefaults(
-            'meanprops', meanprops, zdelta)
-        removed_prop = 'marker' if meanline else 'linestyle'
-        # Only remove the property if it's not set explicitly as a parameter.
-        if meanprops is None or removed_prop not in meanprops:
-            final_meanprops[removed_prop] = ''
-
-        def to_vc(xs, ys):
-            # convert arguments to verts and codes, append (0, 0) (ignored).
-            verts = np.append(np.column_stack([xs, ys]), [(0, 0)], 0)
-            codes = ([mpath.Path.MOVETO]
-                     + [mpath.Path.LINETO] * (len(verts) - 2)
-                     + [mpath.Path.CLOSEPOLY])
-            return verts, codes
-
-        def patch_list(xs, ys, **kwargs):
-            verts, codes = to_vc(xs, ys)
-            path = mpath.Path(verts, codes)
-            patch = mpatches.PathPatch(path, **kwargs)
-            self.add_artist(patch)
-            return [patch]
-
-        # vertical or horizontal plot?
-        if vert:
-            def doplot(*args, **kwargs):
-                return self.plot(*args, **kwargs)
-
-            def dopatch(xs, ys, **kwargs):
-                return patch_list(xs, ys, **kwargs)
-
-        else:
-            def doplot(*args, **kwargs):
-                shuffled = []
-                for i in range(0, len(args), 2):
-                    shuffled.extend([args[i + 1], args[i]])
-                return self.plot(*shuffled, **kwargs)
-
-            def dopatch(xs, ys, **kwargs):
-                xs, ys = ys, xs  # flip X, Y
-                return patch_list(xs, ys, **kwargs)
-
-        # input validation
-        N = len(bxpstats)
-        datashape_message = ("List of boxplot statistics and `{0}` "
-                             "values must have same the length")
-        # check position
-        if positions is None:
-            positions = list(range(1, N + 1))
-        elif len(positions) != N:
-            raise ValueError(datashape_message.format("positions"))
-
-        positions = np.array(positions)
-        if len(positions) > 0 and not isinstance(positions[0], Number):
-            raise TypeError("positions should be an iterable of numbers")
-
-        # width
-        if widths is None:
-            widths = [np.clip(0.15 * np.ptp(positions), 0.15, 0.5)] * N
-        elif np.isscalar(widths):
-            widths = [widths] * N
-        elif len(widths) != N:
-            raise ValueError(datashape_message.format("widths"))
-
-        for pos, width, stats in zip(positions, widths, bxpstats):
-            # try to find a new label
-            datalabels.append(stats.get('label', pos))
-
-            # whisker coords
-            whisker_x = np.ones(2) * pos
-            whiskerlo_y = np.array([stats['q1'], stats['whislo']])
-            whiskerhi_y = np.array([stats['q3'], stats['whishi']])
-
-            # cap coords
-            cap_left = pos - width * 0.25
-            cap_right = pos + width * 0.25
-            cap_x = np.array([cap_left, cap_right])
-            cap_lo = np.ones(2) * stats['whislo']
-            cap_hi = np.ones(2) * stats['whishi']
-
-            # box and median coords
-            box_left = pos - width * 0.5
-            box_right = pos + width * 0.5
-            med_y = [stats['med'], stats['med']]
-
-            # notched boxes
-            if shownotches:
-                box_x = [box_left, box_right, box_right, cap_right, box_right,
-                         box_right, box_left, box_left, cap_left, box_left,
-                         box_left]
-                box_y = [stats['q1'], stats['q1'], stats['cilo'],
-                         stats['med'], stats['cihi'], stats['q3'],
-                         stats['q3'], stats['cihi'], stats['med'],
-                         stats['cilo'], stats['q1']]
-                med_x = cap_x
-
-            # plain boxes
-            else:
-                box_x = [box_left, box_right, box_right, box_left, box_left]
-                box_y = [stats['q1'], stats['q1'], stats['q3'], stats['q3'],
-                         stats['q1']]
-                med_x = [box_left, box_right]
-
-            # maybe draw the box:
-            if showbox:
-                if patch_artist:
-                    boxes.extend(dopatch(box_x, box_y, **final_boxprops))
-                else:
-                    boxes.extend(doplot(box_x, box_y, **final_boxprops))
-
-            # draw the whiskers
-            whiskers.extend(doplot(
-                whisker_x, whiskerlo_y, **final_whiskerprops
-            ))
-            whiskers.extend(doplot(
-                whisker_x, whiskerhi_y, **final_whiskerprops
-            ))
-
-            # maybe draw the caps:
-            if showcaps:
-                caps.extend(doplot(cap_x, cap_lo, **final_capprops))
-                caps.extend(doplot(cap_x, cap_hi, **final_capprops))
-
-            # draw the medians
-            medians.extend(doplot(med_x, med_y, **final_medianprops))
-
-            # maybe draw the means
-            if showmeans:
-                if meanline:
-                    means.extend(doplot(
-                        [box_left, box_right], [stats['mean'], stats['mean']],
-                        **final_meanprops
-                    ))
-                else:
-                    means.extend(doplot(
-                        [pos], [stats['mean']], **final_meanprops
-                    ))
-
-            # maybe draw the fliers
-            if showfliers:
-                # fliers coords
-                flier_x = np.full(len(stats['fliers']), pos, dtype=np.float64)
-                flier_y = stats['fliers']
-
-                fliers.extend(doplot(
-                    flier_x, flier_y, **final_flierprops
-                ))
-
-        if manage_ticks:
-            axis_name = "x" if vert else "y"
-            interval = getattr(self.dataLim, f"interval{axis_name}")
-            axis = getattr(self, f"{axis_name}axis")
-            positions = axis.convert_units(positions)
-            # The 0.5 additional padding ensures reasonable-looking boxes
-            # even when drawing a single box.  We set the sticky edge to
-            # prevent margins expansion, in order to match old behavior (back
-            # when separate calls to boxplot() would completely reset the axis
-            # limits regardless of what was drawn before).  The sticky edges
-            # are attached to the median lines, as they are always present.
-            interval[:] = (min(interval[0], min(positions) - .5),
-                           max(interval[1], max(positions) + .5))
-            for median, position in zip(medians, positions):
-                getattr(median.sticky_edges, axis_name).extend(
-                    [position - .5, position + .5])
-            # Modified from Axis.set_ticks and Axis.set_ticklabels.
-            locator = axis.get_major_locator()
-            if not isinstance(axis.get_major_locator(),
-                              mticker.FixedLocator):
-                locator = mticker.FixedLocator([])
-                axis.set_major_locator(locator)
-            locator.locs = np.array([*locator.locs, *positions])
-            formatter = axis.get_major_formatter()
-            if not isinstance(axis.get_major_formatter(),
-                              mticker.FixedFormatter):
-                formatter = mticker.FixedFormatter([])
-                axis.set_major_formatter(formatter)
-            formatter.seq = [*formatter.seq, *datalabels]
-
-            self._request_autoscale_view(
-                scalex=self._autoscaleXon, scaley=self._autoscaleYon)
-
-        return dict(whiskers=whiskers, caps=caps, boxes=boxes,
-                    medians=medians, fliers=fliers, means=means)
-
-    @staticmethod
-    def _parse_scatter_color_args(c, edgecolors, kwargs, xsize,
-                                  get_next_color_func):
-        """
-        Helper function to process color related arguments of `.Axes.scatter`.
-
-        Argument precedence for facecolors:
-
-        - c (if not None)
-        - kwargs['facecolors']
-        - kwargs['facecolor']
-        - kwargs['color'] (==kwcolor)
-        - 'b' if in classic mode else the result of ``get_next_color_func()``
-
-        Argument precedence for edgecolors:
-
-        - edgecolors (is an explicit kw argument in scatter())
-        - kwargs['edgecolor']
-        - kwargs['color'] (==kwcolor)
-        - 'face' if not in classic mode else None
-
-        Parameters
-        ----------
-        c : color or sequence or sequence of color or None
-            See argument description of `.Axes.scatter`.
-        edgecolors : color or sequence of color or {'face', 'none'} or None
-            See argument description of `.Axes.scatter`.
-        kwargs : dict
-            Additional kwargs. If these keys exist, we pop and process them:
-            'facecolors', 'facecolor', 'edgecolor', 'color'
-            Note: The dict is modified by this function.
-        xsize : int
-            The size of the x and y arrays passed to `.Axes.scatter`.
-        get_next_color_func : callable
-            A callable that returns a color. This color is used as facecolor
-            if no other color is provided.
-
-            Note, that this is a function rather than a fixed color value to
-            support conditional evaluation of the next color.  As of the
-            current implementation obtaining the next color from the
-            property cycle advances the cycle. This must only happen if we
-            actually use the color, which will only be decided within this
-            method.
-
-        Returns
-        -------
-        c
-            The input *c* if it was not *None*, else a color derived from the
-            other inputs or defaults.
-        colors : array(N, 4) or None
-            The facecolors as RGBA values, or *None* if a colormap is used.
-        edgecolors
-            The edgecolor.
-
-        """
-        facecolors = kwargs.pop('facecolors', None)
-        facecolors = kwargs.pop('facecolor', facecolors)
-        edgecolors = kwargs.pop('edgecolor', edgecolors)
-
-        kwcolor = kwargs.pop('color', None)
-
-        if kwcolor is not None and c is not None:
-            raise ValueError("Supply a 'c' argument or a 'color'"
-                             " kwarg but not both; they differ but"
-                             " their functionalities overlap.")
-
-        if kwcolor is not None:
-            try:
-                mcolors.to_rgba_array(kwcolor)
-            except ValueError:
-                raise ValueError(
-                    "'color' kwarg must be an color or sequence of color "
-                    "specs.  For a sequence of values to be color-mapped, use "
-                    "the 'c' argument instead.")
-            if edgecolors is None:
-                edgecolors = kwcolor
-            if facecolors is None:
-                facecolors = kwcolor
-
-        if edgecolors is None and not rcParams['_internal.classic_mode']:
-            edgecolors = rcParams['scatter.edgecolors']
-
-        c_was_none = c is None
-        if c is None:
-            c = (facecolors if facecolors is not None
-                 else "b" if rcParams['_internal.classic_mode']
-                 else get_next_color_func())
-        c_is_string_or_strings = (
-            isinstance(c, str)
-            or (isinstance(c, collections.abc.Iterable) and len(c) > 0
-                and isinstance(cbook.safe_first_element(c), str)))
-
-        def invalid_shape_exception(csize, xsize):
-            return ValueError(
-                f"'c' argument has {csize} elements, which is inconsistent "
-                f"with 'x' and 'y' with size {xsize}.")
-
-        c_is_mapped = False  # Unless proven otherwise below.
-        valid_shape = True  # Unless proven otherwise below.
-        if not c_was_none and kwcolor is None and not c_is_string_or_strings:
-            try:  # First, does 'c' look suitable for value-mapping?
-                c = np.asanyarray(c, dtype=float)
-            except ValueError:
-                pass  # Failed to convert to float array; must be color specs.
-            else:
-                # If c can be either mapped values or a RGB(A) color, prefer
-                # the former if shapes match, the latter otherwise.
-                if c.size == xsize:
-                    c = c.ravel()
-                    c_is_mapped = True
-                else:  # Wrong size; it must not be intended for mapping.
-                    if c.shape in ((3,), (4,)):
-                        _log.warning(
-                            "'c' argument looks like a single numeric RGB or "
-                            "RGBA sequence, which should be avoided as value-"
-                            "mapping will have precedence in case its length "
-                            "matches with 'x' & 'y'.  Please use a 2-D array "
-                            "with a single row if you really want to specify "
-                            "the same RGB or RGBA value for all points.")
-                    valid_shape = False
-        if not c_is_mapped:
-            try:  # Is 'c' acceptable as PathCollection facecolors?
-                colors = mcolors.to_rgba_array(c)
-            except ValueError:
-                if not valid_shape:
-                    raise invalid_shape_exception(c.size, xsize)
-                # Both the mapping *and* the RGBA conversion failed: pretty
-                # severe failure => one may appreciate a verbose feedback.
-                raise ValueError(
-                    f"'c' argument must be a color, a sequence of colors, or "
-                    f"a sequence of numbers, not {c}")
-            else:
-                if len(colors) not in (0, 1, xsize):
-                    # NB: remember that a single color is also acceptable.
-                    # Besides *colors* will be an empty array if c == 'none'.
-                    raise invalid_shape_exception(len(colors), xsize)
-        else:
-            colors = None  # use cmap, norm after collection is created
-        return c, colors, edgecolors
-
-    @_preprocess_data(replace_names=["x", "y", "s", "linewidths",
-                                     "edgecolors", "c", "facecolor",
-                                     "facecolors", "color"],
-                      label_namer="y")
-    @cbook._delete_parameter("3.2", "verts")
-    def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
-                vmin=None, vmax=None, alpha=None, linewidths=None,
-                verts=None, edgecolors=None, *, plotnonfinite=False,
-                **kwargs):
-        """
-        A scatter plot of *y* vs. *x* with varying marker size and/or color.
-
-        Parameters
-        ----------
-        x, y : scalar or array-like, shape (n, )
-            The data positions.
-
-        s : scalar or array-like, shape (n, ), optional
-            The marker size in points**2.
-            Default is ``rcParams['lines.markersize'] ** 2``.
-
-        c : color, sequence, or sequence of colors, optional
-            The marker color. Possible values:
-
-            - A single color format string.
-            - A sequence of colors of length n.
-            - A scalar or sequence of n numbers to be mapped to colors using
-              *cmap* and *norm*.
-            - A 2-D array in which the rows are RGB or RGBA.
-
-            Note that *c* should not be a single numeric RGB or RGBA sequence
-            because that is indistinguishable from an array of values to be
-            colormapped. If you want to specify the same RGB or RGBA value for
-            all points, use a 2-D array with a single row.  Otherwise, value-
-            matching will have precedence in case of a size matching with *x*
-            and *y*.
-
-            Defaults to ``None``. In that case the marker color is determined
-            by the value of ``color``, ``facecolor`` or ``facecolors``. In case
-            those are not specified or ``None``, the marker color is determined
-            by the next color of the ``Axes``' current "shape and fill" color
-            cycle. This cycle defaults to :rc:`axes.prop_cycle`.
-
-        marker : `~matplotlib.markers.MarkerStyle`, optional
-            The marker style. *marker* can be either an instance of the class
-            or the text shorthand for a particular marker.
-            Defaults to ``None``, in which case it takes the value of
-            :rc:`scatter.marker` = 'o'.
-            See `~matplotlib.markers` for more information about marker styles.
-
-        cmap : `~matplotlib.colors.Colormap`, optional, default: None
-            A `.Colormap` instance or registered colormap name. *cmap* is only
-            used if *c* is an array of floats. If ``None``, defaults to rc
-            ``image.cmap``.
-
-        norm : `~matplotlib.colors.Normalize`, optional, default: None
-            A `.Normalize` instance is used to scale luminance data to 0, 1.
-            *norm* is only used if *c* is an array of floats. If *None*, use
-            the default `.colors.Normalize`.
-
-        vmin, vmax : scalar, optional, default: None
-            *vmin* and *vmax* are used in conjunction with *norm* to normalize
-            luminance data. If None, the respective min and max of the color
-            array is used. *vmin* and *vmax* are ignored if you pass a *norm*
-            instance.
-
-        alpha : scalar, optional, default: None
-            The alpha blending value, between 0 (transparent) and 1 (opaque).
-
-        linewidths : scalar or array-like, optional, default: None
-            The linewidth of the marker edges. Note: The default *edgecolors*
-            is 'face'. You may want to change this as well.
-            If *None*, defaults to :rc:`lines.linewidth`.
-
-        edgecolors : {'face', 'none', *None*} or color or sequence of color, \
-optional.
-            The edge color of the marker. Possible values:
-
-            - 'face': The edge color will always be the same as the face color.
-            - 'none': No patch boundary will be drawn.
-            - A Matplotlib color or sequence of color.
-
-            Defaults to ``None``, in which case it takes the value of
-            :rc:`scatter.edgecolors` = 'face'.
-
-            For non-filled markers, the *edgecolors* kwarg is ignored and
-            forced to 'face' internally.
-
-        plotnonfinite : boolean, optional, default: False
-            Set to plot points with nonfinite *c*, in conjunction with
-            `~matplotlib.colors.Colormap.set_bad`.
-
-        Returns
-        -------
-        paths : `~matplotlib.collections.PathCollection`
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.collections.Collection` properties
-
-        See Also
-        --------
-        plot : To plot scatter plots when markers are identical in size and
-            color.
-
-        Notes
-        -----
-        * The `.plot` function will be faster for scatterplots where markers
-          don't vary in size or color.
-
-        * Any or all of *x*, *y*, *s*, and *c* may be masked arrays, in which
-          case all masks will be combined and only unmasked points will be
-          plotted.
-
-        * Fundamentally, scatter works with 1-D arrays; *x*, *y*, *s*, and *c*
-          may be input as N-D arrays, but within scatter they will be
-          flattened. The exception is *c*, which will be flattened only if its
-          size matches the size of *x* and *y*.
-
-        """
-        # Process **kwargs to handle aliases, conflicts with explicit kwargs:
-
-        self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
-        x = self.convert_xunits(x)
-        y = self.convert_yunits(y)
-
-        # np.ma.ravel yields an ndarray, not a masked array,
-        # unless its argument is a masked array.
-        x = np.ma.ravel(x)
-        y = np.ma.ravel(y)
-        if x.size != y.size:
-            raise ValueError("x and y must be the same size")
-
-        if s is None:
-            s = (20 if rcParams['_internal.classic_mode'] else
-                 rcParams['lines.markersize'] ** 2.0)
-        s = np.ma.ravel(s)
-        if len(s) not in (1, x.size):
-            raise ValueError("s must be a scalar, or the same size as x and y")
-
-        c, colors, edgecolors = \
-            self._parse_scatter_color_args(
-                c, edgecolors, kwargs, x.size,
-                get_next_color_func=self._get_patches_for_fill.get_next_color)
-
-        if plotnonfinite and colors is None:
-            c = np.ma.masked_invalid(c)
-            x, y, s, edgecolors, linewidths = \
-                cbook._combine_masks(x, y, s, edgecolors, linewidths)
-        else:
-            x, y, s, c, colors, edgecolors, linewidths = \
-                cbook._combine_masks(
-                    x, y, s, c, colors, edgecolors, linewidths)
-
-        scales = s   # Renamed for readability below.
-
-        # load default marker from rcParams
-        if marker is None:
-            marker = rcParams['scatter.marker']
-
-        if isinstance(marker, mmarkers.MarkerStyle):
-            marker_obj = marker
-        else:
-            marker_obj = mmarkers.MarkerStyle(marker)
-
-        path = marker_obj.get_path().transformed(
-            marker_obj.get_transform())
-        if not marker_obj.is_filled():
-            edgecolors = 'face'
-            linewidths = rcParams['lines.linewidth']
-
-        offsets = np.ma.column_stack([x, y])
-
-        collection = mcoll.PathCollection(
-                (path,), scales,
-                facecolors=colors,
-                edgecolors=edgecolors,
-                linewidths=linewidths,
-                offsets=offsets,
-                transOffset=kwargs.pop('transform', self.transData),
-                alpha=alpha
-                )
-        collection.set_transform(mtransforms.IdentityTransform())
-        collection.update(kwargs)
-
-        if colors is None:
-            collection.set_array(c)
-            collection.set_cmap(cmap)
-            collection.set_norm(norm)
-
-            if vmin is not None or vmax is not None:
-                collection.set_clim(vmin, vmax)
-            else:
-                collection.autoscale_None()
-
-        # Classic mode only:
-        # ensure there are margins to allow for the
-        # finite size of the symbols.  In v2.x, margins
-        # are present by default, so we disable this
-        # scatter-specific override.
-        if rcParams['_internal.classic_mode']:
-            if self._xmargin < 0.05 and x.size > 0:
-                self.set_xmargin(0.05)
-            if self._ymargin < 0.05 and x.size > 0:
-                self.set_ymargin(0.05)
-
-        self.add_collection(collection)
-        self._request_autoscale_view()
-
-        return collection
-
-    @_preprocess_data(replace_names=["x", "y"], label_namer="y")
-    @docstring.dedent_interpd
-    def hexbin(self, x, y, C=None, gridsize=100, bins=None,
-               xscale='linear', yscale='linear', extent=None,
-               cmap=None, norm=None, vmin=None, vmax=None,
-               alpha=None, linewidths=None, edgecolors='face',
-               reduce_C_function=np.mean, mincnt=None, marginals=False,
-               **kwargs):
-        """
-        Make a 2D hexagonal binning plot of points *x*, *y*.
-
-        If *C* is *None*, the value of the hexagon is determined by the number
-        of points in the hexagon. Otherwise, *C* specifies values at the
-        coordinate (x[i], y[i]). For each hexagon, these values are reduced
-        using *reduce_C_function*.
-
-        Parameters
-        ----------
-        x, y : array-like
-            The data positions. *x* and *y* must be of the same length.
-
-        C : array-like, optional
-            If given, these values are accumulated in the bins. Otherwise,
-            every point has a value of 1. Must be of the same length as *x*
-            and *y*.
-
-        gridsize : int or (int, int), default: 100
-            If a single int, the number of hexagons in the *x*-direction.
-            The number of hexagons in the *y*-direction is chosen such that
-            the hexagons are approximately regular.
-
-            Alternatively, if a tuple (*nx*, *ny*), the number of hexagons
-            in the *x*-direction and the *y*-direction.
-
-        bins : 'log' or int or sequence, default: *None*
-            Discretization of the hexagon values.
-
-            - If *None*, no binning is applied; the color of each hexagon
-              directly corresponds to its count value.
-            - If 'log', use a logarithmic scale for the color map.
-              Internally, :math:`log_{10}(i+1)` is used to determine the
-              hexagon color. This is equivalent to ``norm=LogNorm()``.
-            - If an integer, divide the counts in the specified number
-              of bins, and color the hexagons accordingly.
-            - If a sequence of values, the values of the lower bound of
-              the bins to be used.
-
-        xscale : {'linear', 'log'}, default: 'linear'
-            Use a linear or log10 scale on the horizontal axis.
-
-        yscale : {'linear', 'log'}, default: 'linear'
-            Use a linear or log10 scale on the vertical axis.
-
-        mincnt : int > 0, default: *None*
-            If not *None*, only display cells with more than *mincnt*
-            number of points in the cell.
-
-        marginals : bool, default: *False*
-            If marginals is *True*, plot the marginal density as
-            colormapped rectangles along the bottom of the x-axis and
-            left of the y-axis.
-
-        extent : float, default: *None*
-            The limits of the bins. The default assigns the limits
-            based on *gridsize*, *x*, *y*, *xscale* and *yscale*.
-
-            If *xscale* or *yscale* is set to 'log', the limits are
-            expected to be the exponent for a power of 10. E.g. for
-            x-limits of 1 and 50 in 'linear' scale and y-limits
-            of 10 and 1000 in 'log' scale, enter (1, 50, 1, 3).
-
-            Order of scalars is (left, right, bottom, top).
-
-        Other Parameters
-        ----------------
-        cmap : str or `~matplotlib.colors.Colormap`, optional
-            The Colormap instance or registered colormap name used to map
-            the bin values to colors. Defaults to :rc:`image.cmap`.
-
-        norm : `~matplotlib.colors.Normalize`, optional
-            The Normalize instance scales the bin values to the canonical
-            colormap range [0, 1] for mapping to colors. By default, the data
-            range is mapped to the colorbar range using linear scaling.
-
-        vmin, vmax : float, optional, default: None
-            The colorbar range. If *None*, suitable min/max values are
-            automatically chosen by the `~.Normalize` instance (defaults to
-            the respective min/max values of the bins in case of the default
-            linear scaling). This is ignored if *norm* is given.
-
-        alpha : float between 0 and 1, optional
-            The alpha blending value, between 0 (transparent) and 1 (opaque).
-
-        linewidths : float, default: *None*
-            If *None*, defaults to 1.0.
-
-        edgecolors : {'face', 'none', *None*} or color, default: 'face'
-            The color of the hexagon edges. Possible values are:
-
-            - 'face': Draw the edges in the same color as the fill color.
-            - 'none': No edges are drawn. This can sometimes lead to unsightly
-              unpainted pixels between the hexagons.
-            - *None*: Draw outlines in the default color.
-            - An explicit matplotlib color.
-
-        reduce_C_function : callable, default is `numpy.mean`
-            The function to aggregate *C* within the bins. It is ignored if
-            *C* is not given. This must have the signature::
-
-                def reduce_C_function(C: array) -> float
-
-            Commonly used functions are:
-
-            - `numpy.mean`: average of the points
-            - `numpy.sum`: integral of the point values
-            - `numpy.max`: value taken from the largest point
-
-        **kwargs : `~matplotlib.collections.PolyCollection` properties
-            All other keyword arguments are passed on to `.PolyCollection`:
-
-            %(PolyCollection)s
-
-        Returns
-        -------
-        polycollection : `~matplotlib.collections.PolyCollection`
-            A `.PolyCollection` defining the hexagonal bins.
-
-            - `.PolyCollection.get_offset` contains a Mx2 array containing
-              the x, y positions of the M hexagon centers.
-            - `.PolyCollection.get_array` contains the values of the M
-              hexagons.
-
-            If *marginals* is *True*, horizontal
-            bar and vertical bar (both PolyCollections) will be attached
-            to the return collection as attributes *hbar* and *vbar*.
-
-        """
-        self._process_unit_info(xdata=x, ydata=y, kwargs=kwargs)
-
-        x, y, C = cbook.delete_masked_points(x, y, C)
-
-        # Set the size of the hexagon grid
-        if np.iterable(gridsize):
-            nx, ny = gridsize
-        else:
-            nx = gridsize
-            ny = int(nx / math.sqrt(3))
-        # Count the number of data in each hexagon
-        x = np.array(x, float)
-        y = np.array(y, float)
-        if xscale == 'log':
-            if np.any(x <= 0.0):
-                raise ValueError("x contains non-positive values, so can not"
-                                 " be log-scaled")
-            x = np.log10(x)
-        if yscale == 'log':
-            if np.any(y <= 0.0):
-                raise ValueError("y contains non-positive values, so can not"
-                                 " be log-scaled")
-            y = np.log10(y)
-        if extent is not None:
-            xmin, xmax, ymin, ymax = extent
-        else:
-            xmin, xmax = (np.min(x), np.max(x)) if len(x) else (0, 1)
-            ymin, ymax = (np.min(y), np.max(y)) if len(y) else (0, 1)
-
-            # to avoid issues with singular data, expand the min/max pairs
-            xmin, xmax = mtransforms.nonsingular(xmin, xmax, expander=0.1)
-            ymin, ymax = mtransforms.nonsingular(ymin, ymax, expander=0.1)
-
-        # In the x-direction, the hexagons exactly cover the region from
-        # xmin to xmax. Need some padding to avoid roundoff errors.
-        padding = 1.e-9 * (xmax - xmin)
-        xmin -= padding
-        xmax += padding
-        sx = (xmax - xmin) / nx
-        sy = (ymax - ymin) / ny
-
-        if marginals:
-            xorig = x.copy()
-            yorig = y.copy()
-
-        x = (x - xmin) / sx
-        y = (y - ymin) / sy
-        ix1 = np.round(x).astype(int)
-        iy1 = np.round(y).astype(int)
-        ix2 = np.floor(x).astype(int)
-        iy2 = np.floor(y).astype(int)
-
-        nx1 = nx + 1
-        ny1 = ny + 1
-        nx2 = nx
-        ny2 = ny
-        n = nx1 * ny1 + nx2 * ny2
-
-        d1 = (x - ix1) ** 2 + 3.0 * (y - iy1) ** 2
-        d2 = (x - ix2 - 0.5) ** 2 + 3.0 * (y - iy2 - 0.5) ** 2
-        bdist = (d1 < d2)
-        if C is None:
-            lattice1 = np.zeros((nx1, ny1))
-            lattice2 = np.zeros((nx2, ny2))
-            c1 = (0 <= ix1) & (ix1 < nx1) & (0 <= iy1) & (iy1 < ny1) & bdist
-            c2 = (0 <= ix2) & (ix2 < nx2) & (0 <= iy2) & (iy2 < ny2) & ~bdist
-            np.add.at(lattice1, (ix1[c1], iy1[c1]), 1)
-            np.add.at(lattice2, (ix2[c2], iy2[c2]), 1)
-            if mincnt is not None:
-                lattice1[lattice1 < mincnt] = np.nan
-                lattice2[lattice2 < mincnt] = np.nan
-            accum = np.concatenate([lattice1.ravel(), lattice2.ravel()])
-            good_idxs = ~np.isnan(accum)
-
-        else:
-            if mincnt is None:
-                mincnt = 0
-
-            # create accumulation arrays
-            lattice1 = np.empty((nx1, ny1), dtype=object)
-            for i in range(nx1):
-                for j in range(ny1):
-                    lattice1[i, j] = []
-            lattice2 = np.empty((nx2, ny2), dtype=object)
-            for i in range(nx2):
-                for j in range(ny2):
-                    lattice2[i, j] = []
-
-            for i in range(len(x)):
-                if bdist[i]:
-                    if 0 <= ix1[i] < nx1 and 0 <= iy1[i] < ny1:
-                        lattice1[ix1[i], iy1[i]].append(C[i])
-                else:
-                    if 0 <= ix2[i] < nx2 and 0 <= iy2[i] < ny2:
-                        lattice2[ix2[i], iy2[i]].append(C[i])
-
-            for i in range(nx1):
-                for j in range(ny1):
-                    vals = lattice1[i, j]
-                    if len(vals) > mincnt:
-                        lattice1[i, j] = reduce_C_function(vals)
-                    else:
-                        lattice1[i, j] = np.nan
-            for i in range(nx2):
-                for j in range(ny2):
-                    vals = lattice2[i, j]
-                    if len(vals) > mincnt:
-                        lattice2[i, j] = reduce_C_function(vals)
-                    else:
-                        lattice2[i, j] = np.nan
-
-            accum = np.hstack((lattice1.astype(float).ravel(),
-                               lattice2.astype(float).ravel()))
-            good_idxs = ~np.isnan(accum)
-
-        offsets = np.zeros((n, 2), float)
-        offsets[:nx1 * ny1, 0] = np.repeat(np.arange(nx1), ny1)
-        offsets[:nx1 * ny1, 1] = np.tile(np.arange(ny1), nx1)
-        offsets[nx1 * ny1:, 0] = np.repeat(np.arange(nx2) + 0.5, ny2)
-        offsets[nx1 * ny1:, 1] = np.tile(np.arange(ny2), nx2) + 0.5
-        offsets[:, 0] *= sx
-        offsets[:, 1] *= sy
-        offsets[:, 0] += xmin
-        offsets[:, 1] += ymin
-        # remove accumulation bins with no data
-        offsets = offsets[good_idxs, :]
-        accum = accum[good_idxs]
-
-        polygon = [sx, sy / 3] * np.array(
-            [[.5, -.5], [.5, .5], [0., 1.], [-.5, .5], [-.5, -.5], [0., -1.]])
-
-        if linewidths is None:
-            linewidths = [1.0]
-
-        if xscale == 'log' or yscale == 'log':
-            polygons = np.expand_dims(polygon, 0) + np.expand_dims(offsets, 1)
-            if xscale == 'log':
-                polygons[:, :, 0] = 10.0 ** polygons[:, :, 0]
-                xmin = 10.0 ** xmin
-                xmax = 10.0 ** xmax
-                self.set_xscale(xscale)
-            if yscale == 'log':
-                polygons[:, :, 1] = 10.0 ** polygons[:, :, 1]
-                ymin = 10.0 ** ymin
-                ymax = 10.0 ** ymax
-                self.set_yscale(yscale)
-            collection = mcoll.PolyCollection(
-                polygons,
-                edgecolors=edgecolors,
-                linewidths=linewidths,
-                )
-        else:
-            collection = mcoll.PolyCollection(
-                [polygon],
-                edgecolors=edgecolors,
-                linewidths=linewidths,
-                offsets=offsets,
-                transOffset=mtransforms.IdentityTransform(),
-                offset_position="data"
-                )
-
-        # Set normalizer if bins is 'log'
-        if bins == 'log':
-            if norm is not None:
-                cbook._warn_external("Only one of 'bins' and 'norm' "
-                                     "arguments can be supplied, ignoring "
-                                     "bins={}".format(bins))
-            else:
-                norm = mcolors.LogNorm()
-            bins = None
-
-        if isinstance(norm, mcolors.LogNorm):
-            if (accum == 0).any():
-                # make sure we have no zeros
-                accum += 1
-
-        # autoscale the norm with curren accum values if it hasn't
-        # been set
-        if norm is not None:
-            if norm.vmin is None and norm.vmax is None:
-                norm.autoscale(accum)
-
-        if bins is not None:
-            if not np.iterable(bins):
-                minimum, maximum = min(accum), max(accum)
-                bins -= 1  # one less edge than bins
-                bins = minimum + (maximum - minimum) * np.arange(bins) / bins
-            bins = np.sort(bins)
-            accum = bins.searchsorted(accum)
-
-        collection.set_array(accum)
-        collection.set_cmap(cmap)
-        collection.set_norm(norm)
-        collection.set_alpha(alpha)
-        collection.update(kwargs)
-
-        if vmin is not None or vmax is not None:
-            collection.set_clim(vmin, vmax)
-        else:
-            collection.autoscale_None()
-
-        corners = ((xmin, ymin), (xmax, ymax))
-        self.update_datalim(corners)
-        self._request_autoscale_view(tight=True)
-
-        # add the collection last
-        self.add_collection(collection, autolim=False)
-        if not marginals:
-            return collection
-
-        if C is None:
-            C = np.ones(len(x))
-
-        def coarse_bin(x, y, coarse):
-            ind = coarse.searchsorted(x).clip(0, len(coarse) - 1)
-            mus = np.zeros(len(coarse))
-            for i in range(len(coarse)):
-                yi = y[ind == i]
-                if len(yi) > 0:
-                    mu = reduce_C_function(yi)
-                else:
-                    mu = np.nan
-                mus[i] = mu
-            return mus
-
-        coarse = np.linspace(xmin, xmax, gridsize)
-
-        xcoarse = coarse_bin(xorig, C, coarse)
-        valid = ~np.isnan(xcoarse)
-        verts, values = [], []
-        for i, val in enumerate(xcoarse):
-            thismin = coarse[i]
-            if i < len(coarse) - 1:
-                thismax = coarse[i + 1]
-            else:
-                thismax = thismin + np.diff(coarse)[-1]
-
-            if not valid[i]:
-                continue
-
-            verts.append([(thismin, 0),
-                          (thismin, 0.05),
-                          (thismax, 0.05),
-                          (thismax, 0)])
-            values.append(val)
-
-        values = np.array(values)
-        trans = self.get_xaxis_transform(which='grid')
-
-        hbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face')
-
-        hbar.set_array(values)
-        hbar.set_cmap(cmap)
-        hbar.set_norm(norm)
-        hbar.set_alpha(alpha)
-        hbar.update(kwargs)
-        self.add_collection(hbar, autolim=False)
-
-        coarse = np.linspace(ymin, ymax, gridsize)
-        ycoarse = coarse_bin(yorig, C, coarse)
-        valid = ~np.isnan(ycoarse)
-        verts, values = [], []
-        for i, val in enumerate(ycoarse):
-            thismin = coarse[i]
-            if i < len(coarse) - 1:
-                thismax = coarse[i + 1]
-            else:
-                thismax = thismin + np.diff(coarse)[-1]
-            if not valid[i]:
-                continue
-            verts.append([(0, thismin), (0.0, thismax),
-                          (0.05, thismax), (0.05, thismin)])
-            values.append(val)
-
-        values = np.array(values)
-
-        trans = self.get_yaxis_transform(which='grid')
-
-        vbar = mcoll.PolyCollection(verts, transform=trans, edgecolors='face')
-        vbar.set_array(values)
-        vbar.set_cmap(cmap)
-        vbar.set_norm(norm)
-        vbar.set_alpha(alpha)
-        vbar.update(kwargs)
-        self.add_collection(vbar, autolim=False)
-
-        collection.hbar = hbar
-        collection.vbar = vbar
-
-        def on_changed(collection):
-            hbar.set_cmap(collection.get_cmap())
-            hbar.set_clim(collection.get_clim())
-            vbar.set_cmap(collection.get_cmap())
-            vbar.set_clim(collection.get_clim())
-
-        collection.callbacksSM.connect('changed', on_changed)
-
-        return collection
-
-    @docstring.dedent_interpd
-    def arrow(self, x, y, dx, dy, **kwargs):
-        """
-        Add an arrow to the axes.
-
-        This draws an arrow from ``(x, y)`` to ``(x+dx, y+dy)``.
-
-        Parameters
-        ----------
-        x, y : float
-            The x and y coordinates of the arrow base.
-        dx, dy : float
-            The length of the arrow along x and y direction.
-
-        Returns
-        -------
-        arrow : `.FancyArrow`
-            The created `.FancyArrow` object.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Optional kwargs (inherited from `.FancyArrow` patch) control the
-            arrow construction and properties:
-
-        %(FancyArrow)s
-
-        Notes
-        -----
-        The resulting arrow is affected by the axes aspect ratio and limits.
-        This may produce an arrow whose head is not square with its stem. To
-        create an arrow whose head is square with its stem,
-        use :meth:`annotate` for example:
-
-        >>> ax.annotate("", xy=(0.5, 0.5), xytext=(0, 0),
-        ...             arrowprops=dict(arrowstyle="->"))
-
-        """
-        # Strip away units for the underlying patch since units
-        # do not make sense to most patch-like code
-        x = self.convert_xunits(x)
-        y = self.convert_yunits(y)
-        dx = self.convert_xunits(dx)
-        dy = self.convert_yunits(dy)
-
-        a = mpatches.FancyArrow(x, y, dx, dy, **kwargs)
-        self.add_artist(a)
-        return a
-
-    @docstring.copy(mquiver.QuiverKey.__init__)
-    def quiverkey(self, Q, X, Y, U, label, **kw):
-        qk = mquiver.QuiverKey(Q, X, Y, U, label, **kw)
-        self.add_artist(qk)
-        return qk
-
-    # Handle units for x and y, if they've been passed
-    def _quiver_units(self, args, kw):
-        if len(args) > 3:
-            x, y = args[0:2]
-            self._process_unit_info(xdata=x, ydata=y, kwargs=kw)
-            x = self.convert_xunits(x)
-            y = self.convert_yunits(y)
-            return (x, y) + args[2:]
-        return args
-
-    # args can by a combination if X, Y, U, V, C and all should be replaced
-    @_preprocess_data()
-    def quiver(self, *args, **kw):
-        # Make sure units are handled for x and y values
-        args = self._quiver_units(args, kw)
-
-        q = mquiver.Quiver(self, *args, **kw)
-
-        self.add_collection(q, autolim=True)
-        self._request_autoscale_view()
-        return q
-    quiver.__doc__ = mquiver.Quiver.quiver_doc
-
-    # args can be some combination of X, Y, U, V, C and all should be replaced
-    @_preprocess_data()
-    @docstring.dedent_interpd
-    def barbs(self, *args, **kw):
-        """
-        %(barbs_doc)s
-        """
-        # Make sure units are handled for x and y values
-        args = self._quiver_units(args, kw)
-
-        b = mquiver.Barbs(self, *args, **kw)
-        self.add_collection(b, autolim=True)
-        self._request_autoscale_view()
-        return b
-
-    # Uses a custom implementation of data-kwarg handling in
-    # _process_plot_var_args.
-    def fill(self, *args, data=None, **kwargs):
-        """
-        Plot filled polygons.
-
-        Parameters
-        ----------
-        *args : sequence of x, y, [color]
-            Each polygon is defined by the lists of *x* and *y* positions of
-            its nodes, optionally followed by a *color* specifier. See
-            :mod:`matplotlib.colors` for supported color specifiers. The
-            standard color cycle is used for polygons without a color
-            specifier.
-
-            You can plot multiple polygons by providing multiple *x*, *y*,
-            *[color]* groups.
-
-            For example, each of the following is legal::
-
-                ax.fill(x, y)                    # a polygon with default color
-                ax.fill(x, y, "b")               # a blue polygon
-                ax.fill(x, y, x2, y2)            # two polygons
-                ax.fill(x, y, "b", x2, y2, "r")  # a blue and a red polygon
-
-        data : indexable object, optional
-            An object with labelled data. If given, provide the label names to
-            plot in *x* and *y*, e.g.::
-
-                ax.fill("time", "signal",
-                        data={"time": [0, 1, 2], "signal": [0, 1, 0]})
-
-        Returns
-        -------
-        a list of :class:`~matplotlib.patches.Polygon`
-
-        Other Parameters
-        ----------------
-        **kwargs : :class:`~matplotlib.patches.Polygon` properties
-
-        Notes
-        -----
-        Use :meth:`fill_between` if you would like to fill the region between
-        two curves.
-        """
-        # For compatibility(!), get aliases from Line2D rather than Patch.
-        kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D)
-        # _get_patches_for_fill returns a generator, convert it to a list.
-        patches = [*self._get_patches_for_fill(*args, data=data, **kwargs)]
-        for poly in patches:
-            self.add_patch(poly)
-        self._request_autoscale_view()
-        return patches
-
-    @_preprocess_data(replace_names=["x", "y1", "y2", "where"])
-    @docstring.dedent_interpd
-    def fill_between(self, x, y1, y2=0, where=None, interpolate=False,
-                     step=None, **kwargs):
-        """
-        Fill the area between two horizontal curves.
-
-        The curves are defined by the points (*x*, *y1*) and (*x*, *y2*). This
-        creates one or multiple polygons describing the filled area.
-
-        You may exclude some horizontal sections from filling using *where*.
-
-        By default, the edges connect the given points directly. Use *step* if
-        the filling should be a step function, i.e. constant in between *x*.
-
-
-        Parameters
-        ----------
-        x : array (length N)
-            The x coordinates of the nodes defining the curves.
-
-        y1 : array (length N) or scalar
-            The y coordinates of the nodes defining the first curve.
-
-        y2 : array (length N) or scalar, optional, default: 0
-            The y coordinates of the nodes defining the second curve.
-
-        where : array of bool (length N), optional, default: None
-            Define *where* to exclude some horizontal regions from being
-            filled. The filled regions are defined by the coordinates
-            ``x[where]``.  More precisely, fill between ``x[i]`` and ``x[i+1]``
-            if ``where[i] and where[i+1]``.  Note that this definition implies
-            that an isolated *True* value between two *False* values in
-            *where* will not result in filling.  Both sides of the *True*
-            position remain unfilled due to the adjacent *False* values.
-
-        interpolate : bool, optional
-            This option is only relevant if *where* is used and the two curves
-            are crossing each other.
-
-            Semantically, *where* is often used for *y1* > *y2* or similar.
-            By default, the nodes of the polygon defining the filled region
-            will only be placed at the positions in the *x* array.  Such a
-            polygon cannot describe the above semantics close to the
-            intersection.  The x-sections containing the intersection are
-            simply clipped.
-
-            Setting *interpolate* to *True* will calculate the actual
-            intersection point and extend the filled region up to this point.
-
-        step : {'pre', 'post', 'mid'}, optional
-            Define *step* if the filling should be a step function,
-            i.e. constant in between *x*. The value determines where the
-            step will occur:
-
-            - 'pre': The y value is continued constantly to the left from
-              every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the
-              value ``y[i]``.
-            - 'post': The y value is continued constantly to the right from
-              every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the
-              value ``y[i]``.
-            - 'mid': Steps occur half-way between the *x* positions.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            All other keyword arguments are passed on to `.PolyCollection`.
-            They control the `.Polygon` properties:
-
-            %(PolyCollection)s
-
-        Returns
-        -------
-        `.PolyCollection`
-            A `.PolyCollection` containing the plotted polygons.
-
-        See Also
-        --------
-        fill_betweenx : Fill between two sets of x-values.
-
-        Notes
-        -----
-        .. [notes section required to get data note injection right]
-
-        """
-        if not rcParams['_internal.classic_mode']:
-            kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection)
-            if not any(c in kwargs for c in ('color', 'facecolor')):
-                kwargs['facecolor'] = \
-                    self._get_patches_for_fill.get_next_color()
-
-        # Handle united data, such as dates
-        self._process_unit_info(xdata=x, ydata=y1, kwargs=kwargs)
-        self._process_unit_info(ydata=y2)
-
-        # Convert the arrays so we can work with them
-        x = ma.masked_invalid(self.convert_xunits(x))
-        y1 = ma.masked_invalid(self.convert_yunits(y1))
-        y2 = ma.masked_invalid(self.convert_yunits(y2))
-
-        for name, array in [('x', x), ('y1', y1), ('y2', y2)]:
-            if array.ndim > 1:
-                raise ValueError('Input passed into argument "%r"' % name +
-                                 'is not 1-dimensional.')
-
-        if where is None:
-            where = True
-        else:
-            where = np.asarray(where, dtype=bool)
-            if where.size != x.size:
-                cbook.warn_deprecated(
-                    "3.2",
-                    message="The parameter where must have the same size as x "
-                            "in fill_between(). This will become an error in "
-                            "future versions of Matplotlib.")
-        where = where & ~functools.reduce(np.logical_or,
-                                          map(np.ma.getmask, [x, y1, y2]))
-
-        x, y1, y2 = np.broadcast_arrays(np.atleast_1d(x), y1, y2)
-
-        polys = []
-        for ind0, ind1 in cbook.contiguous_regions(where):
-            xslice = x[ind0:ind1]
-            y1slice = y1[ind0:ind1]
-            y2slice = y2[ind0:ind1]
-            if step is not None:
-                step_func = cbook.STEP_LOOKUP_MAP["steps-" + step]
-                xslice, y1slice, y2slice = step_func(xslice, y1slice, y2slice)
-
-            if not len(xslice):
-                continue
-
-            N = len(xslice)
-            X = np.zeros((2 * N + 2, 2), float)
-
-            if interpolate:
-                def get_interp_point(ind):
-                    im1 = max(ind - 1, 0)
-                    x_values = x[im1:ind + 1]
-                    diff_values = y1[im1:ind + 1] - y2[im1:ind + 1]
-                    y1_values = y1[im1:ind + 1]
-
-                    if len(diff_values) == 2:
-                        if np.ma.is_masked(diff_values[1]):
-                            return x[im1], y1[im1]
-                        elif np.ma.is_masked(diff_values[0]):
-                            return x[ind], y1[ind]
-
-                    diff_order = diff_values.argsort()
-                    diff_root_x = np.interp(
-                        0, diff_values[diff_order], x_values[diff_order])
-                    x_order = x_values.argsort()
-                    diff_root_y = np.interp(diff_root_x, x_values[x_order],
-                                            y1_values[x_order])
-                    return diff_root_x, diff_root_y
-
-                start = get_interp_point(ind0)
-                end = get_interp_point(ind1)
-            else:
-                # the purpose of the next two lines is for when y2 is a
-                # scalar like 0 and we want the fill to go all the way
-                # down to 0 even if none of the y1 sample points do
-                start = xslice[0], y2slice[0]
-                end = xslice[-1], y2slice[-1]
-
-            X[0] = start
-            X[N + 1] = end
-
-            X[1:N + 1, 0] = xslice
-            X[1:N + 1, 1] = y1slice
-            X[N + 2:, 0] = xslice[::-1]
-            X[N + 2:, 1] = y2slice[::-1]
-
-            polys.append(X)
-
-        collection = mcoll.PolyCollection(polys, **kwargs)
-
-        # now update the datalim and autoscale
-        XY1 = np.array([x[where], y1[where]]).T
-        XY2 = np.array([x[where], y2[where]]).T
-        self.dataLim.update_from_data_xy(XY1, self.ignore_existing_data_limits,
-                                         updatex=True, updatey=True)
-        self.ignore_existing_data_limits = False
-        self.dataLim.update_from_data_xy(XY2, self.ignore_existing_data_limits,
-                                         updatex=False, updatey=True)
-        self.add_collection(collection, autolim=False)
-        self._request_autoscale_view()
-        return collection
-
-    @_preprocess_data(replace_names=["y", "x1", "x2", "where"])
-    @docstring.dedent_interpd
-    def fill_betweenx(self, y, x1, x2=0, where=None,
-                      step=None, interpolate=False, **kwargs):
-        """
-        Fill the area between two vertical curves.
-
-        The curves are defined by the points (*x1*, *y*) and (*x2*, *y*). This
-        creates one or multiple polygons describing the filled area.
-
-        You may exclude some vertical sections from filling using *where*.
-
-        By default, the edges connect the given points directly. Use *step* if
-        the filling should be a step function, i.e. constant in between *y*.
-
-
-        Parameters
-        ----------
-        y : array (length N)
-            The y coordinates of the nodes defining the curves.
-
-        x1 : array (length N) or scalar
-            The x coordinates of the nodes defining the first curve.
-
-        x2 : array (length N) or scalar, optional, default: 0
-            The x coordinates of the nodes defining the second curve.
-
-        where : array of bool (length N), optional, default: None
-            Define *where* to exclude some vertical regions from being
-            filled. The filled regions are defined by the coordinates
-            ``y[where]``.  More precisely, fill between ``y[i]`` and ``y[i+1]``
-            if ``where[i] and where[i+1]``.  Note that this definition implies
-            that an isolated *True* value between two *False* values in
-            *where* will not result in filling.  Both sides of the *True*
-            position remain unfilled due to the adjacent *False* values.
-
-        interpolate : bool, optional
-            This option is only relevant if *where* is used and the two curves
-            are crossing each other.
-
-            Semantically, *where* is often used for *x1* > *x2* or similar.
-            By default, the nodes of the polygon defining the filled region
-            will only be placed at the positions in the *y* array.  Such a
-            polygon cannot describe the above semantics close to the
-            intersection.  The y-sections containing the intersection are
-            simply clipped.
-
-            Setting *interpolate* to *True* will calculate the actual
-            intersection point and extend the filled region up to this point.
-
-        step : {'pre', 'post', 'mid'}, optional
-            Define *step* if the filling should be a step function,
-            i.e. constant in between *y*. The value determines where the
-            step will occur:
-
-            - 'pre': The y value is continued constantly to the left from
-              every *x* position, i.e. the interval ``(x[i-1], x[i]]`` has the
-              value ``y[i]``.
-            - 'post': The y value is continued constantly to the right from
-              every *x* position, i.e. the interval ``[x[i], x[i+1])`` has the
-              value ``y[i]``.
-            - 'mid': Steps occur half-way between the *x* positions.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            All other keyword arguments are passed on to `.PolyCollection`.
-            They control the `.Polygon` properties:
-
-            %(PolyCollection)s
-
-        Returns
-        -------
-        `.PolyCollection`
-            A `.PolyCollection` containing the plotted polygons.
-
-        See Also
-        --------
-        fill_between : Fill between two sets of y-values.
-
-        Notes
-        -----
-        .. [notes section required to get data note injection right]
-
-        """
-        if not rcParams['_internal.classic_mode']:
-            kwargs = cbook.normalize_kwargs(kwargs, mcoll.Collection)
-            if not any(c in kwargs for c in ('color', 'facecolor')):
-                kwargs['facecolor'] = \
-                    self._get_patches_for_fill.get_next_color()
-
-        # Handle united data, such as dates
-        self._process_unit_info(ydata=y, xdata=x1, kwargs=kwargs)
-        self._process_unit_info(xdata=x2)
-
-        # Convert the arrays so we can work with them
-        y = ma.masked_invalid(self.convert_yunits(y))
-        x1 = ma.masked_invalid(self.convert_xunits(x1))
-        x2 = ma.masked_invalid(self.convert_xunits(x2))
-
-        for name, array in [('y', y), ('x1', x1), ('x2', x2)]:
-            if array.ndim > 1:
-                raise ValueError('Input passed into argument "%r"' % name +
-                                 'is not 1-dimensional.')
-
-        if where is None:
-            where = True
-        else:
-            where = np.asarray(where, dtype=bool)
-            if where.size != y.size:
-                cbook.warn_deprecated(
-                    "3.2",
-                    message="The parameter where must have the same size as y "
-                            "in fill_between(). This will become an error in "
-                            "future versions of Matplotlib.")
-        where = where & ~functools.reduce(np.logical_or,
-                                          map(np.ma.getmask, [y, x1, x2]))
-
-        y, x1, x2 = np.broadcast_arrays(np.atleast_1d(y), x1, x2)
-
-        polys = []
-        for ind0, ind1 in cbook.contiguous_regions(where):
-            yslice = y[ind0:ind1]
-            x1slice = x1[ind0:ind1]
-            x2slice = x2[ind0:ind1]
-            if step is not None:
-                step_func = cbook.STEP_LOOKUP_MAP["steps-" + step]
-                yslice, x1slice, x2slice = step_func(yslice, x1slice, x2slice)
-
-            if not len(yslice):
-                continue
-
-            N = len(yslice)
-            Y = np.zeros((2 * N + 2, 2), float)
-            if interpolate:
-                def get_interp_point(ind):
-                    im1 = max(ind - 1, 0)
-                    y_values = y[im1:ind + 1]
-                    diff_values = x1[im1:ind + 1] - x2[im1:ind + 1]
-                    x1_values = x1[im1:ind + 1]
-
-                    if len(diff_values) == 2:
-                        if np.ma.is_masked(diff_values[1]):
-                            return x1[im1], y[im1]
-                        elif np.ma.is_masked(diff_values[0]):
-                            return x1[ind], y[ind]
-
-                    diff_order = diff_values.argsort()
-                    diff_root_y = np.interp(
-                        0, diff_values[diff_order], y_values[diff_order])
-                    y_order = y_values.argsort()
-                    diff_root_x = np.interp(diff_root_y, y_values[y_order],
-                                            x1_values[y_order])
-                    return diff_root_x, diff_root_y
-
-                start = get_interp_point(ind0)
-                end = get_interp_point(ind1)
-            else:
-                # the purpose of the next two lines is for when x2 is a
-                # scalar like 0 and we want the fill to go all the way
-                # down to 0 even if none of the x1 sample points do
-                start = x2slice[0], yslice[0]
-                end = x2slice[-1], yslice[-1]
-
-            Y[0] = start
-            Y[N + 1] = end
-
-            Y[1:N + 1, 0] = x1slice
-            Y[1:N + 1, 1] = yslice
-            Y[N + 2:, 0] = x2slice[::-1]
-            Y[N + 2:, 1] = yslice[::-1]
-
-            polys.append(Y)
-
-        collection = mcoll.PolyCollection(polys, **kwargs)
-
-        # now update the datalim and autoscale
-        X1Y = np.array([x1[where], y[where]]).T
-        X2Y = np.array([x2[where], y[where]]).T
-        self.dataLim.update_from_data_xy(X1Y, self.ignore_existing_data_limits,
-                                         updatex=True, updatey=True)
-        self.ignore_existing_data_limits = False
-        self.dataLim.update_from_data_xy(X2Y, self.ignore_existing_data_limits,
-                                         updatex=True, updatey=False)
-        self.add_collection(collection, autolim=False)
-        self._request_autoscale_view()
-        return collection
-
-    #### plotting z(x, y): imshow, pcolor and relatives, contour
-    @_preprocess_data()
-    @cbook._delete_parameter("3.1", "shape")
-    @cbook._delete_parameter("3.1", "imlim")
-    def imshow(self, X, cmap=None, norm=None, aspect=None,
-               interpolation=None, alpha=None, vmin=None, vmax=None,
-               origin=None, extent=None, shape=None, filternorm=1,
-               filterrad=4.0, imlim=None, resample=None, url=None, **kwargs):
-        """
-        Display data as an image; i.e. on a 2D regular raster.
-
-        The input may either be actual RGB(A) data, or 2D scalar data, which
-        will be rendered as a pseudocolor image. Note: For actually displaying
-        a grayscale image set up the color mapping using the parameters
-        ``cmap='gray', vmin=0, vmax=255``.
-
-        Parameters
-        ----------
-        X : array-like or PIL image
-            The image data. Supported array shapes are:
-
-            - (M, N): an image with scalar data. The values are mapped to
-              colors using normalization and a colormap. See parameters *norm*,
-              *cmap*, *vmin*, *vmax*.
-            - (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
-            - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
-              i.e. including transparency.
-
-            The first two dimensions (M, N) define the rows and columns of
-            the image.
-
-            Out-of-range RGB(A) values are clipped.
-
-        cmap : str or `~matplotlib.colors.Colormap`, optional
-            The Colormap instance or registered colormap name used to map
-            scalar data to colors. This parameter is ignored for RGB(A) data.
-            Defaults to :rc:`image.cmap`.
-
-        norm : `~matplotlib.colors.Normalize`, optional
-            The `Normalize` instance used to scale scalar data to the [0, 1]
-            range before mapping to colors using *cmap*. By default, a linear
-            scaling mapping the lowest value to 0 and the highest to 1 is used.
-            This parameter is ignored for RGB(A) data.
-
-        aspect : {'equal', 'auto'} or float, optional
-            Controls the aspect ratio of the axes. The aspect is of particular
-            relevance for images since it may distort the image, i.e. pixel
-            will not be square.
-
-            This parameter is a shortcut for explicitly calling
-            `.Axes.set_aspect`. See there for further details.
-
-            - 'equal': Ensures an aspect ratio of 1. Pixels will be square
-              (unless pixel sizes are explicitly made non-square in data
-              coordinates using *extent*).
-            - 'auto': The axes is kept fixed and the aspect is adjusted so
-              that the data fit in the axes. In general, this will result in
-              non-square pixels.
-
-            If not given, use :rc:`image.aspect`.
-
-        interpolation : str, optional
-            The interpolation method used. If *None*, :rc:`image.interpolation`
-            is used.
-
-            Supported values are 'none', 'antialiased', 'nearest', 'bilinear',
-            'bicubic', 'spline16', 'spline36', 'hanning', 'hamming', 'hermite',
-            'kaiser', 'quadric', 'catrom', 'gaussian', 'bessel', 'mitchell',
-            'sinc', 'lanczos'.
-
-            If *interpolation* is 'none', then no interpolation is performed
-            on the Agg, ps, pdf and svg backends. Other backends will fall back
-            to 'nearest'. Note that most SVG renders perform interpolation at
-            rendering and that the default interpolation method they implement
-            may differ.
-
-            If *interpolation* is the default 'antialiased', then 'nearest'
-            interpolation is used if the image is upsampled by more than a
-            factor of three (i.e. the number of display pixels is at least
-            three times the size of the data array).  If the upsampling rate is
-            smaller than 3, or the image is downsampled, then 'hanning'
-            interpolation is used to act as an anti-aliasing filter, unless the
-            image happens to be upsampled by exactly a factor of two or one.
-
-            See
-            :doc:`/gallery/images_contours_and_fields/interpolation_methods`
-            for an overview of the supported interpolation methods, and
-            :doc:`/gallery/images_contours_and_fields/image_antialiasing` for
-            a discussion of image antialiasing.
-
-            Some interpolation methods require an additional radius parameter,
-            which can be set by *filterrad*. Additionally, the antigrain image
-            resize filter is controlled by the parameter *filternorm*.
-
-        alpha : scalar or array-like, optional
-            The alpha blending value, between 0 (transparent) and 1 (opaque).
-            If *alpha* is an array, the alpha blending values are applied pixel
-            by pixel, and *alpha* must have the same shape as *X*.
-
-        vmin, vmax : scalar, optional
-            When using scalar data and no explicit *norm*, *vmin* and *vmax*
-            define the data range that the colormap covers. By default,
-            the colormap covers the complete value range of the supplied
-            data. *vmin*, *vmax* are ignored if the *norm* parameter is used.
-
-        origin : {'upper', 'lower'}, optional
-            Place the [0, 0] index of the array in the upper left or lower left
-            corner of the axes. The convention 'upper' is typically used for
-            matrices and images.
-            If not given, :rc:`image.origin` is used, defaulting to 'upper'.
-
-            Note that the vertical axes points upward for 'lower'
-            but downward for 'upper'.
-
-            See the :doc:`/tutorials/intermediate/imshow_extent` tutorial for
-            examples and a more detailed description.
-
-        extent : scalars (left, right, bottom, top), optional
-            The bounding box in data coordinates that the image will fill.
-            The image is stretched individually along x and y to fill the box.
-
-            The default extent is determined by the following conditions.
-            Pixels have unit size in data coordinates. Their centers are on
-            integer coordinates, and their center coordinates range from 0 to
-            columns-1 horizontally and from 0 to rows-1 vertically.
-
-            Note that the direction of the vertical axis and thus the default
-            values for top and bottom depend on *origin*:
-
-            - For ``origin == 'upper'`` the default is
-              ``(-0.5, numcols-0.5, numrows-0.5, -0.5)``.
-            - For ``origin == 'lower'`` the default is
-              ``(-0.5, numcols-0.5, -0.5, numrows-0.5)``.
-
-            See the :doc:`/tutorials/intermediate/imshow_extent` tutorial for
-            examples and a more detailed description.
-
-        filternorm : bool, optional, default: True
-            A parameter for the antigrain image resize filter (see the
-            antigrain documentation).  If *filternorm* is set, the filter
-            normalizes integer values and corrects the rounding errors. It
-            doesn't do anything with the source floating point values, it
-            corrects only integers according to the rule of 1.0 which means
-            that any sum of pixel weights must be equal to 1.0.  So, the
-            filter function must produce a graph of the proper shape.
-
-        filterrad : float > 0, optional, default: 4.0
-            The filter radius for filters that have a radius parameter, i.e.
-            when interpolation is one of: 'sinc', 'lanczos' or 'blackman'.
-
-        resample : bool, optional
-            When *True*, use a full resampling method.  When *False*, only
-            resample when the output image is larger than the input image.
-
-        url : str, optional
-            Set the url of the created `.AxesImage`. See `.Artist.set_url`.
-
-        Returns
-        -------
-        image : `~matplotlib.image.AxesImage`
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.artist.Artist` properties
-            These parameters are passed on to the constructor of the
-            `.AxesImage` artist.
-
-        See also
-        --------
-        matshow : Plot a matrix or an array as an image.
-
-        Notes
-        -----
-        Unless *extent* is used, pixel centers will be located at integer
-        coordinates. In other words: the origin will coincide with the center
-        of pixel (0, 0).
-
-        There are two common representations for RGB images with an alpha
-        channel:
-
-        -   Straight (unassociated) alpha: R, G, and B channels represent the
-            color of the pixel, disregarding its opacity.
-        -   Premultiplied (associated) alpha: R, G, and B channels represent
-            the color of the pixel, adjusted for its opacity by multiplication.
-
-        `~matplotlib.pyplot.imshow` expects RGB images adopting the straight
-        (unassociated) alpha representation.
-        """
-        if aspect is None:
-            aspect = rcParams['image.aspect']
-        self.set_aspect(aspect)
-        im = mimage.AxesImage(self, cmap, norm, interpolation, origin, extent,
-                              filternorm=filternorm, filterrad=filterrad,
-                              resample=resample, **kwargs)
-
-        im.set_data(X)
-        im.set_alpha(alpha)
-        if im.get_clip_path() is None:
-            # image does not already have clipping set, clip to axes patch
-            im.set_clip_path(self.patch)
-        if vmin is not None or vmax is not None:
-            im.set_clim(vmin, vmax)
-        else:
-            im.autoscale_None()
-        im.set_url(url)
-
-        # update ax.dataLim, and, if autoscaling, set viewLim
-        # to tightly fit the image, regardless of dataLim.
-        im.set_extent(im.get_extent())
-
-        self.add_image(im)
-        return im
-
-    @staticmethod
-    def _pcolorargs(funcname, *args, allmatch=False):
-        # If allmatch is True, then the incoming X, Y, C must have matching
-        # dimensions, taking into account that X and Y can be 1-D rather than
-        # 2-D.  This perfect match is required for Gouraud shading.  For flat
-        # shading, X and Y specify boundaries, so we need one more boundary
-        # than color in each direction.  For convenience, and consistent with
-        # Matlab, we discard the last row and/or column of C if necessary to
-        # meet this condition.  This is done if allmatch is False.
-
-        if len(args) == 1:
-            C = np.asanyarray(args[0])
-            nrows, ncols = C.shape
-            if allmatch:
-                X, Y = np.meshgrid(np.arange(ncols), np.arange(nrows))
-            else:
-                X, Y = np.meshgrid(np.arange(ncols + 1), np.arange(nrows + 1))
-            C = cbook.safe_masked_invalid(C)
-            return X, Y, C
-
-        if len(args) == 3:
-            # Check x and y for bad data...
-            C = np.asanyarray(args[2])
-            X, Y = [cbook.safe_masked_invalid(a) for a in args[:2]]
-            if funcname == 'pcolormesh':
-                if np.ma.is_masked(X) or np.ma.is_masked(Y):
-                    raise ValueError(
-                        'x and y arguments to pcolormesh cannot have '
-                        'non-finite values or be of type '
-                        'numpy.ma.core.MaskedArray with masked values')
-                # safe_masked_invalid() returns an ndarray for dtypes other
-                # than floating point.
-                if isinstance(X, np.ma.core.MaskedArray):
-                    X = X.data  # strip mask as downstream doesn't like it...
-                if isinstance(Y, np.ma.core.MaskedArray):
-                    Y = Y.data
-            nrows, ncols = C.shape
-        else:
-            raise TypeError(
-                'Illegal arguments to %s; see help(%s)' % (funcname, funcname))
-
-        Nx = X.shape[-1]
-        Ny = Y.shape[0]
-        if X.ndim != 2 or X.shape[0] == 1:
-            x = X.reshape(1, Nx)
-            X = x.repeat(Ny, axis=0)
-        if Y.ndim != 2 or Y.shape[1] == 1:
-            y = Y.reshape(Ny, 1)
-            Y = y.repeat(Nx, axis=1)
-        if X.shape != Y.shape:
-            raise TypeError(
-                'Incompatible X, Y inputs to %s; see help(%s)' % (
-                funcname, funcname))
-        if allmatch:
-            if (Nx, Ny) != (ncols, nrows):
-                raise TypeError('Dimensions of C %s are incompatible with'
-                                ' X (%d) and/or Y (%d); see help(%s)' % (
-                                    C.shape, Nx, Ny, funcname))
-        else:
-            if not (ncols in (Nx, Nx - 1) and nrows in (Ny, Ny - 1)):
-                raise TypeError('Dimensions of C %s are incompatible with'
-                                ' X (%d) and/or Y (%d); see help(%s)' % (
-                                    C.shape, Nx, Ny, funcname))
-            C = C[:Ny - 1, :Nx - 1]
-        C = cbook.safe_masked_invalid(C)
-        return X, Y, C
-
-    @_preprocess_data()
-    @docstring.dedent_interpd
-    def pcolor(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
-               vmax=None, **kwargs):
-        r"""
-        Create a pseudocolor plot with a non-regular rectangular grid.
-
-        Call signature::
-
-            pcolor([X, Y,] C, **kwargs)
-
-        *X* and *Y* can be used to specify the corners of the quadrilaterals.
-
-        .. hint::
-
-            ``pcolor()`` can be very slow for large arrays. In most
-            cases you should use the similar but much faster
-            `~.Axes.pcolormesh` instead. See there for a discussion of the
-            differences.
-
-        Parameters
-        ----------
-        C : array-like
-            A scalar 2-D array. The values will be color-mapped.
-
-        X, Y : array-like, optional
-            The coordinates of the quadrilateral corners. The quadrilateral
-            for ``C[i, j]`` has corners at::
-
-                (X[i+1, j], Y[i+1, j])           (X[i+1, j+1], Y[i+1, j+1])
-                                      +---------+
-                                      | C[i, j] |
-                                      +---------+
-                    (X[i, j], Y[i, j])           (X[i, j+1], Y[i, j+1])
-
-            Note that the column index corresponds to the
-            x-coordinate, and the row index corresponds to y. For
-            details, see the :ref:`Notes <axes-pcolor-grid-orientation>`
-            section below.
-
-            The dimensions of *X* and *Y* should be one greater than those of
-            *C*. Alternatively, *X*, *Y* and *C* may have equal dimensions, in
-            which case the last row and column of *C* will be ignored.
-
-            If *X* and/or *Y* are 1-D arrays or column vectors they will be
-            expanded as needed into the appropriate 2-D arrays, making a
-            rectangular grid.
-
-        cmap : str or `~matplotlib.colors.Colormap`, optional
-            A Colormap instance or registered colormap name. The colormap
-            maps the *C* values to colors. Defaults to :rc:`image.cmap`.
-
-        norm : `~matplotlib.colors.Normalize`, optional
-            The Normalize instance scales the data values to the canonical
-            colormap range [0, 1] for mapping to colors. By default, the data
-            range is mapped to the colorbar range using linear scaling.
-
-        vmin, vmax : scalar, optional, default: None
-            The colorbar range. If *None*, suitable min/max values are
-            automatically chosen by the `~.Normalize` instance (defaults to
-            the respective min/max values of *C* in case of the default linear
-            scaling).
-
-        edgecolors : {'none', None, 'face', color, color sequence}, optional
-            The color of the edges. Defaults to 'none'. Possible values:
-
-            - 'none' or '': No edge.
-            - *None*: :rc:`patch.edgecolor` will be used. Note that currently
-              :rc:`patch.force_edgecolor` has to be True for this to work.
-            - 'face': Use the adjacent face color.
-            - A color or sequence of colors will set the edge color.
-
-            The singular form *edgecolor* works as an alias.
-
-        alpha : scalar, optional, default: None
-            The alpha blending value of the face color, between 0 (transparent)
-            and 1 (opaque). Note: The edgecolor is currently not affected by
-            this.
-
-        snap : bool, optional, default: False
-            Whether to snap the mesh to pixel boundaries.
-
-        Returns
-        -------
-        collection : `matplotlib.collections.Collection`
-
-        Other Parameters
-        ----------------
-        antialiaseds : bool, optional, default: False
-            The default *antialiaseds* is False if the default
-            *edgecolors*\ ="none" is used.  This eliminates artificial lines
-            at patch boundaries, and works regardless of the value of alpha.
-            If *edgecolors* is not "none", then the default *antialiaseds*
-            is taken from :rc:`patch.antialiased`.
-            Stroking the edges may be preferred if *alpha* is 1, but will
-            cause artifacts otherwise.
-
-        **kwargs
-            Additionally, the following arguments are allowed. They are passed
-            along to the `~matplotlib.collections.PolyCollection` constructor:
-
-        %(PolyCollection)s
-
-        See Also
-        --------
-        pcolormesh : for an explanation of the differences between
-            pcolor and pcolormesh.
-        imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a
-            faster alternative.
-
-        Notes
-        -----
-        **Masked arrays**
-
-        *X*, *Y* and *C* may be masked arrays. If either ``C[i, j]``, or one
-        of the vertices surrounding ``C[i, j]`` (*X* or *Y* at
-        ``[i, j], [i+1, j], [i, j+1], [i+1, j+1]``) is masked, nothing is
-        plotted.
-
-        .. _axes-pcolor-grid-orientation:
-
-        **Grid orientation**
-
-        The grid orientation follows the standard matrix convention: An array
-        *C* with shape (nrows, ncolumns) is plotted with the column number as
-        *X* and the row number as *Y*.
-
-        **Handling of pcolor() end-cases**
-
-        ``pcolor()`` displays all columns of *C* if *X* and *Y* are not
-        specified, or if *X* and *Y* have one more column than *C*.
-        If *X* and *Y* have the same number of columns as *C* then the last
-        column of *C* is dropped. Similarly for the rows.
-
-        Note: This behavior is different from MATLAB's ``pcolor()``, which
-        always discards the last row and column of *C*.
-        """
-        X, Y, C = self._pcolorargs('pcolor', *args, allmatch=False)
-        Ny, Nx = X.shape
-
-        # unit conversion allows e.g. datetime objects as axis values
-        self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
-        X = self.convert_xunits(X)
-        Y = self.convert_yunits(Y)
-
-        # convert to MA, if necessary.
-        C = ma.asarray(C)
-        X = ma.asarray(X)
-        Y = ma.asarray(Y)
-
-        mask = ma.getmaskarray(X) + ma.getmaskarray(Y)
-        xymask = (mask[0:-1, 0:-1] + mask[1:, 1:] +
-                  mask[0:-1, 1:] + mask[1:, 0:-1])
-        # don't plot if C or any of the surrounding vertices are masked.
-        mask = ma.getmaskarray(C) + xymask
-
-        unmask = ~mask
-        X1 = ma.filled(X[:-1, :-1])[unmask]
-        Y1 = ma.filled(Y[:-1, :-1])[unmask]
-        X2 = ma.filled(X[1:, :-1])[unmask]
-        Y2 = ma.filled(Y[1:, :-1])[unmask]
-        X3 = ma.filled(X[1:, 1:])[unmask]
-        Y3 = ma.filled(Y[1:, 1:])[unmask]
-        X4 = ma.filled(X[:-1, 1:])[unmask]
-        Y4 = ma.filled(Y[:-1, 1:])[unmask]
-        npoly = len(X1)
-
-        xy = np.stack([X1, Y1, X2, Y2, X3, Y3, X4, Y4, X1, Y1], axis=-1)
-        verts = xy.reshape((npoly, 5, 2))
-
-        C = ma.filled(C[:Ny - 1, :Nx - 1])[unmask]
-
-        linewidths = (0.25,)
-        if 'linewidth' in kwargs:
-            kwargs['linewidths'] = kwargs.pop('linewidth')
-        kwargs.setdefault('linewidths', linewidths)
-
-        if 'edgecolor' in kwargs:
-            kwargs['edgecolors'] = kwargs.pop('edgecolor')
-        ec = kwargs.setdefault('edgecolors', 'none')
-
-        # aa setting will default via collections to patch.antialiased
-        # unless the boundary is not stroked, in which case the
-        # default will be False; with unstroked boundaries, aa
-        # makes artifacts that are often disturbing.
-        if 'antialiased' in kwargs:
-            kwargs['antialiaseds'] = kwargs.pop('antialiased')
-        if 'antialiaseds' not in kwargs and cbook._str_lower_equal(ec, "none"):
-            kwargs['antialiaseds'] = False
-
-        kwargs.setdefault('snap', False)
-
-        collection = mcoll.PolyCollection(verts, **kwargs)
-
-        collection.set_alpha(alpha)
-        collection.set_array(C)
-        collection.set_cmap(cmap)
-        collection.set_norm(norm)
-        collection.set_clim(vmin, vmax)
-        collection.autoscale_None()
-        self.grid(False)
-
-        x = X.compressed()
-        y = Y.compressed()
-
-        # Transform from native to data coordinates?
-        t = collection._transform
-        if (not isinstance(t, mtransforms.Transform) and
-            hasattr(t, '_as_mpl_transform')):
-            t = t._as_mpl_transform(self.axes)
-
-        if t and any(t.contains_branch_seperately(self.transData)):
-            trans_to_data = t - self.transData
-            pts = np.vstack([x, y]).T.astype(float)
-            transformed_pts = trans_to_data.transform(pts)
-            x = transformed_pts[..., 0]
-            y = transformed_pts[..., 1]
-
-        self.add_collection(collection, autolim=False)
-
-        minx = np.min(x)
-        maxx = np.max(x)
-        miny = np.min(y)
-        maxy = np.max(y)
-        collection.sticky_edges.x[:] = [minx, maxx]
-        collection.sticky_edges.y[:] = [miny, maxy]
-        corners = (minx, miny), (maxx, maxy)
-        self.update_datalim(corners)
-        self._request_autoscale_view()
-        return collection
-
-    @_preprocess_data()
-    @docstring.dedent_interpd
-    def pcolormesh(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
-                   vmax=None, shading='flat', antialiased=False, **kwargs):
-        """
-        Create a pseudocolor plot with a non-regular rectangular grid.
-
-        Call signature::
-
-            pcolor([X, Y,] C, **kwargs)
-
-        *X* and *Y* can be used to specify the corners of the quadrilaterals.
-
-        .. note::
-
-           `~Axes.pcolormesh` is similar to `~Axes.pcolor`. It's much faster
-           and preferred in most cases. For a detailed discussion on the
-           differences see :ref:`Differences between pcolor() and pcolormesh()
-           <differences-pcolor-pcolormesh>`.
-
-        Parameters
-        ----------
-        C : array-like
-            A scalar 2-D array. The values will be color-mapped.
-
-        X, Y : array-like, optional
-            The coordinates of the quadrilateral corners. The quadrilateral
-            for ``C[i, j]`` has corners at::
-
-                (X[i+1, j], Y[i+1, j])           (X[i+1, j+1], Y[i+1, j+1])
-                                      +---------+
-                                      | C[i, j] |
-                                      +---------+
-                    (X[i, j], Y[i, j])           (X[i, j+1], Y[i, j+1])
-
-            Note that the column index corresponds to the
-            x-coordinate, and the row index corresponds to y. For
-            details, see the :ref:`Notes <axes-pcolormesh-grid-orientation>`
-            section below.
-
-            The dimensions of *X* and *Y* should be one greater than those of
-            *C*. Alternatively, *X*, *Y* and *C* may have equal dimensions, in
-            which case the last row and column of *C* will be ignored.
-
-            If *X* and/or *Y* are 1-D arrays or column vectors they will be
-            expanded as needed into the appropriate 2-D arrays, making a
-            rectangular grid.
-
-        cmap : str or `~matplotlib.colors.Colormap`, optional
-            A Colormap instance or registered colormap name. The colormap
-            maps the *C* values to colors. Defaults to :rc:`image.cmap`.
-
-        norm : `~matplotlib.colors.Normalize`, optional
-            The Normalize instance scales the data values to the canonical
-            colormap range [0, 1] for mapping to colors. By default, the data
-            range is mapped to the colorbar range using linear scaling.
-
-        vmin, vmax : scalar, optional, default: None
-            The colorbar range. If *None*, suitable min/max values are
-            automatically chosen by the `~.Normalize` instance (defaults to
-            the respective min/max values of *C* in case of the default linear
-            scaling).
-
-        edgecolors : {'none', None, 'face', color, color sequence}, optional
-            The color of the edges. Defaults to 'none'. Possible values:
-
-            - 'none' or '': No edge.
-            - *None*: :rc:`patch.edgecolor` will be used. Note that currently
-              :rc:`patch.force_edgecolor` has to be True for this to work.
-            - 'face': Use the adjacent face color.
-            - A color or sequence of colors will set the edge color.
-
-            The singular form *edgecolor* works as an alias.
-
-        alpha : scalar, optional, default: None
-            The alpha blending value, between 0 (transparent) and 1 (opaque).
-
-        shading : {'flat', 'gouraud'}, optional
-            The fill style, Possible values:
-
-            - 'flat': A solid color is used for each quad. The color of the
-              quad (i, j), (i+1, j), (i, j+1), (i+1, j+1) is given by
-              ``C[i, j]``.
-            - 'gouraud': Each quad will be Gouraud shaded: The color of the
-              corners (i', j') are given by ``C[i',j']``. The color values of
-              the area in between is interpolated from the corner values.
-              When Gouraud shading is used, *edgecolors* is ignored.
-
-        snap : bool, optional, default: False
-            Whether to snap the mesh to pixel boundaries.
-
-        Returns
-        -------
-        mesh : `matplotlib.collections.QuadMesh`
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Additionally, the following arguments are allowed. They are passed
-            along to the `~matplotlib.collections.QuadMesh` constructor:
-
-        %(QuadMesh)s
-
-        See Also
-        --------
-        pcolor : An alternative implementation with slightly different
-            features. For a detailed discussion on the differences see
-            :ref:`Differences between pcolor() and pcolormesh()
-            <differences-pcolor-pcolormesh>`.
-        imshow : If *X* and *Y* are each equidistant, `~.Axes.imshow` can be a
-            faster alternative.
-
-        Notes
-        -----
-        **Masked arrays**
-
-        *C* may be a masked array. If ``C[i, j]`` is masked, the corresponding
-        quadrilateral will be transparent. Masking of *X* and *Y* is not
-        supported. Use `~.Axes.pcolor` if you need this functionality.
-
-        .. _axes-pcolormesh-grid-orientation:
-
-        **Grid orientation**
-
-        The grid orientation follows the standard matrix convention: An array
-        *C* with shape (nrows, ncolumns) is plotted with the column number as
-        *X* and the row number as *Y*.
-
-        .. _differences-pcolor-pcolormesh:
-
-        **Differences between pcolor() and pcolormesh()**
-
-        Both methods are used to create a pseudocolor plot of a 2-D array
-        using quadrilaterals.
-
-        The main difference lies in the created object and internal data
-        handling:
-        While `~.Axes.pcolor` returns a `.PolyCollection`, `~.Axes.pcolormesh`
-        returns a `.QuadMesh`. The latter is more specialized for the given
-        purpose and thus is faster. It should almost always be preferred.
-
-        There is also a slight difference in the handling of masked arrays.
-        Both `~.Axes.pcolor` and `~.Axes.pcolormesh` support masked arrays
-        for *C*. However, only `~.Axes.pcolor` supports masked arrays for *X*
-        and *Y*. The reason lies in the internal handling of the masked values.
-        `~.Axes.pcolor` leaves out the respective polygons from the
-        PolyCollection. `~.Axes.pcolormesh` sets the facecolor of the masked
-        elements to transparent. You can see the difference when using
-        edgecolors. While all edges are drawn irrespective of masking in a
-        QuadMesh, the edge between two adjacent masked quadrilaterals in
-        `~.Axes.pcolor` is not drawn as the corresponding polygons do not
-        exist in the PolyCollection.
-
-        Another difference is the support of Gouraud shading in
-        `~.Axes.pcolormesh`, which is not available with `~.Axes.pcolor`.
-
-        """
-        shading = shading.lower()
-        kwargs.setdefault('edgecolors', 'None')
-
-        allmatch = (shading == 'gouraud')
-
-        X, Y, C = self._pcolorargs('pcolormesh', *args, allmatch=allmatch)
-        Ny, Nx = X.shape
-        X = X.ravel()
-        Y = Y.ravel()
-        # unit conversion allows e.g. datetime objects as axis values
-        self._process_unit_info(xdata=X, ydata=Y, kwargs=kwargs)
-        X = self.convert_xunits(X)
-        Y = self.convert_yunits(Y)
-
-        # convert to one dimensional arrays
-        C = C.ravel()
-        coords = np.column_stack((X, Y)).astype(float, copy=False)
-        collection = mcoll.QuadMesh(Nx - 1, Ny - 1, coords,
-                                    antialiased=antialiased, shading=shading,
-                                    **kwargs)
-        collection.set_alpha(alpha)
-        collection.set_array(C)
-        collection.set_cmap(cmap)
-        collection.set_norm(norm)
-        collection.set_clim(vmin, vmax)
-        collection.autoscale_None()
-
-        self.grid(False)
-
-        # Transform from native to data coordinates?
-        t = collection._transform
-        if (not isinstance(t, mtransforms.Transform) and
-            hasattr(t, '_as_mpl_transform')):
-            t = t._as_mpl_transform(self.axes)
-
-        if t and any(t.contains_branch_seperately(self.transData)):
-            trans_to_data = t - self.transData
-            coords = trans_to_data.transform(coords)
-
-        self.add_collection(collection, autolim=False)
-
-        minx, miny = np.min(coords, axis=0)
-        maxx, maxy = np.max(coords, axis=0)
-        collection.sticky_edges.x[:] = [minx, maxx]
-        collection.sticky_edges.y[:] = [miny, maxy]
-        corners = (minx, miny), (maxx, maxy)
-        self.update_datalim(corners)
-        self._request_autoscale_view()
-        return collection
-
-    @_preprocess_data()
-    @docstring.dedent_interpd
-    def pcolorfast(self, *args, alpha=None, norm=None, cmap=None, vmin=None,
-                   vmax=None, **kwargs):
-        """
-        Create a pseudocolor plot with a non-regular rectangular grid.
-
-        Call signature::
-
-          ax.pcolorfast([X, Y], C, /, **kwargs)
-
-        This method is similar to ~.Axes.pcolor` and `~.Axes.pcolormesh`.
-        It's designed to provide the fastest pcolor-type plotting with the
-        Agg backend. To achieve this, it uses different algorithms internally
-        depending on the complexity of the input grid (regular rectangular,
-        non-regular rectangular or arbitrary quadrilateral).
-
-        .. warning::
-
-           This method is experimental. Compared to `~.Axes.pcolor` or
-           `~.Axes.pcolormesh` it has some limitations:
-
-           - It supports only flat shading (no outlines)
-           - It lacks support for log scaling of the axes.
-           - It does not have a have a pyplot wrapper.
-
-        Parameters
-        ----------
-        C : array-like(M, N)
-            The image data. Supported array shapes are:
-
-            - (M, N): an image with scalar data. The data is visualized
-              using a colormap.
-            - (M, N, 3): an image with RGB values (0-1 float or 0-255 int).
-            - (M, N, 4): an image with RGBA values (0-1 float or 0-255 int),
-              i.e. including transparency.
-
-            The first two dimensions (M, N) define the rows and columns of
-            the image.
-
-            This parameter can only be passed positionally.
-
-        X, Y : tuple or array-like, default: ``(0, N)``, ``(0, M)``
-            *X* and *Y* are used to specify the coordinates of the
-            quadrilaterals. There are different ways to do this:
-
-            - Use tuples ``X=(xmin, xmax)`` and ``Y=(ymin, ymax)`` to define
-              a *uniform rectangular grid*.
-
-              The tuples define the outer edges of the grid. All individual
-              quadrilaterals will be of the same size. This is the fastest
-              version.
-
-            - Use 1D arrays *X*, *Y* to specify a *non-uniform rectangular
-              grid*.
-
-              In this case *X* and *Y* have to be monotonic 1D arrays of length
-              *N+1* and *M+1*, specifying the x and y boundaries of the cells.
-
-              The speed is intermediate. Note: The grid is checked, and if
-              found to be uniform the fast version is used.
-
-            - Use 2D arrays *X*, *Y* if you need an *arbitrary quadrilateral
-              grid* (i.e. if the quadrilaterals are not rectangular).
-
-              In this case *X* and *Y* are 2D arrays with shape (M + 1, N + 1),
-              specifying the x and y coordinates of the corners of the colored
-              quadrilaterals.
-
-              This is the most general, but the slowest to render.  It may
-              produce faster and more compact output using ps, pdf, and
-              svg backends, however.
-
-            These arguments can only be passed positionally.
-
-        cmap : str or `~matplotlib.colors.Colormap`, optional
-            A Colormap instance or registered colormap name. The colormap
-            maps the *C* values to colors. Defaults to :rc:`image.cmap`.
-
-        norm : `~matplotlib.colors.Normalize`, optional
-            The Normalize instance scales the data values to the canonical
-            colormap range [0, 1] for mapping to colors. By default, the data
-            range is mapped to the colorbar range using linear scaling.
-
-        vmin, vmax : scalar, optional, default: None
-            The colorbar range. If *None*, suitable min/max values are
-            automatically chosen by the `~.Normalize` instance (defaults to
-            the respective min/max values of *C* in case of the default linear
-            scaling).
-
-        alpha : scalar, optional, default: None
-            The alpha blending value, between 0 (transparent) and 1 (opaque).
-
-        snap : bool, optional, default: False
-            Whether to snap the mesh to pixel boundaries.
-
-        Returns
-        -------
-        image : `.AxesImage` or `.PcolorImage` or `.QuadMesh`
-            The return type depends on the type of grid:
-
-            - `.AxesImage` for a regular rectangular grid.
-            - `.PcolorImage` for a non-regular rectangular grid.
-            - `.QuadMesh` for a non-rectangular grid.
-
-        Notes
-        -----
-        .. [notes section required to get data note injection right]
-        """
-
-        C = args[-1]
-        nr, nc = np.shape(C)[:2]
-        if len(args) == 1:
-            style = "image"
-            x = [0, nc]
-            y = [0, nr]
-        elif len(args) == 3:
-            x, y = args[:2]
-            x = np.asarray(x)
-            y = np.asarray(y)
-            if x.ndim == 1 and y.ndim == 1:
-                if x.size == 2 and y.size == 2:
-                    style = "image"
-                else:
-                    dx = np.diff(x)
-                    dy = np.diff(y)
-                    if (np.ptp(dx) < 0.01 * np.abs(dx.mean()) and
-                        np.ptp(dy) < 0.01 * np.abs(dy.mean())):
-                        style = "image"
-                    else:
-                        style = "pcolorimage"
-            elif x.ndim == 2 and y.ndim == 2:
-                style = "quadmesh"
-            else:
-                raise TypeError("arguments do not match valid signatures")
-        else:
-            raise TypeError("need 1 argument or 3 arguments")
-
-        if style == "quadmesh":
-            # data point in each cell is value at lower left corner
-            coords = np.stack([x, y], axis=-1)
-            if np.ndim(C) == 2:
-                qm_kwargs = {"array": np.ma.ravel(C)}
-            elif np.ndim(C) == 3:
-                qm_kwargs = {"color": np.ma.reshape(C, (-1, C.shape[-1]))}
-            else:
-                raise ValueError("C must be 2D or 3D")
-            collection = mcoll.QuadMesh(
-                nc, nr, coords, **qm_kwargs,
-                alpha=alpha, cmap=cmap, norm=norm,
-                antialiased=False, edgecolors="none")
-            self.add_collection(collection, autolim=False)
-            xl, xr, yb, yt = x.min(), x.max(), y.min(), y.max()
-            ret = collection
-
-        else:  # It's one of the two image styles.
-            extent = xl, xr, yb, yt = x[0], x[-1], y[0], y[-1]
-            if style == "image":
-                im = mimage.AxesImage(
-                    self, cmap, norm,
-                    data=C, alpha=alpha, extent=extent,
-                    interpolation='nearest', origin='lower',
-                    **kwargs)
-            elif style == "pcolorimage":
-                im = mimage.PcolorImage(
-                    self, x, y, C,
-                    cmap=cmap, norm=norm, alpha=alpha, extent=extent,
-                    **kwargs)
-            self.add_image(im)
-            ret = im
-
-        if vmin is not None or vmax is not None:
-            ret.set_clim(vmin, vmax)
-        elif np.ndim(C) == 2:  # C.ndim == 3 is RGB(A) so doesn't need scaling.
-            ret.autoscale_None()
-        if ret.get_clip_path() is None:
-            # image does not already have clipping set, clip to axes patch
-            ret.set_clip_path(self.patch)
-
-        ret.sticky_edges.x[:] = [xl, xr]
-        ret.sticky_edges.y[:] = [yb, yt]
-        self.update_datalim(np.array([[xl, yb], [xr, yt]]))
-        self._request_autoscale_view(tight=True)
-        return ret
-
-    @_preprocess_data()
-    def contour(self, *args, **kwargs):
-        kwargs['filled'] = False
-        contours = mcontour.QuadContourSet(self, *args, **kwargs)
-        self._request_autoscale_view()
-        return contours
-    contour.__doc__ = mcontour.QuadContourSet._contour_doc
-
-    @_preprocess_data()
-    def contourf(self, *args, **kwargs):
-        kwargs['filled'] = True
-        contours = mcontour.QuadContourSet(self, *args, **kwargs)
-        self._request_autoscale_view()
-        return contours
-    contourf.__doc__ = mcontour.QuadContourSet._contour_doc
-
-    def clabel(self, CS, *args, **kwargs):
-        return CS.clabel(*args, **kwargs)
-    clabel.__doc__ = mcontour.ContourSet.clabel.__doc__
-
-    #### Data analysis
-
-    @_preprocess_data(replace_names=["x", 'weights'], label_namer="x")
-    def hist(self, x, bins=None, range=None, density=False, weights=None,
-             cumulative=False, bottom=None, histtype='bar', align='mid',
-             orientation='vertical', rwidth=None, log=False,
-             color=None, label=None, stacked=False, **kwargs):
-        """
-        Plot a histogram.
-
-        Compute and draw the histogram of *x*.  The return value is a tuple
-        (*n*, *bins*, *patches*) or ([*n0*, *n1*, ...], *bins*, [*patches0*,
-        *patches1*,...]) if the input contains multiple data.  See the
-        documentation of the *weights* parameter to draw a histogram of
-        already-binned data.
-
-        Multiple data can be provided via *x* as a list of datasets
-        of potentially different length ([*x0*, *x1*, ...]), or as
-        a 2-D ndarray in which each column is a dataset.  Note that
-        the ndarray form is transposed relative to the list form.
-
-        Masked arrays are not supported.
-
-        The *bins*, *range*, *weights*, and *density* parameters behave as in
-        `numpy.histogram`.
-
-        Parameters
-        ----------
-        x : (n,) array or sequence of (n,) arrays
-            Input values, this takes either a single array or a sequence of
-            arrays which are not required to be of the same length.
-
-        bins : int or sequence or str, optional
-            If *bins* is an integer, it defines the number of equal-width bins
-            in the range.
-
-            If *bins* is a sequence, it defines the bin edges, including the
-            left edge of the first bin and the right edge of the last bin;
-            in this case, bins may be unequally spaced.  All but the last
-            (righthand-most) bin is half-open.  In other words, if *bins* is::
-
-                [1, 2, 3, 4]
-
-            then the first bin is ``[1, 2)`` (including 1, but excluding 2) and
-            the second ``[2, 3)``.  The last bin, however, is ``[3, 4]``, which
-            *includes* 4.
-
-            If *bins* is a string, it is one of the binning strategies
-            supported by `numpy.histogram_bin_edges`: 'auto', 'fd', 'doane',
-            'scott', 'stone', 'rice', 'sturges', or 'sqrt'.
-
-            The default is :rc:`hist.bins`.
-
-        range : tuple or None, optional
-            The lower and upper range of the bins. Lower and upper outliers
-            are ignored. If not provided, *range* is ``(x.min(), x.max())``.
-            Range has no effect if *bins* is a sequence.
-
-            If *bins* is a sequence or *range* is specified, autoscaling
-            is based on the specified bin range instead of the
-            range of x.
-
-            Default is ``None``
-
-        density : bool, optional
-            If ``True``, the first element of the return tuple will
-            be the counts normalized to form a probability density, i.e.,
-            the area (or integral) under the histogram will sum to 1.
-            This is achieved by dividing the count by the number of
-            observations times the bin width and not dividing by the total
-            number of observations. If *stacked* is also ``True``, the sum of
-            the histograms is normalized to 1.
-
-            Default is ``False``.
-
-        weights : (n, ) array-like or None, optional
-            An array of weights, of the same shape as *x*.  Each value in *x*
-            only contributes its associated weight towards the bin count
-            (instead of 1).  If *normed* or *density* is ``True``,
-            the weights are normalized, so that the integral of the density
-            over the range remains 1.
-
-            Default is ``None``.
-
-            This parameter can be used to draw a histogram of data that has
-            already been binned, e.g. using `np.histogram` (by treating each
-            bin as a single point with a weight equal to its count) ::
-
-                counts, bins = np.histogram(data)
-                plt.hist(bins[:-1], bins, weights=counts)
-
-            (or you may alternatively use `~.bar()`).
-
-        cumulative : bool or -1, optional
-            If ``True``, then a histogram is computed where each bin gives the
-            counts in that bin plus all bins for smaller values. The last bin
-            gives the total number of datapoints.
-
-            If *density* is also ``True`` then the histogram is normalized such
-            that the last bin equals 1.
-
-            If *cumulative* is a number less than 0 (e.g., -1), the direction
-            of accumulation is reversed.  In this case, if *density* is also
-            ``True``, then the histogram is normalized such that the first bin
-            equals 1.
-
-        bottom : array-like, scalar, or None, default: None
-            Location of the bottom of each bin, ie. bins are drawn from
-            ``bottom`` to ``bottom + hist(x, bins)`` If a scalar, the bottom
-            of each bin is shifted by the same amount. If an array, each bin
-            is shifted independently and the length of bottom must match the
-            number of bins. If None, defaults to 0.
-
-        histtype : {'bar', 'barstacked', 'step',  'stepfilled'}, optional
-            The type of histogram to draw.
-
-            - 'bar' is a traditional bar-type histogram.  If multiple data
-              are given the bars are arranged side by side.
-            - 'barstacked' is a bar-type histogram where multiple
-              data are stacked on top of each other.
-            - 'step' generates a lineplot that is by default unfilled.
-            - 'stepfilled' generates a lineplot that is by default filled.
-
-            Default is 'bar'
-
-        align : {'left', 'mid', 'right'}, optional
-            Controls how the histogram is plotted.
-
-            - 'left': bars are centered on the left bin edges.
-            - 'mid': bars are centered between the bin edges.
-            - 'right': bars are centered on the right bin edges.
-
-            Default is 'mid'
-
-        orientation : {'horizontal', 'vertical'}, optional
-            If 'horizontal', `~matplotlib.pyplot.barh` will be used for
-            bar-type histograms and the *bottom* kwarg will be the left edges.
-
-        rwidth : scalar or None, optional
-            The relative width of the bars as a fraction of the bin width.  If
-            ``None``, automatically compute the width.
-
-            Ignored if *histtype* is 'step' or 'stepfilled'.
-
-            Default is ``None``
-
-        log : bool, optional
-            If ``True``, the histogram axis will be set to a log scale. If
-            *log* is ``True`` and *x* is a 1D array, empty bins will be
-            filtered out and only the non-empty ``(n, bins, patches)``
-            will be returned.
-
-            Default is ``False``
-
-        color : color or array-like of colors or None, optional
-            Color or sequence of colors, one per dataset.  Default (``None``)
-            uses the standard line color sequence.
-
-            Default is ``None``
-
-        label : str or None, optional
-            String, or sequence of strings to match multiple datasets.  Bar
-            charts yield multiple patches per dataset, but only the first gets
-            the label, so that the legend command will work as expected.
-
-            default is ``None``
-
-        stacked : bool, optional
-            If ``True``, multiple data are stacked on top of each other If
-            ``False`` multiple data are arranged side by side if histtype is
-            'bar' or on top of each other if histtype is 'step'
-
-            Default is ``False``
-
-        Returns
-        -------
-        n : array or list of arrays
-            The values of the histogram bins. See *density* and *weights* for a
-            description of the possible semantics.  If input *x* is an array,
-            then this is an array of length *nbins*. If input is a sequence of
-            arrays ``[data1, data2, ...]``, then this is a list of arrays with
-            the values of the histograms for each of the arrays in the same
-            order.  The dtype of the array *n* (or of its element arrays) will
-            always be float even if no weighting or normalization is used.
-
-        bins : array
-            The edges of the bins. Length nbins + 1 (nbins left edges and right
-            edge of last bin).  Always a single array even when multiple data
-            sets are passed in.
-
-        patches : list or list of lists
-            Silent list of individual patches used to create the histogram
-            or list of such list if multiple input datasets.
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.patches.Patch` properties
-
-        See also
-        --------
-        hist2d : 2D histograms
-
-        """
-        # Avoid shadowing the builtin.
-        bin_range = range
-        from builtins import range
-
-        if np.isscalar(x):
-            x = [x]
-
-        if bins is None:
-            bins = rcParams['hist.bins']
-
-        # Validate string inputs here to avoid cluttering subsequent code.
-        cbook._check_in_list(['bar', 'barstacked', 'step', 'stepfilled'],
-                             histtype=histtype)
-        cbook._check_in_list(['left', 'mid', 'right'], align=align)
-        cbook._check_in_list(['horizontal', 'vertical'],
-                             orientation=orientation)
-
-        if histtype == 'barstacked' and not stacked:
-            stacked = True
-
-        # basic input validation
-        input_empty = np.size(x) == 0
-        # Massage 'x' for processing.
-        x = cbook._reshape_2D(x, 'x')
-        nx = len(x)  # number of datasets
-
-        # Process unit information
-        # Unit conversion is done individually on each dataset
-        self._process_unit_info(xdata=x[0], kwargs=kwargs)
-        x = [self.convert_xunits(xi) for xi in x]
-
-        if bin_range is not None:
-            bin_range = self.convert_xunits(bin_range)
-
-        if not cbook.is_scalar_or_string(bins):
-            bins = self.convert_xunits(bins)
-
-        # We need to do to 'weights' what was done to 'x'
-        if weights is not None:
-            w = cbook._reshape_2D(weights, 'weights')
-        else:
-            w = [None] * nx
-
-        if len(w) != nx:
-            raise ValueError('weights should have the same shape as x')
-
-        for xi, wi in zip(x, w):
-            if wi is not None and len(wi) != len(xi):
-                raise ValueError(
-                    'weights should have the same shape as x')
-
-        if color is None:
-            color = [self._get_lines.get_next_color() for i in range(nx)]
-        else:
-            color = mcolors.to_rgba_array(color)
-            if len(color) != nx:
-                error_message = (
-                    "color kwarg must have one color per data set. %d data "
-                    "sets and %d colors were provided" % (nx, len(color)))
-                raise ValueError(error_message)
-
-        hist_kwargs = dict()
-
-        # if the bin_range is not given, compute without nan numpy
-        # does not do this for us when guessing the range (but will
-        # happily ignore nans when computing the histogram).
-        if bin_range is None:
-            xmin = np.inf
-            xmax = -np.inf
-            for xi in x:
-                if len(xi):
-                    # python's min/max ignore nan,
-                    # np.minnan returns nan for all nan input
-                    xmin = min(xmin, np.nanmin(xi))
-                    xmax = max(xmax, np.nanmax(xi))
-            # make sure we have seen at least one non-nan and finite
-            # value before we reset the bin range
-            if not np.isnan([xmin, xmax]).any() and not (xmin > xmax):
-                bin_range = (xmin, xmax)
-
-        # If bins are not specified either explicitly or via range,
-        # we need to figure out the range required for all datasets,
-        # and supply that to np.histogram.
-        if not input_empty and len(x) > 1:
-            if weights is not None:
-                _w = np.concatenate(w)
-            else:
-                _w = None
-
-            bins = _histogram_bin_edges(np.concatenate(x), bins, bin_range, _w)
-        else:
-            hist_kwargs['range'] = bin_range
-
-        density = bool(density)
-        if density and not stacked:
-            hist_kwargs['density'] = density
-
-        # List to store all the top coordinates of the histograms
-        tops = []  # Will have shape (n_datasets, n_bins).
-        # Loop through datasets
-        for i in range(nx):
-            # this will automatically overwrite bins,
-            # so that each histogram uses the same bins
-            m, bins = np.histogram(x[i], bins, weights=w[i], **hist_kwargs)
-            tops.append(m)
-        tops = np.array(tops, float)  # causes problems later if it's an int
-        if stacked:
-            tops = tops.cumsum(axis=0)
-            # If a stacked density plot, normalize so the area of all the
-            # stacked histograms together is 1
-            if density:
-                tops = (tops / np.diff(bins)) / tops[-1].sum()
-        if cumulative:
-            slc = slice(None)
-            if isinstance(cumulative, Number) and cumulative < 0:
-                slc = slice(None, None, -1)
-            if density:
-                tops = (tops * np.diff(bins))[:, slc].cumsum(axis=1)[:, slc]
-            else:
-                tops = tops[:, slc].cumsum(axis=1)[:, slc]
-
-        patches = []
-
-        # Save autoscale state for later restoration; turn autoscaling
-        # off so we can do it all a single time at the end, instead
-        # of having it done by bar or fill and then having to be redone.
-        _saved_autoscalex = self.get_autoscalex_on()
-        _saved_autoscaley = self.get_autoscaley_on()
-        self.set_autoscalex_on(False)
-        self.set_autoscaley_on(False)
-
-        if histtype.startswith('bar'):
-
-            totwidth = np.diff(bins)
-
-            if rwidth is not None:
-                dr = np.clip(rwidth, 0, 1)
-            elif (len(tops) > 1 and
-                  ((not stacked) or rcParams['_internal.classic_mode'])):
-                dr = 0.8
-            else:
-                dr = 1.0
-
-            if histtype == 'bar' and not stacked:
-                width = dr * totwidth / nx
-                dw = width
-                boffset = -0.5 * dr * totwidth * (1 - 1 / nx)
-            elif histtype == 'barstacked' or stacked:
-                width = dr * totwidth
-                boffset, dw = 0.0, 0.0
-
-            if align == 'mid':
-                boffset += 0.5 * totwidth
-            elif align == 'right':
-                boffset += totwidth
-
-            if orientation == 'horizontal':
-                _barfunc = self.barh
-                bottom_kwarg = 'left'
-            else:  # orientation == 'vertical'
-                _barfunc = self.bar
-                bottom_kwarg = 'bottom'
-
-            for m, c in zip(tops, color):
-                if bottom is None:
-                    bottom = np.zeros(len(m))
-                if stacked:
-                    height = m - bottom
-                else:
-                    height = m
-                patch = _barfunc(bins[:-1]+boffset, height, width,
-                                 align='center', log=log,
-                                 color=c, **{bottom_kwarg: bottom})
-                patches.append(patch)
-                if stacked:
-                    bottom[:] = m
-                boffset += dw
-
-        elif histtype.startswith('step'):
-            # these define the perimeter of the polygon
-            x = np.zeros(4 * len(bins) - 3)
-            y = np.zeros(4 * len(bins) - 3)
-
-            x[0:2*len(bins)-1:2], x[1:2*len(bins)-1:2] = bins, bins[:-1]
-            x[2*len(bins)-1:] = x[1:2*len(bins)-1][::-1]
-
-            if bottom is None:
-                bottom = np.zeros(len(bins) - 1)
-
-            y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = bottom, bottom
-            y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1]
-
-            if log:
-                if orientation == 'horizontal':
-                    self.set_xscale('log', nonposx='clip')
-                else:  # orientation == 'vertical'
-                    self.set_yscale('log', nonposy='clip')
-
-            if align == 'left':
-                x -= 0.5*(bins[1]-bins[0])
-            elif align == 'right':
-                x += 0.5*(bins[1]-bins[0])
-
-            # If fill kwarg is set, it will be passed to the patch collection,
-            # overriding this
-            fill = (histtype == 'stepfilled')
-
-            xvals, yvals = [], []
-            for m in tops:
-                if stacked:
-                    # starting point for drawing polygon
-                    y[0] = y[1]
-                    # top of the previous polygon becomes the bottom
-                    y[2*len(bins)-1:] = y[1:2*len(bins)-1][::-1]
-                # set the top of this polygon
-                y[1:2*len(bins)-1:2], y[2:2*len(bins):2] = (m + bottom,
-                                                            m + bottom)
-                if orientation == 'horizontal':
-                    xvals.append(y.copy())
-                    yvals.append(x.copy())
-                else:
-                    xvals.append(x.copy())
-                    yvals.append(y.copy())
-
-            # stepfill is closed, step is not
-            split = -1 if fill else 2 * len(bins)
-            # add patches in reverse order so that when stacking,
-            # items lower in the stack are plotted on top of
-            # items higher in the stack
-            for x, y, c in reversed(list(zip(xvals, yvals, color))):
-                patches.append(self.fill(
-                    x[:split], y[:split],
-                    closed=True if fill else None,
-                    facecolor=c,
-                    edgecolor=None if fill else c,
-                    fill=fill if fill else None))
-            for patch_list in patches:
-                for patch in patch_list:
-                    if orientation == 'vertical':
-                        patch.sticky_edges.y.append(0)
-                    elif orientation == 'horizontal':
-                        patch.sticky_edges.x.append(0)
-
-            # we return patches, so put it back in the expected order
-            patches.reverse()
-
-        self.set_autoscalex_on(_saved_autoscalex)
-        self.set_autoscaley_on(_saved_autoscaley)
-        self._request_autoscale_view()
-
-        if label is None:
-            labels = [None]
-        elif isinstance(label, str):
-            labels = [label]
-        elif not np.iterable(label):
-            labels = [str(label)]
-        else:
-            labels = [str(lab) for lab in label]
-
-        for patch, lbl in itertools.zip_longest(patches, labels):
-            if patch:
-                p = patch[0]
-                p.update(kwargs)
-                if lbl is not None:
-                    p.set_label(lbl)
-
-                for p in patch[1:]:
-                    p.update(kwargs)
-                    p.set_label('_nolegend_')
-
-        if nx == 1:
-            return tops[0], bins, cbook.silent_list('Patch', patches[0])
-        else:
-            return tops, bins, cbook.silent_list('Lists of Patches', patches)
-
-    @_preprocess_data(replace_names=["x", "y", "weights"])
-    @cbook._rename_parameter("3.1", "normed", "density")
-    def hist2d(self, x, y, bins=10, range=None, density=False, weights=None,
-               cmin=None, cmax=None, **kwargs):
-        """
-        Make a 2D histogram plot.
-
-        Parameters
-        ----------
-        x, y : array-like, shape (n, )
-            Input values
-
-        bins : None or int or [int, int] or array-like or [array, array]
-
-            The bin specification:
-
-            - If int, the number of bins for the two dimensions
-              (nx=ny=bins).
-            - If ``[int, int]``, the number of bins in each dimension
-              (nx, ny = bins).
-            - If array-like, the bin edges for the two dimensions
-              (x_edges=y_edges=bins).
-            - If ``[array, array]``, the bin edges in each dimension
-              (x_edges, y_edges = bins).
-
-            The default value is 10.
-
-        range : array-like shape(2, 2), optional, default: None
-            The leftmost and rightmost edges of the bins along each dimension
-            (if not specified explicitly in the bins parameters): ``[[xmin,
-            xmax], [ymin, ymax]]``. All values outside of this range will be
-            considered outliers and not tallied in the histogram.
-
-        density : bool, optional, default: False
-            Normalize histogram.  *normed* is a deprecated synonym for this
-            parameter.
-
-        weights : array-like, shape (n, ), optional, default: None
-            An array of values w_i weighing each sample (x_i, y_i).
-
-        cmin : scalar, optional, default: None
-            All bins that has count less than cmin will not be displayed (set
-            to NaN before passing to imshow) and these count values in the
-            return value count histogram will also be set to nan upon return.
-
-        cmax : scalar, optional, default: None
-            All bins that has count more than cmax will not be displayed (set
-            to NaN before passing to imshow) and these count values in the
-            return value count histogram will also be set to nan upon return.
-
-        Returns
-        -------
-        h : 2D array
-            The bi-dimensional histogram of samples x and y. Values in x are
-            histogrammed along the first dimension and values in y are
-            histogrammed along the second dimension.
-        xedges : 1D array
-            The bin edges along the x axis.
-        yedges : 1D array
-            The bin edges along the y axis.
-        image : `~.matplotlib.collections.QuadMesh`
-
-        Other Parameters
-        ----------------
-        cmap : Colormap or str, optional
-            A `.colors.Colormap` instance.  If not set, use rc settings.
-
-        norm : Normalize, optional
-            A `.colors.Normalize` instance is used to
-            scale luminance data to ``[0, 1]``. If not set, defaults to
-            `.colors.Normalize()`.
-
-        vmin/vmax : None or scalar, optional
-            Arguments passed to the `~.colors.Normalize` instance.
-
-        alpha : ``0 <= scalar <= 1`` or ``None``, optional
-            The alpha blending value.
-
-        See also
-        --------
-        hist : 1D histogram plotting
-
-        Notes
-        -----
-        - Currently ``hist2d`` calculates its own axis limits, and any limits
-          previously set are ignored.
-        - Rendering the histogram with a logarithmic color scale is
-          accomplished by passing a `.colors.LogNorm` instance to the *norm*
-          keyword argument. Likewise, power-law normalization (similar
-          in effect to gamma correction) can be accomplished with
-          `.colors.PowerNorm`.
-        """
-
-        h, xedges, yedges = np.histogram2d(x, y, bins=bins, range=range,
-                                           normed=density, weights=weights)
-
-        if cmin is not None:
-            h[h < cmin] = None
-        if cmax is not None:
-            h[h > cmax] = None
-
-        pc = self.pcolormesh(xedges, yedges, h.T, **kwargs)
-        self.set_xlim(xedges[0], xedges[-1])
-        self.set_ylim(yedges[0], yedges[-1])
-
-        return h, xedges, yedges, pc
-
-    @_preprocess_data(replace_names=["x"])
-    @docstring.dedent_interpd
-    def psd(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
-            window=None, noverlap=None, pad_to=None,
-            sides=None, scale_by_freq=None, return_line=None, **kwargs):
-        r"""
-        Plot the power spectral density.
-
-        The power spectral density :math:`P_{xx}` by Welch's average
-        periodogram method.  The vector *x* is divided into *NFFT* length
-        segments.  Each segment is detrended by function *detrend* and
-        windowed by function *window*.  *noverlap* gives the length of
-        the overlap between segments.  The :math:`|\mathrm{fft}(i)|^2`
-        of each segment :math:`i` are averaged to compute :math:`P_{xx}`,
-        with a scaling to correct for power loss due to windowing.
-
-        If len(*x*) < *NFFT*, it will be zero padded to *NFFT*.
-
-        Parameters
-        ----------
-        x : 1-D array or sequence
-            Array or sequence containing the data
-
-        %(Spectral)s
-
-        %(PSD)s
-
-        noverlap : int
-            The number of points of overlap between segments.
-            The default value is 0 (no overlap).
-
-        Fc : int
-            The center frequency of *x* (defaults to 0), which offsets
-            the x extents of the plot to reflect the frequency range used
-            when a signal is acquired and then filtered and downsampled to
-            baseband.
-
-        return_line : bool
-            Whether to include the line object plotted in the returned values.
-            Default is False.
-
-        Returns
-        -------
-        Pxx : 1-D array
-            The values for the power spectrum `P_{xx}` before scaling
-            (real valued).
-
-        freqs : 1-D array
-            The frequencies corresponding to the elements in *Pxx*.
-
-        line : `~matplotlib.lines.Line2D`
-            The line created by this function.
-            Only returned if *return_line* is True.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Keyword arguments control the `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        See Also
-        --------
-        :func:`specgram`
-            :func:`specgram` differs in the default overlap; in not returning
-            the mean of the segment periodograms; in returning the times of the
-            segments; and in plotting a colormap instead of a line.
-
-        :func:`magnitude_spectrum`
-            :func:`magnitude_spectrum` plots the magnitude spectrum.
-
-        :func:`csd`
-            :func:`csd` plots the spectral density between two signals.
-
-        Notes
-        -----
-        For plotting, the power is plotted as
-        :math:`10\log_{10}(P_{xx})` for decibels, though *Pxx* itself
-        is returned.
-
-        References
-        ----------
-        Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
-        John Wiley & Sons (1986)
-        """
-        if Fc is None:
-            Fc = 0
-
-        pxx, freqs = mlab.psd(x=x, NFFT=NFFT, Fs=Fs, detrend=detrend,
-                              window=window, noverlap=noverlap, pad_to=pad_to,
-                              sides=sides, scale_by_freq=scale_by_freq)
-        freqs += Fc
-
-        if scale_by_freq in (None, True):
-            psd_units = 'dB/Hz'
-        else:
-            psd_units = 'dB'
-
-        line = self.plot(freqs, 10 * np.log10(pxx), **kwargs)
-        self.set_xlabel('Frequency')
-        self.set_ylabel('Power Spectral Density (%s)' % psd_units)
-        self.grid(True)
-        vmin, vmax = self.viewLim.intervaly
-        intv = vmax - vmin
-        logi = int(np.log10(intv))
-        if logi == 0:
-            logi = .1
-        step = 10 * logi
-        ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step)
-        self.set_yticks(ticks)
-
-        if return_line is None or not return_line:
-            return pxx, freqs
-        else:
-            return pxx, freqs, line
-
-    @_preprocess_data(replace_names=["x", "y"], label_namer="y")
-    @docstring.dedent_interpd
-    def csd(self, x, y, NFFT=None, Fs=None, Fc=None, detrend=None,
-            window=None, noverlap=None, pad_to=None,
-            sides=None, scale_by_freq=None, return_line=None, **kwargs):
-        r"""
-        Plot the cross-spectral density.
-
-        The cross spectral density :math:`P_{xy}` by Welch's average
-        periodogram method.  The vectors *x* and *y* are divided into
-        *NFFT* length segments.  Each segment is detrended by function
-        *detrend* and windowed by function *window*.  *noverlap* gives
-        the length of the overlap between segments.  The product of
-        the direct FFTs of *x* and *y* are averaged over each segment
-        to compute :math:`P_{xy}`, with a scaling to correct for power
-        loss due to windowing.
-
-        If len(*x*) < *NFFT* or len(*y*) < *NFFT*, they will be zero
-        padded to *NFFT*.
-
-        Parameters
-        ----------
-        x, y : 1-D arrays or sequences
-            Arrays or sequences containing the data.
-
-        %(Spectral)s
-
-        %(PSD)s
-
-        noverlap : int
-            The number of points of overlap between segments.
-            The default value is 0 (no overlap).
-
-        Fc : int
-            The center frequency of *x* (defaults to 0), which offsets
-            the x extents of the plot to reflect the frequency range used
-            when a signal is acquired and then filtered and downsampled to
-            baseband.
-
-        return_line : bool
-            Whether to include the line object plotted in the returned values.
-            Default is False.
-
-        Returns
-        -------
-        Pxy : 1-D array
-            The values for the cross spectrum `P_{xy}` before scaling
-            (complex valued).
-
-        freqs : 1-D array
-            The frequencies corresponding to the elements in *Pxy*.
-
-        line : `~matplotlib.lines.Line2D`
-            The line created by this function.
-            Only returned if *return_line* is True.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Keyword arguments control the `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        See Also
-        --------
-        :func:`psd`
-            :func:`psd` is the equivalent to setting y=x.
-
-        Notes
-        -----
-        For plotting, the power is plotted as
-        :math:`10 \log_{10}(P_{xy})` for decibels, though `P_{xy}` itself
-        is returned.
-
-        References
-        ----------
-        Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
-        John Wiley & Sons (1986)
-        """
-        if Fc is None:
-            Fc = 0
-
-        pxy, freqs = mlab.csd(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend,
-                              window=window, noverlap=noverlap, pad_to=pad_to,
-                              sides=sides, scale_by_freq=scale_by_freq)
-        # pxy is complex
-        freqs += Fc
-
-        line = self.plot(freqs, 10 * np.log10(np.abs(pxy)), **kwargs)
-        self.set_xlabel('Frequency')
-        self.set_ylabel('Cross Spectrum Magnitude (dB)')
-        self.grid(True)
-        vmin, vmax = self.viewLim.intervaly
-
-        intv = vmax - vmin
-        step = 10 * int(np.log10(intv))
-
-        ticks = np.arange(math.floor(vmin), math.ceil(vmax) + 1, step)
-        self.set_yticks(ticks)
-
-        if return_line is None or not return_line:
-            return pxy, freqs
-        else:
-            return pxy, freqs, line
-
-    @_preprocess_data(replace_names=["x"])
-    @docstring.dedent_interpd
-    def magnitude_spectrum(self, x, Fs=None, Fc=None, window=None,
-                           pad_to=None, sides=None, scale=None,
-                           **kwargs):
-        """
-        Plot the magnitude spectrum.
-
-        Compute the magnitude spectrum of *x*.  Data is padded to a
-        length of *pad_to* and the windowing function *window* is applied to
-        the signal.
-
-        Parameters
-        ----------
-        x : 1-D array or sequence
-            Array or sequence containing the data.
-
-        %(Spectral)s
-
-        %(Single_Spectrum)s
-
-        scale : {'default', 'linear', 'dB'}
-            The scaling of the values in the *spec*.  'linear' is no scaling.
-            'dB' returns the values in dB scale, i.e., the dB amplitude
-            (20 * log10). 'default' is 'linear'.
-
-        Fc : int
-            The center frequency of *x* (defaults to 0), which offsets
-            the x extents of the plot to reflect the frequency range used
-            when a signal is acquired and then filtered and downsampled to
-            baseband.
-
-        Returns
-        -------
-        spectrum : 1-D array
-            The values for the magnitude spectrum before scaling (real valued).
-
-        freqs : 1-D array
-            The frequencies corresponding to the elements in *spectrum*.
-
-        line : `~matplotlib.lines.Line2D`
-            The line created by this function.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Keyword arguments control the `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        See Also
-        --------
-        :func:`psd`
-            :func:`psd` plots the power spectral density.`.
-
-        :func:`angle_spectrum`
-            :func:`angle_spectrum` plots the angles of the corresponding
-            frequencies.
-
-        :func:`phase_spectrum`
-            :func:`phase_spectrum` plots the phase (unwrapped angle) of the
-            corresponding frequencies.
-
-        :func:`specgram`
-            :func:`specgram` can plot the magnitude spectrum of segments within
-            the signal in a colormap.
-
-        """
-        if Fc is None:
-            Fc = 0
-
-        if scale is None or scale == 'default':
-            scale = 'linear'
-
-        spec, freqs = mlab.magnitude_spectrum(x=x, Fs=Fs, window=window,
-                                              pad_to=pad_to, sides=sides)
-        freqs += Fc
-
-        if scale == 'linear':
-            Z = spec
-            yunits = 'energy'
-        elif scale == 'dB':
-            Z = 20. * np.log10(spec)
-            yunits = 'dB'
-        else:
-            raise ValueError('Unknown scale %s', scale)
-
-        lines = self.plot(freqs, Z, **kwargs)
-        self.set_xlabel('Frequency')
-        self.set_ylabel('Magnitude (%s)' % yunits)
-
-        return spec, freqs, lines[0]
-
-    @_preprocess_data(replace_names=["x"])
-    @docstring.dedent_interpd
-    def angle_spectrum(self, x, Fs=None, Fc=None, window=None,
-                       pad_to=None, sides=None, **kwargs):
-        """
-        Plot the angle spectrum.
-
-        Compute the angle spectrum (wrapped phase spectrum) of *x*.
-        Data is padded to a length of *pad_to* and the windowing function
-        *window* is applied to the signal.
-
-        Parameters
-        ----------
-        x : 1-D array or sequence
-            Array or sequence containing the data.
-
-        %(Spectral)s
-
-        %(Single_Spectrum)s
-
-        Fc : int
-            The center frequency of *x* (defaults to 0), which offsets
-            the x extents of the plot to reflect the frequency range used
-            when a signal is acquired and then filtered and downsampled to
-            baseband.
-
-        Returns
-        -------
-        spectrum : 1-D array
-            The values for the angle spectrum in radians (real valued).
-
-        freqs : 1-D array
-            The frequencies corresponding to the elements in *spectrum*.
-
-        line : `~matplotlib.lines.Line2D`
-            The line created by this function.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Keyword arguments control the `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        See Also
-        --------
-        :func:`magnitude_spectrum`
-            :func:`angle_spectrum` plots the magnitudes of the corresponding
-            frequencies.
-
-        :func:`phase_spectrum`
-            :func:`phase_spectrum` plots the unwrapped version of this
-            function.
-
-        :func:`specgram`
-            :func:`specgram` can plot the angle spectrum of segments within the
-            signal in a colormap.
-
-        """
-        if Fc is None:
-            Fc = 0
-
-        spec, freqs = mlab.angle_spectrum(x=x, Fs=Fs, window=window,
-                                          pad_to=pad_to, sides=sides)
-        freqs += Fc
-
-        lines = self.plot(freqs, spec, **kwargs)
-        self.set_xlabel('Frequency')
-        self.set_ylabel('Angle (radians)')
-
-        return spec, freqs, lines[0]
-
-    @_preprocess_data(replace_names=["x"])
-    @docstring.dedent_interpd
-    def phase_spectrum(self, x, Fs=None, Fc=None, window=None,
-                       pad_to=None, sides=None, **kwargs):
-        """
-        Plot the phase spectrum.
-
-        Compute the phase spectrum (unwrapped angle spectrum) of *x*.
-        Data is padded to a length of *pad_to* and the windowing function
-        *window* is applied to the signal.
-
-        Parameters
-        ----------
-        x : 1-D array or sequence
-            Array or sequence containing the data
-
-        %(Spectral)s
-
-        %(Single_Spectrum)s
-
-        Fc : int
-            The center frequency of *x* (defaults to 0), which offsets
-            the x extents of the plot to reflect the frequency range used
-            when a signal is acquired and then filtered and downsampled to
-            baseband.
-
-        Returns
-        -------
-        spectrum : 1-D array
-            The values for the phase spectrum in radians (real valued).
-
-        freqs : 1-D array
-            The frequencies corresponding to the elements in *spectrum*.
-
-        line : `~matplotlib.lines.Line2D`
-            The line created by this function.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Keyword arguments control the `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        See Also
-        --------
-        :func:`magnitude_spectrum`
-            :func:`magnitude_spectrum` plots the magnitudes of the
-            corresponding frequencies.
-
-        :func:`angle_spectrum`
-            :func:`angle_spectrum` plots the wrapped version of this function.
-
-        :func:`specgram`
-            :func:`specgram` can plot the phase spectrum of segments within the
-            signal in a colormap.
-
-        """
-        if Fc is None:
-            Fc = 0
-
-        spec, freqs = mlab.phase_spectrum(x=x, Fs=Fs, window=window,
-                                          pad_to=pad_to, sides=sides)
-        freqs += Fc
-
-        lines = self.plot(freqs, spec, **kwargs)
-        self.set_xlabel('Frequency')
-        self.set_ylabel('Phase (radians)')
-
-        return spec, freqs, lines[0]
-
-    @_preprocess_data(replace_names=["x", "y"])
-    @docstring.dedent_interpd
-    def cohere(self, x, y, NFFT=256, Fs=2, Fc=0, detrend=mlab.detrend_none,
-               window=mlab.window_hanning, noverlap=0, pad_to=None,
-               sides='default', scale_by_freq=None, **kwargs):
-        r"""
-        Plot the coherence between *x* and *y*.
-
-        Plot the coherence between *x* and *y*.  Coherence is the
-        normalized cross spectral density:
-
-        .. math::
-
-          C_{xy} = \frac{|P_{xy}|^2}{P_{xx}P_{yy}}
-
-        Parameters
-        ----------
-        %(Spectral)s
-
-        %(PSD)s
-
-        noverlap : int
-            The number of points of overlap between blocks.  The
-            default value is 0 (no overlap).
-
-        Fc : int
-            The center frequency of *x* (defaults to 0), which offsets
-            the x extents of the plot to reflect the frequency range used
-            when a signal is acquired and then filtered and downsampled to
-            baseband.
-
-
-        Returns
-        -------
-        Cxy : 1-D array
-            The coherence vector.
-
-        freqs : 1-D array
-            The frequencies for the elements in *Cxy*.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Keyword arguments control the `.Line2D` properties:
-
-            %(_Line2D_docstr)s
-
-        References
-        ----------
-        Bendat & Piersol -- Random Data: Analysis and Measurement Procedures,
-        John Wiley & Sons (1986)
-        """
-        cxy, freqs = mlab.cohere(x=x, y=y, NFFT=NFFT, Fs=Fs, detrend=detrend,
-                                 window=window, noverlap=noverlap,
-                                 scale_by_freq=scale_by_freq)
-        freqs += Fc
-
-        self.plot(freqs, cxy, **kwargs)
-        self.set_xlabel('Frequency')
-        self.set_ylabel('Coherence')
-        self.grid(True)
-
-        return cxy, freqs
-
-    @_preprocess_data(replace_names=["x"])
-    @docstring.dedent_interpd
-    def specgram(self, x, NFFT=None, Fs=None, Fc=None, detrend=None,
-                 window=None, noverlap=None,
-                 cmap=None, xextent=None, pad_to=None, sides=None,
-                 scale_by_freq=None, mode=None, scale=None,
-                 vmin=None, vmax=None, **kwargs):
-        """
-        Plot a spectrogram.
-
-        Compute and plot a spectrogram of data in *x*.  Data are split into
-        *NFFT* length segments and the spectrum of each section is
-        computed.  The windowing function *window* is applied to each
-        segment, and the amount of overlap of each segment is
-        specified with *noverlap*. The spectrogram is plotted as a colormap
-        (using imshow).
-
-        Parameters
-        ----------
-        x : 1-D array or sequence
-            Array or sequence containing the data.
-
-        %(Spectral)s
-
-        %(PSD)s
-
-        mode : {'default', 'psd', 'magnitude', 'angle', 'phase'}
-            What sort of spectrum to use.  Default is 'psd', which takes the
-            power spectral density.  'magnitude' returns the magnitude
-            spectrum.  'angle' returns the phase spectrum without unwrapping.
-            'phase' returns the phase spectrum with unwrapping.
-
-        noverlap : int
-            The number of points of overlap between blocks.  The
-            default value is 128.
-
-        scale : {'default', 'linear', 'dB'}
-            The scaling of the values in the *spec*.  'linear' is no scaling.
-            'dB' returns the values in dB scale.  When *mode* is 'psd',
-            this is dB power (10 * log10).  Otherwise this is dB amplitude
-            (20 * log10). 'default' is 'dB' if *mode* is 'psd' or
-            'magnitude' and 'linear' otherwise.  This must be 'linear'
-            if *mode* is 'angle' or 'phase'.
-
-        Fc : int
-            The center frequency of *x* (defaults to 0), which offsets
-            the x extents of the plot to reflect the frequency range used
-            when a signal is acquired and then filtered and downsampled to
-            baseband.
-
-        cmap
-            A :class:`matplotlib.colors.Colormap` instance; if *None*, use
-            default determined by rc
-
-        xextent : *None* or (xmin, xmax)
-            The image extent along the x-axis. The default sets *xmin* to the
-            left border of the first bin (*spectrum* column) and *xmax* to the
-            right border of the last bin. Note that for *noverlap>0* the width
-            of the bins is smaller than those of the segments.
-
-        **kwargs
-            Additional keyword arguments are passed on to imshow which makes
-            the specgram image.
-
-        Returns
-        -------
-        spectrum : 2-D array
-            Columns are the periodograms of successive segments.
-
-        freqs : 1-D array
-            The frequencies corresponding to the rows in *spectrum*.
-
-        t : 1-D array
-            The times corresponding to midpoints of segments (i.e., the columns
-            in *spectrum*).
-
-        im : instance of class :class:`~matplotlib.image.AxesImage`
-            The image created by imshow containing the spectrogram
-
-        See Also
-        --------
-        :func:`psd`
-            :func:`psd` differs in the default overlap; in returning the mean
-            of the segment periodograms; in not returning times; and in
-            generating a line plot instead of colormap.
-
-        :func:`magnitude_spectrum`
-            A single spectrum, similar to having a single segment when *mode*
-            is 'magnitude'. Plots a line instead of a colormap.
-
-        :func:`angle_spectrum`
-            A single spectrum, similar to having a single segment when *mode*
-            is 'angle'. Plots a line instead of a colormap.
-
-        :func:`phase_spectrum`
-            A single spectrum, similar to having a single segment when *mode*
-            is 'phase'. Plots a line instead of a colormap.
-
-        Notes
-        -----
-        The parameters *detrend* and *scale_by_freq* do only apply when *mode*
-        is set to 'psd'.
-        """
-        if NFFT is None:
-            NFFT = 256  # same default as in mlab.specgram()
-        if Fc is None:
-            Fc = 0  # same default as in mlab._spectral_helper()
-        if noverlap is None:
-            noverlap = 128  # same default as in mlab.specgram()
-
-        if mode == 'complex':
-            raise ValueError('Cannot plot a complex specgram')
-
-        if scale is None or scale == 'default':
-            if mode in ['angle', 'phase']:
-                scale = 'linear'
-            else:
-                scale = 'dB'
-        elif mode in ['angle', 'phase'] and scale == 'dB':
-            raise ValueError('Cannot use dB scale with angle or phase mode')
-
-        spec, freqs, t = mlab.specgram(x=x, NFFT=NFFT, Fs=Fs,
-                                       detrend=detrend, window=window,
-                                       noverlap=noverlap, pad_to=pad_to,
-                                       sides=sides,
-                                       scale_by_freq=scale_by_freq,
-                                       mode=mode)
-
-        if scale == 'linear':
-            Z = spec
-        elif scale == 'dB':
-            if mode is None or mode == 'default' or mode == 'psd':
-                Z = 10. * np.log10(spec)
-            else:
-                Z = 20. * np.log10(spec)
-        else:
-            raise ValueError('Unknown scale %s', scale)
-
-        Z = np.flipud(Z)
-
-        if xextent is None:
-            # padding is needed for first and last segment:
-            pad_xextent = (NFFT-noverlap) / Fs / 2
-            xextent = np.min(t) - pad_xextent, np.max(t) + pad_xextent
-        xmin, xmax = xextent
-        freqs += Fc
-        extent = xmin, xmax, freqs[0], freqs[-1]
-        im = self.imshow(Z, cmap, extent=extent, vmin=vmin, vmax=vmax,
-                         **kwargs)
-        self.axis('auto')
-
-        return spec, freqs, t, im
-
-    @docstring.dedent_interpd
-    def spy(self, Z, precision=0, marker=None, markersize=None,
-            aspect='equal', origin="upper", **kwargs):
-        """
-        Plot the sparsity pattern of a 2D array.
-
-        This visualizes the non-zero values of the array.
-
-        Two plotting styles are available: image and marker. Both
-        are available for full arrays, but only the marker style
-        works for `scipy.sparse.spmatrix` instances.
-
-        **Image style**
-
-        If *marker* and *markersize* are *None*, `~.Axes.imshow` is used. Any
-        extra remaining keyword arguments are passed to this method.
-
-        **Marker style**
-
-        If *Z* is a `scipy.sparse.spmatrix` or *marker* or *markersize* are
-        *None*, a `.Line2D` object will be returned with the value of marker
-        determining the marker type, and any remaining keyword arguments
-        passed to `~.Axes.plot`.
-
-        Parameters
-        ----------
-        Z : array-like (M, N)
-            The array to be plotted.
-
-        precision : float or 'present', optional, default: 0
-            If *precision* is 0, any non-zero value will be plotted. Otherwise,
-            values of :math:`|Z| > precision` will be plotted.
-
-            For :class:`scipy.sparse.spmatrix` instances, you can also
-            pass 'present'. In this case any value present in the array
-            will be plotted, even if it is identically zero.
-
-        origin : {'upper', 'lower'}, optional
-            Place the [0, 0] index of the array in the upper left or lower left
-            corner of the axes. The convention 'upper' is typically used for
-            matrices and images.
-            If not given, :rc:`image.origin` is used, defaulting to 'upper'.
-
-
-        aspect : {'equal', 'auto', None} or float, optional
-            Controls the aspect ratio of the axes. The aspect is of particular
-            relevance for images since it may distort the image, i.e. pixel
-            will not be square.
-
-            This parameter is a shortcut for explicitly calling
-            `.Axes.set_aspect`. See there for further details.
-
-            - 'equal': Ensures an aspect ratio of 1. Pixels will be square.
-            - 'auto': The axes is kept fixed and the aspect is adjusted so
-              that the data fit in the axes. In general, this will result in
-              non-square pixels.
-            - *None*: Use :rc:`image.aspect`.
-
-            Default: 'equal'
-
-        Returns
-        -------
-        ret : `~matplotlib.image.AxesImage` or `.Line2D`
-            The return type depends on the plotting style (see above).
-
-        Other Parameters
-        ----------------
-        **kwargs
-            The supported additional parameters depend on the plotting style.
-
-            For the image style, you can pass the following additional
-            parameters of `~.Axes.imshow`:
-
-            - *cmap*
-            - *alpha*
-            - *url*
-            - any `.Artist` properties (passed on to the `.AxesImage`)
-
-            For the marker style, you can pass any `.Line2D` property except
-            for *linestyle*:
-
-            %(_Line2D_docstr)s
-        """
-        if marker is None and markersize is None and hasattr(Z, 'tocoo'):
-            marker = 's'
-        if marker is None and markersize is None:
-            Z = np.asarray(Z)
-            mask = np.abs(Z) > precision
-
-            if 'cmap' not in kwargs:
-                kwargs['cmap'] = mcolors.ListedColormap(['w', 'k'],
-                                                        name='binary')
-            if 'interpolation' in kwargs:
-                raise TypeError(
-                    "spy() got an unexpected keyword argument 'interpolation'")
-            ret = self.imshow(mask, interpolation='nearest', aspect=aspect,
-                              origin=origin, **kwargs)
-        else:
-            if hasattr(Z, 'tocoo'):
-                c = Z.tocoo()
-                if precision == 'present':
-                    y = c.row
-                    x = c.col
-                else:
-                    nonzero = np.abs(c.data) > precision
-                    y = c.row[nonzero]
-                    x = c.col[nonzero]
-            else:
-                Z = np.asarray(Z)
-                nonzero = np.abs(Z) > precision
-                y, x = np.nonzero(nonzero)
-            if marker is None:
-                marker = 's'
-            if markersize is None:
-                markersize = 10
-            if 'linestyle' in kwargs:
-                raise TypeError(
-                    "spy() got an unexpected keyword argument 'linestyle'")
-            marks = mlines.Line2D(x, y, linestyle='None',
-                         marker=marker, markersize=markersize, **kwargs)
-            self.add_line(marks)
-            nr, nc = Z.shape
-            self.set_xlim(-0.5, nc - 0.5)
-            self.set_ylim(nr - 0.5, -0.5)
-            self.set_aspect(aspect)
-            ret = marks
-        self.title.set_y(1.05)
-        self.xaxis.tick_top()
-        self.xaxis.set_ticks_position('both')
-        self.xaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
-                                                 steps=[1, 2, 5, 10],
-                                                 integer=True))
-        self.yaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
-                                                 steps=[1, 2, 5, 10],
-                                                 integer=True))
-        return ret
-
-    def matshow(self, Z, **kwargs):
-        """
-        Plot the values of a 2D matrix or array as color-coded image.
-
-        The matrix will be shown the way it would be printed, with the first
-        row at the top.  Row and column numbering is zero-based.
-
-        Parameters
-        ----------
-        Z : array-like(M, N)
-            The matrix to be displayed.
-
-        Returns
-        -------
-        image : `~matplotlib.image.AxesImage`
-
-        Other Parameters
-        ----------------
-        **kwargs : `~matplotlib.axes.Axes.imshow` arguments
-
-        See Also
-        --------
-        imshow : More general function to plot data on a 2D regular raster.
-
-        Notes
-        -----
-        This is just a convenience function wrapping `.imshow` to set useful
-        defaults for displaying a matrix. In particular:
-
-        - Set ``origin='upper'``.
-        - Set ``interpolation='nearest'``.
-        - Set ``aspect='equal'``.
-        - Ticks are placed to the left and above.
-        - Ticks are formatted to show integer indices.
-
-        """
-        Z = np.asanyarray(Z)
-        kw = {'origin': 'upper',
-              'interpolation': 'nearest',
-              'aspect': 'equal',          # (already the imshow default)
-              **kwargs}
-        im = self.imshow(Z, **kw)
-        self.title.set_y(1.05)
-        self.xaxis.tick_top()
-        self.xaxis.set_ticks_position('both')
-        self.xaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
-                                                 steps=[1, 2, 5, 10],
-                                                 integer=True))
-        self.yaxis.set_major_locator(mticker.MaxNLocator(nbins=9,
-                                                 steps=[1, 2, 5, 10],
-                                                 integer=True))
-        return im
-
-    @_preprocess_data(replace_names=["dataset"])
-    def violinplot(self, dataset, positions=None, vert=True, widths=0.5,
-                   showmeans=False, showextrema=True, showmedians=False,
-                   quantiles=None, points=100, bw_method=None):
-        """
-        Make a violin plot.
-
-        Make a violin plot for each column of *dataset* or each vector in
-        sequence *dataset*.  Each filled area extends to represent the
-        entire data range, with optional lines at the mean, the median,
-        the minimum, the maximum, and user-specified quantiles.
-
-        Parameters
-        ----------
-        dataset : Array or a sequence of vectors.
-          The input data.
-
-        positions : array-like, default = [1, 2, ..., n]
-          Sets the positions of the violins. The ticks and limits are
-          automatically set to match the positions.
-
-        vert : bool, default = True.
-          If true, creates a vertical violin plot.
-          Otherwise, creates a horizontal violin plot.
-
-        widths : array-like, default = 0.5
-          Either a scalar or a vector that sets the maximal width of
-          each violin. The default is 0.5, which uses about half of the
-          available horizontal space.
-
-        showmeans : bool, default = False
-          If `True`, will toggle rendering of the means.
-
-        showextrema : bool, default = True
-          If `True`, will toggle rendering of the extrema.
-
-        showmedians : bool, default = False
-          If `True`, will toggle rendering of the medians.
-
-        quantiles : array-like, default = None
-          If not None, set a list of floats in interval [0, 1] for each violin,
-          which stands for the quantiles that will be rendered for that
-          violin.
-
-        points : scalar, default = 100
-          Defines the number of points to evaluate each of the
-          gaussian kernel density estimations at.
-
-        bw_method : str, scalar or callable, optional
-          The method used to calculate the estimator bandwidth.  This can be
-          'scott', 'silverman', a scalar constant or a callable.  If a
-          scalar, this will be used directly as `kde.factor`.  If a
-          callable, it should take a `GaussianKDE` instance as its only
-          parameter and return a scalar. If None (default), 'scott' is used.
-
-        Returns
-        -------
-        result : dict
-          A dictionary mapping each component of the violinplot to a
-          list of the corresponding collection instances created. The
-          dictionary has the following keys:
-
-          - ``bodies``: A list of the `~.collections.PolyCollection`
-            instances containing the filled area of each violin.
-
-          - ``cmeans``: A `~.collections.LineCollection` instance that marks
-            the mean values of each of the violin's distribution.
-
-          - ``cmins``: A `~.collections.LineCollection` instance that marks
-            the bottom of each violin's distribution.
-
-          - ``cmaxes``: A `~.collections.LineCollection` instance that marks
-            the top of each violin's distribution.
-
-          - ``cbars``: A `~.collections.LineCollection` instance that marks
-            the centers of each violin's distribution.
-
-          - ``cmedians``: A `~.collections.LineCollection` instance that
-            marks the median values of each of the violin's distribution.
-
-          - ``cquantiles``: A `~.collections.LineCollection` instance created
-            to identify the quantile values of each of the violin's
-            distribution.
-
-        """
-
-        def _kde_method(X, coords):
-            # fallback gracefully if the vector contains only one value
-            if np.all(X[0] == X):
-                return (X[0] == coords).astype(float)
-            kde = mlab.GaussianKDE(X, bw_method)
-            return kde.evaluate(coords)
-
-        vpstats = cbook.violin_stats(dataset, _kde_method, points=points,
-                                     quantiles=quantiles)
-        return self.violin(vpstats, positions=positions, vert=vert,
-                           widths=widths, showmeans=showmeans,
-                           showextrema=showextrema, showmedians=showmedians)
-
-    def violin(self, vpstats, positions=None, vert=True, widths=0.5,
-               showmeans=False, showextrema=True, showmedians=False):
-        """Drawing function for violin plots.
-
-        Draw a violin plot for each column of *vpstats*. Each filled area
-        extends to represent the entire data range, with optional lines at the
-        mean, the median, the minimum, the maximum, and the quantiles values.
-
-        Parameters
-        ----------
-        vpstats : list of dicts
-          A list of dictionaries containing stats for each violin plot.
-          Required keys are:
-
-          - ``coords``: A list of scalars containing the coordinates that
-            the violin's kernel density estimate were evaluated at.
-
-          - ``vals``: A list of scalars containing the values of the
-            kernel density estimate at each of the coordinates given
-            in *coords*.
-
-          - ``mean``: The mean value for this violin's dataset.
-
-          - ``median``: The median value for this violin's dataset.
-
-          - ``min``: The minimum value for this violin's dataset.
-
-          - ``max``: The maximum value for this violin's dataset.
-
-          Optional keys are:
-
-          - ``quantiles``: A list of scalars containing the quantile values
-            for this violin's dataset.
-
-        positions : array-like, default = [1, 2, ..., n]
-          Sets the positions of the violins. The ticks and limits are
-          automatically set to match the positions.
-
-        vert : bool, default = True.
-          If true, plots the violins vertically.
-          Otherwise, plots the violins horizontally.
-
-        widths : array-like, default = 0.5
-          Either a scalar or a vector that sets the maximal width of
-          each violin. The default is 0.5, which uses about half of the
-          available horizontal space.
-
-        showmeans : bool, default = False
-          If true, will toggle rendering of the means.
-
-        showextrema : bool, default = True
-          If true, will toggle rendering of the extrema.
-
-        showmedians : bool, default = False
-          If true, will toggle rendering of the medians.
-
-        Returns
-        -------
-        result : dict
-          A dictionary mapping each component of the violinplot to a
-          list of the corresponding collection instances created. The
-          dictionary has the following keys:
-
-          - ``bodies``: A list of the `~.collections.PolyCollection`
-            instances containing the filled area of each violin.
-
-          - ``cmeans``: A `~.collections.LineCollection` instance that marks
-            the mean values of each of the violin's distribution.
-
-          - ``cmins``: A `~.collections.LineCollection` instance that marks
-            the bottom of each violin's distribution.
-
-          - ``cmaxes``: A `~.collections.LineCollection` instance that marks
-            the top of each violin's distribution.
-
-          - ``cbars``: A `~.collections.LineCollection` instance that marks
-            the centers of each violin's distribution.
-
-          - ``cmedians``: A `~.collections.LineCollection` instance that
-            marks the median values of each of the violin's distribution.
-
-          - ``cquantiles``: A `~.collections.LineCollection` instance created
-            to identify the quantiles values of each of the violin's
-            distribution.
-
-        """
-
-        # Statistical quantities to be plotted on the violins
-        means = []
-        mins = []
-        maxes = []
-        medians = []
-        quantiles = np.asarray([])
-
-        # Collections to be returned
-        artists = {}
-
-        N = len(vpstats)
-        datashape_message = ("List of violinplot statistics and `{0}` "
-                             "values must have the same length")
-
-        # Validate positions
-        if positions is None:
-            positions = range(1, N + 1)
-        elif len(positions) != N:
-            raise ValueError(datashape_message.format("positions"))
-
-        # Validate widths
-        if np.isscalar(widths):
-            widths = [widths] * N
-        elif len(widths) != N:
-            raise ValueError(datashape_message.format("widths"))
-
-        # Calculate ranges for statistics lines
-        pmins = -0.25 * np.array(widths) + positions
-        pmaxes = 0.25 * np.array(widths) + positions
-
-        # Check whether we are rendering vertically or horizontally
-        if vert:
-            fill = self.fill_betweenx
-            perp_lines = self.hlines
-            par_lines = self.vlines
-        else:
-            fill = self.fill_between
-            perp_lines = self.vlines
-            par_lines = self.hlines
-
-        if rcParams['_internal.classic_mode']:
-            fillcolor = 'y'
-            edgecolor = 'r'
-        else:
-            fillcolor = edgecolor = self._get_lines.get_next_color()
-
-        # Render violins
-        bodies = []
-        for stats, pos, width in zip(vpstats, positions, widths):
-            # The 0.5 factor reflects the fact that we plot from v-p to
-            # v+p
-            vals = np.array(stats['vals'])
-            vals = 0.5 * width * vals / vals.max()
-            bodies += [fill(stats['coords'],
-                            -vals + pos,
-                            vals + pos,
-                            facecolor=fillcolor,
-                            alpha=0.3)]
-            means.append(stats['mean'])
-            mins.append(stats['min'])
-            maxes.append(stats['max'])
-            medians.append(stats['median'])
-            q = stats.get('quantiles')
-            if q is not None:
-                # If exist key quantiles, assume it's a list of floats
-                quantiles = np.concatenate((quantiles, q))
-        artists['bodies'] = bodies
-
-        # Render means
-        if showmeans:
-            artists['cmeans'] = perp_lines(means, pmins, pmaxes,
-                                           colors=edgecolor)
-
-        # Render extrema
-        if showextrema:
-            artists['cmaxes'] = perp_lines(maxes, pmins, pmaxes,
-                                           colors=edgecolor)
-            artists['cmins'] = perp_lines(mins, pmins, pmaxes,
-                                          colors=edgecolor)
-            artists['cbars'] = par_lines(positions, mins, maxes,
-                                         colors=edgecolor)
-
-        # Render medians
-        if showmedians:
-            artists['cmedians'] = perp_lines(medians,
-                                             pmins,
-                                             pmaxes,
-                                             colors=edgecolor)
-
-        # Render quantile values
-        if quantiles.size > 0:
-            # Recalculate ranges for statistics lines for quantiles.
-            # ppmins are the left end of quantiles lines
-            ppmins = np.asarray([])
-            # pmaxes are the right end of quantiles lines
-            ppmaxs = np.asarray([])
-            for stats, cmin, cmax in zip(vpstats, pmins, pmaxes):
-                q = stats.get('quantiles')
-                if q is not None:
-                    ppmins = np.concatenate((ppmins, [cmin] * np.size(q)))
-                    ppmaxs = np.concatenate((ppmaxs, [cmax] * np.size(q)))
-            # Start rendering
-            artists['cquantiles'] = perp_lines(quantiles, ppmins, ppmaxs,
-                                                 colors=edgecolor)
-
-        return artists
-
-    # Methods that are entirely implemented in other modules.
-
-    table = mtable.table
-
-    # args can by either Y or y1, y2, ... and all should be replaced
-    stackplot = _preprocess_data()(mstack.stackplot)
-
-    streamplot = _preprocess_data(
-        replace_names=["x", "y", "u", "v", "start_points"])(mstream.streamplot)
-
-    tricontour = mtri.tricontour
-    tricontourf = mtri.tricontourf
-    tripcolor = mtri.tripcolor
-    triplot = mtri.triplot

+ 0 - 4441
venv/lib/python3.8/site-packages/matplotlib/axes/_base.py

@@ -1,4441 +0,0 @@
-from collections import OrderedDict
-import itertools
-import logging
-import math
-from numbers import Real
-from operator import attrgetter
-import types
-
-import numpy as np
-
-import matplotlib as mpl
-from matplotlib import cbook, rcParams
-from matplotlib.cbook import _OrderedSet, _check_1d, index_of
-from matplotlib import docstring
-import matplotlib.colors as mcolors
-import matplotlib.lines as mlines
-import matplotlib.patches as mpatches
-import matplotlib.artist as martist
-import matplotlib.transforms as mtransforms
-import matplotlib.ticker as mticker
-import matplotlib.axis as maxis
-import matplotlib.spines as mspines
-import matplotlib.font_manager as font_manager
-import matplotlib.text as mtext
-import matplotlib.image as mimage
-from matplotlib.rcsetup import cycler, validate_axisbelow
-
-_log = logging.getLogger(__name__)
-
-
-def _process_plot_format(fmt):
-    """
-    Convert a MATLAB style color/line style format string to a (*linestyle*,
-    *marker*, *color*) tuple.
-
-    Example format strings include:
-
-    * 'ko': black circles
-    * '.b': blue dots
-    * 'r--': red dashed lines
-    * 'C2--': the third color in the color cycle, dashed lines
-
-    See Also
-    --------
-    matplotlib.Line2D.lineStyles, matplotlib.colors.cnames
-        All possible styles and color format strings.
-    """
-
-    linestyle = None
-    marker = None
-    color = None
-
-    # Is fmt just a colorspec?
-    try:
-        color = mcolors.to_rgba(fmt)
-
-        # We need to differentiate grayscale '1.0' from tri_down marker '1'
-        try:
-            fmtint = str(int(fmt))
-        except ValueError:
-            return linestyle, marker, color  # Yes
-        else:
-            if fmt != fmtint:
-                # user definitely doesn't want tri_down marker
-                return linestyle, marker, color  # Yes
-            else:
-                # ignore converted color
-                color = None
-    except ValueError:
-        pass  # No, not just a color.
-
-    i = 0
-    while i < len(fmt):
-        c = fmt[i]
-        if fmt[i:i+2] in mlines.lineStyles:  # First, the two-char styles.
-            if linestyle is not None:
-                raise ValueError(
-                    'Illegal format string "%s"; two linestyle symbols' % fmt)
-            linestyle = fmt[i:i+2]
-            i += 2
-        elif c in mlines.lineStyles:
-            if linestyle is not None:
-                raise ValueError(
-                    'Illegal format string "%s"; two linestyle symbols' % fmt)
-            linestyle = c
-            i += 1
-        elif c in mlines.lineMarkers:
-            if marker is not None:
-                raise ValueError(
-                    'Illegal format string "%s"; two marker symbols' % fmt)
-            marker = c
-            i += 1
-        elif c in mcolors.get_named_colors_mapping():
-            if color is not None:
-                raise ValueError(
-                    'Illegal format string "%s"; two color symbols' % fmt)
-            color = c
-            i += 1
-        elif c == 'C' and i < len(fmt) - 1:
-            color_cycle_number = int(fmt[i + 1])
-            color = mcolors.to_rgba("C{}".format(color_cycle_number))
-            i += 2
-        else:
-            raise ValueError(
-                'Unrecognized character %c in format string' % c)
-
-    if linestyle is None and marker is None:
-        linestyle = rcParams['lines.linestyle']
-    if linestyle is None:
-        linestyle = 'None'
-    if marker is None:
-        marker = 'None'
-
-    return linestyle, marker, color
-
-
-class _process_plot_var_args:
-    """
-    Process variable length arguments to the plot command, so that
-    plot commands like the following are supported::
-
-      plot(t, s)
-      plot(t1, s1, t2, s2)
-      plot(t1, s1, 'ko', t2, s2)
-      plot(t1, s1, 'ko', t2, s2, 'r--', t3, e3)
-
-    an arbitrary number of *x*, *y*, *fmt* are allowed
-    """
-    def __init__(self, axes, command='plot'):
-        self.axes = axes
-        self.command = command
-        self.set_prop_cycle()
-
-    def __getstate__(self):
-        # note: it is not possible to pickle a generator (and thus a cycler).
-        return {'axes': self.axes, 'command': self.command}
-
-    def __setstate__(self, state):
-        self.__dict__ = state.copy()
-        self.set_prop_cycle()
-
-    def set_prop_cycle(self, *args, **kwargs):
-        # Can't do `args == (None,)` as that crashes cycler.
-        if not (args or kwargs) or (len(args) == 1 and args[0] is None):
-            prop_cycler = rcParams['axes.prop_cycle']
-        else:
-            prop_cycler = cycler(*args, **kwargs)
-
-        self.prop_cycler = itertools.cycle(prop_cycler)
-        # This should make a copy
-        self._prop_keys = prop_cycler.keys
-
-    def __call__(self, *args, **kwargs):
-        self.axes._process_unit_info(kwargs=kwargs)
-
-        for pos_only in "xy":
-            if pos_only in kwargs:
-                raise TypeError("{} got an unexpected keyword argument {!r}"
-                                .format(self.command, pos_only))
-
-        if not args:
-            return
-
-        # Process the 'data' kwarg.
-        data = kwargs.pop("data", None)
-        if data is not None:
-            replaced = [mpl._replacer(data, arg) for arg in args]
-            if len(args) == 1:
-                label_namer_idx = 0
-            elif len(args) == 2:  # Can be x, y or y, c.
-                # Figure out what the second argument is.
-                # 1) If the second argument cannot be a format shorthand, the
-                #    second argument is the label_namer.
-                # 2) Otherwise (it could have been a format shorthand),
-                #    a) if we did perform a substitution, emit a warning, and
-                #       use it as label_namer.
-                #    b) otherwise, it is indeed a format shorthand; use the
-                #       first argument as label_namer.
-                try:
-                    _process_plot_format(args[1])
-                except ValueError:  # case 1)
-                    label_namer_idx = 1
-                else:
-                    if replaced[1] is not args[1]:  # case 2a)
-                        cbook._warn_external(
-                            f"Second argument {args[1]!r} is ambiguous: could "
-                            f"be a format string but is in 'data'; using as "
-                            f"data.  If it was intended as data, set the "
-                            f"format string to an empty string to suppress "
-                            f"this warning.  If it was intended as a format "
-                            f"string, explicitly pass the x-values as well.  "
-                            f"Alternatively, rename the entry in 'data'.",
-                            RuntimeWarning)
-                        label_namer_idx = 1
-                    else:  # case 2b)
-                        label_namer_idx = 0
-            elif len(args) == 3:
-                label_namer_idx = 1
-            else:
-                raise ValueError(
-                    "Using arbitrary long args with data is not supported due "
-                    "to ambiguity of arguments; use multiple plotting calls "
-                    "instead")
-            if kwargs.get("label") is None:
-                kwargs["label"] = mpl._label_from_arg(
-                    replaced[label_namer_idx], args[label_namer_idx])
-            args = replaced
-
-        # Repeatedly grab (x, y) or (x, y, format) from the front of args and
-        # massage them into arguments to plot() or fill().
-        while args:
-            this, args = args[:2], args[2:]
-            if args and isinstance(args[0], str):
-                this += args[0],
-                args = args[1:]
-            yield from self._plot_args(this, kwargs)
-
-    def get_next_color(self):
-        """Return the next color in the cycle."""
-        if 'color' not in self._prop_keys:
-            return 'k'
-        return next(self.prop_cycler)['color']
-
-    def _getdefaults(self, ignore, kw):
-        """
-        If some keys in the property cycle (excluding those in the set
-        *ignore*) are absent or set to None in the dict *kw*, return a copy
-        of the next entry in the property cycle, excluding keys in *ignore*.
-        Otherwise, don't advance the property cycle, and return an empty dict.
-        """
-        prop_keys = self._prop_keys - ignore
-        if any(kw.get(k, None) is None for k in prop_keys):
-            # Need to copy this dictionary or else the next time around
-            # in the cycle, the dictionary could be missing entries.
-            default_dict = next(self.prop_cycler).copy()
-            for p in ignore:
-                default_dict.pop(p, None)
-        else:
-            default_dict = {}
-        return default_dict
-
-    def _setdefaults(self, defaults, kw):
-        """
-        Add to the dict *kw* the entries in the dict *default* that are absent
-        or set to None in *kw*.
-        """
-        for k in defaults:
-            if kw.get(k, None) is None:
-                kw[k] = defaults[k]
-
-    def _makeline(self, x, y, kw, kwargs):
-        kw = {**kw, **kwargs}  # Don't modify the original kw.
-        default_dict = self._getdefaults(set(), kw)
-        self._setdefaults(default_dict, kw)
-        seg = mlines.Line2D(x, y, **kw)
-        return seg
-
-    def _makefill(self, x, y, kw, kwargs):
-        # Polygon doesn't directly support unitized inputs.
-        x = self.axes.convert_xunits(x)
-        y = self.axes.convert_yunits(y)
-
-        kw = kw.copy()  # Don't modify the original kw.
-        kwargs = kwargs.copy()
-
-        # Ignore 'marker'-related properties as they aren't Polygon
-        # properties, but they are Line2D properties, and so they are
-        # likely to appear in the default cycler construction.
-        # This is done here to the defaults dictionary as opposed to the
-        # other two dictionaries because we do want to capture when a
-        # *user* explicitly specifies a marker which should be an error.
-        # We also want to prevent advancing the cycler if there are no
-        # defaults needed after ignoring the given properties.
-        ignores = {'marker', 'markersize', 'markeredgecolor',
-                   'markerfacecolor', 'markeredgewidth'}
-        # Also ignore anything provided by *kwargs*.
-        for k, v in kwargs.items():
-            if v is not None:
-                ignores.add(k)
-
-        # Only using the first dictionary to use as basis
-        # for getting defaults for back-compat reasons.
-        # Doing it with both seems to mess things up in
-        # various places (probably due to logic bugs elsewhere).
-        default_dict = self._getdefaults(ignores, kw)
-        self._setdefaults(default_dict, kw)
-
-        # Looks like we don't want "color" to be interpreted to
-        # mean both facecolor and edgecolor for some reason.
-        # So the "kw" dictionary is thrown out, and only its
-        # 'color' value is kept and translated as a 'facecolor'.
-        # This design should probably be revisited as it increases
-        # complexity.
-        facecolor = kw.get('color', None)
-
-        # Throw out 'color' as it is now handled as a facecolor
-        default_dict.pop('color', None)
-
-        # To get other properties set from the cycler
-        # modify the kwargs dictionary.
-        self._setdefaults(default_dict, kwargs)
-
-        seg = mpatches.Polygon(np.column_stack((x, y)),
-                               facecolor=facecolor,
-                               fill=kwargs.get('fill', True),
-                               closed=kw['closed'])
-        seg.set(**kwargs)
-        return seg
-
-    def _plot_args(self, tup, kwargs):
-        if len(tup) > 1 and isinstance(tup[-1], str):
-            linestyle, marker, color = _process_plot_format(tup[-1])
-            tup = tup[:-1]
-        elif len(tup) == 3:
-            raise ValueError('third arg must be a format string')
-        else:
-            linestyle, marker, color = None, None, None
-
-        # Don't allow any None value; these would be up-converted to one
-        # element array of None which causes problems downstream.
-        if any(v is None for v in tup):
-            raise ValueError("x, y, and format string must not be None")
-
-        kw = {}
-        for k, v in zip(('linestyle', 'marker', 'color'),
-                        (linestyle, marker, color)):
-            if v is not None:
-                kw[k] = v
-
-        if len(tup) == 2:
-            x = _check_1d(tup[0])
-            y = _check_1d(tup[-1])
-        else:
-            x, y = index_of(tup[-1])
-
-        if self.axes.xaxis is not None:
-            self.axes.xaxis.update_units(x)
-        if self.axes.yaxis is not None:
-            self.axes.yaxis.update_units(y)
-
-        if x.shape[0] != y.shape[0]:
-            raise ValueError(f"x and y must have same first dimension, but "
-                             f"have shapes {x.shape} and {y.shape}")
-        if x.ndim > 2 or y.ndim > 2:
-            raise ValueError(f"x and y can be no greater than 2-D, but have "
-                             f"shapes {x.shape} and {y.shape}")
-        if x.ndim == 1:
-            x = x[:, np.newaxis]
-        if y.ndim == 1:
-            y = y[:, np.newaxis]
-
-        if self.command == 'plot':
-            func = self._makeline
-        else:
-            kw['closed'] = kwargs.get('closed', True)
-            func = self._makefill
-
-        ncx, ncy = x.shape[1], y.shape[1]
-        if ncx > 1 and ncy > 1 and ncx != ncy:
-            cbook.warn_deprecated(
-                "2.2", message="cycling among columns of inputs with "
-                "non-matching shapes is deprecated.")
-        return [func(x[:, j % ncx], y[:, j % ncy], kw, kwargs)
-                for j in range(max(ncx, ncy))]
-
-
-class _AxesBase(martist.Artist):
-    name = "rectilinear"
-
-    _shared_x_axes = cbook.Grouper()
-    _shared_y_axes = cbook.Grouper()
-    _twinned_axes = cbook.Grouper()
-
-    def __str__(self):
-        return "{0}({1[0]:g},{1[1]:g};{1[2]:g}x{1[3]:g})".format(
-            type(self).__name__, self._position.bounds)
-
-    def __init__(self, fig, rect,
-                 facecolor=None,  # defaults to rc axes.facecolor
-                 frameon=True,
-                 sharex=None,  # use Axes instance's xaxis info
-                 sharey=None,  # use Axes instance's yaxis info
-                 label='',
-                 xscale=None,
-                 yscale=None,
-                 **kwargs
-                 ):
-        """
-        Build an axes in a figure.
-
-        Parameters
-        ----------
-        fig : `~matplotlib.figure.Figure`
-            The axes is build in the `.Figure` *fig*.
-
-        rect : [left, bottom, width, height]
-            The axes is build in the rectangle *rect*. *rect* is in
-            `.Figure` coordinates.
-
-        sharex, sharey : `~.axes.Axes`, optional
-            The x or y `~.matplotlib.axis` is shared with the x or
-            y axis in the input `~.axes.Axes`.
-
-        frameon : bool, optional
-            True means that the axes frame is visible.
-
-        **kwargs
-            Other optional keyword arguments:
-
-            %(Axes)s
-
-        Returns
-        -------
-        axes : `~.axes.Axes`
-            The new `~.axes.Axes` object.
-        """
-
-        martist.Artist.__init__(self)
-        if isinstance(rect, mtransforms.Bbox):
-            self._position = rect
-        else:
-            self._position = mtransforms.Bbox.from_bounds(*rect)
-        if self._position.width < 0 or self._position.height < 0:
-            raise ValueError('Width and height specified must be non-negative')
-        self._originalPosition = self._position.frozen()
-        self.axes = self
-        self._aspect = 'auto'
-        self._adjustable = 'box'
-        self._anchor = 'C'
-        self._stale_viewlim_x = False
-        self._stale_viewlim_y = False
-        self._sharex = sharex
-        self._sharey = sharey
-        if sharex is not None:
-            self._shared_x_axes.join(self, sharex)
-        if sharey is not None:
-            self._shared_y_axes.join(self, sharey)
-        self.set_label(label)
-        self.set_figure(fig)
-
-        self.set_axes_locator(kwargs.get("axes_locator", None))
-
-        self.spines = self._gen_axes_spines()
-
-        # this call may differ for non-sep axes, e.g., polar
-        self._init_axis()
-        if facecolor is None:
-            facecolor = rcParams['axes.facecolor']
-        self._facecolor = facecolor
-        self._frameon = frameon
-        self.set_axisbelow(rcParams['axes.axisbelow'])
-
-        self._rasterization_zorder = None
-        self.cla()
-
-        # funcs used to format x and y - fall back on major formatters
-        self.fmt_xdata = None
-        self.fmt_ydata = None
-
-        self.set_navigate(True)
-        self.set_navigate_mode(None)
-
-        if xscale:
-            self.set_xscale(xscale)
-        if yscale:
-            self.set_yscale(yscale)
-
-        self.update(kwargs)
-
-        if self.xaxis is not None:
-            self._xcid = self.xaxis.callbacks.connect(
-                'units finalize', lambda: self._on_units_changed(scalex=True))
-
-        if self.yaxis is not None:
-            self._ycid = self.yaxis.callbacks.connect(
-                'units finalize', lambda: self._on_units_changed(scaley=True))
-
-        self.tick_params(
-            top=rcParams['xtick.top'] and rcParams['xtick.minor.top'],
-            bottom=rcParams['xtick.bottom'] and rcParams['xtick.minor.bottom'],
-            labeltop=(rcParams['xtick.labeltop'] and
-                      rcParams['xtick.minor.top']),
-            labelbottom=(rcParams['xtick.labelbottom'] and
-                         rcParams['xtick.minor.bottom']),
-            left=rcParams['ytick.left'] and rcParams['ytick.minor.left'],
-            right=rcParams['ytick.right'] and rcParams['ytick.minor.right'],
-            labelleft=(rcParams['ytick.labelleft'] and
-                       rcParams['ytick.minor.left']),
-            labelright=(rcParams['ytick.labelright'] and
-                        rcParams['ytick.minor.right']),
-            which='minor')
-
-        self.tick_params(
-            top=rcParams['xtick.top'] and rcParams['xtick.major.top'],
-            bottom=rcParams['xtick.bottom'] and rcParams['xtick.major.bottom'],
-            labeltop=(rcParams['xtick.labeltop'] and
-                      rcParams['xtick.major.top']),
-            labelbottom=(rcParams['xtick.labelbottom'] and
-                         rcParams['xtick.major.bottom']),
-            left=rcParams['ytick.left'] and rcParams['ytick.major.left'],
-            right=rcParams['ytick.right'] and rcParams['ytick.major.right'],
-            labelleft=(rcParams['ytick.labelleft'] and
-                       rcParams['ytick.major.left']),
-            labelright=(rcParams['ytick.labelright'] and
-                        rcParams['ytick.major.right']),
-            which='major')
-
-        self._layoutbox = None
-        self._poslayoutbox = None
-
-    def __getstate__(self):
-        # The renderer should be re-created by the figure, and then cached at
-        # that point.
-        state = super().__getstate__()
-        for key in ['_layoutbox', '_poslayoutbox']:
-            state[key] = None
-        # Prune the sharing & twinning info to only contain the current group.
-        for grouper_name in [
-                '_shared_x_axes', '_shared_y_axes', '_twinned_axes']:
-            grouper = getattr(self, grouper_name)
-            state[grouper_name] = (grouper.get_siblings(self)
-                                   if self in grouper else None)
-        return state
-
-    def __setstate__(self, state):
-        # Merge the grouping info back into the global groupers.
-        for grouper_name in [
-                '_shared_x_axes', '_shared_y_axes', '_twinned_axes']:
-            siblings = state.pop(grouper_name)
-            if siblings:
-                getattr(self, grouper_name).join(*siblings)
-        self.__dict__ = state
-        self._stale = True
-
-    def get_window_extent(self, *args, **kwargs):
-        """
-        Return the axes bounding box in display space; *args* and *kwargs*
-        are empty.
-
-        This bounding box does not include the spines, ticks, ticklables,
-        or other labels.  For a bounding box including these elements use
-        `~matplotlib.axes.Axes.get_tightbbox`.
-
-        See Also
-        --------
-        matplotlib.axes.Axes.get_tightbbox
-        matplotlib.axis.Axis.get_tightbbox
-        matplotlib.spines.get_window_extent
-
-        """
-        return self.bbox
-
-    def _init_axis(self):
-        "move this out of __init__ because non-separable axes don't use it"
-        self.xaxis = maxis.XAxis(self)
-        self.spines['bottom'].register_axis(self.xaxis)
-        self.spines['top'].register_axis(self.xaxis)
-        self.yaxis = maxis.YAxis(self)
-        self.spines['left'].register_axis(self.yaxis)
-        self.spines['right'].register_axis(self.yaxis)
-        self._update_transScale()
-
-    def set_figure(self, fig):
-        """
-        Set the `.Figure` for this `.Axes`.
-
-        Parameters
-        ----------
-        fig : `.Figure`
-        """
-        martist.Artist.set_figure(self, fig)
-
-        self.bbox = mtransforms.TransformedBbox(self._position,
-                                                fig.transFigure)
-        # these will be updated later as data is added
-        self.dataLim = mtransforms.Bbox.null()
-        self._viewLim = mtransforms.Bbox.unit()
-        self.transScale = mtransforms.TransformWrapper(
-            mtransforms.IdentityTransform())
-
-        self._set_lim_and_transforms()
-
-    def _unstale_viewLim(self):
-        # We should arrange to store this information once per share-group
-        # instead of on every axis.
-        scalex = any(ax._stale_viewlim_x
-                     for ax in self._shared_x_axes.get_siblings(self))
-        scaley = any(ax._stale_viewlim_y
-                     for ax in self._shared_y_axes.get_siblings(self))
-        if scalex or scaley:
-            for ax in self._shared_x_axes.get_siblings(self):
-                ax._stale_viewlim_x = False
-            for ax in self._shared_y_axes.get_siblings(self):
-                ax._stale_viewlim_y = False
-            self.autoscale_view(scalex=scalex, scaley=scaley)
-
-    @property
-    def viewLim(self):
-        self._unstale_viewLim()
-        return self._viewLim
-
-    # API could be better, right now this is just to match the old calls to
-    # autoscale_view() after each plotting method.
-    def _request_autoscale_view(self, tight=None, scalex=True, scaley=True):
-        if tight is not None:
-            self._tight = tight
-        if scalex:
-            self._stale_viewlim_x = True  # Else keep old state.
-        if scaley:
-            self._stale_viewlim_y = True
-
-    def _set_lim_and_transforms(self):
-        """
-        Set the *_xaxis_transform*, *_yaxis_transform*, *transScale*,
-        *transData*, *transLimits* and *transAxes* transformations.
-
-        .. note::
-
-            This method is primarily used by rectilinear projections of the
-            `~matplotlib.axes.Axes` class, and is meant to be overridden by
-            new kinds of projection axes that need different transformations
-            and limits. (See `~matplotlib.projections.polar.PolarAxes` for an
-            example.)
-        """
-        self.transAxes = mtransforms.BboxTransformTo(self.bbox)
-
-        # Transforms the x and y axis separately by a scale factor.
-        # It is assumed that this part will have non-linear components
-        # (e.g., for a log scale).
-        self.transScale = mtransforms.TransformWrapper(
-            mtransforms.IdentityTransform())
-
-        # An affine transformation on the data, generally to limit the
-        # range of the axes
-        self.transLimits = mtransforms.BboxTransformFrom(
-            mtransforms.TransformedBbox(self._viewLim, self.transScale))
-
-        # The parentheses are important for efficiency here -- they
-        # group the last two (which are usually affines) separately
-        # from the first (which, with log-scaling can be non-affine).
-        self.transData = self.transScale + (self.transLimits + self.transAxes)
-
-        self._xaxis_transform = mtransforms.blended_transform_factory(
-            self.transData, self.transAxes)
-        self._yaxis_transform = mtransforms.blended_transform_factory(
-            self.transAxes, self.transData)
-
-    def get_xaxis_transform(self, which='grid'):
-        """
-        Get the transformation used for drawing x-axis labels, ticks
-        and gridlines.  The x-direction is in data coordinates and the
-        y-direction is in axis coordinates.
-
-        .. note::
-
-            This transformation is primarily used by the
-            `~matplotlib.axis.Axis` class, and is meant to be
-            overridden by new kinds of projections that may need to
-            place axis elements in different locations.
-        """
-        if which == 'grid':
-            return self._xaxis_transform
-        elif which == 'tick1':
-            # for cartesian projection, this is bottom spine
-            return self.spines['bottom'].get_spine_transform()
-        elif which == 'tick2':
-            # for cartesian projection, this is top spine
-            return self.spines['top'].get_spine_transform()
-        else:
-            raise ValueError('unknown value for which')
-
-    def get_xaxis_text1_transform(self, pad_points):
-        """
-        Returns
-        -------
-        transform : Transform
-            The transform used for drawing x-axis labels, which will add
-            *pad_points* of padding (in points) between the axes and the label.
-            The x-direction is in data coordinates and the y-direction is in
-            axis corrdinates
-        valign : {'center', 'top', 'bottom', 'baseline', 'center_baseline'}
-            The text vertical alignment.
-        halign : {'center', 'left', 'right'}
-            The text horizontal alignment.
-
-        Notes
-        -----
-        This transformation is primarily used by the `~matplotlib.axis.Axis`
-        class, and is meant to be overridden by new kinds of projections that
-        may need to place axis elements in different locations.
-        """
-        labels_align = rcParams["xtick.alignment"]
-        return (self.get_xaxis_transform(which='tick1') +
-                mtransforms.ScaledTranslation(0, -1 * pad_points / 72,
-                                              self.figure.dpi_scale_trans),
-                "top", labels_align)
-
-    def get_xaxis_text2_transform(self, pad_points):
-        """
-        Returns
-        -------
-        transform : Transform
-            The transform used for drawing secondary x-axis labels, which will
-            add *pad_points* of padding (in points) between the axes and the
-            label.  The x-direction is in data coordinates and the y-direction
-            is in axis corrdinates
-        valign : {'center', 'top', 'bottom', 'baseline', 'center_baseline'}
-            The text vertical alignment.
-        halign : {'center', 'left', 'right'}
-            The text horizontal alignment.
-
-        Notes
-        -----
-        This transformation is primarily used by the `~matplotlib.axis.Axis`
-        class, and is meant to be overridden by new kinds of projections that
-        may need to place axis elements in different locations.
-        """
-        labels_align = rcParams["xtick.alignment"]
-        return (self.get_xaxis_transform(which='tick2') +
-                mtransforms.ScaledTranslation(0, pad_points / 72,
-                                              self.figure.dpi_scale_trans),
-                "bottom", labels_align)
-
-    def get_yaxis_transform(self, which='grid'):
-        """
-        Get the transformation used for drawing y-axis labels, ticks
-        and gridlines.  The x-direction is in axis coordinates and the
-        y-direction is in data coordinates.
-
-        .. note::
-
-            This transformation is primarily used by the
-            `~matplotlib.axis.Axis` class, and is meant to be
-            overridden by new kinds of projections that may need to
-            place axis elements in different locations.
-        """
-        if which == 'grid':
-            return self._yaxis_transform
-        elif which == 'tick1':
-            # for cartesian projection, this is bottom spine
-            return self.spines['left'].get_spine_transform()
-        elif which == 'tick2':
-            # for cartesian projection, this is top spine
-            return self.spines['right'].get_spine_transform()
-        else:
-            raise ValueError('unknown value for which')
-
-    def get_yaxis_text1_transform(self, pad_points):
-        """
-        Returns
-        -------
-        transform : Transform
-            The transform used for drawing y-axis labels, which will add
-            *pad_points* of padding (in points) between the axes and the label.
-            The x-direction is in axis coordinates and the y-direction is in
-            data corrdinates
-        valign : {'center', 'top', 'bottom', 'baseline', 'center_baseline'}
-            The text vertical alignment.
-        halign : {'center', 'left', 'right'}
-            The text horizontal alignment.
-
-        Notes
-        -----
-        This transformation is primarily used by the `~matplotlib.axis.Axis`
-        class, and is meant to be overridden by new kinds of projections that
-        may need to place axis elements in different locations.
-        """
-        labels_align = rcParams["ytick.alignment"]
-        return (self.get_yaxis_transform(which='tick1') +
-                mtransforms.ScaledTranslation(-1 * pad_points / 72, 0,
-                                              self.figure.dpi_scale_trans),
-                labels_align, "right")
-
-    def get_yaxis_text2_transform(self, pad_points):
-        """
-        Returns
-        -------
-        transform : Transform
-            The transform used for drawing secondart y-axis labels, which will
-            add *pad_points* of padding (in points) between the axes and the
-            label.  The x-direction is in axis coordinates and the y-direction
-            is in data corrdinates
-        valign : {'center', 'top', 'bottom', 'baseline', 'center_baseline'}
-            The text vertical alignment.
-        halign : {'center', 'left', 'right'}
-            The text horizontal alignment.
-
-        Notes
-        -----
-        This transformation is primarily used by the `~matplotlib.axis.Axis`
-        class, and is meant to be overridden by new kinds of projections that
-        may need to place axis elements in different locations.
-        """
-        labels_align = rcParams["ytick.alignment"]
-        return (self.get_yaxis_transform(which='tick2') +
-                mtransforms.ScaledTranslation(pad_points / 72, 0,
-                                              self.figure.dpi_scale_trans),
-                labels_align, "left")
-
-    def _update_transScale(self):
-        self.transScale.set(
-            mtransforms.blended_transform_factory(
-                self.xaxis.get_transform(), self.yaxis.get_transform()))
-        for line in getattr(self, "lines", []):  # Not set during init.
-            try:
-                line._transformed_path.invalidate()
-            except AttributeError:
-                pass
-
-    def get_position(self, original=False):
-        """
-        Get a copy of the axes rectangle as a `.Bbox`.
-
-        Parameters
-        ----------
-        original : bool
-            If ``True``, return the original position. Otherwise return the
-            active position. For an explanation of the positions see
-            `.set_position`.
-
-        Returns
-        -------
-        pos : `.Bbox`
-
-        """
-        if original:
-            return self._originalPosition.frozen()
-        else:
-            locator = self.get_axes_locator()
-            if not locator:
-                self.apply_aspect()
-            return self._position.frozen()
-
-    def set_position(self, pos, which='both'):
-        """
-        Set the axes position.
-
-        Axes have two position attributes. The 'original' position is the
-        position allocated for the Axes. The 'active' position is the
-        position the Axes is actually drawn at. These positions are usually
-        the same unless a fixed aspect is set to the Axes. See `.set_aspect`
-        for details.
-
-        Parameters
-        ----------
-        pos : [left, bottom, width, height] or `~matplotlib.transforms.Bbox`
-            The new position of the in `.Figure` coordinates.
-
-        which : {'both', 'active', 'original'}, optional
-            Determines which position variables to change.
-
-        """
-        self._set_position(pos, which=which)
-        # because this is being called externally to the library we
-        # zero the constrained layout parts.
-        self._layoutbox = None
-        self._poslayoutbox = None
-
-    def _set_position(self, pos, which='both'):
-        """
-        private version of set_position.  Call this internally
-        to get the same functionality of `get_position`, but not
-        to take the axis out of the constrained_layout
-        hierarchy.
-        """
-        if not isinstance(pos, mtransforms.BboxBase):
-            pos = mtransforms.Bbox.from_bounds(*pos)
-        for ax in self._twinned_axes.get_siblings(self):
-            if which in ('both', 'active'):
-                ax._position.set(pos)
-            if which in ('both', 'original'):
-                ax._originalPosition.set(pos)
-        self.stale = True
-
-    def reset_position(self):
-        """
-        Reset the active position to the original position.
-
-        This resets the a possible position change due to aspect constraints.
-        For an explanation of the positions see `.set_position`.
-        """
-        for ax in self._twinned_axes.get_siblings(self):
-            pos = ax.get_position(original=True)
-            ax.set_position(pos, which='active')
-
-    def set_axes_locator(self, locator):
-        """
-        Set the axes locator.
-
-        Parameters
-        ----------
-        locator : Callable[[Axes, Renderer], Bbox]
-        """
-        self._axes_locator = locator
-        self.stale = True
-
-    def get_axes_locator(self):
-        """
-        Return the axes_locator.
-        """
-        return self._axes_locator
-
-    def _set_artist_props(self, a):
-        """set the boilerplate props for artists added to axes"""
-        a.set_figure(self.figure)
-        if not a.is_transform_set():
-            a.set_transform(self.transData)
-
-        a.axes = self
-        if a.mouseover:
-            self._mouseover_set.add(a)
-
-    def _gen_axes_patch(self):
-        """
-        Returns
-        -------
-        Patch
-            The patch used to draw the background of the axes.  It is also used
-            as the clipping path for any data elements on the axes.
-
-            In the standard axes, this is a rectangle, but in other projections
-            it may not be.
-
-        Notes
-        -----
-        Intended to be overridden by new projection types.
-        """
-        return mpatches.Rectangle((0.0, 0.0), 1.0, 1.0)
-
-    def _gen_axes_spines(self, locations=None, offset=0.0, units='inches'):
-        """
-        Returns
-        -------
-        dict
-            Mapping of spine names to `Line2D` or `Patch` instances that are
-            used to draw axes spines.
-
-            In the standard axes, spines are single line segments, but in other
-            projections they may not be.
-
-        Notes
-        -----
-        Intended to be overridden by new projection types.
-        """
-        return OrderedDict((side, mspines.Spine.linear_spine(self, side))
-                           for side in ['left', 'right', 'bottom', 'top'])
-
-    def cla(self):
-        """Clear the current axes."""
-        # Note: this is called by Axes.__init__()
-
-        # stash the current visibility state
-        if hasattr(self, 'patch'):
-            patch_visible = self.patch.get_visible()
-        else:
-            patch_visible = True
-
-        xaxis_visible = self.xaxis.get_visible()
-        yaxis_visible = self.yaxis.get_visible()
-
-        self.xaxis.cla()
-        self.yaxis.cla()
-
-        for name, spine in self.spines.items():
-            spine.cla()
-
-        self.ignore_existing_data_limits = True
-        self.callbacks = cbook.CallbackRegistry()
-
-        if self._sharex is not None:
-            # major and minor are axis.Ticker class instances with
-            # locator and formatter attributes
-            self.xaxis.major = self._sharex.xaxis.major
-            self.xaxis.minor = self._sharex.xaxis.minor
-            x0, x1 = self._sharex.get_xlim()
-            self.set_xlim(x0, x1, emit=False,
-                          auto=self._sharex.get_autoscalex_on())
-            self.xaxis._scale = self._sharex.xaxis._scale
-        else:
-            self.xaxis._set_scale('linear')
-            try:
-                self.set_xlim(0, 1)
-            except TypeError:
-                pass
-
-        if self._sharey is not None:
-            self.yaxis.major = self._sharey.yaxis.major
-            self.yaxis.minor = self._sharey.yaxis.minor
-            y0, y1 = self._sharey.get_ylim()
-            self.set_ylim(y0, y1, emit=False,
-                          auto=self._sharey.get_autoscaley_on())
-            self.yaxis._scale = self._sharey.yaxis._scale
-        else:
-            self.yaxis._set_scale('linear')
-            try:
-                self.set_ylim(0, 1)
-            except TypeError:
-                pass
-        # update the minor locator for x and y axis based on rcParams
-        if rcParams['xtick.minor.visible']:
-            self.xaxis.set_minor_locator(mticker.AutoMinorLocator())
-
-        if rcParams['ytick.minor.visible']:
-            self.yaxis.set_minor_locator(mticker.AutoMinorLocator())
-
-        if self._sharex is None:
-            self._autoscaleXon = True
-        if self._sharey is None:
-            self._autoscaleYon = True
-        self._xmargin = rcParams['axes.xmargin']
-        self._ymargin = rcParams['axes.ymargin']
-        self._tight = None
-        self._use_sticky_edges = True
-        self._update_transScale()  # needed?
-
-        self._get_lines = _process_plot_var_args(self)
-        self._get_patches_for_fill = _process_plot_var_args(self, 'fill')
-
-        self._gridOn = rcParams['axes.grid']
-        self.lines = []
-        self.patches = []
-        self.texts = []
-        self.tables = []
-        self.artists = []
-        self.images = []
-        self._mouseover_set = _OrderedSet()
-        self.child_axes = []
-        self._current_image = None  # strictly for pyplot via _sci, _gci
-        self.legend_ = None
-        self.collections = []  # collection.Collection instances
-        self.containers = []
-
-        self.grid(False)  # Disable grid on init to use rcParameter
-        self.grid(self._gridOn, which=rcParams['axes.grid.which'],
-                  axis=rcParams['axes.grid.axis'])
-        props = font_manager.FontProperties(
-            size=rcParams['axes.titlesize'],
-            weight=rcParams['axes.titleweight'])
-
-        self.title = mtext.Text(
-            x=0.5, y=1.0, text='',
-            fontproperties=props,
-            verticalalignment='baseline',
-            horizontalalignment='center',
-            )
-        self._left_title = mtext.Text(
-            x=0.0, y=1.0, text='',
-            fontproperties=props.copy(),
-            verticalalignment='baseline',
-            horizontalalignment='left', )
-        self._right_title = mtext.Text(
-            x=1.0, y=1.0, text='',
-            fontproperties=props.copy(),
-            verticalalignment='baseline',
-            horizontalalignment='right',
-            )
-        title_offset_points = rcParams['axes.titlepad']
-        # refactor this out so it can be called in ax.set_title if
-        # pad argument used...
-        self._set_title_offset_trans(title_offset_points)
-        # determine if the title position has been set manually:
-        self._autotitlepos = None
-
-        for _title in (self.title, self._left_title, self._right_title):
-            self._set_artist_props(_title)
-
-        # The patch draws the background of the axes.  We want this to be below
-        # the other artists.  We use the frame to draw the edges so we are
-        # setting the edgecolor to None.
-        self.patch = self._gen_axes_patch()
-        self.patch.set_figure(self.figure)
-        self.patch.set_facecolor(self._facecolor)
-        self.patch.set_edgecolor('None')
-        self.patch.set_linewidth(0)
-        self.patch.set_transform(self.transAxes)
-
-        self.set_axis_on()
-
-        self.xaxis.set_clip_path(self.patch)
-        self.yaxis.set_clip_path(self.patch)
-
-        self._shared_x_axes.clean()
-        self._shared_y_axes.clean()
-        if self._sharex:
-            self.xaxis.set_visible(xaxis_visible)
-            self.patch.set_visible(patch_visible)
-
-        if self._sharey:
-            self.yaxis.set_visible(yaxis_visible)
-            self.patch.set_visible(patch_visible)
-
-        self.stale = True
-
-    def clear(self):
-        """Clear the axes."""
-        self.cla()
-
-    def get_facecolor(self):
-        """Get the facecolor of the Axes."""
-        return self.patch.get_facecolor()
-    get_fc = get_facecolor
-
-    def set_facecolor(self, color):
-        """
-        Set the facecolor of the Axes.
-
-        Parameters
-        ----------
-        color : color
-        """
-        self._facecolor = color
-        self.stale = True
-        return self.patch.set_facecolor(color)
-    set_fc = set_facecolor
-
-    def _set_title_offset_trans(self, title_offset_points):
-        """
-        Set the offset for the title either from rcParams['axes.titlepad']
-        or from set_title kwarg ``pad``.
-        """
-        self.titleOffsetTrans = mtransforms.ScaledTranslation(
-                0.0, title_offset_points / 72,
-                self.figure.dpi_scale_trans)
-        for _title in (self.title, self._left_title, self._right_title):
-            _title.set_transform(self.transAxes + self.titleOffsetTrans)
-            _title.set_clip_box(None)
-
-    def set_prop_cycle(self, *args, **kwargs):
-        """
-        Set the property cycle of the Axes.
-
-        The property cycle controls the style properties such as color,
-        marker and linestyle of future plot commands. The style properties
-        of data already added to the Axes are not modified.
-
-        Call signatures::
-
-          set_prop_cycle(cycler)
-          set_prop_cycle(label=values[, label2=values2[, ...]])
-          set_prop_cycle(label, values)
-
-        Form 1 sets given `~cycler.Cycler` object.
-
-        Form 2 creates a `~cycler.Cycler` which cycles over one or more
-        properties simultaneously and set it as the property cycle of the
-        axes. If multiple properties are given, their value lists must have
-        the same length. This is just a shortcut for explicitly creating a
-        cycler and passing it to the function, i.e. it's short for
-        ``set_prop_cycle(cycler(label=values label2=values2, ...))``.
-
-        Form 3 creates a `~cycler.Cycler` for a single property and set it
-        as the property cycle of the axes. This form exists for compatibility
-        with the original `cycler.cycler` interface. Its use is discouraged
-        in favor of the kwarg form, i.e. ``set_prop_cycle(label=values)``.
-
-        Parameters
-        ----------
-        cycler : Cycler
-            Set the given Cycler. *None* resets to the cycle defined by the
-            current style.
-
-        label : str
-            The property key. Must be a valid `.Artist` property.
-            For example, 'color' or 'linestyle'. Aliases are allowed,
-            such as 'c' for 'color' and 'lw' for 'linewidth'.
-
-        values : iterable
-            Finite-length iterable of the property values. These values
-            are validated and will raise a ValueError if invalid.
-
-        Examples
-        --------
-        Setting the property cycle for a single property:
-
-        >>> ax.set_prop_cycle(color=['red', 'green', 'blue'])
-
-        Setting the property cycle for simultaneously cycling over multiple
-        properties (e.g. red circle, green plus, blue cross):
-
-        >>> ax.set_prop_cycle(color=['red', 'green', 'blue'],
-        ...                   marker=['o', '+', 'x'])
-
-        See Also
-        --------
-        matplotlib.rcsetup.cycler
-            Convenience function for creating validated cyclers for properties.
-        cycler.cycler
-            The original function for creating unvalidated cyclers.
-
-        """
-        if args and kwargs:
-            raise TypeError("Cannot supply both positional and keyword "
-                            "arguments to this method.")
-        # Can't do `args == (None,)` as that crashes cycler.
-        if len(args) == 1 and args[0] is None:
-            prop_cycle = None
-        else:
-            prop_cycle = cycler(*args, **kwargs)
-        self._get_lines.set_prop_cycle(prop_cycle)
-        self._get_patches_for_fill.set_prop_cycle(prop_cycle)
-
-    def get_aspect(self):
-        return self._aspect
-
-    def set_aspect(self, aspect, adjustable=None, anchor=None, share=False):
-        """
-        Set the aspect of the axis scaling, i.e. the ratio of y-unit to x-unit.
-
-        Parameters
-        ----------
-        aspect : {'auto', 'equal'} or num
-            Possible values:
-
-            ========   ================================================
-            value      description
-            ========   ================================================
-            'auto'     automatic; fill the position rectangle with data
-            'equal'    same scaling from data to plot units for x and y
-             num       a circle will be stretched such that the height
-                       is num times the width. aspect=1 is the same as
-                       aspect='equal'.
-            ========   ================================================
-
-        adjustable : None or {'box', 'datalim'}, optional
-            If not ``None``, this defines which parameter will be adjusted to
-            meet the required aspect. See `.set_adjustable` for further
-            details.
-
-        anchor : None or str or 2-tuple of float, optional
-            If not ``None``, this defines where the Axes will be drawn if there
-            is extra space due to aspect constraints. The most common way to
-            to specify the anchor are abbreviations of cardinal directions:
-
-            =====   =====================
-            value   description
-            =====   =====================
-            'C'     centered
-            'SW'    lower left corner
-            'S'     middle of bottom edge
-            'SE'    lower right corner
-            etc.
-            =====   =====================
-
-            See `.set_anchor` for further details.
-
-        share : bool, optional
-            If ``True``, apply the settings to all shared Axes.
-            Default is ``False``.
-
-        See Also
-        --------
-        matplotlib.axes.Axes.set_adjustable
-            defining the parameter to adjust in order to meet the required
-            aspect.
-        matplotlib.axes.Axes.set_anchor
-            defining the position in case of extra space.
-        """
-        if not (cbook._str_equal(aspect, 'equal')
-                or cbook._str_equal(aspect, 'auto')):
-            aspect = float(aspect)  # raise ValueError if necessary
-
-        if (not cbook._str_equal(aspect, 'auto')) and self.name == '3d':
-            raise NotImplementedError(
-                'It is not currently possible to manually set the aspect '
-                'on 3D axes')
-
-        if share:
-            axes = {*self._shared_x_axes.get_siblings(self),
-                    *self._shared_y_axes.get_siblings(self)}
-        else:
-            axes = [self]
-
-        for ax in axes:
-            ax._aspect = aspect
-
-        if adjustable is None:
-            adjustable = self._adjustable
-        self.set_adjustable(adjustable, share=share)  # Handle sharing.
-
-        if anchor is not None:
-            self.set_anchor(anchor, share=share)
-        self.stale = True
-
-    def get_adjustable(self):
-        return self._adjustable
-
-    def set_adjustable(self, adjustable, share=False):
-        """
-        Define which parameter the Axes will change to achieve a given aspect.
-
-        Parameters
-        ----------
-        adjustable : {'box', 'datalim'}
-            If 'box', change the physical dimensions of the Axes.
-            If 'datalim', change the ``x`` or ``y`` data limits.
-
-        share : bool, optional
-            If ``True``, apply the settings to all shared Axes.
-            Default is ``False``.
-
-        See Also
-        --------
-        matplotlib.axes.Axes.set_aspect
-            for a description of aspect handling.
-
-        Notes
-        -----
-        Shared Axes (of which twinned Axes are a special case)
-        impose restrictions on how aspect ratios can be imposed.
-        For twinned Axes, use 'datalim'.  For Axes that share both
-        x and y, use 'box'.  Otherwise, either 'datalim' or 'box'
-        may be used.  These limitations are partly a requirement
-        to avoid over-specification, and partly a result of the
-        particular implementation we are currently using, in
-        which the adjustments for aspect ratios are done sequentially
-        and independently on each Axes as it is drawn.
-        """
-        cbook._check_in_list(["box", "datalim"], adjustable=adjustable)
-        if share:
-            axs = {*self._shared_x_axes.get_siblings(self),
-                   *self._shared_y_axes.get_siblings(self)}
-        else:
-            axs = [self]
-        if (adjustable == "datalim"
-                and any(getattr(ax.get_data_ratio, "__func__", None)
-                        != _AxesBase.get_data_ratio
-                        for ax in axs)):
-            # Limits adjustment by apply_aspect assumes that the axes' aspect
-            # ratio can be computed from the data limits and scales.
-            raise ValueError("Cannot set axes adjustable to 'datalim' for "
-                             "Axes which override 'get_data_ratio'")
-        for ax in axs:
-            ax._adjustable = adjustable
-        self.stale = True
-
-    def get_anchor(self):
-        """
-        Get the anchor location.
-
-        See Also
-        --------
-        matplotlib.axes.Axes.set_anchor
-            for a description of the anchor.
-        matplotlib.axes.Axes.set_aspect
-            for a description of aspect handling.
-        """
-        return self._anchor
-
-    def set_anchor(self, anchor, share=False):
-        """
-        Define the anchor location.
-
-        The actual drawing area (active position) of the Axes may be smaller
-        than the Bbox (original position) when a fixed aspect is required. The
-        anchor defines where the drawing area will be located within the
-        available space.
-
-        Parameters
-        ----------
-        anchor : 2-tuple of floats or {'C', 'SW', 'S', 'SE', ...}
-            The anchor position may be either:
-
-            - a sequence (*cx*, *cy*). *cx* and *cy* may range from 0
-              to 1, where 0 is left or bottom and 1 is right or top.
-
-            - a string using cardinal directions as abbreviation:
-
-              - 'C' for centered
-              - 'S' (south) for bottom-center
-              - 'SW' (south west) for bottom-left
-              - etc.
-
-              Here is an overview of the possible positions:
-
-              +------+------+------+
-              | 'NW' | 'N'  | 'NE' |
-              +------+------+------+
-              | 'W'  | 'C'  | 'E'  |
-              +------+------+------+
-              | 'SW' | 'S'  | 'SE' |
-              +------+------+------+
-
-        share : bool, optional
-            If ``True``, apply the settings to all shared Axes.
-            Default is ``False``.
-
-        See Also
-        --------
-        matplotlib.axes.Axes.set_aspect
-            for a description of aspect handling.
-        """
-        if not (anchor in mtransforms.Bbox.coefs or len(anchor) == 2):
-            raise ValueError('argument must be among %s' %
-                             ', '.join(mtransforms.Bbox.coefs))
-        if share:
-            axes = {*self._shared_x_axes.get_siblings(self),
-                    *self._shared_y_axes.get_siblings(self)}
-        else:
-            axes = [self]
-        for ax in axes:
-            ax._anchor = anchor
-
-        self.stale = True
-
-    def get_data_ratio(self):
-        """
-        Return the aspect ratio of the scaled data.
-
-        Notes
-        -----
-        This method is intended to be overridden by new projection types.
-        """
-        txmin, txmax = self.xaxis.get_transform().transform(self.get_xbound())
-        tymin, tymax = self.yaxis.get_transform().transform(self.get_ybound())
-        xsize = max(abs(txmax - txmin), 1e-30)
-        ysize = max(abs(tymax - tymin), 1e-30)
-        return ysize / xsize
-
-    @cbook.deprecated("3.2")
-    def get_data_ratio_log(self):
-        """
-        Return the aspect ratio of the raw data in log scale.
-
-        Notes
-        -----
-        Will be used when both axis are in log scale.
-        """
-        xmin, xmax = self.get_xbound()
-        ymin, ymax = self.get_ybound()
-
-        xsize = max(abs(math.log10(xmax) - math.log10(xmin)), 1e-30)
-        ysize = max(abs(math.log10(ymax) - math.log10(ymin)), 1e-30)
-
-        return ysize / xsize
-
-    def apply_aspect(self, position=None):
-        """
-        Adjust the Axes for a specified data aspect ratio.
-
-        Depending on `.get_adjustable` this will modify either the Axes box
-        (position) or the view limits. In the former case, `.get_anchor`
-        will affect the position.
-
-        Notes
-        -----
-        This is called automatically when each Axes is drawn.  You may need
-        to call it yourself if you need to update the Axes position and/or
-        view limits before the Figure is drawn.
-
-        See Also
-        --------
-        matplotlib.axes.Axes.set_aspect
-            for a description of aspect ratio handling.
-        matplotlib.axes.Axes.set_adjustable
-            defining the parameter to adjust in order to meet the required
-            aspect.
-        matplotlib.axes.Axes.set_anchor
-            defining the position in case of extra space.
-        """
-        if position is None:
-            position = self.get_position(original=True)
-
-        aspect = self.get_aspect()
-
-        if aspect == 'auto':
-            self._set_position(position, which='active')
-            return
-
-        if aspect == 'equal':
-            aspect = 1
-
-        fig_width, fig_height = self.get_figure().get_size_inches()
-        fig_aspect = fig_height / fig_width
-
-        if self._adjustable == 'box':
-            if self in self._twinned_axes:
-                raise RuntimeError("Adjustable 'box' is not allowed in a "
-                                   "twinned Axes; use 'datalim' instead")
-            box_aspect = aspect * self.get_data_ratio()
-            pb = position.frozen()
-            pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect)
-            self._set_position(pb1.anchored(self.get_anchor(), pb), 'active')
-            return
-
-        # self._adjustable == 'datalim'
-
-        # reset active to original in case it had been changed by prior use
-        # of 'box'
-        self._set_position(position, which='active')
-
-        x_trf = self.xaxis.get_transform()
-        y_trf = self.yaxis.get_transform()
-        xmin, xmax = x_trf.transform(self.get_xbound())
-        ymin, ymax = y_trf.transform(self.get_ybound())
-        xsize = max(abs(xmax - xmin), 1e-30)
-        ysize = max(abs(ymax - ymin), 1e-30)
-
-        l, b, w, h = position.bounds
-        box_aspect = fig_aspect * (h / w)
-        data_ratio = box_aspect / aspect
-
-        y_expander = data_ratio * xsize / ysize - 1
-        # If y_expander > 0, the dy/dx viewLim ratio needs to increase
-        if abs(y_expander) < 0.005:
-            return
-
-        dL = self.dataLim
-        x0, x1 = x_trf.transform(dL.intervalx)
-        y0, y1 = y_trf.transform(dL.intervaly)
-        xr = 1.05 * (x1 - x0)
-        yr = 1.05 * (y1 - y0)
-
-        xmarg = xsize - xr
-        ymarg = ysize - yr
-        Ysize = data_ratio * xsize
-        Xsize = ysize / data_ratio
-        Xmarg = Xsize - xr
-        Ymarg = Ysize - yr
-        # Setting these targets to, e.g., 0.05*xr does not seem to help.
-        xm = 0
-        ym = 0
-
-        shared_x = self in self._shared_x_axes
-        shared_y = self in self._shared_y_axes
-        # Not sure whether we need this check:
-        if shared_x and shared_y:
-            raise RuntimeError("adjustable='datalim' is not allowed when both "
-                               "axes are shared")
-
-        # If y is shared, then we are only allowed to change x, etc.
-        if shared_y:
-            adjust_y = False
-        else:
-            if xmarg > xm and ymarg > ym:
-                adjy = ((Ymarg > 0 and y_expander < 0) or
-                        (Xmarg < 0 and y_expander > 0))
-            else:
-                adjy = y_expander > 0
-            adjust_y = shared_x or adjy  # (Ymarg > xmarg)
-
-        if adjust_y:
-            yc = 0.5 * (ymin + ymax)
-            y0 = yc - Ysize / 2.0
-            y1 = yc + Ysize / 2.0
-            self.set_ybound(y_trf.inverted().transform([y0, y1]))
-        else:
-            xc = 0.5 * (xmin + xmax)
-            x0 = xc - Xsize / 2.0
-            x1 = xc + Xsize / 2.0
-            self.set_xbound(x_trf.inverted().transform([x0, x1]))
-
-    def axis(self, *args, emit=True, **kwargs):
-        """
-        Convenience method to get or set some axis properties.
-
-        Call signatures::
-
-          xmin, xmax, ymin, ymax = axis()
-          xmin, xmax, ymin, ymax = axis([xmin, xmax, ymin, ymax])
-          xmin, xmax, ymin, ymax = axis(option)
-          xmin, xmax, ymin, ymax = axis(**kwargs)
-
-        Parameters
-        ----------
-        xmin, xmax, ymin, ymax : float, optional
-            The axis limits to be set.  This can also be achieved using ::
-
-                ax.set(xlim=(xmin, xmax), ylim=(ymin, ymax))
-
-        option : bool or str
-            If a bool, turns axis lines and labels on or off. If a string,
-            possible values are:
-
-            ======== ==========================================================
-            Value    Description
-            ======== ==========================================================
-            'on'     Turn on axis lines and labels. Same as ``True``.
-            'off'    Turn off axis lines and labels. Same as ``False``.
-            'equal'  Set equal scaling (i.e., make circles circular) by
-                     changing axis limits. This is the same as
-                     ``ax.set_aspect('equal', adjustable='datalim')``.
-                     Explicit data limits may not be respected in this case.
-            'scaled' Set equal scaling (i.e., make circles circular) by
-                     changing dimensions of the plot box. This is the same as
-                     ``ax.set_aspect('equal', adjustable='box', anchor='C')``.
-                     Additionally, further autoscaling will be disabled.
-            'tight'  Set limits just large enough to show all data, then
-                     disable further autoscaling.
-            'auto'   Automatic scaling (fill plot box with data).
-            'normal' Same as 'auto'; deprecated.
-            'image'  'scaled' with axis limits equal to data limits.
-            'square' Square plot; similar to 'scaled', but initially forcing
-                     ``xmax-xmin == ymax-ymin``.
-            ======== ==========================================================
-
-        emit : bool, optional, default *True*
-            Whether observers are notified of the axis limit change.
-            This option is passed on to `~.Axes.set_xlim` and
-            `~.Axes.set_ylim`.
-
-        Returns
-        -------
-        xmin, xmax, ymin, ymax : float
-            The axis limits.
-
-        See also
-        --------
-        matplotlib.axes.Axes.set_xlim
-        matplotlib.axes.Axes.set_ylim
-        """
-        if len(args) == 1 and isinstance(args[0], (str, bool)):
-            s = args[0]
-            if s is True:
-                s = 'on'
-            if s is False:
-                s = 'off'
-            s = s.lower()
-            if s == 'on':
-                self.set_axis_on()
-            elif s == 'off':
-                self.set_axis_off()
-            elif s in ('equal', 'tight', 'scaled', 'normal',
-                       'auto', 'image', 'square'):
-                if s == 'normal':
-                    cbook.warn_deprecated(
-                        "3.1", message="Passing 'normal' to axis() is "
-                        "deprecated since %(since)s; use 'auto' instead.")
-                self.set_autoscale_on(True)
-                self.set_aspect('auto')
-                self.autoscale_view(tight=False)
-                # self.apply_aspect()
-                if s == 'equal':
-                    self.set_aspect('equal', adjustable='datalim')
-                elif s == 'scaled':
-                    self.set_aspect('equal', adjustable='box', anchor='C')
-                    self.set_autoscale_on(False)  # Req. by Mark Bakker
-                elif s == 'tight':
-                    self.autoscale_view(tight=True)
-                    self.set_autoscale_on(False)
-                elif s == 'image':
-                    self.autoscale_view(tight=True)
-                    self.set_autoscale_on(False)
-                    self.set_aspect('equal', adjustable='box', anchor='C')
-                elif s == 'square':
-                    self.set_aspect('equal', adjustable='box', anchor='C')
-                    self.set_autoscale_on(False)
-                    xlim = self.get_xlim()
-                    ylim = self.get_ylim()
-                    edge_size = max(np.diff(xlim), np.diff(ylim))[0]
-                    self.set_xlim([xlim[0], xlim[0] + edge_size],
-                                  emit=emit, auto=False)
-                    self.set_ylim([ylim[0], ylim[0] + edge_size],
-                                  emit=emit, auto=False)
-            else:
-                raise ValueError('Unrecognized string %s to axis; '
-                                 'try on or off' % s)
-        else:
-            if len(args) >= 1:
-                if len(args) != 1:
-                    cbook.warn_deprecated(
-                        "3.2", message="Passing more than one positional "
-                        "argument to axis() is deprecated and will raise a "
-                        "TypeError %(removal)s.")
-                limits = args[0]
-                try:
-                    xmin, xmax, ymin, ymax = limits
-                except (TypeError, ValueError):
-                    raise TypeError('the first argument to axis() must be an '
-                                    'interable of the form '
-                                    '[xmin, xmax, ymin, ymax]')
-            else:
-                xmin = kwargs.pop('xmin', None)
-                xmax = kwargs.pop('xmax', None)
-                ymin = kwargs.pop('ymin', None)
-                ymax = kwargs.pop('ymax', None)
-            xauto = (None  # Keep autoscale state as is.
-                     if xmin is None and xmax is None
-                     else False)  # Turn off autoscale.
-            yauto = (None
-                     if ymin is None and ymax is None
-                     else False)
-            self.set_xlim(xmin, xmax, emit=emit, auto=xauto)
-            self.set_ylim(ymin, ymax, emit=emit, auto=yauto)
-        if kwargs:
-            cbook.warn_deprecated(
-                "3.1", message="Passing unsupported keyword arguments to "
-                "axis() will raise a TypeError %(removal)s.")
-        return (*self.get_xlim(), *self.get_ylim())
-
-    def get_legend(self):
-        """Return the `Legend` instance, or None if no legend is defined."""
-        return self.legend_
-
-    def get_images(self):
-        """return a list of Axes images contained by the Axes"""
-        return cbook.silent_list('AxesImage', self.images)
-
-    def get_lines(self):
-        """Return a list of lines contained by the Axes"""
-        return cbook.silent_list('Line2D', self.lines)
-
-    def get_xaxis(self):
-        """Return the XAxis instance."""
-        return self.xaxis
-
-    def get_xgridlines(self):
-        """Get the x grid lines as a list of `Line2D` instances."""
-        return self.xaxis.get_gridlines()
-
-    def get_xticklines(self):
-        """Get the x tick lines as a list of `Line2D` instances."""
-        return self.xaxis.get_ticklines()
-
-    def get_yaxis(self):
-        """Return the YAxis instance."""
-        return self.yaxis
-
-    def get_ygridlines(self):
-        """Get the y grid lines as a list of `Line2D` instances."""
-        return self.yaxis.get_gridlines()
-
-    def get_yticklines(self):
-        """Get the y tick lines as a list of `Line2D` instances."""
-        return self.yaxis.get_ticklines()
-
-    # Adding and tracking artists
-
-    def _sci(self, im):
-        """Set the current image.
-
-        This image will be the target of colormap functions like
-        `~.pyplot.viridis`, and other functions such as `~.pyplot.clim`.  The
-        current image is an attribute of the current axes.
-        """
-        if isinstance(im, mpl.contour.ContourSet):
-            if im.collections[0] not in self.collections:
-                raise ValueError("ContourSet must be in current Axes")
-        elif im not in self.images and im not in self.collections:
-            raise ValueError("Argument must be an image, collection, or "
-                             "ContourSet in this Axes")
-        self._current_image = im
-
-    def _gci(self):
-        """
-        Helper for :func:`~matplotlib.pyplot.gci`;
-        do not use elsewhere.
-        """
-        return self._current_image
-
-    def has_data(self):
-        """
-        Return *True* if any artists have been added to axes.
-
-        This should not be used to determine whether the *dataLim*
-        need to be updated, and may not actually be useful for
-        anything.
-        """
-        return (
-            len(self.collections) +
-            len(self.images) +
-            len(self.lines) +
-            len(self.patches)) > 0
-
-    def add_artist(self, a):
-        """
-        Add an `~.Artist` to the axes, and return the artist.
-
-        Use `add_artist` only for artists for which there is no dedicated
-        "add" method; and if necessary, use a method such as `update_datalim`
-        to manually update the dataLim if the artist is to be included in
-        autoscaling.
-
-        If no ``transform`` has been specified when creating the artist (e.g.
-        ``artist.get_transform() == None``) then the transform is set to
-        ``ax.transData``.
-        """
-        a.axes = self
-        self.artists.append(a)
-        a._remove_method = self.artists.remove
-        self._set_artist_props(a)
-        a.set_clip_path(self.patch)
-        self.stale = True
-        return a
-
-    def add_child_axes(self, ax):
-        """
-        Add an `~.AxesBase` to the axes' children; return the child axes.
-
-        This is the lowlevel version.  See `.axes.Axes.inset_axes`.
-        """
-
-        # normally axes have themselves as the axes, but these need to have
-        # their parent...
-        # Need to bypass the getter...
-        ax._axes = self
-        ax.stale_callback = martist._stale_axes_callback
-
-        self.child_axes.append(ax)
-        ax._remove_method = self.child_axes.remove
-        self.stale = True
-        return ax
-
-    def add_collection(self, collection, autolim=True):
-        """
-        Add a `~.Collection` to the axes' collections; return the collection.
-        """
-        label = collection.get_label()
-        if not label:
-            collection.set_label('_collection%d' % len(self.collections))
-        self.collections.append(collection)
-        collection._remove_method = self.collections.remove
-        self._set_artist_props(collection)
-
-        if collection.get_clip_path() is None:
-            collection.set_clip_path(self.patch)
-
-        if autolim:
-            # Make sure viewLim is not stale (mostly to match
-            # pre-lazy-autoscale behavior, which is not really better).
-            self._unstale_viewLim()
-            self.update_datalim(collection.get_datalim(self.transData))
-
-        self.stale = True
-        return collection
-
-    def add_image(self, image):
-        """
-        Add an `~.AxesImage` to the axes' images; return the image.
-        """
-        self._set_artist_props(image)
-        if not image.get_label():
-            image.set_label('_image%d' % len(self.images))
-        self.images.append(image)
-        image._remove_method = self.images.remove
-        self.stale = True
-        return image
-
-    def _update_image_limits(self, image):
-        xmin, xmax, ymin, ymax = image.get_extent()
-        self.axes.update_datalim(((xmin, ymin), (xmax, ymax)))
-
-    def add_line(self, line):
-        """
-        Add a `.Line2D` to the axes' lines; return the line.
-        """
-        self._set_artist_props(line)
-        if line.get_clip_path() is None:
-            line.set_clip_path(self.patch)
-
-        self._update_line_limits(line)
-        if not line.get_label():
-            line.set_label('_line%d' % len(self.lines))
-        self.lines.append(line)
-        line._remove_method = self.lines.remove
-        self.stale = True
-        return line
-
-    def _add_text(self, txt):
-        """
-        Add a `~.Text` to the axes' texts; return the text.
-        """
-        self._set_artist_props(txt)
-        self.texts.append(txt)
-        txt._remove_method = self.texts.remove
-        self.stale = True
-        return txt
-
-    def _update_line_limits(self, line):
-        """
-        Figures out the data limit of the given line, updating self.dataLim.
-        """
-        path = line.get_path()
-        if path.vertices.size == 0:
-            return
-
-        line_trans = line.get_transform()
-
-        if line_trans == self.transData:
-            data_path = path
-
-        elif any(line_trans.contains_branch_seperately(self.transData)):
-            # identify the transform to go from line's coordinates
-            # to data coordinates
-            trans_to_data = line_trans - self.transData
-
-            # if transData is affine we can use the cached non-affine component
-            # of line's path. (since the non-affine part of line_trans is
-            # entirely encapsulated in trans_to_data).
-            if self.transData.is_affine:
-                line_trans_path = line._get_transformed_path()
-                na_path, _ = line_trans_path.get_transformed_path_and_affine()
-                data_path = trans_to_data.transform_path_affine(na_path)
-            else:
-                data_path = trans_to_data.transform_path(path)
-        else:
-            # for backwards compatibility we update the dataLim with the
-            # coordinate range of the given path, even though the coordinate
-            # systems are completely different. This may occur in situations
-            # such as when ax.transAxes is passed through for absolute
-            # positioning.
-            data_path = path
-
-        if data_path.vertices.size > 0:
-            updatex, updatey = line_trans.contains_branch_seperately(
-                self.transData)
-            self.dataLim.update_from_path(data_path,
-                                          self.ignore_existing_data_limits,
-                                          updatex=updatex,
-                                          updatey=updatey)
-            self.ignore_existing_data_limits = False
-
-    def add_patch(self, p):
-        """
-        Add a `~.Patch` to the axes' patches; return the patch.
-        """
-        self._set_artist_props(p)
-        if p.get_clip_path() is None:
-            p.set_clip_path(self.patch)
-        self._update_patch_limits(p)
-        self.patches.append(p)
-        p._remove_method = self.patches.remove
-        return p
-
-    def _update_patch_limits(self, patch):
-        """update the data limits for patch *p*"""
-        # hist can add zero height Rectangles, which is useful to keep
-        # the bins, counts and patches lined up, but it throws off log
-        # scaling.  We'll ignore rects with zero height or width in
-        # the auto-scaling
-
-        # cannot check for '==0' since unitized data may not compare to zero
-        # issue #2150 - we update the limits if patch has non zero width
-        # or height.
-        if (isinstance(patch, mpatches.Rectangle) and
-                ((not patch.get_width()) and (not patch.get_height()))):
-            return
-        vertices = patch.get_path().vertices
-        if vertices.size > 0:
-            xys = patch.get_patch_transform().transform(vertices)
-            if patch.get_data_transform() != self.transData:
-                patch_to_data = (patch.get_data_transform() -
-                                 self.transData)
-                xys = patch_to_data.transform(xys)
-
-            updatex, updatey = patch.get_transform().\
-                contains_branch_seperately(self.transData)
-            self.update_datalim(xys, updatex=updatex,
-                                updatey=updatey)
-
-    def add_table(self, tab):
-        """
-        Add a `~.Table` to the axes' tables; return the table.
-        """
-        self._set_artist_props(tab)
-        self.tables.append(tab)
-        tab.set_clip_path(self.patch)
-        tab._remove_method = self.tables.remove
-        return tab
-
-    def add_container(self, container):
-        """
-        Add a `~.Container` to the axes' containers; return the container.
-        """
-        label = container.get_label()
-        if not label:
-            container.set_label('_container%d' % len(self.containers))
-        self.containers.append(container)
-        container._remove_method = self.containers.remove
-        return container
-
-    def _on_units_changed(self, scalex=False, scaley=False):
-        """
-        Callback for processing changes to axis units.
-
-        Currently requests updates of data limits and view limits.
-        """
-        self.relim()
-        self._request_autoscale_view(scalex=scalex, scaley=scaley)
-
-    def relim(self, visible_only=False):
-        """
-        Recompute the data limits based on current artists.
-
-        At present, `~.Collection` instances are not supported.
-
-        Parameters
-        ----------
-        visible_only : bool
-            Whether to exclude invisible artists.  Defaults to False.
-        """
-        # Collections are deliberately not supported (yet); see
-        # the TODO note in artists.py.
-        self.dataLim.ignore(True)
-        self.dataLim.set_points(mtransforms.Bbox.null().get_points())
-        self.ignore_existing_data_limits = True
-
-        for line in self.lines:
-            if not visible_only or line.get_visible():
-                self._update_line_limits(line)
-
-        for p in self.patches:
-            if not visible_only or p.get_visible():
-                self._update_patch_limits(p)
-
-        for image in self.images:
-            if not visible_only or image.get_visible():
-                self._update_image_limits(image)
-
-    def update_datalim(self, xys, updatex=True, updatey=True):
-        """
-        Extend the `~.Axes.dataLim` Bbox to include the given points.
-
-        If no data is set currently, the Bbox will ignore its limits and set
-        the bound to be the bounds of the xydata (*xys*). Otherwise, it will
-        compute the bounds of the union of its current data and the data in
-        *xys*.
-
-        Parameters
-        ----------
-        xys : 2D array-like
-            The points to include in the data limits Bbox. This can be either
-            a list of (x, y) tuples or a Nx2 array.
-
-        updatex, updatey : bool, optional, default *True*
-            Whether to update the x/y limits.
-        """
-        xys = np.asarray(xys)
-        if not len(xys):
-            return
-        self.dataLim.update_from_data_xy(xys, self.ignore_existing_data_limits,
-                                         updatex=updatex, updatey=updatey)
-        self.ignore_existing_data_limits = False
-
-    def update_datalim_bounds(self, bounds):
-        """
-        Extend the `~.Axes.datalim` Bbox to include the given
-        `~matplotlib.transforms.Bbox`.
-
-        Parameters
-        ----------
-        bounds : `~matplotlib.transforms.Bbox`
-        """
-        self.dataLim.set(mtransforms.Bbox.union([self.dataLim, bounds]))
-
-    def _process_unit_info(self, xdata=None, ydata=None, kwargs=None):
-        """Look for unit *kwargs* and update the axis instances as necessary"""
-
-        def _process_single_axis(data, axis, unit_name, kwargs):
-            # Return if there's no axis set
-            if axis is None:
-                return kwargs
-
-            if data is not None:
-                # We only need to update if there is nothing set yet.
-                if not axis.have_units():
-                    axis.update_units(data)
-
-            # Check for units in the kwargs, and if present update axis
-            if kwargs is not None:
-                units = kwargs.pop(unit_name, axis.units)
-                if self.name == 'polar':
-                    polar_units = {'xunits': 'thetaunits', 'yunits': 'runits'}
-                    units = kwargs.pop(polar_units[unit_name], units)
-
-                if units != axis.units:
-                    axis.set_units(units)
-                    # If the units being set imply a different converter,
-                    # we need to update.
-                    if data is not None:
-                        axis.update_units(data)
-            return kwargs
-
-        kwargs = _process_single_axis(xdata, self.xaxis, 'xunits', kwargs)
-        kwargs = _process_single_axis(ydata, self.yaxis, 'yunits', kwargs)
-        return kwargs
-
-    def in_axes(self, mouseevent):
-        """
-        Return *True* if the given *mouseevent* (in display coords)
-        is in the Axes
-        """
-        return self.patch.contains(mouseevent)[0]
-
-    def get_autoscale_on(self):
-        """
-        Get whether autoscaling is applied for both axes on plot commands
-        """
-        return self._autoscaleXon and self._autoscaleYon
-
-    def get_autoscalex_on(self):
-        """
-        Get whether autoscaling for the x-axis is applied on plot commands
-        """
-        return self._autoscaleXon
-
-    def get_autoscaley_on(self):
-        """
-        Get whether autoscaling for the y-axis is applied on plot commands
-        """
-        return self._autoscaleYon
-
-    def set_autoscale_on(self, b):
-        """
-        Set whether autoscaling is applied on plot commands
-
-        Parameters
-        ----------
-        b : bool
-        """
-        self._autoscaleXon = b
-        self._autoscaleYon = b
-
-    def set_autoscalex_on(self, b):
-        """
-        Set whether autoscaling for the x-axis is applied on plot commands
-
-        Parameters
-        ----------
-        b : bool
-        """
-        self._autoscaleXon = b
-
-    def set_autoscaley_on(self, b):
-        """
-        Set whether autoscaling for the y-axis is applied on plot commands
-
-        Parameters
-        ----------
-        b : bool
-        """
-        self._autoscaleYon = b
-
-    @property
-    def use_sticky_edges(self):
-        """
-        When autoscaling, whether to obey all `Artist.sticky_edges`.
-
-        Default is ``True``.
-
-        Setting this to ``False`` ensures that the specified margins
-        will be applied, even if the plot includes an image, for
-        example, which would otherwise force a view limit to coincide
-        with its data limit.
-
-        The changing this property does not change the plot until
-        `autoscale` or `autoscale_view` is called.
-        """
-        return self._use_sticky_edges
-
-    @use_sticky_edges.setter
-    def use_sticky_edges(self, b):
-        self._use_sticky_edges = bool(b)
-        # No effect until next autoscaling, which will mark the axes as stale.
-
-    def set_xmargin(self, m):
-        """
-        Set padding of X data limits prior to autoscaling.
-
-        *m* times the data interval will be added to each
-        end of that interval before it is used in autoscaling.
-        For example, if your data is in the range [0, 2], a factor of
-        ``m = 0.1`` will result in a range [-0.2, 2.2].
-
-        Negative values -0.5 < m < 0 will result in clipping of the data range.
-        I.e. for a data range [0, 2], a factor of ``m = -0.1`` will result in
-        a range [0.2, 1.8].
-
-        Parameters
-        ----------
-        m : float greater than -0.5
-        """
-        if m <= -0.5:
-            raise ValueError("margin must be greater than -0.5")
-        self._xmargin = m
-        self.stale = True
-
-    def set_ymargin(self, m):
-        """
-        Set padding of Y data limits prior to autoscaling.
-
-        *m* times the data interval will be added to each
-        end of that interval before it is used in autoscaling.
-        For example, if your data is in the range [0, 2], a factor of
-        ``m = 0.1`` will result in a range [-0.2, 2.2].
-
-        Negative values -0.5 < m < 0 will result in clipping of the data range.
-        I.e. for a data range [0, 2], a factor of ``m = -0.1`` will result in
-        a range [0.2, 1.8].
-
-        Parameters
-        ----------
-        m : float greater than -0.5
-        """
-        if m <= -0.5:
-            raise ValueError("margin must be greater than -0.5")
-        self._ymargin = m
-        self.stale = True
-
-    def margins(self, *margins, x=None, y=None, tight=True):
-        """
-        Set or retrieve autoscaling margins.
-
-        The padding added to each limit of the axes is the *margin*
-        times the data interval. All input parameters must be floats
-        within the range [0, 1]. Passing both positional and keyword
-        arguments is invalid and will raise a TypeError. If no
-        arguments (positional or otherwise) are provided, the current
-        margins will remain in place and simply be returned.
-
-        Specifying any margin changes only the autoscaling; for example,
-        if *xmargin* is not None, then *xmargin* times the X data
-        interval will be added to each end of that interval before
-        it is used in autoscaling.
-
-        Parameters
-        ----------
-        *margins : float, optional
-            If a single positional argument is provided, it specifies
-            both margins of the x-axis and y-axis limits. If two
-            positional arguments are provided, they will be interpreted
-            as *xmargin*, *ymargin*. If setting the margin on a single
-            axis is desired, use the keyword arguments described below.
-
-        x, y : float, optional
-            Specific margin values for the x-axis and y-axis,
-            respectively. These cannot be used with positional
-            arguments, but can be used individually to alter on e.g.,
-            only the y-axis.
-
-        tight : bool or None, default is True
-            The *tight* parameter is passed to :meth:`autoscale_view`,
-            which is executed after a margin is changed; the default
-            here is *True*, on the assumption that when margins are
-            specified, no additional padding to match tick marks is
-            usually desired.  Set *tight* to *None* will preserve
-            the previous setting.
-
-        Returns
-        -------
-        xmargin, ymargin : float
-
-        Notes
-        -----
-        If a previously used Axes method such as :meth:`pcolor` has set
-        :attr:`use_sticky_edges` to `True`, only the limits not set by
-        the "sticky artists" will be modified. To force all of the
-        margins to be set, set :attr:`use_sticky_edges` to `False`
-        before calling :meth:`margins`.
-        """
-
-        if margins and x is not None and y is not None:
-            raise TypeError('Cannot pass both positional and keyword '
-                            'arguments for x and/or y.')
-        elif len(margins) == 1:
-            x = y = margins[0]
-        elif len(margins) == 2:
-            x, y = margins
-        elif margins:
-            raise TypeError('Must pass a single positional argument for all '
-                            'margins, or one for each margin (x, y).')
-
-        if x is None and y is None:
-            if tight is not True:
-                cbook._warn_external(f'ignoring tight={tight!r} in get mode')
-            return self._xmargin, self._ymargin
-
-        if x is not None:
-            self.set_xmargin(x)
-        if y is not None:
-            self.set_ymargin(y)
-
-        self._request_autoscale_view(
-            tight=tight, scalex=(x is not None), scaley=(y is not None)
-        )
-
-    def set_rasterization_zorder(self, z):
-        """
-        Parameters
-        ----------
-        z : float or None
-            zorder below which artists are rasterized.  ``None`` means that
-            artists do not get rasterized based on zorder.
-        """
-        self._rasterization_zorder = z
-        self.stale = True
-
-    def get_rasterization_zorder(self):
-        """Return the zorder value below which artists will be rasterized."""
-        return self._rasterization_zorder
-
-    def autoscale(self, enable=True, axis='both', tight=None):
-        """
-        Autoscale the axis view to the data (toggle).
-
-        Convenience method for simple axis view autoscaling.
-        It turns autoscaling on or off, and then,
-        if autoscaling for either axis is on, it performs
-        the autoscaling on the specified axis or axes.
-
-        Parameters
-        ----------
-        enable : bool or None, optional
-            True (default) turns autoscaling on, False turns it off.
-            None leaves the autoscaling state unchanged.
-
-        axis : {'both', 'x', 'y'}, optional
-            Which axis to operate on; default is 'both'.
-
-        tight : bool or None, optional
-            If True, first set the margins to zero.  Then, this argument is
-            forwarded to `autoscale_view` (regardless of its value); see the
-            description of its behavior there.
-        """
-        if enable is None:
-            scalex = True
-            scaley = True
-        else:
-            scalex = False
-            scaley = False
-            if axis in ['x', 'both']:
-                self._autoscaleXon = bool(enable)
-                scalex = self._autoscaleXon
-            if axis in ['y', 'both']:
-                self._autoscaleYon = bool(enable)
-                scaley = self._autoscaleYon
-        if tight and scalex:
-            self._xmargin = 0
-        if tight and scaley:
-            self._ymargin = 0
-        self._request_autoscale_view(tight=tight, scalex=scalex, scaley=scaley)
-
-    def autoscale_view(self, tight=None, scalex=True, scaley=True):
-        """
-        Autoscale the view limits using the data limits.
-
-        Parameters
-        ----------
-        tight : bool or None
-            If *True*, only expand the axis limits using the margins.  Note
-            that unlike for `autoscale`, ``tight=True`` does *not* set the
-            margins to zero.
-
-            If *False* and :rc:`axes.autolimit_mode` is 'round_numbers', then
-            after expansion by the margins, further expand the axis limits
-            using the axis major locator.
-
-            If None (the default), reuse the value set in the previous call to
-            `autoscale_view` (the initial value is False, but the default style
-            sets :rc:`axes.autolimit_mode` to 'data', in which case this
-            behaves like True).
-
-        scalex : bool
-            Whether to autoscale the x axis (default is True).
-
-        scaley : bool
-            Whether to autoscale the x axis (default is True).
-
-        Notes
-        -----
-        The autoscaling preserves any preexisting axis direction reversal.
-
-        The data limits are not updated automatically when artist data are
-        changed after the artist has been added to an Axes instance.  In that
-        case, use :meth:`matplotlib.axes.Axes.relim` prior to calling
-        autoscale_view.
-
-        If the views of the axes are fixed, e.g. via `set_xlim`, they will
-        not be changed by autoscale_view().
-        See :meth:`matplotlib.axes.Axes.autoscale` for an alternative.
-        """
-        if tight is not None:
-            self._tight = bool(tight)
-
-        x_stickies = y_stickies = np.array([])
-        if self.use_sticky_edges:
-            # Only iterate over axes and artists if needed.  The check for
-            # ``hasattr(ax, "lines")`` is necessary because this can be called
-            # very early in the axes init process (e.g., for twin axes) when
-            # these attributes don't even exist yet, in which case
-            # `get_children` would raise an AttributeError.
-            if self._xmargin and scalex and self._autoscaleXon:
-                x_stickies = np.sort(np.concatenate([
-                    artist.sticky_edges.x
-                    for ax in self._shared_x_axes.get_siblings(self)
-                    if hasattr(ax, "lines")
-                    for artist in ax.get_children()]))
-            if self._ymargin and scaley and self._autoscaleYon:
-                y_stickies = np.sort(np.concatenate([
-                    artist.sticky_edges.y
-                    for ax in self._shared_y_axes.get_siblings(self)
-                    if hasattr(ax, "lines")
-                    for artist in ax.get_children()]))
-        if self.get_xscale().lower() == 'log':
-            x_stickies = x_stickies[x_stickies > 0]
-        if self.get_yscale().lower() == 'log':
-            y_stickies = y_stickies[y_stickies > 0]
-
-        def handle_single_axis(scale, autoscaleon, shared_axes, interval,
-                               minpos, axis, margin, stickies, set_bound):
-
-            if not (scale and autoscaleon):
-                return  # nothing to do...
-
-            shared = shared_axes.get_siblings(self)
-            dl = [ax.dataLim for ax in shared]
-            # ignore non-finite data limits if good limits exist
-            finite_dl = [d for d in dl if np.isfinite(d).all()]
-            if len(finite_dl):
-                # if finite limits exist for atleast one axis (and the
-                # other is infinite), restore the finite limits
-                x_finite = [d for d in dl
-                            if (np.isfinite(d.intervalx).all() and
-                                (d not in finite_dl))]
-                y_finite = [d for d in dl
-                            if (np.isfinite(d.intervaly).all() and
-                                (d not in finite_dl))]
-
-                dl = finite_dl
-                dl.extend(x_finite)
-                dl.extend(y_finite)
-
-            bb = mtransforms.BboxBase.union(dl)
-            x0, x1 = getattr(bb, interval)
-            # If x0 and x1 are non finite, use the locator to figure out
-            # default limits.
-            locator = axis.get_major_locator()
-            x0, x1 = locator.nonsingular(x0, x1)
-
-            # Prevent margin addition from crossing a sticky value.  Small
-            # tolerances (whose values come from isclose()) must be used due to
-            # floating point issues with streamplot.
-            def tol(x): return 1e-5 * abs(x) + 1e-8
-            # Index of largest element < x0 + tol, if any.
-            i0 = stickies.searchsorted(x0 + tol(x0)) - 1
-            x0bound = stickies[i0] if i0 != -1 else None
-            # Index of smallest element > x1 - tol, if any.
-            i1 = stickies.searchsorted(x1 - tol(x1))
-            x1bound = stickies[i1] if i1 != len(stickies) else None
-
-            # Add the margin in figure space and then transform back, to handle
-            # non-linear scales.
-            minpos = getattr(bb, minpos)
-            transform = axis.get_transform()
-            inverse_trans = transform.inverted()
-            x0, x1 = axis._scale.limit_range_for_scale(x0, x1, minpos)
-            x0t, x1t = transform.transform([x0, x1])
-            delta = (x1t - x0t) * margin
-            if not np.isfinite(delta):
-                delta = 0  # If a bound isn't finite, set margin to zero.
-            x0, x1 = inverse_trans.transform([x0t - delta, x1t + delta])
-
-            # Apply sticky bounds.
-            if x0bound is not None:
-                x0 = max(x0, x0bound)
-            if x1bound is not None:
-                x1 = min(x1, x1bound)
-
-            if not self._tight:
-                x0, x1 = locator.view_limits(x0, x1)
-            set_bound(x0, x1)
-            # End of definition of internal function 'handle_single_axis'.
-
-        handle_single_axis(
-            scalex, self._autoscaleXon, self._shared_x_axes, 'intervalx',
-            'minposx', self.xaxis, self._xmargin, x_stickies, self.set_xbound)
-        handle_single_axis(
-            scaley, self._autoscaleYon, self._shared_y_axes, 'intervaly',
-            'minposy', self.yaxis, self._ymargin, y_stickies, self.set_ybound)
-
-    def _get_axis_list(self):
-        return (self.xaxis, self.yaxis)
-
-    def _get_axis_map(self):
-        """
-        Return a mapping of `Axis` "names" to `Axis` instances.
-
-        The `Axis` name is derived from the attribute under which the instance
-        is stored, so e.g. for polar axes, the theta-axis is still named "x"
-        and the r-axis is still named "y" (for back-compatibility).
-
-        In practice, this means that the entries are typically "x" and "y", and
-        additionally "z" for 3D axes.
-        """
-        d = {}
-        axis_list = self._get_axis_list()
-        for k, v in vars(self).items():
-            if k.endswith("axis") and v in axis_list:
-                d[k[:-len("axis")]] = v
-        return d
-
-    def _update_title_position(self, renderer):
-        """
-        Update the title position based on the bounding box enclosing
-        all the ticklabels and x-axis spine and xlabel...
-        """
-
-        if self._autotitlepos is not None and not self._autotitlepos:
-            _log.debug('title position was updated manually, not adjusting')
-            return
-
-        titles = (self.title, self._left_title, self._right_title)
-
-        if self._autotitlepos is None:
-            for title in titles:
-                x, y = title.get_position()
-                if not np.isclose(y, 1.0):
-                    self._autotitlepos = False
-                    _log.debug('not adjusting title pos because a title was'
-                             ' already placed manually: %f', y)
-                    return
-            self._autotitlepos = True
-
-        for title in titles:
-            x, _ = title.get_position()
-            # need to start again in case of window resizing
-            title.set_position((x, 1.0))
-            # need to check all our twins too...
-            axs = self._twinned_axes.get_siblings(self)
-            # and all the children
-            for ax in self.child_axes:
-                if ax is not None:
-                    locator = ax.get_axes_locator()
-                    if locator:
-                        pos = locator(self, renderer)
-                        ax.apply_aspect(pos)
-                    else:
-                        ax.apply_aspect()
-                    axs = axs + [ax]
-            top = 0
-            for ax in axs:
-                if (ax.xaxis.get_ticks_position() in ['top', 'unknown']
-                        or ax.xaxis.get_label_position() == 'top'):
-                    bb = ax.xaxis.get_tightbbox(renderer)
-                else:
-                    bb = ax.get_window_extent(renderer)
-                if bb is not None:
-                    top = max(top, bb.ymax)
-            if title.get_window_extent(renderer).ymin < top:
-                _, y = self.transAxes.inverted().transform((0, top))
-                title.set_position((x, y))
-                # empirically, this doesn't always get the min to top,
-                # so we need to adjust again.
-                if title.get_window_extent(renderer).ymin < top:
-                    _, y = self.transAxes.inverted().transform(
-                        (0., 2 * top - title.get_window_extent(renderer).ymin))
-                    title.set_position((x, y))
-
-        ymax = max(title.get_position()[1] for title in titles)
-        for title in titles:
-            # now line up all the titles at the highest baseline.
-            x, _ = title.get_position()
-            title.set_position((x, ymax))
-
-    # Drawing
-    @martist.allow_rasterization
-    def draw(self, renderer=None, inframe=False):
-        """Draw everything (plot lines, axes, labels)"""
-        if renderer is None:
-            renderer = self.figure._cachedRenderer
-        if renderer is None:
-            raise RuntimeError('No renderer defined')
-        if not self.get_visible():
-            return
-        self._unstale_viewLim()
-
-        renderer.open_group('axes', gid=self.get_gid())
-
-        # prevent triggering call backs during the draw process
-        self._stale = True
-
-        # loop over self and child axes...
-        locator = self.get_axes_locator()
-        if locator:
-            pos = locator(self, renderer)
-            self.apply_aspect(pos)
-        else:
-            self.apply_aspect()
-
-        artists = self.get_children()
-        artists.remove(self.patch)
-
-        # the frame draws the edges around the axes patch -- we
-        # decouple these so the patch can be in the background and the
-        # frame in the foreground. Do this before drawing the axis
-        # objects so that the spine has the opportunity to update them.
-        if not (self.axison and self._frameon):
-            for spine in self.spines.values():
-                artists.remove(spine)
-
-        self._update_title_position(renderer)
-
-        if not self.axison or inframe:
-            for _axis in self._get_axis_list():
-                artists.remove(_axis)
-
-        if inframe:
-            artists.remove(self.title)
-            artists.remove(self._left_title)
-            artists.remove(self._right_title)
-
-        if not self.figure.canvas.is_saving():
-            artists = [a for a in artists
-                       if not a.get_animated() or a in self.images]
-        artists = sorted(artists, key=attrgetter('zorder'))
-
-        # rasterize artists with negative zorder
-        # if the minimum zorder is negative, start rasterization
-        rasterization_zorder = self._rasterization_zorder
-
-        if (rasterization_zorder is not None and
-                artists and artists[0].zorder < rasterization_zorder):
-            renderer.start_rasterizing()
-            artists_rasterized = [a for a in artists
-                                  if a.zorder < rasterization_zorder]
-            artists = [a for a in artists
-                       if a.zorder >= rasterization_zorder]
-        else:
-            artists_rasterized = []
-
-        # the patch draws the background rectangle -- the frame below
-        # will draw the edges
-        if self.axison and self._frameon:
-            self.patch.draw(renderer)
-
-        if artists_rasterized:
-            for a in artists_rasterized:
-                a.draw(renderer)
-            renderer.stop_rasterizing()
-
-        mimage._draw_list_compositing_images(renderer, self, artists)
-
-        renderer.close_group('axes')
-        self.stale = False
-
-    def draw_artist(self, a):
-        """
-        This method can only be used after an initial draw which
-        caches the renderer.  It is used to efficiently update Axes
-        data (axis ticks, labels, etc are not updated)
-        """
-        if self.figure._cachedRenderer is None:
-            raise AttributeError("draw_artist can only be used after an "
-                                 "initial draw which caches the renderer")
-        a.draw(self.figure._cachedRenderer)
-
-    def redraw_in_frame(self):
-        """
-        This method can only be used after an initial draw which
-        caches the renderer.  It is used to efficiently update Axes
-        data (axis ticks, labels, etc are not updated)
-        """
-        if self.figure._cachedRenderer is None:
-            raise AttributeError("redraw_in_frame can only be used after an "
-                                 "initial draw which caches the renderer")
-        self.draw(self.figure._cachedRenderer, inframe=True)
-
-    def get_renderer_cache(self):
-        return self.figure._cachedRenderer
-
-    # Axes rectangle characteristics
-
-    def get_frame_on(self):
-        """Get whether the axes rectangle patch is drawn."""
-        return self._frameon
-
-    def set_frame_on(self, b):
-        """
-        Set whether the axes rectangle patch is drawn.
-
-        Parameters
-        ----------
-        b : bool
-        """
-        self._frameon = b
-        self.stale = True
-
-    def get_axisbelow(self):
-        """
-        Get whether axis ticks and gridlines are above or below most artists.
-
-        Returns
-        -------
-        axisbelow : bool or 'line'
-
-        See Also
-        --------
-        set_axisbelow
-        """
-        return self._axisbelow
-
-    def set_axisbelow(self, b):
-        """
-        Set whether axis ticks and gridlines are above or below most artists.
-
-        This controls the zorder of the ticks and gridlines. For more
-        information on the zorder see :doc:`/gallery/misc/zorder_demo`.
-
-        Parameters
-        ----------
-        b : bool or 'line'
-            Possible values:
-
-            - *True* (zorder = 0.5): Ticks and gridlines are below all Artists.
-            - 'line' (zorder = 1.5): Ticks and gridlines are above patches
-              (e.g. rectangles, with default zorder = 1) but still below lines
-              and markers (with their default zorder = 2).
-            - *False* (zorder = 2.5): Ticks and gridlines are above patches
-              and lines / markers.
-
-        See Also
-        --------
-        get_axisbelow
-        """
-        self._axisbelow = axisbelow = validate_axisbelow(b)
-        if axisbelow is True:
-            zorder = 0.5
-        elif axisbelow is False:
-            zorder = 2.5
-        elif axisbelow == "line":
-            zorder = 1.5
-        else:
-            raise ValueError("Unexpected axisbelow value")
-        for axis in self._get_axis_list():
-            axis.set_zorder(zorder)
-        self.stale = True
-
-    @docstring.dedent_interpd
-    def grid(self, b=None, which='major', axis='both', **kwargs):
-        """
-        Configure the grid lines.
-
-        Parameters
-        ----------
-        b : bool or None, optional
-            Whether to show the grid lines. If any *kwargs* are supplied,
-            it is assumed you want the grid on and *b* will be set to True.
-
-            If *b* is *None* and there are no *kwargs*, this toggles the
-            visibility of the lines.
-
-        which : {'major', 'minor', 'both'}, optional
-            The grid lines to apply the changes on.
-
-        axis : {'both', 'x', 'y'}, optional
-            The axis to apply the changes on.
-
-        **kwargs : `.Line2D` properties
-            Define the line properties of the grid, e.g.::
-
-                grid(color='r', linestyle='-', linewidth=2)
-
-            Valid keyword arguments are:
-
-            %(_Line2D_docstr)s
-
-        Notes
-        -----
-        The axis is drawn as a unit, so the effective zorder for drawing the
-        grid is determined by the zorder of each axis, not by the zorder of the
-        `.Line2D` objects comprising the grid.  Therefore, to set grid zorder,
-        use `.set_axisbelow` or, for more control, call the
-        `~matplotlib.axis.Axis.set_zorder` method of each axis.
-        """
-        if len(kwargs):
-            b = True
-        cbook._check_in_list(['x', 'y', 'both'], axis=axis)
-        if axis in ['x', 'both']:
-            self.xaxis.grid(b, which=which, **kwargs)
-        if axis in ['y', 'both']:
-            self.yaxis.grid(b, which=which, **kwargs)
-
-    def ticklabel_format(self, *, axis='both', style='', scilimits=None,
-                         useOffset=None, useLocale=None, useMathText=None):
-        r"""
-        Change the `~matplotlib.ticker.ScalarFormatter` used by
-        default for linear axes.
-
-        Optional keyword arguments:
-
-          ==============   =========================================
-          Keyword          Description
-          ==============   =========================================
-          *axis*           {'x', 'y', 'both'}
-          *style*          {'sci' (or 'scientific'), 'plain'}
-                           plain turns off scientific notation
-          *scilimits*      (m, n), pair of integers; if *style*
-                           is 'sci', scientific notation will
-                           be used for numbers outside the range
-                           10\ :sup:`m` to 10\ :sup:`n`.
-                           Use (0, 0) to include all numbers.
-                           Use (m, m) where m != 0 to fix the order
-                           of magnitude to 10\ :sup:`m`.
-          *useOffset*      bool or float
-                           If True, the offset will be calculated as
-                           needed; if False, no offset will be used;
-                           if a numeric offset is specified, it will
-                           be used.
-          *useLocale*      If True, format the number according to
-                           the current locale.  This affects things
-                           such as the character used for the
-                           decimal separator.  If False, use
-                           C-style (English) formatting.  The
-                           default setting is controlled by the
-                           axes.formatter.use_locale rcparam.
-          *useMathText*    If True, render the offset and scientific
-                           notation in mathtext
-          ==============   =========================================
-
-        Only the major ticks are affected.
-        If the method is called when the `~matplotlib.ticker.ScalarFormatter`
-        is not the `~matplotlib.ticker.Formatter` being used, an
-        `AttributeError` will be raised.
-        """
-        style = style.lower()
-        axis = axis.lower()
-        if scilimits is not None:
-            try:
-                m, n = scilimits
-                m + n + 1  # check that both are numbers
-            except (ValueError, TypeError):
-                raise ValueError("scilimits must be a sequence of 2 integers")
-        STYLES = {'sci': True, 'scientific': True, 'plain': False, '': None}
-        is_sci_style = cbook._check_getitem(STYLES, style=style)
-        axis_map = {**{k: [v] for k, v in self._get_axis_map().items()},
-                    'both': self._get_axis_list()}
-        axises = cbook._check_getitem(axis_map, axis=axis)
-        try:
-            for axis in axises:
-                if is_sci_style is not None:
-                    axis.major.formatter.set_scientific(is_sci_style)
-                if scilimits is not None:
-                    axis.major.formatter.set_powerlimits(scilimits)
-                if useOffset is not None:
-                    axis.major.formatter.set_useOffset(useOffset)
-                if useLocale is not None:
-                    axis.major.formatter.set_useLocale(useLocale)
-                if useMathText is not None:
-                    axis.major.formatter.set_useMathText(useMathText)
-        except AttributeError:
-            raise AttributeError(
-                "This method only works with the ScalarFormatter")
-
-    def locator_params(self, axis='both', tight=None, **kwargs):
-        """
-        Control behavior of major tick locators.
-
-        Because the locator is involved in autoscaling, `~.Axes.autoscale_view`
-        is called automatically after the parameters are changed.
-
-        Parameters
-        ----------
-        axis : {'both', 'x', 'y'}, optional
-            The axis on which to operate.
-
-        tight : bool or None, optional
-            Parameter passed to `~.Axes.autoscale_view`.
-            Default is None, for no change.
-
-        Other Parameters
-        ----------------
-        **kwargs
-            Remaining keyword arguments are passed to directly to the
-            ``set_params()`` method of the locator. Supported keywords depend
-            on the type of the locator. See for example
-            `~.ticker.MaxNLocator.set_params` for the `.ticker.MaxNLocator`
-            used by default for linear axes.
-
-        Examples
-        --------
-        When plotting small subplots, one might want to reduce the maximum
-        number of ticks and use tight bounds, for example::
-
-            ax.locator_params(tight=True, nbins=4)
-
-        """
-        _x = axis in ['x', 'both']
-        _y = axis in ['y', 'both']
-        if _x:
-            self.xaxis.get_major_locator().set_params(**kwargs)
-        if _y:
-            self.yaxis.get_major_locator().set_params(**kwargs)
-        self._request_autoscale_view(tight=tight, scalex=_x, scaley=_y)
-
-    def tick_params(self, axis='both', **kwargs):
-        """Change the appearance of ticks, tick labels, and gridlines.
-
-        Parameters
-        ----------
-        axis : {'x', 'y', 'both'}, optional
-            Which axis to apply the parameters to.
-
-        Other Parameters
-        ----------------
-        axis : {'x', 'y', 'both'}
-            Axis on which to operate; default is 'both'.
-        reset : bool, default: False
-            If *True*, set all parameters to defaults before processing other
-            keyword arguments.
-        which : {'major', 'minor', 'both'}
-            Default is 'major'; apply arguments to *which* ticks.
-        direction : {'in', 'out', 'inout'}
-            Puts ticks inside the axes, outside the axes, or both.
-        length : float
-            Tick length in points.
-        width : float
-            Tick width in points.
-        color : color
-            Tick color.
-        pad : float
-            Distance in points between tick and label.
-        labelsize : float or str
-            Tick label font size in points or as a string (e.g., 'large').
-        labelcolor : color
-            Tick label color.
-        colors : color
-            Tick color and label color.
-        zorder : float
-            Tick and label zorder.
-        bottom, top, left, right : bool
-            Whether to draw the respective ticks.
-        labelbottom, labeltop, labelleft, labelright : bool
-            Whether to draw the respective tick labels.
-        labelrotation : float
-            Tick label rotation
-        grid_color : color
-            Gridline color.
-        grid_alpha : float
-            Transparency of gridlines: 0 (transparent) to 1 (opaque).
-        grid_linewidth : float
-            Width of gridlines in points.
-        grid_linestyle : str
-            Any valid `.Line2D` line style spec.
-
-        Examples
-        --------
-        Usage ::
-
-            ax.tick_params(direction='out', length=6, width=2, colors='r',
-                           grid_color='r', grid_alpha=0.5)
-
-        This will make all major ticks be red, pointing out of the box,
-        and with dimensions 6 points by 2 points.  Tick labels will
-        also be red.  Gridlines will be red and translucent.
-
-        """
-        cbook._check_in_list(['x', 'y', 'both'], axis=axis)
-        if axis in ['x', 'both']:
-            xkw = dict(kwargs)
-            xkw.pop('left', None)
-            xkw.pop('right', None)
-            xkw.pop('labelleft', None)
-            xkw.pop('labelright', None)
-            self.xaxis.set_tick_params(**xkw)
-        if axis in ['y', 'both']:
-            ykw = dict(kwargs)
-            ykw.pop('top', None)
-            ykw.pop('bottom', None)
-            ykw.pop('labeltop', None)
-            ykw.pop('labelbottom', None)
-            self.yaxis.set_tick_params(**ykw)
-
-    def set_axis_off(self):
-        """
-        Turn the x- and y-axis off.
-
-        This affects the axis lines, ticks, ticklabels, grid and axis labels.
-        """
-        self.axison = False
-        self.stale = True
-
-    def set_axis_on(self):
-        """
-        Turn the x- and y-axis on.
-
-        This affects the axis lines, ticks, ticklabels, grid and axis labels.
-        """
-        self.axison = True
-        self.stale = True
-
-    # data limits, ticks, tick labels, and formatting
-
-    def invert_xaxis(self):
-        """
-        Invert the x-axis.
-
-        See Also
-        --------
-        xaxis_inverted
-        get_xlim, set_xlim
-        get_xbound, set_xbound
-        """
-        self.xaxis.set_inverted(not self.xaxis.get_inverted())
-
-    def xaxis_inverted(self):
-        """
-        Return whether the x-axis is inverted.
-
-        The axis is inverted if the left value is larger than the right value.
-
-        See Also
-        --------
-        invert_xaxis
-        get_xlim, set_xlim
-        get_xbound, set_xbound
-        """
-        return self.xaxis.get_inverted()
-
-    def get_xbound(self):
-        """
-        Return the lower and upper x-axis bounds, in increasing order.
-
-        See Also
-        --------
-        set_xbound
-        get_xlim, set_xlim
-        invert_xaxis, xaxis_inverted
-        """
-        left, right = self.get_xlim()
-        if left < right:
-            return left, right
-        else:
-            return right, left
-
-    def set_xbound(self, lower=None, upper=None):
-        """
-        Set the lower and upper numerical bounds of the x-axis.
-
-        This method will honor axes inversion regardless of parameter order.
-        It will not change the autoscaling setting (``Axes._autoscaleXon``).
-
-        Parameters
-        ----------
-        lower, upper : float or None
-            The lower and upper bounds. If *None*, the respective axis bound
-            is not modified.
-
-        See Also
-        --------
-        get_xbound
-        get_xlim, set_xlim
-        invert_xaxis, xaxis_inverted
-        """
-        if upper is None and np.iterable(lower):
-            lower, upper = lower
-
-        old_lower, old_upper = self.get_xbound()
-
-        if lower is None:
-            lower = old_lower
-        if upper is None:
-            upper = old_upper
-
-        if self.xaxis_inverted():
-            if lower < upper:
-                self.set_xlim(upper, lower, auto=None)
-            else:
-                self.set_xlim(lower, upper, auto=None)
-        else:
-            if lower < upper:
-                self.set_xlim(lower, upper, auto=None)
-            else:
-                self.set_xlim(upper, lower, auto=None)
-
-    def get_xlim(self):
-        """
-        Return the x-axis view limits.
-
-        Returns
-        -------
-        left, right : (float, float)
-            The current x-axis limits in data coordinates.
-
-        See Also
-        --------
-        set_xlim
-        set_xbound, get_xbound
-        invert_xaxis, xaxis_inverted
-
-        Notes
-        -----
-        The x-axis may be inverted, in which case the *left* value will
-        be greater than the *right* value.
-
-        """
-        return tuple(self.viewLim.intervalx)
-
-    def _validate_converted_limits(self, limit, convert):
-        """
-        Raise ValueError if converted limits are non-finite.
-
-        Note that this function also accepts None as a limit argument.
-
-        Returns
-        -------
-        The limit value after call to convert(), or None if limit is None.
-        """
-        if limit is not None:
-            converted_limit = convert(limit)
-            if (isinstance(converted_limit, Real)
-                    and not np.isfinite(converted_limit)):
-                raise ValueError("Axis limits cannot be NaN or Inf")
-            return converted_limit
-
-    def set_xlim(self, left=None, right=None, emit=True, auto=False,
-                 *, xmin=None, xmax=None):
-        """
-        Set the x-axis view limits.
-
-        Parameters
-        ----------
-        left : float, optional
-            The left xlim in data coordinates. Passing *None* leaves the
-            limit unchanged.
-
-            The left and right xlims may also be passed as the tuple
-            (*left*, *right*) as the first positional argument (or as
-            the *left* keyword argument).
-
-            .. ACCEPTS: (bottom: float, top: float)
-
-        right : float, optional
-            The right xlim in data coordinates. Passing *None* leaves the
-            limit unchanged.
-
-        emit : bool, optional
-            Whether to notify observers of limit change (default: True).
-
-        auto : bool or None, optional
-            Whether to turn on autoscaling of the x-axis. True turns on,
-            False turns off (default action), None leaves unchanged.
-
-        xmin, xmax : scalar, optional
-            They are equivalent to left and right respectively,
-            and it is an error to pass both *xmin* and *left* or
-            *xmax* and *right*.
-
-        Returns
-        -------
-        left, right : (float, float)
-            The new x-axis limits in data coordinates.
-
-        See Also
-        --------
-        get_xlim
-        set_xbound, get_xbound
-        invert_xaxis, xaxis_inverted
-
-        Notes
-        -----
-        The *left* value may be greater than the *right* value, in which
-        case the x-axis values will decrease from left to right.
-
-        Examples
-        --------
-        >>> set_xlim(left, right)
-        >>> set_xlim((left, right))
-        >>> left, right = set_xlim(left, right)
-
-        One limit may be left unchanged.
-
-        >>> set_xlim(right=right_lim)
-
-        Limits may be passed in reverse order to flip the direction of
-        the x-axis. For example, suppose *x* represents the number of
-        years before present. The x-axis limits might be set like the
-        following so 5000 years ago is on the left of the plot and the
-        present is on the right.
-
-        >>> set_xlim(5000, 0)
-
-        """
-        if right is None and np.iterable(left):
-            left, right = left
-        if xmin is not None:
-            if left is not None:
-                raise TypeError('Cannot pass both `xmin` and `left`')
-            left = xmin
-        if xmax is not None:
-            if right is not None:
-                raise TypeError('Cannot pass both `xmax` and `right`')
-            right = xmax
-
-        self._process_unit_info(xdata=(left, right))
-        left = self._validate_converted_limits(left, self.convert_xunits)
-        right = self._validate_converted_limits(right, self.convert_xunits)
-
-        if left is None or right is None:
-            # Axes init calls set_xlim(0, 1) before get_xlim() can be called,
-            # so only grab the limits if we really need them.
-            old_left, old_right = self.get_xlim()
-            if left is None:
-                left = old_left
-            if right is None:
-                right = old_right
-
-        if self.get_xscale() == 'log' and (left <= 0 or right <= 0):
-            # Axes init calls set_xlim(0, 1) before get_xlim() can be called,
-            # so only grab the limits if we really need them.
-            old_left, old_right = self.get_xlim()
-            if left <= 0:
-                cbook._warn_external(
-                    'Attempted to set non-positive left xlim on a '
-                    'log-scaled axis.\n'
-                    'Invalid limit will be ignored.')
-                left = old_left
-            if right <= 0:
-                cbook._warn_external(
-                    'Attempted to set non-positive right xlim on a '
-                    'log-scaled axis.\n'
-                    'Invalid limit will be ignored.')
-                right = old_right
-        if left == right:
-            cbook._warn_external(
-                f"Attempting to set identical left == right == {left} results "
-                f"in singular transformations; automatically expanding.")
-        reverse = left > right
-        left, right = self.xaxis.get_major_locator().nonsingular(left, right)
-        left, right = self.xaxis.limit_range_for_scale(left, right)
-        # cast to bool to avoid bad interaction between python 3.8 and np.bool_
-        left, right = sorted([left, right], reverse=bool(reverse))
-
-        self._viewLim.intervalx = (left, right)
-        if auto is not None:
-            self._autoscaleXon = bool(auto)
-
-        if emit:
-            self.callbacks.process('xlim_changed', self)
-            # Call all of the other x-axes that are shared with this one
-            for other in self._shared_x_axes.get_siblings(self):
-                if other is not self:
-                    other.set_xlim(self.viewLim.intervalx,
-                                   emit=False, auto=auto)
-                    if other.figure != self.figure:
-                        other.figure.canvas.draw_idle()
-        self.stale = True
-        return left, right
-
-    def get_xscale(self):
-        """
-        Return the x-axis scale as string.
-
-        See Also
-        --------
-        set_xscale
-        """
-        return self.xaxis.get_scale()
-
-    def set_xscale(self, value, **kwargs):
-        """
-        Set the x-axis scale.
-
-        Parameters
-        ----------
-        value : {"linear", "log", "symlog", "logit", ...}
-            The axis scale type to apply.
-
-        **kwargs
-            Different keyword arguments are accepted, depending on the scale.
-            See the respective class keyword arguments:
-
-            - `matplotlib.scale.LinearScale`
-            - `matplotlib.scale.LogScale`
-            - `matplotlib.scale.SymmetricalLogScale`
-            - `matplotlib.scale.LogitScale`
-
-        Notes
-        -----
-        By default, Matplotlib supports the above mentioned scales.
-        Additionally, custom scales may be registered using
-        `matplotlib.scale.register_scale`. These scales can then also
-        be used here.
-        """
-        old_default_lims = (self.xaxis.get_major_locator()
-                            .nonsingular(-np.inf, np.inf))
-        g = self.get_shared_x_axes()
-        for ax in g.get_siblings(self):
-            ax.xaxis._set_scale(value, **kwargs)
-            ax._update_transScale()
-            ax.stale = True
-        new_default_lims = (self.xaxis.get_major_locator()
-                            .nonsingular(-np.inf, np.inf))
-        if old_default_lims != new_default_lims:
-            # Force autoscaling now, to take advantage of the scale locator's
-            # nonsingular() before it possibly gets swapped out by the user.
-            self.autoscale_view(scaley=False)
-
-    @cbook._make_keyword_only("3.2", "minor")
-    def get_xticks(self, minor=False):
-        """Return the x ticks as a list of locations"""
-        return self.xaxis.get_ticklocs(minor=minor)
-
-    @cbook._make_keyword_only("3.2", "minor")
-    def set_xticks(self, ticks, minor=False):
-        """
-        Set the x ticks with list of *ticks*
-
-        Parameters
-        ----------
-        ticks : list
-            List of x-axis tick locations.
-
-        minor : bool, optional
-            If ``False`` sets major ticks, if ``True`` sets minor ticks.
-            Default is ``False``.
-        """
-        ret = self.xaxis.set_ticks(ticks, minor=minor)
-        self.stale = True
-        return ret
-
-    def get_xmajorticklabels(self):
-        """
-        Get the major x tick labels.
-
-        Returns
-        -------
-        labels : list
-            List of `~matplotlib.text.Text` instances
-        """
-        return self.xaxis.get_majorticklabels()
-
-    def get_xminorticklabels(self):
-        """
-        Get the minor x tick labels.
-
-        Returns
-        -------
-        labels : list
-            List of `~matplotlib.text.Text` instances
-        """
-        return self.xaxis.get_minorticklabels()
-
-    def get_xticklabels(self, minor=False, which=None):
-        """
-        Get the x tick labels as a list of `~matplotlib.text.Text` instances.
-
-        Parameters
-        ----------
-        minor : bool, optional
-           If True return the minor ticklabels,
-           else return the major ticklabels.
-
-        which : None, ('minor', 'major', 'both')
-           Overrides *minor*.
-
-           Selects which ticklabels to return
-
-        Returns
-        -------
-        ret : list
-           List of `~matplotlib.text.Text` instances.
-        """
-        return self.xaxis.get_ticklabels(minor=minor, which=which)
-
-    def set_xticklabels(self, labels, fontdict=None, minor=False, **kwargs):
-        """
-        Set the x-tick labels with list of string labels.
-
-        Parameters
-        ----------
-        labels : List[str]
-            List of string labels.
-
-        fontdict : dict, optional
-            A dictionary controlling the appearance of the ticklabels.
-            The default *fontdict* is::
-
-               {'fontsize': rcParams['axes.titlesize'],
-                'fontweight': rcParams['axes.titleweight'],
-                'verticalalignment': 'baseline',
-                'horizontalalignment': loc}
-
-        minor : bool, optional
-            Whether to set the minor ticklabels rather than the major ones.
-
-        Returns
-        -------
-        A list of `~.text.Text` instances.
-
-        Other Parameters
-        -----------------
-        **kwargs : `~.text.Text` properties.
-        """
-        if fontdict is not None:
-            kwargs.update(fontdict)
-        ret = self.xaxis.set_ticklabels(labels,
-                                        minor=minor, **kwargs)
-        self.stale = True
-        return ret
-
-    def invert_yaxis(self):
-        """
-        Invert the y-axis.
-
-        See Also
-        --------
-        yaxis_inverted
-        get_ylim, set_ylim
-        get_ybound, set_ybound
-        """
-        self.yaxis.set_inverted(not self.yaxis.get_inverted())
-
-    def yaxis_inverted(self):
-        """
-        Return whether the y-axis is inverted.
-
-        The axis is inverted if the bottom value is larger than the top value.
-
-        See Also
-        --------
-        invert_yaxis
-        get_ylim, set_ylim
-        get_ybound, set_ybound
-        """
-        return self.yaxis.get_inverted()
-
-    def get_ybound(self):
-        """
-        Return the lower and upper y-axis bounds, in increasing order.
-
-        See Also
-        --------
-        set_ybound
-        get_ylim, set_ylim
-        invert_yaxis, yaxis_inverted
-        """
-        bottom, top = self.get_ylim()
-        if bottom < top:
-            return bottom, top
-        else:
-            return top, bottom
-
-    def set_ybound(self, lower=None, upper=None):
-        """
-        Set the lower and upper numerical bounds of the y-axis.
-
-        This method will honor axes inversion regardless of parameter order.
-        It will not change the autoscaling setting (``Axes._autoscaleYon``).
-
-        Parameters
-        ----------
-        lower, upper : float or None
-            The lower and upper bounds. If *None*, the respective axis bound
-            is not modified.
-
-        See Also
-        --------
-        get_ybound
-        get_ylim, set_ylim
-        invert_yaxis, yaxis_inverted
-        """
-        if upper is None and np.iterable(lower):
-            lower, upper = lower
-
-        old_lower, old_upper = self.get_ybound()
-
-        if lower is None:
-            lower = old_lower
-        if upper is None:
-            upper = old_upper
-
-        if self.yaxis_inverted():
-            if lower < upper:
-                self.set_ylim(upper, lower, auto=None)
-            else:
-                self.set_ylim(lower, upper, auto=None)
-        else:
-            if lower < upper:
-                self.set_ylim(lower, upper, auto=None)
-            else:
-                self.set_ylim(upper, lower, auto=None)
-
-    def get_ylim(self):
-        """
-        Return the y-axis view limits.
-
-        Returns
-        -------
-        bottom, top : (float, float)
-            The current y-axis limits in data coordinates.
-
-        See Also
-        --------
-        set_ylim
-        set_ybound, get_ybound
-        invert_yaxis, yaxis_inverted
-
-        Notes
-        -----
-        The y-axis may be inverted, in which case the *bottom* value
-        will be greater than the *top* value.
-
-        """
-        return tuple(self.viewLim.intervaly)
-
-    def set_ylim(self, bottom=None, top=None, emit=True, auto=False,
-                 *, ymin=None, ymax=None):
-        """
-        Set the y-axis view limits.
-
-        Parameters
-        ----------
-        bottom : float, optional
-            The bottom ylim in data coordinates. Passing *None* leaves the
-            limit unchanged.
-
-            The bottom and top ylims may also be passed as the tuple
-            (*bottom*, *top*) as the first positional argument (or as
-            the *bottom* keyword argument).
-
-            .. ACCEPTS: (bottom: float, top: float)
-
-        top : float, optional
-            The top ylim in data coordinates. Passing *None* leaves the
-            limit unchanged.
-
-        emit : bool, optional
-            Whether to notify observers of limit change (default: ``True``).
-
-        auto : bool or None, optional
-            Whether to turn on autoscaling of the y-axis. *True* turns on,
-            *False* turns off (default action), *None* leaves unchanged.
-
-        ymin, ymax : scalar, optional
-            They are equivalent to bottom and top respectively,
-            and it is an error to pass both *ymin* and *bottom* or
-            *ymax* and *top*.
-
-        Returns
-        -------
-        bottom, top : (float, float)
-            The new y-axis limits in data coordinates.
-
-        See Also
-        --------
-        get_ylim
-        set_ybound, get_ybound
-        invert_yaxis, yaxis_inverted
-
-        Notes
-        -----
-        The *bottom* value may be greater than the *top* value, in which
-        case the y-axis values will decrease from *bottom* to *top*.
-
-        Examples
-        --------
-        >>> set_ylim(bottom, top)
-        >>> set_ylim((bottom, top))
-        >>> bottom, top = set_ylim(bottom, top)
-
-        One limit may be left unchanged.
-
-        >>> set_ylim(top=top_lim)
-
-        Limits may be passed in reverse order to flip the direction of
-        the y-axis. For example, suppose ``y`` represents depth of the
-        ocean in m. The y-axis limits might be set like the following
-        so 5000 m depth is at the bottom of the plot and the surface,
-        0 m, is at the top.
-
-        >>> set_ylim(5000, 0)
-        """
-        if top is None and np.iterable(bottom):
-            bottom, top = bottom
-        if ymin is not None:
-            if bottom is not None:
-                raise TypeError('Cannot pass both `ymin` and `bottom`')
-            bottom = ymin
-        if ymax is not None:
-            if top is not None:
-                raise TypeError('Cannot pass both `ymax` and `top`')
-            top = ymax
-
-        self._process_unit_info(ydata=(bottom, top))
-        bottom = self._validate_converted_limits(bottom, self.convert_yunits)
-        top = self._validate_converted_limits(top, self.convert_yunits)
-
-        if bottom is None or top is None:
-            # Axes init calls set_ylim(0, 1) before get_ylim() can be called,
-            # so only grab the limits if we really need them.
-            old_bottom, old_top = self.get_ylim()
-            if bottom is None:
-                bottom = old_bottom
-            if top is None:
-                top = old_top
-
-        if self.get_yscale() == 'log' and (bottom <= 0 or top <= 0):
-            # Axes init calls set_xlim(0, 1) before get_xlim() can be called,
-            # so only grab the limits if we really need them.
-            old_bottom, old_top = self.get_ylim()
-            if bottom <= 0:
-                cbook._warn_external(
-                    'Attempted to set non-positive bottom ylim on a '
-                    'log-scaled axis.\n'
-                    'Invalid limit will be ignored.')
-                bottom = old_bottom
-            if top <= 0:
-                cbook._warn_external(
-                    'Attempted to set non-positive top ylim on a '
-                    'log-scaled axis.\n'
-                    'Invalid limit will be ignored.')
-                top = old_top
-        if bottom == top:
-            cbook._warn_external(
-                f"Attempting to set identical bottom == top == {bottom} "
-                f"results in singular transformations; automatically "
-                f"expanding.")
-        reverse = bottom > top
-        bottom, top = self.yaxis.get_major_locator().nonsingular(bottom, top)
-        bottom, top = self.yaxis.limit_range_for_scale(bottom, top)
-        # cast to bool to avoid bad interaction between python 3.8 and np.bool_
-        bottom, top = sorted([bottom, top], reverse=bool(reverse))
-
-        self._viewLim.intervaly = (bottom, top)
-        if auto is not None:
-            self._autoscaleYon = bool(auto)
-
-        if emit:
-            self.callbacks.process('ylim_changed', self)
-            # Call all of the other y-axes that are shared with this one
-            for other in self._shared_y_axes.get_siblings(self):
-                if other is not self:
-                    other.set_ylim(self.viewLim.intervaly,
-                                   emit=False, auto=auto)
-                    if other.figure != self.figure:
-                        other.figure.canvas.draw_idle()
-        self.stale = True
-        return bottom, top
-
-    def get_yscale(self):
-        """
-        Return the y-axis scale as string.
-
-        See Also
-        --------
-        set_yscale
-        """
-        return self.yaxis.get_scale()
-
-    def set_yscale(self, value, **kwargs):
-        """
-        Set the y-axis scale.
-
-        Parameters
-        ----------
-        value : {"linear", "log", "symlog", "logit", ...}
-            The axis scale type to apply.
-
-        **kwargs
-            Different keyword arguments are accepted, depending on the scale.
-            See the respective class keyword arguments:
-
-            - `matplotlib.scale.LinearScale`
-            - `matplotlib.scale.LogScale`
-            - `matplotlib.scale.SymmetricalLogScale`
-            - `matplotlib.scale.LogitScale`
-
-        Notes
-        -----
-        By default, Matplotlib supports the above mentioned scales.
-        Additionally, custom scales may be registered using
-        `matplotlib.scale.register_scale`. These scales can then also
-        be used here.
-        """
-        old_default_lims = (self.yaxis.get_major_locator()
-                            .nonsingular(-np.inf, np.inf))
-        g = self.get_shared_y_axes()
-        for ax in g.get_siblings(self):
-            ax.yaxis._set_scale(value, **kwargs)
-            ax._update_transScale()
-            ax.stale = True
-        new_default_lims = (self.yaxis.get_major_locator()
-                            .nonsingular(-np.inf, np.inf))
-        if old_default_lims != new_default_lims:
-            # Force autoscaling now, to take advantage of the scale locator's
-            # nonsingular() before it possibly gets swapped out by the user.
-            self.autoscale_view(scalex=False)
-
-    @cbook._make_keyword_only("3.2", "minor")
-    def get_yticks(self, minor=False):
-        """Return the y ticks as a list of locations"""
-        return self.yaxis.get_ticklocs(minor=minor)
-
-    @cbook._make_keyword_only("3.2", "minor")
-    def set_yticks(self, ticks, minor=False):
-        """
-        Set the y ticks with list of *ticks*
-
-        Parameters
-        ----------
-        ticks : list
-            List of y-axis tick locations
-
-        minor : bool, optional
-            If ``False`` sets major ticks, if ``True`` sets minor ticks.
-            Default is ``False``.
-        """
-        ret = self.yaxis.set_ticks(ticks, minor=minor)
-        return ret
-
-    def get_ymajorticklabels(self):
-        """
-        Get the major y tick labels.
-
-        Returns
-        -------
-        labels : list
-            List of `~matplotlib.text.Text` instances
-        """
-        return self.yaxis.get_majorticklabels()
-
-    def get_yminorticklabels(self):
-        """
-        Get the minor y tick labels.
-
-        Returns
-        -------
-        labels : list
-            List of `~matplotlib.text.Text` instances
-        """
-        return self.yaxis.get_minorticklabels()
-
-    def get_yticklabels(self, minor=False, which=None):
-        """
-        Get the y tick labels as a list of `~matplotlib.text.Text` instances.
-
-        Parameters
-        ----------
-        minor : bool
-           If True return the minor ticklabels,
-           else return the major ticklabels
-
-        which : None, ('minor', 'major', 'both')
-           Overrides *minor*.
-
-           Selects which ticklabels to return
-
-        Returns
-        -------
-        ret : list
-           List of `~matplotlib.text.Text` instances.
-        """
-        return self.yaxis.get_ticklabels(minor=minor, which=which)
-
-    def set_yticklabels(self, labels, fontdict=None, minor=False, **kwargs):
-        """
-        Set the y-tick labels with list of strings labels.
-
-        Parameters
-        ----------
-        labels : List[str]
-            list of string labels
-
-        fontdict : dict, optional
-            A dictionary controlling the appearance of the ticklabels.
-            The default *fontdict* is::
-
-               {'fontsize': rcParams['axes.titlesize'],
-                'fontweight': rcParams['axes.titleweight'],
-                'verticalalignment': 'baseline',
-                'horizontalalignment': loc}
-
-        minor : bool, optional
-            Whether to set the minor ticklabels rather than the major ones.
-
-        Returns
-        -------
-        A list of `~.text.Text` instances.
-
-        Other Parameters
-        ----------------
-        **kwargs : `~.text.Text` properties.
-        """
-        if fontdict is not None:
-            kwargs.update(fontdict)
-        return self.yaxis.set_ticklabels(labels,
-                                         minor=minor, **kwargs)
-
-    def xaxis_date(self, tz=None):
-        """
-        Sets up x-axis ticks and labels that treat the x data as dates.
-
-        Parameters
-        ----------
-        tz : str or `tzinfo` instance, optional
-            Timezone.  Defaults to :rc:`timezone`.
-        """
-        # should be enough to inform the unit conversion interface
-        # dates are coming in
-        self.xaxis.axis_date(tz)
-
-    def yaxis_date(self, tz=None):
-        """
-        Sets up y-axis ticks and labels that treat the y data as dates.
-
-        Parameters
-        ----------
-        tz : str or `tzinfo` instance, optional
-            Timezone.  Defaults to :rc:`timezone`.
-        """
-        self.yaxis.axis_date(tz)
-
-    def format_xdata(self, x):
-        """
-        Return *x* formatted as an x-value.
-
-        This function will use the `.fmt_xdata` attribute if it is not None,
-        else will fall back on the xaxis major formatter.
-        """
-        return (self.fmt_xdata if self.fmt_xdata is not None
-                else self.xaxis.get_major_formatter().format_data_short)(x)
-
-    def format_ydata(self, y):
-        """
-        Return *y* formatted as an y-value.
-
-        This function will use the `.fmt_ydata` attribute if it is not None,
-        else will fall back on the yaxis major formatter.
-        """
-        return (self.fmt_ydata if self.fmt_ydata is not None
-                else self.yaxis.get_major_formatter().format_data_short)(y)
-
-    def format_coord(self, x, y):
-        """Return a format string formatting the *x*, *y* coordinates."""
-        if x is None:
-            xs = '???'
-        else:
-            xs = self.format_xdata(x)
-        if y is None:
-            ys = '???'
-        else:
-            ys = self.format_ydata(y)
-        return 'x=%s y=%s' % (xs, ys)
-
-    def minorticks_on(self):
-        """
-        Display minor ticks on the axes.
-
-        Displaying minor ticks may reduce performance; you may turn them off
-        using `minorticks_off()` if drawing speed is a problem.
-        """
-        for ax in (self.xaxis, self.yaxis):
-            scale = ax.get_scale()
-            if scale == 'log':
-                s = ax._scale
-                ax.set_minor_locator(mticker.LogLocator(s.base, s.subs))
-            elif scale == 'symlog':
-                s = ax._scale
-                ax.set_minor_locator(
-                    mticker.SymmetricalLogLocator(s._transform, s.subs))
-            else:
-                ax.set_minor_locator(mticker.AutoMinorLocator())
-
-    def minorticks_off(self):
-        """Remove minor ticks from the axes."""
-        self.xaxis.set_minor_locator(mticker.NullLocator())
-        self.yaxis.set_minor_locator(mticker.NullLocator())
-
-    # Interactive manipulation
-
-    def can_zoom(self):
-        """
-        Return *True* if this axes supports the zoom box button functionality.
-        """
-        return True
-
-    def can_pan(self):
-        """
-        Return *True* if this axes supports any pan/zoom button functionality.
-        """
-        return True
-
-    def get_navigate(self):
-        """
-        Get whether the axes responds to navigation commands
-        """
-        return self._navigate
-
-    def set_navigate(self, b):
-        """
-        Set whether the axes responds to navigation toolbar commands
-
-        Parameters
-        ----------
-        b : bool
-        """
-        self._navigate = b
-
-    def get_navigate_mode(self):
-        """
-        Get the navigation toolbar button status: 'PAN', 'ZOOM', or None
-        """
-        return self._navigate_mode
-
-    def set_navigate_mode(self, b):
-        """
-        Set the navigation toolbar button status;
-
-        .. warning::
-            this is not a user-API function.
-
-        """
-        self._navigate_mode = b
-
-    def _get_view(self):
-        """
-        Save information required to reproduce the current view.
-
-        Called before a view is changed, such as during a pan or zoom
-        initiated by the user. You may return any information you deem
-        necessary to describe the view.
-
-        .. note::
-
-            Intended to be overridden by new projection types, but if not, the
-            default implementation saves the view limits. You *must* implement
-            :meth:`_set_view` if you implement this method.
-        """
-        xmin, xmax = self.get_xlim()
-        ymin, ymax = self.get_ylim()
-        return (xmin, xmax, ymin, ymax)
-
-    def _set_view(self, view):
-        """
-        Apply a previously saved view.
-
-        Called when restoring a view, such as with the navigation buttons.
-
-        .. note::
-
-            Intended to be overridden by new projection types, but if not, the
-            default implementation restores the view limits. You *must*
-            implement :meth:`_get_view` if you implement this method.
-        """
-        xmin, xmax, ymin, ymax = view
-        self.set_xlim((xmin, xmax))
-        self.set_ylim((ymin, ymax))
-
-    def _set_view_from_bbox(self, bbox, direction='in',
-                            mode=None, twinx=False, twiny=False):
-        """
-        Update view from a selection bbox.
-
-        .. note::
-
-            Intended to be overridden by new projection types, but if not, the
-            default implementation sets the view limits to the bbox directly.
-
-        Parameters
-        ----------
-        bbox : 4-tuple or 3 tuple
-            * If bbox is a 4 tuple, it is the selected bounding box limits,
-              in *display* coordinates.
-            * If bbox is a 3 tuple, it is an (xp, yp, scl) triple, where
-              (xp, yp) is the center of zooming and scl the scale factor to
-              zoom by.
-
-        direction : str
-            The direction to apply the bounding box.
-                * `'in'` - The bounding box describes the view directly, i.e.,
-                           it zooms in.
-                * `'out'` - The bounding box describes the size to make the
-                            existing view, i.e., it zooms out.
-
-        mode : str or None
-            The selection mode, whether to apply the bounding box in only the
-            `'x'` direction, `'y'` direction or both (`None`).
-
-        twinx : bool
-            Whether this axis is twinned in the *x*-direction.
-
-        twiny : bool
-            Whether this axis is twinned in the *y*-direction.
-        """
-        Xmin, Xmax = self.get_xlim()
-        Ymin, Ymax = self.get_ylim()
-
-        if len(bbox) == 3:
-            # Zooming code
-            xp, yp, scl = bbox
-
-            # Should not happen
-            if scl == 0:
-                scl = 1.
-
-            # direction = 'in'
-            if scl > 1:
-                direction = 'in'
-            else:
-                direction = 'out'
-                scl = 1/scl
-
-            # get the limits of the axes
-            tranD2C = self.transData.transform
-            xmin, ymin = tranD2C((Xmin, Ymin))
-            xmax, ymax = tranD2C((Xmax, Ymax))
-
-            # set the range
-            xwidth = xmax - xmin
-            ywidth = ymax - ymin
-            xcen = (xmax + xmin)*.5
-            ycen = (ymax + ymin)*.5
-            xzc = (xp*(scl - 1) + xcen)/scl
-            yzc = (yp*(scl - 1) + ycen)/scl
-
-            bbox = [xzc - xwidth/2./scl, yzc - ywidth/2./scl,
-                    xzc + xwidth/2./scl, yzc + ywidth/2./scl]
-        elif len(bbox) != 4:
-            # should be len 3 or 4 but nothing else
-            cbook._warn_external(
-                "Warning in _set_view_from_bbox: bounding box is not a tuple "
-                "of length 3 or 4. Ignoring the view change.")
-            return
-
-        # Just grab bounding box
-        lastx, lasty, x, y = bbox
-
-        # zoom to rect
-        inverse = self.transData.inverted()
-        (lastx, lasty), (x, y) = inverse.transform([(lastx, lasty), (x, y)])
-
-        if twinx:
-            x0, x1 = Xmin, Xmax
-        else:
-            if Xmin < Xmax:
-                if x < lastx:
-                    x0, x1 = x, lastx
-                else:
-                    x0, x1 = lastx, x
-                if x0 < Xmin:
-                    x0 = Xmin
-                if x1 > Xmax:
-                    x1 = Xmax
-            else:
-                if x > lastx:
-                    x0, x1 = x, lastx
-                else:
-                    x0, x1 = lastx, x
-                if x0 > Xmin:
-                    x0 = Xmin
-                if x1 < Xmax:
-                    x1 = Xmax
-
-        if twiny:
-            y0, y1 = Ymin, Ymax
-        else:
-            if Ymin < Ymax:
-                if y < lasty:
-                    y0, y1 = y, lasty
-                else:
-                    y0, y1 = lasty, y
-                if y0 < Ymin:
-                    y0 = Ymin
-                if y1 > Ymax:
-                    y1 = Ymax
-            else:
-                if y > lasty:
-                    y0, y1 = y, lasty
-                else:
-                    y0, y1 = lasty, y
-                if y0 > Ymin:
-                    y0 = Ymin
-                if y1 < Ymax:
-                    y1 = Ymax
-
-        if direction == 'in':
-            if mode == 'x':
-                self.set_xlim((x0, x1))
-            elif mode == 'y':
-                self.set_ylim((y0, y1))
-            else:
-                self.set_xlim((x0, x1))
-                self.set_ylim((y0, y1))
-        elif direction == 'out':
-            if self.get_xscale() == 'log':
-                alpha = np.log(Xmax / Xmin) / np.log(x1 / x0)
-                rx1 = pow(Xmin / x0, alpha) * Xmin
-                rx2 = pow(Xmax / x0, alpha) * Xmin
-            else:
-                alpha = (Xmax - Xmin) / (x1 - x0)
-                rx1 = alpha * (Xmin - x0) + Xmin
-                rx2 = alpha * (Xmax - x0) + Xmin
-            if self.get_yscale() == 'log':
-                alpha = np.log(Ymax / Ymin) / np.log(y1 / y0)
-                ry1 = pow(Ymin / y0, alpha) * Ymin
-                ry2 = pow(Ymax / y0, alpha) * Ymin
-            else:
-                alpha = (Ymax - Ymin) / (y1 - y0)
-                ry1 = alpha * (Ymin - y0) + Ymin
-                ry2 = alpha * (Ymax - y0) + Ymin
-
-            if mode == 'x':
-                self.set_xlim((rx1, rx2))
-            elif mode == 'y':
-                self.set_ylim((ry1, ry2))
-            else:
-                self.set_xlim((rx1, rx2))
-                self.set_ylim((ry1, ry2))
-
-    def start_pan(self, x, y, button):
-        """
-        Called when a pan operation has started.
-
-        *x*, *y* are the mouse coordinates in display coords.
-        button is the mouse button number:
-
-        * 1: LEFT
-        * 2: MIDDLE
-        * 3: RIGHT
-
-        .. note::
-
-            Intended to be overridden by new projection types.
-
-        """
-        self._pan_start = types.SimpleNamespace(
-            lim=self.viewLim.frozen(),
-            trans=self.transData.frozen(),
-            trans_inverse=self.transData.inverted().frozen(),
-            bbox=self.bbox.frozen(),
-            x=x,
-            y=y)
-
-    def end_pan(self):
-        """
-        Called when a pan operation completes (when the mouse button
-        is up.)
-
-        .. note::
-
-            Intended to be overridden by new projection types.
-
-        """
-        del self._pan_start
-
-    def drag_pan(self, button, key, x, y):
-        """
-        Called when the mouse moves during a pan operation.
-
-        *button* is the mouse button number:
-
-        * 1: LEFT
-        * 2: MIDDLE
-        * 3: RIGHT
-
-        *key* is a "shift" key
-
-        *x*, *y* are the mouse coordinates in display coords.
-
-        .. note::
-
-            Intended to be overridden by new projection types.
-
-        """
-        def format_deltas(key, dx, dy):
-            if key == 'control':
-                if abs(dx) > abs(dy):
-                    dy = dx
-                else:
-                    dx = dy
-            elif key == 'x':
-                dy = 0
-            elif key == 'y':
-                dx = 0
-            elif key == 'shift':
-                if 2 * abs(dx) < abs(dy):
-                    dx = 0
-                elif 2 * abs(dy) < abs(dx):
-                    dy = 0
-                elif abs(dx) > abs(dy):
-                    dy = dy / abs(dy) * abs(dx)
-                else:
-                    dx = dx / abs(dx) * abs(dy)
-            return dx, dy
-
-        p = self._pan_start
-        dx = x - p.x
-        dy = y - p.y
-        if dx == dy == 0:
-            return
-        if button == 1:
-            dx, dy = format_deltas(key, dx, dy)
-            result = p.bbox.translated(-dx, -dy).transformed(p.trans_inverse)
-        elif button == 3:
-            try:
-                dx = -dx / self.bbox.width
-                dy = -dy / self.bbox.height
-                dx, dy = format_deltas(key, dx, dy)
-                if self.get_aspect() != 'auto':
-                    dx = dy = 0.5 * (dx + dy)
-                alpha = np.power(10.0, (dx, dy))
-                start = np.array([p.x, p.y])
-                oldpoints = p.lim.transformed(p.trans)
-                newpoints = start + alpha * (oldpoints - start)
-                result = (mtransforms.Bbox(newpoints)
-                          .transformed(p.trans_inverse))
-            except OverflowError:
-                cbook._warn_external('Overflow while panning')
-                return
-        else:
-            return
-
-        valid = np.isfinite(result.transformed(p.trans))
-        points = result.get_points().astype(object)
-        # Just ignore invalid limits (typically, underflow in log-scale).
-        points[~valid] = None
-        self.set_xlim(points[:, 0])
-        self.set_ylim(points[:, 1])
-
-    def get_children(self):
-        # docstring inherited.
-        return [
-            *self.collections,
-            *self.patches,
-            *self.lines,
-            *self.texts,
-            *self.artists,
-            *self.spines.values(),
-            *self._get_axis_list(),
-            self.title, self._left_title, self._right_title,
-            *self.tables,
-            *self.images,
-            *self.child_axes,
-            *([self.legend_] if self.legend_ is not None else []),
-            self.patch,
-        ]
-
-    def contains(self, mouseevent):
-        # docstring inherited.
-        inside, info = self._default_contains(mouseevent)
-        if inside is not None:
-            return inside, info
-        return self.patch.contains(mouseevent)
-
-    def contains_point(self, point):
-        """
-        Return whether *point* (pair of pixel coordinates) is inside the axes
-        patch.
-        """
-        return self.patch.contains_point(point, radius=1.0)
-
-    def get_default_bbox_extra_artists(self):
-        """
-        Return a default list of artists that are used for the bounding box
-        calculation.
-
-        Artists are excluded either by not being visible or
-        ``artist.set_in_layout(False)``.
-        """
-
-        artists = self.get_children()
-
-        if not (self.axison and self._frameon):
-            # don't do bbox on spines if frame not on.
-            for spine in self.spines.values():
-                artists.remove(spine)
-
-        if not self.axison:
-            for _axis in self._get_axis_list():
-                artists.remove(_axis)
-
-        return [artist for artist in artists
-                if (artist.get_visible() and artist.get_in_layout())]
-
-    def get_tightbbox(self, renderer, call_axes_locator=True,
-                      bbox_extra_artists=None):
-        """
-        Return the tight bounding box of the axes, including axis and their
-        decorators (xlabel, title, etc).
-
-        Artists that have ``artist.set_in_layout(False)`` are not included
-        in the bbox.
-
-        Parameters
-        ----------
-        renderer : `.RendererBase` instance
-            renderer that will be used to draw the figures (i.e.
-            ``fig.canvas.get_renderer()``)
-
-        bbox_extra_artists : list of `.Artist` or ``None``
-            List of artists to include in the tight bounding box.  If
-            ``None`` (default), then all artist children of the axes are
-            included in the tight bounding box.
-
-        call_axes_locator : boolean (default ``True``)
-            If *call_axes_locator* is ``False``, it does not call the
-            ``_axes_locator`` attribute, which is necessary to get the correct
-            bounding box. ``call_axes_locator=False`` can be used if the
-            caller is only interested in the relative size of the tightbbox
-            compared to the axes bbox.
-
-        Returns
-        -------
-        bbox : `.BboxBase`
-            bounding box in figure pixel coordinates.
-
-        See Also
-        --------
-        matplotlib.axes.Axes.get_window_extent
-        matplotlib.axis.Axis.get_tightbbox
-        matplotlib.spines.Spine.get_window_extent
-
-        """
-
-        bb = []
-
-        if not self.get_visible():
-            return None
-
-        locator = self.get_axes_locator()
-        if locator and call_axes_locator:
-            pos = locator(self, renderer)
-            self.apply_aspect(pos)
-        else:
-            self.apply_aspect()
-
-        if self.axison:
-            bb_xaxis = self.xaxis.get_tightbbox(renderer)
-            if bb_xaxis:
-                bb.append(bb_xaxis)
-
-            bb_yaxis = self.yaxis.get_tightbbox(renderer)
-            if bb_yaxis:
-                bb.append(bb_yaxis)
-
-        self._update_title_position(renderer)
-        axbbox = self.get_window_extent(renderer)
-        bb.append(axbbox)
-
-        self._update_title_position(renderer)
-        if self.title.get_visible():
-            bb.append(self.title.get_window_extent(renderer))
-        if self._left_title.get_visible():
-            bb.append(self._left_title.get_window_extent(renderer))
-        if self._right_title.get_visible():
-            bb.append(self._right_title.get_window_extent(renderer))
-
-        bb.append(self.get_window_extent(renderer))
-
-        bbox_artists = bbox_extra_artists
-        if bbox_artists is None:
-            bbox_artists = self.get_default_bbox_extra_artists()
-
-        for a in bbox_artists:
-            # Extra check here to quickly see if clipping is on and
-            # contained in the axes.  If it is, don't get the tightbbox for
-            # this artist because this can be expensive:
-            clip_extent = a._get_clipping_extent_bbox()
-            if clip_extent is not None:
-                clip_extent = mtransforms.Bbox.intersection(clip_extent,
-                    axbbox)
-                if np.all(clip_extent.extents == axbbox.extents):
-                    # clip extent is inside the axes bbox so don't check
-                    # this artist
-                    continue
-            bbox = a.get_tightbbox(renderer)
-            if (bbox is not None
-                    and 0 < bbox.width < np.inf
-                    and 0 < bbox.height < np.inf):
-                bb.append(bbox)
-        _bbox = mtransforms.Bbox.union(
-            [b for b in bb if b.width != 0 or b.height != 0])
-
-        return _bbox
-
-    def _make_twin_axes(self, *args, **kwargs):
-        """Make a twinx axes of self. This is used for twinx and twiny."""
-        # Typically, SubplotBase._make_twin_axes is called instead of this.
-        if 'sharex' in kwargs and 'sharey' in kwargs:
-            raise ValueError("Twinned Axes may share only one axis")
-        ax2 = self.figure.add_axes(self.get_position(True), *args, **kwargs)
-        self.set_adjustable('datalim')
-        ax2.set_adjustable('datalim')
-        self._twinned_axes.join(self, ax2)
-        return ax2
-
-    def twinx(self):
-        """
-        Create a twin Axes sharing the xaxis.
-
-        Create a new Axes with an invisible x-axis and an independent
-        y-axis positioned opposite to the original one (i.e. at right). The
-        x-axis autoscale setting will be inherited from the original
-        Axes.  To ensure that the tick marks of both y-axes align, see
-        `~matplotlib.ticker.LinearLocator`.
-
-        Returns
-        -------
-        ax_twin : Axes
-            The newly created Axes instance
-
-        Notes
-        -----
-        For those who are 'picking' artists while using twinx, pick
-        events are only called for the artists in the top-most axes.
-        """
-        ax2 = self._make_twin_axes(sharex=self)
-        ax2.yaxis.tick_right()
-        ax2.yaxis.set_label_position('right')
-        ax2.yaxis.set_offset_position('right')
-        ax2.set_autoscalex_on(self.get_autoscalex_on())
-        self.yaxis.tick_left()
-        ax2.xaxis.set_visible(False)
-        ax2.patch.set_visible(False)
-        return ax2
-
-    def twiny(self):
-        """
-        Create a twin Axes sharing the yaxis.
-
-        Create a new Axes with an invisible y-axis and an independent
-        x-axis positioned opposite to the original one (i.e. at top). The
-        y-axis autoscale setting will be inherited from the original Axes.
-        To ensure that the tick marks of both x-axes align, see
-        `~matplotlib.ticker.LinearLocator`.
-
-        Returns
-        -------
-        ax_twin : Axes
-            The newly created Axes instance
-
-        Notes
-        -----
-        For those who are 'picking' artists while using twiny, pick
-        events are only called for the artists in the top-most axes.
-        """
-        ax2 = self._make_twin_axes(sharey=self)
-        ax2.xaxis.tick_top()
-        ax2.xaxis.set_label_position('top')
-        ax2.set_autoscaley_on(self.get_autoscaley_on())
-        self.xaxis.tick_bottom()
-        ax2.yaxis.set_visible(False)
-        ax2.patch.set_visible(False)
-        return ax2
-
-    def get_shared_x_axes(self):
-        """Return a reference to the shared axes Grouper object for x axes."""
-        return self._shared_x_axes
-
-    def get_shared_y_axes(self):
-        """Return a reference to the shared axes Grouper object for y axes."""
-        return self._shared_y_axes

+ 0 - 408
venv/lib/python3.8/site-packages/matplotlib/axes/_secondary_axes.py

@@ -1,408 +0,0 @@
-import numpy as np
-
-import matplotlib.cbook as cbook
-import matplotlib.docstring as docstring
-import matplotlib.ticker as mticker
-import matplotlib.transforms as mtransforms
-from matplotlib.axes._base import _AxesBase
-
-
-def _make_secondary_locator(rect, parent):
-    """
-    Helper function to locate the secondary axes.
-
-    A locator gets used in `Axes.set_aspect` to override the default
-    locations...  It is a function that takes an axes object and
-    a renderer and tells `set_aspect` where it is to be placed.
-
-    This locator make the transform be in axes-relative co-coordinates
-    because that is how we specify the "location" of the secondary axes.
-
-    Here *rect* is a rectangle [l, b, w, h] that specifies the
-    location for the axes in the transform given by *trans* on the
-    *parent*.
-    """
-    _rect = mtransforms.Bbox.from_bounds(*rect)
-    def secondary_locator(ax, renderer):
-        # delay evaluating transform until draw time because the
-        # parent transform may have changed (i.e. if window reesized)
-        bb = mtransforms.TransformedBbox(_rect, parent.transAxes)
-        tr = parent.figure.transFigure.inverted()
-        bb = mtransforms.TransformedBbox(bb, tr)
-        return bb
-
-    return secondary_locator
-
-
-class SecondaryAxis(_AxesBase):
-    """
-    General class to hold a Secondary_X/Yaxis.
-    """
-
-    def __init__(self, parent, orientation,
-                  location, functions, **kwargs):
-        """
-        See `.secondary_xaxis` and `.secondary_yaxis` for the doc string.
-        While there is no need for this to be private, it should really be
-        called by those higher level functions.
-        """
-
-        self._functions = functions
-        self._parent = parent
-        self._orientation = orientation
-        self._ticks_set = False
-
-        if self._orientation == 'x':
-            super().__init__(self._parent.figure, [0, 1., 1, 0.0001], **kwargs)
-            self._axis = self.xaxis
-            self._locstrings = ['top', 'bottom']
-            self._otherstrings = ['left', 'right']
-        elif self._orientation == 'y':
-            super().__init__(self._parent.figure, [0, 1., 0.0001, 1], **kwargs)
-            self._axis = self.yaxis
-            self._locstrings = ['right', 'left']
-            self._otherstrings = ['top', 'bottom']
-        self._parentscale = self._axis.get_scale()
-        # this gets positioned w/o constrained_layout so exclude:
-        self._layoutbox = None
-        self._poslayoutbox = None
-
-        self.set_location(location)
-        self.set_functions(functions)
-
-        # styling:
-        if self._orientation == 'x':
-            otheraxis = self.yaxis
-        else:
-            otheraxis = self.xaxis
-
-        otheraxis.set_major_locator(mticker.NullLocator())
-        otheraxis.set_ticks_position('none')
-
-        for st in self._otherstrings:
-            self.spines[st].set_visible(False)
-        for st in self._locstrings:
-            self.spines[st].set_visible(True)
-
-        if self._pos < 0.5:
-            # flip the location strings...
-            self._locstrings = self._locstrings[::-1]
-        self.set_alignment(self._locstrings[0])
-
-    def set_alignment(self, align):
-        """
-        Set if axes spine and labels are drawn at top or bottom (or left/right)
-        of the axes.
-
-        Parameters
-        ----------
-        align : str
-            either 'top' or 'bottom' for orientation='x' or
-            'left' or 'right' for orientation='y' axis.
-        """
-        if align in self._locstrings:
-            if align == self._locstrings[1]:
-                # need to change the orientation.
-                self._locstrings = self._locstrings[::-1]
-            elif align != self._locstrings[0]:
-                raise ValueError('"{}" is not a valid axis orientation, '
-                                 'not changing the orientation;'
-                                 'choose "{}" or "{}""'.format(align,
-                                 self._locstrings[0], self._locstrings[1]))
-            self.spines[self._locstrings[0]].set_visible(True)
-            self.spines[self._locstrings[1]].set_visible(False)
-            self._axis.set_ticks_position(align)
-            self._axis.set_label_position(align)
-
-    def set_location(self, location):
-        """
-        Set the vertical or horizontal location of the axes in
-        parent-normalized co-ordinates.
-
-        Parameters
-        ----------
-        location : {'top', 'bottom', 'left', 'right'} or float
-            The position to put the secondary axis.  Strings can be 'top' or
-            'bottom' for orientation='x' and 'right' or 'left' for
-            orientation='y'. A float indicates the relative position on the
-            parent axes to put the new axes, 0.0 being the bottom (or left)
-            and 1.0 being the top (or right).
-        """
-
-        # This puts the rectangle into figure-relative coordinates.
-        if isinstance(location, str):
-            if location in ['top', 'right']:
-                self._pos = 1.
-            elif location in ['bottom', 'left']:
-                self._pos = 0.
-            else:
-                raise ValueError("location must be '{}', '{}', or a "
-                                 "float, not '{}'".format(location,
-                                 self._locstrings[0], self._locstrings[1]))
-        else:
-            self._pos = location
-        self._loc = location
-
-        if self._orientation == 'x':
-            bounds = [0, self._pos, 1., 1e-10]
-        else:
-            bounds = [self._pos, 0, 1e-10, 1]
-
-        secondary_locator = _make_secondary_locator(bounds, self._parent)
-
-        # this locator lets the axes move in the parent axes coordinates.
-        # so it never needs to know where the parent is explicitly in
-        # figure co-ordinates.
-        # it gets called in `ax.apply_aspect() (of all places)
-        self.set_axes_locator(secondary_locator)
-
-    def apply_aspect(self, position=None):
-        # docstring inherited.
-        self._set_lims()
-        super().apply_aspect(position)
-
-    @cbook._make_keyword_only("3.2", "minor")
-    def set_ticks(self, ticks, minor=False):
-        """
-        Set the x ticks with list of *ticks*
-
-        Parameters
-        ----------
-        ticks : list
-            List of x-axis tick locations.
-        minor : bool, optional
-            If ``False`` sets major ticks, if ``True`` sets minor ticks.
-            Default is ``False``.
-        """
-        ret = self._axis.set_ticks(ticks, minor=minor)
-        self.stale = True
-        self._ticks_set = True
-        return ret
-
-    def set_functions(self, functions):
-        """
-        Set how the secondary axis converts limits from the parent axes.
-
-        Parameters
-        ----------
-        functions : 2-tuple of func, or `Transform` with an inverse.
-            Transform between the parent axis values and the secondary axis
-            values.
-
-            If supplied as a 2-tuple of functions, the first function is
-            the forward transform function and the second is the inverse
-            transform.
-
-            If a transform is supplied, then the transform must have an
-            inverse.
-        """
-
-        if self._orientation == 'x':
-            set_scale = self.set_xscale
-            parent_scale = self._parent.get_xscale()
-        else:
-            set_scale = self.set_yscale
-            parent_scale = self._parent.get_yscale()
-        # we need to use a modified scale so the scale can receive the
-        # transform.  Only types supported are linear and log10 for now.
-        # Probably possible to add other transforms as a todo...
-        if parent_scale == 'log':
-            defscale = 'functionlog'
-        else:
-            defscale = 'function'
-
-        if (isinstance(functions, tuple) and len(functions) == 2 and
-            callable(functions[0]) and callable(functions[1])):
-            # make an arbitrary convert from a two-tuple of functions
-            # forward and inverse.
-            self._functions = functions
-        elif functions is None:
-            self._functions = (lambda x: x, lambda x: x)
-        else:
-            raise ValueError('functions argument of secondary axes '
-                             'must be a two-tuple of callable functions '
-                             'with the first function being the transform '
-                             'and the second being the inverse')
-        # need to invert the roles here for the ticks to line up.
-        set_scale(defscale, functions=self._functions[::-1])
-
-    def draw(self, renderer=None, inframe=False):
-        """
-        Draw the secondary axes.
-
-        Consults the parent axes for its limits and converts them
-        using the converter specified by
-        `~.axes._secondary_axes.set_functions` (or *functions*
-        parameter when axes initialized.)
-        """
-        self._set_lims()
-        # this sets the scale in case the parent has set its scale.
-        self._set_scale()
-        super().draw(renderer=renderer, inframe=inframe)
-
-    def _set_scale(self):
-        """
-        Check if parent has set its scale
-        """
-
-        if self._orientation == 'x':
-            pscale = self._parent.xaxis.get_scale()
-            set_scale = self.set_xscale
-        if self._orientation == 'y':
-            pscale = self._parent.yaxis.get_scale()
-            set_scale = self.set_yscale
-        if pscale == self._parentscale:
-            return
-        else:
-            self._parentscale = pscale
-
-        if pscale == 'log':
-            defscale = 'functionlog'
-        else:
-            defscale = 'function'
-
-        if self._ticks_set:
-            ticks = self._axis.get_ticklocs()
-
-        # need to invert the roles here for the ticks to line up.
-        set_scale(defscale, functions=self._functions[::-1])
-
-        # OK, set_scale sets the locators, but if we've called
-        # axsecond.set_ticks, we want to keep those.
-        if self._ticks_set:
-            self._axis.set_major_locator(mticker.FixedLocator(ticks))
-
-    def _set_lims(self):
-        """
-        Set the limits based on parent limits and the convert method
-        between the parent and this secondary axes.
-        """
-        if self._orientation == 'x':
-            lims = self._parent.get_xlim()
-            set_lim = self.set_xlim
-        if self._orientation == 'y':
-            lims = self._parent.get_ylim()
-            set_lim = self.set_ylim
-        order = lims[0] < lims[1]
-        lims = self._functions[0](np.array(lims))
-        neworder = lims[0] < lims[1]
-        if neworder != order:
-            # Flip because the transform will take care of the flipping.
-            lims = lims[::-1]
-        set_lim(lims)
-
-    def set_aspect(self, *args, **kwargs):
-        """
-        Secondary axes cannot set the aspect ratio, so calling this just
-        sets a warning.
-        """
-        cbook._warn_external("Secondary axes can't set the aspect ratio")
-
-    def set_xlabel(self, xlabel, fontdict=None, labelpad=None, **kwargs):
-        """
-        Set the label for the x-axis.
-
-        Parameters
-        ----------
-        xlabel : str
-            The label text.
-
-        labelpad : scalar, optional, default: None
-            Spacing in points between the label and the x-axis.
-
-        Other Parameters
-        ----------------
-        **kwargs : `.Text` properties
-            `.Text` properties control the appearance of the label.
-
-        See also
-        --------
-        text : for information on how override and the optional args work
-        """
-        if labelpad is not None:
-            self.xaxis.labelpad = labelpad
-        return self.xaxis.set_label_text(xlabel, fontdict, **kwargs)
-
-    def set_ylabel(self, ylabel, fontdict=None, labelpad=None, **kwargs):
-        """
-        Set the label for the x-axis.
-
-        Parameters
-        ----------
-        ylabel : str
-            The label text.
-
-        labelpad : scalar, optional, default: None
-            Spacing in points between the label and the x-axis.
-
-        Other Parameters
-        ----------------
-        **kwargs : `.Text` properties
-            `.Text` properties control the appearance of the label.
-
-        See also
-        --------
-        text : for information on how override and the optional args work
-        """
-        if labelpad is not None:
-            self.yaxis.labelpad = labelpad
-        return self.yaxis.set_label_text(ylabel, fontdict, **kwargs)
-
-    def set_color(self, color):
-        """
-        Change the color of the secondary axes and all decorators.
-
-        Parameters
-        ----------
-        color : Matplotlib color
-        """
-        if self._orientation == 'x':
-            self.tick_params(axis='x', colors=color)
-            self.spines['bottom'].set_color(color)
-            self.spines['top'].set_color(color)
-            self.xaxis.label.set_color(color)
-        else:
-            self.tick_params(axis='y', colors=color)
-            self.spines['left'].set_color(color)
-            self.spines['right'].set_color(color)
-            self.yaxis.label.set_color(color)
-
-
-_secax_docstring = '''
-Warnings
---------
-This method is experimental as of 3.1, and the API may change.
-
-Parameters
-----------
-location : {'top', 'bottom', 'left', 'right'} or float
-    The position to put the secondary axis.  Strings can be 'top' or
-    'bottom' for orientation='x' and 'right' or 'left' for
-    orientation='y'. A float indicates the relative position on the
-    parent axes to put the new axes, 0.0 being the bottom (or left)
-    and 1.0 being the top (or right).
-
-functions : 2-tuple of func, or Transform with an inverse
-
-    If a 2-tuple of functions, the user specifies the transform
-    function and its inverse.  i.e.
-    `functions=(lambda x: 2 / x, lambda x: 2 / x)` would be an
-    reciprocal transform with a factor of 2.
-
-    The user can also directly supply a subclass of
-    `.transforms.Transform` so long as it has an inverse.
-
-    See :doc:`/gallery/subplots_axes_and_figures/secondary_axis`
-    for examples of making these conversions.
-
-
-Other Parameters
-----------------
-**kwargs : `~matplotlib.axes.Axes` properties.
-    Other miscellaneous axes parameters.
-
-Returns
--------
-ax : axes._secondary_axes.SecondaryAxis
-'''
-docstring.interpd.update(_secax_docstring=_secax_docstring)

+ 0 - 255
venv/lib/python3.8/site-packages/matplotlib/axes/_subplots.py

@@ -1,255 +0,0 @@
-import functools
-import uuid
-
-from matplotlib import cbook, docstring
-import matplotlib.artist as martist
-from matplotlib.axes._axes import Axes
-from matplotlib.gridspec import GridSpec, SubplotSpec
-import matplotlib._layoutbox as layoutbox
-
-
-class SubplotBase:
-    """
-    Base class for subplots, which are :class:`Axes` instances with
-    additional methods to facilitate generating and manipulating a set
-    of :class:`Axes` within a figure.
-    """
-
-    def __init__(self, fig, *args, **kwargs):
-        """
-        Parameters
-        ----------
-        fig : `matplotlib.figure.Figure`
-
-        *args : tuple (*nrows*, *ncols*, *index*) or int
-            The array of subplots in the figure has dimensions ``(nrows,
-            ncols)``, and *index* is the index of the subplot being created.
-            *index* starts at 1 in the upper left corner and increases to the
-            right.
-
-            If *nrows*, *ncols*, and *index* are all single digit numbers, then
-            *args* can be passed as a single 3-digit number (e.g. 234 for
-            (2, 3, 4)).
-        """
-
-        self.figure = fig
-
-        if len(args) == 1:
-            if isinstance(args[0], SubplotSpec):
-                self._subplotspec = args[0]
-            else:
-                try:
-                    s = str(int(args[0]))
-                    rows, cols, num = map(int, s)
-                except ValueError:
-                    raise ValueError('Single argument to subplot must be '
-                        'a 3-digit integer')
-                self._subplotspec = GridSpec(rows, cols,
-                                             figure=self.figure)[num - 1]
-                # num - 1 for converting from MATLAB to python indexing
-        elif len(args) == 3:
-            rows, cols, num = args
-            rows = int(rows)
-            cols = int(cols)
-            if rows <= 0:
-                raise ValueError(f'Number of rows must be > 0, not {rows}')
-            if cols <= 0:
-                raise ValueError(f'Number of columns must be > 0, not {cols}')
-            if isinstance(num, tuple) and len(num) == 2:
-                num = [int(n) for n in num]
-                self._subplotspec = GridSpec(
-                        rows, cols,
-                        figure=self.figure)[(num[0] - 1):num[1]]
-            else:
-                if num < 1 or num > rows*cols:
-                    raise ValueError(
-                        f"num must be 1 <= num <= {rows*cols}, not {num}")
-                self._subplotspec = GridSpec(
-                        rows, cols, figure=self.figure)[int(num) - 1]
-                # num - 1 for converting from MATLAB to python indexing
-        else:
-            raise ValueError(f'Illegal argument(s) to subplot: {args}')
-
-        self.update_params()
-
-        # _axes_class is set in the subplot_class_factory
-        self._axes_class.__init__(self, fig, self.figbox, **kwargs)
-        # add a layout box to this, for both the full axis, and the poss
-        # of the axis.  We need both because the axes may become smaller
-        # due to parasitic axes and hence no longer fill the subplotspec.
-        if self._subplotspec._layoutbox is None:
-            self._layoutbox = None
-            self._poslayoutbox = None
-        else:
-            name = self._subplotspec._layoutbox.name + '.ax'
-            name = name + layoutbox.seq_id()
-            self._layoutbox = layoutbox.LayoutBox(
-                    parent=self._subplotspec._layoutbox,
-                    name=name,
-                    artist=self)
-            self._poslayoutbox = layoutbox.LayoutBox(
-                    parent=self._layoutbox,
-                    name=self._layoutbox.name+'.pos',
-                    pos=True, subplot=True, artist=self)
-
-    def __reduce__(self):
-        # get the first axes class which does not inherit from a subplotbase
-        axes_class = next(
-            c for c in type(self).__mro__
-            if issubclass(c, Axes) and not issubclass(c, SubplotBase))
-        return (_picklable_subplot_class_constructor,
-                (axes_class,),
-                self.__getstate__())
-
-    def get_geometry(self):
-        """Get the subplot geometry, e.g., (2, 2, 3)."""
-        rows, cols, num1, num2 = self.get_subplotspec().get_geometry()
-        return rows, cols, num1 + 1  # for compatibility
-
-    # COVERAGE NOTE: Never used internally or from examples
-    def change_geometry(self, numrows, numcols, num):
-        """Change subplot geometry, e.g., from (1, 1, 1) to (2, 2, 3)."""
-        self._subplotspec = GridSpec(numrows, numcols,
-                                     figure=self.figure)[num - 1]
-        self.update_params()
-        self.set_position(self.figbox)
-
-    def get_subplotspec(self):
-        """get the SubplotSpec instance associated with the subplot"""
-        return self._subplotspec
-
-    def set_subplotspec(self, subplotspec):
-        """set the SubplotSpec instance associated with the subplot"""
-        self._subplotspec = subplotspec
-
-    def get_gridspec(self):
-        """get the GridSpec instance associated with the subplot"""
-        return self._subplotspec.get_gridspec()
-
-    def update_params(self):
-        """update the subplot position from fig.subplotpars"""
-        self.figbox, _, _, self.numRows, self.numCols = \
-            self.get_subplotspec().get_position(self.figure,
-                                                return_all=True)
-
-    @cbook.deprecated("3.2", alternative="ax.get_subplotspec().rowspan.start")
-    @property
-    def rowNum(self):
-        return self.get_subplotspec().rowspan.start
-
-    @cbook.deprecated("3.2", alternative="ax.get_subplotspec().colspan.start")
-    @property
-    def colNum(self):
-        return self.get_subplotspec().colspan.start
-
-    def is_first_row(self):
-        return self.get_subplotspec().rowspan.start == 0
-
-    def is_last_row(self):
-        return self.get_subplotspec().rowspan.stop == self.get_gridspec().nrows
-
-    def is_first_col(self):
-        return self.get_subplotspec().colspan.start == 0
-
-    def is_last_col(self):
-        return self.get_subplotspec().colspan.stop == self.get_gridspec().ncols
-
-    def label_outer(self):
-        """
-        Only show "outer" labels and tick labels.
-
-        x-labels are only kept for subplots on the last row; y-labels only for
-        subplots on the first column.
-        """
-        lastrow = self.is_last_row()
-        firstcol = self.is_first_col()
-        if not lastrow:
-            for label in self.get_xticklabels(which="both"):
-                label.set_visible(False)
-            self.get_xaxis().get_offset_text().set_visible(False)
-            self.set_xlabel("")
-        if not firstcol:
-            for label in self.get_yticklabels(which="both"):
-                label.set_visible(False)
-            self.get_yaxis().get_offset_text().set_visible(False)
-            self.set_ylabel("")
-
-    def _make_twin_axes(self, *args, **kwargs):
-        """Make a twinx axes of self. This is used for twinx and twiny."""
-        if 'sharex' in kwargs and 'sharey' in kwargs:
-            # The following line is added in v2.2 to avoid breaking Seaborn,
-            # which currently uses this internal API.
-            if kwargs["sharex"] is not self and kwargs["sharey"] is not self:
-                raise ValueError("Twinned Axes may share only one axis")
-        # The dance here with label is to force add_subplot() to create a new
-        # Axes (by passing in a label never seen before).  Note that this does
-        # not affect plot reactivation by subplot() as twin axes can never be
-        # reactivated by subplot().
-        sentinel = str(uuid.uuid4())
-        real_label = kwargs.pop("label", sentinel)
-        twin = self.figure.add_subplot(
-            self.get_subplotspec(), *args, label=sentinel, **kwargs)
-        if real_label is not sentinel:
-            twin.set_label(real_label)
-        self.set_adjustable('datalim')
-        twin.set_adjustable('datalim')
-        if self._layoutbox is not None and twin._layoutbox is not None:
-            # make the layout boxes be explicitly the same
-            twin._layoutbox.constrain_same(self._layoutbox)
-            twin._poslayoutbox.constrain_same(self._poslayoutbox)
-        self._twinned_axes.join(self, twin)
-        return twin
-
-
-# this here to support cartopy which was using a private part of the
-# API to register their Axes subclasses.
-
-# In 3.1 this should be changed to a dict subclass that warns on use
-# In 3.3 to a dict subclass that raises a useful exception on use
-# In 3.4 should be removed
-
-# The slow timeline is to give cartopy enough time to get several
-# release out before we break them.
-_subplot_classes = {}
-
-
-@functools.lru_cache(None)
-def subplot_class_factory(axes_class=None):
-    """
-    This makes a new class that inherits from `.SubplotBase` and the
-    given axes_class (which is assumed to be a subclass of `.axes.Axes`).
-    This is perhaps a little bit roundabout to make a new class on
-    the fly like this, but it means that a new Subplot class does
-    not have to be created for every type of Axes.
-    """
-    if axes_class is None:
-        axes_class = Axes
-    try:
-        # Avoid creating two different instances of GeoAxesSubplot...
-        # Only a temporary backcompat fix.  This should be removed in
-        # 3.4
-        return next(cls for cls in SubplotBase.__subclasses__()
-                    if cls.__bases__ == (SubplotBase, axes_class))
-    except StopIteration:
-        return type("%sSubplot" % axes_class.__name__,
-                    (SubplotBase, axes_class),
-                    {'_axes_class': axes_class})
-
-
-# This is provided for backward compatibility
-Subplot = subplot_class_factory()
-
-
-def _picklable_subplot_class_constructor(axes_class):
-    """
-    This stub class exists to return the appropriate subplot class when called
-    with an axes class. This is purely to allow pickling of Axes and Subplots.
-    """
-    subplot_class = subplot_class_factory(axes_class)
-    return subplot_class.__new__(subplot_class)
-
-
-docstring.interpd.update(Axes=martist.kwdoc(Axes))
-docstring.dedent_interpd(Axes.__init__)
-
-docstring.interpd.update(Subplot=martist.kwdoc(Axes))

+ 0 - 2496
venv/lib/python3.8/site-packages/matplotlib/axis.py

@@ -1,2496 +0,0 @@
-"""
-Classes for the ticks and x and y axis.
-"""
-
-import datetime
-import logging
-
-import numpy as np
-
-from matplotlib import rcParams
-import matplotlib.artist as martist
-import matplotlib.cbook as cbook
-import matplotlib.font_manager as font_manager
-import matplotlib.lines as mlines
-import matplotlib.scale as mscale
-import matplotlib.text as mtext
-import matplotlib.ticker as mticker
-import matplotlib.transforms as mtransforms
-import matplotlib.units as munits
-
-_log = logging.getLogger(__name__)
-
-GRIDLINE_INTERPOLATION_STEPS = 180
-
-# This list is being used for compatibility with Axes.grid, which
-# allows all Line2D kwargs.
-_line_AI = martist.ArtistInspector(mlines.Line2D)
-_line_param_names = _line_AI.get_setters()
-_line_param_aliases = [list(d)[0] for d in _line_AI.aliasd.values()]
-_gridline_param_names = ['grid_' + name
-                         for name in _line_param_names + _line_param_aliases]
-
-
-class Tick(martist.Artist):
-    """
-    Abstract base class for the axis ticks, grid lines and labels.
-
-    Ticks mark a position on an Axis. They contain two lines as markers and
-    two labels; one each for the bottom and top positions (in case of an
-    `.XAxis`) or for the left and right positions (in case of a `.YAxis`).
-
-    Attributes
-    ----------
-    tick1line : `.Line2D`
-        The left/bottom tick marker.
-    tick2line : `.Line2D`
-        The right/top tick marker.
-    gridline : `.Line2D`
-        The grid line associated with the label position.
-    label1 : `.Text`
-        The left/bottom tick label.
-    label2 : `.Text`
-        The right/top tick label.
-
-    """
-    def __init__(self, axes, loc, label,
-                 size=None,  # points
-                 width=None,
-                 color=None,
-                 tickdir=None,
-                 pad=None,
-                 labelsize=None,
-                 labelcolor=None,
-                 zorder=None,
-                 gridOn=None,  # defaults to axes.grid depending on
-                               # axes.grid.which
-                 tick1On=True,
-                 tick2On=True,
-                 label1On=True,
-                 label2On=False,
-                 major=True,
-                 labelrotation=0,
-                 grid_color=None,
-                 grid_linestyle=None,
-                 grid_linewidth=None,
-                 grid_alpha=None,
-                 **kw  # Other Line2D kwargs applied to gridlines.
-                 ):
-        """
-        bbox is the Bound2D bounding box in display coords of the Axes
-        loc is the tick location in data coords
-        size is the tick size in points
-        """
-        martist.Artist.__init__(self)
-
-        if gridOn is None:
-            if major and (rcParams['axes.grid.which'] in ('both', 'major')):
-                gridOn = rcParams['axes.grid']
-            elif (not major) and (rcParams['axes.grid.which']
-                                  in ('both', 'minor')):
-                gridOn = rcParams['axes.grid']
-            else:
-                gridOn = False
-
-        self.set_figure(axes.figure)
-        self.axes = axes
-
-        name = self.__name__.lower()
-
-        self._loc = loc
-
-        if size is None:
-            if major:
-                size = rcParams['%s.major.size' % name]
-            else:
-                size = rcParams['%s.minor.size' % name]
-        self._size = size
-
-        if width is None:
-            if major:
-                width = rcParams['%s.major.width' % name]
-            else:
-                width = rcParams['%s.minor.width' % name]
-        self._width = width
-
-        if color is None:
-            color = rcParams['%s.color' % name]
-        self._color = color
-
-        if pad is None:
-            if major:
-                pad = rcParams['%s.major.pad' % name]
-            else:
-                pad = rcParams['%s.minor.pad' % name]
-        self._base_pad = pad
-
-        if labelcolor is None:
-            labelcolor = rcParams['%s.color' % name]
-        self._labelcolor = labelcolor
-
-        if labelsize is None:
-            labelsize = rcParams['%s.labelsize' % name]
-        self._labelsize = labelsize
-
-        self._set_labelrotation(labelrotation)
-
-        if zorder is None:
-            if major:
-                zorder = mlines.Line2D.zorder + 0.01
-            else:
-                zorder = mlines.Line2D.zorder
-        self._zorder = zorder
-
-        self._grid_color = (rcParams['grid.color']
-                            if grid_color is None else grid_color)
-        self._grid_linestyle = (rcParams['grid.linestyle']
-                                if grid_linestyle is None else grid_linestyle)
-        self._grid_linewidth = (rcParams['grid.linewidth']
-                                if grid_linewidth is None else grid_linewidth)
-        self._grid_alpha = (rcParams['grid.alpha']
-                            if grid_alpha is None else grid_alpha)
-
-        self._grid_kw = {k[5:]: v for k, v in kw.items()}
-
-        self.apply_tickdir(tickdir)
-
-        self.tick1line = self._get_tick1line()
-        self.tick2line = self._get_tick2line()
-        self.gridline = self._get_gridline()
-        self.label1 = self._get_text1()
-        self.label2 = self._get_text2()
-
-        self.gridline.set_visible(gridOn)
-        self.tick1line.set_visible(tick1On)
-        self.tick2line.set_visible(tick2On)
-        self.label1.set_visible(label1On)
-        self.label2.set_visible(label2On)
-
-        self.update_position(loc)
-
-    for _old_name, _new_name in [
-            ("gridOn", "gridline"),
-            ("tick1On", "tick1line"),
-            ("tick2On", "tick2line"),
-            ("label1On", "label1"),
-            ("label2On", "label2")]:
-        locals()[_old_name] = property(
-            cbook.deprecated(
-                "3.1",
-                name=_old_name,
-                alternative="Tick.{}.get_visible".format(_new_name))(
-                    lambda self, _new_name=_new_name:
-                        getattr(self, _new_name).get_visible()),
-            cbook.deprecated(
-                "3.1",
-                name=_old_name,
-                alternative="Tick.{}.set_visible".format(_new_name))(
-                    lambda self, value, _new_name=_new_name:
-                        getattr(self, _new_name).set_visible(value)))
-    del _old_name, _new_name
-
-    @property
-    @cbook.deprecated("3.1", alternative="Tick.label1", pending=True)
-    def label(self):
-        return self.label1
-
-    def _set_labelrotation(self, labelrotation):
-        if isinstance(labelrotation, str):
-            mode = labelrotation
-            angle = 0
-        elif isinstance(labelrotation, (tuple, list)):
-            mode, angle = labelrotation
-        else:
-            mode = 'default'
-            angle = labelrotation
-        cbook._check_in_list(['auto', 'default'], labelrotation=mode)
-        self._labelrotation = (mode, angle)
-
-    def apply_tickdir(self, tickdir):
-        """Calculate self._pad and self._tickmarkers."""
-
-    def get_tickdir(self):
-        return self._tickdir
-
-    def get_tick_padding(self):
-        """Get the length of the tick outside of the axes."""
-        padding = {
-            'in': 0.0,
-            'inout': 0.5,
-            'out': 1.0
-        }
-        return self._size * padding[self._tickdir]
-
-    def get_children(self):
-        children = [self.tick1line, self.tick2line,
-                    self.gridline, self.label1, self.label2]
-        return children
-
-    def set_clip_path(self, clippath, transform=None):
-        # docstring inherited
-        martist.Artist.set_clip_path(self, clippath, transform)
-        self.gridline.set_clip_path(clippath, transform)
-        self.stale = True
-
-    def get_pad_pixels(self):
-        return self.figure.dpi * self._base_pad / 72
-
-    def contains(self, mouseevent):
-        """
-        Test whether the mouse event occurred in the Tick marks.
-
-        This function always returns false.  It is more useful to test if the
-        axis as a whole contains the mouse rather than the set of tick marks.
-        """
-        inside, info = self._default_contains(mouseevent)
-        if inside is not None:
-            return inside, info
-        return False, {}
-
-    def set_pad(self, val):
-        """
-        Set the tick label pad in points
-
-        Parameters
-        ----------
-        val : float
-        """
-        self._apply_params(pad=val)
-        self.stale = True
-
-    def get_pad(self):
-        'Get the value of the tick label pad in points'
-        return self._base_pad
-
-    def _get_text1(self):
-        'Get the default Text 1 instance'
-        pass
-
-    def _get_text2(self):
-        'Get the default Text 2 instance'
-        pass
-
-    def _get_tick1line(self):
-        'Get the default line2D instance for tick1'
-        pass
-
-    def _get_tick2line(self):
-        'Get the default line2D instance for tick2'
-        pass
-
-    def _get_gridline(self):
-        'Get the default grid Line2d instance for this tick'
-        pass
-
-    def get_loc(self):
-        'Return the tick location (data coords) as a scalar'
-        return self._loc
-
-    @martist.allow_rasterization
-    def draw(self, renderer):
-        if not self.get_visible():
-            self.stale = False
-            return
-        renderer.open_group(self.__name__, gid=self.get_gid())
-        for artist in [self.gridline, self.tick1line, self.tick2line,
-                       self.label1, self.label2]:
-            artist.draw(renderer)
-        renderer.close_group(self.__name__)
-        self.stale = False
-
-    def set_label1(self, s):
-        """
-        Set the label1 text.
-
-        Parameters
-        ----------
-        s : str
-        """
-        self.label1.set_text(s)
-        self.stale = True
-
-    set_label = set_label1
-
-    def set_label2(self, s):
-        """
-        Set the label2 text.
-
-        Parameters
-        ----------
-        s : str
-        """
-        self.label2.set_text(s)
-        self.stale = True
-
-    def _set_artist_props(self, a):
-        a.set_figure(self.figure)
-
-    def get_view_interval(self):
-        """
-        Return the view limits ``(min, max)`` of the axis the tick belongs to.
-        """
-        raise NotImplementedError('Derived must override')
-
-    def _apply_params(self, **kw):
-        for name, target in [("gridOn", self.gridline),
-                               ("tick1On", self.tick1line),
-                               ("tick2On", self.tick2line),
-                               ("label1On", self.label1),
-                               ("label2On", self.label2)]:
-            if name in kw:
-                target.set_visible(kw.pop(name))
-        if any(k in kw for k in ['size', 'width', 'pad', 'tickdir']):
-            self._size = kw.pop('size', self._size)
-            # Width could be handled outside this block, but it is
-            # convenient to leave it here.
-            self._width = kw.pop('width', self._width)
-            self._base_pad = kw.pop('pad', self._base_pad)
-            # apply_tickdir uses _size and _base_pad to make _pad,
-            # and also makes _tickmarkers.
-            self.apply_tickdir(kw.pop('tickdir', self._tickdir))
-            self.tick1line.set_marker(self._tickmarkers[0])
-            self.tick2line.set_marker(self._tickmarkers[1])
-            for line in (self.tick1line, self.tick2line):
-                line.set_markersize(self._size)
-                line.set_markeredgewidth(self._width)
-            # _get_text1_transform uses _pad from apply_tickdir.
-            trans = self._get_text1_transform()[0]
-            self.label1.set_transform(trans)
-            trans = self._get_text2_transform()[0]
-            self.label2.set_transform(trans)
-        tick_kw = {k: v for k, v in kw.items() if k in ['color', 'zorder']}
-        self.tick1line.set(**tick_kw)
-        self.tick2line.set(**tick_kw)
-        for k, v in tick_kw.items():
-            setattr(self, '_' + k, v)
-
-        if 'labelrotation' in kw:
-            self._set_labelrotation(kw.pop('labelrotation'))
-            self.label1.set(rotation=self._labelrotation[1])
-            self.label2.set(rotation=self._labelrotation[1])
-
-        label_kw = {k[5:]: v for k, v in kw.items()
-                    if k in ['labelsize', 'labelcolor']}
-        self.label1.set(**label_kw)
-        self.label2.set(**label_kw)
-        for k, v in label_kw.items():
-            # for labelsize the text objects covert str ('small')
-            # -> points. grab the integer from the `Text` object
-            # instead of saving the string representation
-            v = getattr(self.label1, 'get_' + k)()
-            setattr(self, '_label' + k, v)
-
-        grid_kw = {k[5:]: v for k, v in kw.items()
-                   if k in _gridline_param_names}
-        self.gridline.set(**grid_kw)
-        for k, v in grid_kw.items():
-            setattr(self, '_grid_' + k, v)
-
-    def update_position(self, loc):
-        'Set the location of tick in data coords with scalar *loc*'
-        raise NotImplementedError('Derived must override')
-
-    def _get_text1_transform(self):
-        raise NotImplementedError('Derived must override')
-
-    def _get_text2_transform(self):
-        raise NotImplementedError('Derived must override')
-
-
-class XTick(Tick):
-    """
-    Contains all the Artists needed to make an x tick - the tick line,
-    the label text and the grid line
-    """
-    __name__ = 'xtick'
-
-    def _get_text1_transform(self):
-        return self.axes.get_xaxis_text1_transform(self._pad)
-
-    def _get_text2_transform(self):
-        return self.axes.get_xaxis_text2_transform(self._pad)
-
-    def apply_tickdir(self, tickdir):
-        if tickdir is None:
-            tickdir = rcParams['%s.direction' % self.__name__.lower()]
-        self._tickdir = tickdir
-
-        if self._tickdir == 'in':
-            self._tickmarkers = (mlines.TICKUP, mlines.TICKDOWN)
-        elif self._tickdir == 'inout':
-            self._tickmarkers = ('|', '|')
-        else:
-            self._tickmarkers = (mlines.TICKDOWN, mlines.TICKUP)
-        self._pad = self._base_pad + self.get_tick_padding()
-        self.stale = True
-
-    def _get_text1(self):
-        'Get the default Text instance'
-        # the y loc is 3 points below the min of y axis
-        # get the affine as an a, b, c, d, tx, ty list
-        # x in data coords, y in axes coords
-        trans, vert, horiz = self._get_text1_transform()
-        t = mtext.Text(
-            x=0, y=0,
-            fontproperties=font_manager.FontProperties(size=self._labelsize),
-            color=self._labelcolor,
-            verticalalignment=vert,
-            horizontalalignment=horiz,
-            )
-        t.set_transform(trans)
-        self._set_artist_props(t)
-        return t
-
-    def _get_text2(self):
-        'Get the default Text 2 instance'
-        # x in data coords, y in axes coords
-        trans, vert, horiz = self._get_text2_transform()
-        t = mtext.Text(
-            x=0, y=1,
-            fontproperties=font_manager.FontProperties(size=self._labelsize),
-            color=self._labelcolor,
-            verticalalignment=vert,
-            horizontalalignment=horiz,
-            )
-        t.set_transform(trans)
-        self._set_artist_props(t)
-        return t
-
-    def _get_tick1line(self):
-        'Get the default line2D instance'
-        # x in data coords, y in axes coords
-        l = mlines.Line2D(xdata=(0,), ydata=(0,), color=self._color,
-                          linestyle='None', marker=self._tickmarkers[0],
-                          markersize=self._size,
-                          markeredgewidth=self._width, zorder=self._zorder)
-        l.set_transform(self.axes.get_xaxis_transform(which='tick1'))
-        self._set_artist_props(l)
-        return l
-
-    def _get_tick2line(self):
-        'Get the default line2D instance'
-        # x in data coords, y in axes coords
-        l = mlines.Line2D(xdata=(0,), ydata=(1,),
-                          color=self._color,
-                          linestyle='None',
-                          marker=self._tickmarkers[1],
-                          markersize=self._size,
-                          markeredgewidth=self._width,
-                          zorder=self._zorder)
-
-        l.set_transform(self.axes.get_xaxis_transform(which='tick2'))
-        self._set_artist_props(l)
-        return l
-
-    def _get_gridline(self):
-        'Get the default line2D instance'
-        # x in data coords, y in axes coords
-        l = mlines.Line2D(xdata=(0.0, 0.0), ydata=(0, 1.0),
-                          color=self._grid_color,
-                          linestyle=self._grid_linestyle,
-                          linewidth=self._grid_linewidth,
-                          alpha=self._grid_alpha,
-                          markersize=0,
-                          **self._grid_kw)
-        l.set_transform(self.axes.get_xaxis_transform(which='grid'))
-        l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS
-        self._set_artist_props(l)
-
-        return l
-
-    def update_position(self, loc):
-        """Set the location of tick in data coords with scalar *loc*."""
-        self.tick1line.set_xdata((loc,))
-        self.tick2line.set_xdata((loc,))
-        self.gridline.set_xdata((loc,))
-        self.label1.set_x(loc)
-        self.label2.set_x(loc)
-        self._loc = loc
-        self.stale = True
-
-    def get_view_interval(self):
-        # docstring inherited
-        return self.axes.viewLim.intervalx
-
-
-class YTick(Tick):
-    """
-    Contains all the Artists needed to make a Y tick - the tick line,
-    the label text and the grid line
-    """
-    __name__ = 'ytick'
-
-    def _get_text1_transform(self):
-        return self.axes.get_yaxis_text1_transform(self._pad)
-
-    def _get_text2_transform(self):
-        return self.axes.get_yaxis_text2_transform(self._pad)
-
-    def apply_tickdir(self, tickdir):
-        if tickdir is None:
-            tickdir = rcParams['%s.direction' % self.__name__.lower()]
-        self._tickdir = tickdir
-
-        if self._tickdir == 'in':
-            self._tickmarkers = (mlines.TICKRIGHT, mlines.TICKLEFT)
-        elif self._tickdir == 'inout':
-            self._tickmarkers = ('_', '_')
-        else:
-            self._tickmarkers = (mlines.TICKLEFT, mlines.TICKRIGHT)
-        self._pad = self._base_pad + self.get_tick_padding()
-        self.stale = True
-
-    # how far from the y axis line the right of the ticklabel are
-    def _get_text1(self):
-        'Get the default Text instance'
-        # x in axes coords, y in data coords
-        trans, vert, horiz = self._get_text1_transform()
-        t = mtext.Text(
-            x=0, y=0,
-            fontproperties=font_manager.FontProperties(size=self._labelsize),
-            color=self._labelcolor,
-            verticalalignment=vert,
-            horizontalalignment=horiz,
-            )
-        t.set_transform(trans)
-        self._set_artist_props(t)
-        return t
-
-    def _get_text2(self):
-        'Get the default Text instance'
-        # x in axes coords, y in data coords
-        trans, vert, horiz = self._get_text2_transform()
-        t = mtext.Text(
-            x=1, y=0,
-            fontproperties=font_manager.FontProperties(size=self._labelsize),
-            color=self._labelcolor,
-            verticalalignment=vert,
-            horizontalalignment=horiz,
-            )
-        t.set_transform(trans)
-        self._set_artist_props(t)
-        return t
-
-    def _get_tick1line(self):
-        'Get the default line2D instance'
-        # x in axes coords, y in data coords
-
-        l = mlines.Line2D((0,), (0,),
-                          color=self._color,
-                          marker=self._tickmarkers[0],
-                          linestyle='None',
-                          markersize=self._size,
-                          markeredgewidth=self._width,
-                          zorder=self._zorder)
-        l.set_transform(self.axes.get_yaxis_transform(which='tick1'))
-        self._set_artist_props(l)
-        return l
-
-    def _get_tick2line(self):
-        'Get the default line2D instance'
-        # x in axes coords, y in data coords
-        l = mlines.Line2D((1,), (0,),
-                          color=self._color,
-                          marker=self._tickmarkers[1],
-                          linestyle='None',
-                          markersize=self._size,
-                          markeredgewidth=self._width,
-                          zorder=self._zorder)
-        l.set_transform(self.axes.get_yaxis_transform(which='tick2'))
-        self._set_artist_props(l)
-        return l
-
-    def _get_gridline(self):
-        'Get the default line2D instance'
-        # x in axes coords, y in data coords
-        l = mlines.Line2D(xdata=(0, 1), ydata=(0, 0),
-                          color=self._grid_color,
-                          linestyle=self._grid_linestyle,
-                          linewidth=self._grid_linewidth,
-                          alpha=self._grid_alpha,
-                          markersize=0,
-                          **self._grid_kw)
-        l.set_transform(self.axes.get_yaxis_transform(which='grid'))
-        l.get_path()._interpolation_steps = GRIDLINE_INTERPOLATION_STEPS
-        self._set_artist_props(l)
-        return l
-
-    def update_position(self, loc):
-        """Set the location of tick in data coords with scalar *loc*."""
-        self.tick1line.set_ydata((loc,))
-        self.tick2line.set_ydata((loc,))
-        self.gridline.set_ydata((loc,))
-        self.label1.set_y(loc)
-        self.label2.set_y(loc)
-        self._loc = loc
-        self.stale = True
-
-    def get_view_interval(self):
-        # docstring inherited
-        return self.axes.viewLim.intervaly
-
-
-class Ticker:
-    """
-    A container for the objects defining tick position and format.
-
-    Attributes
-    ----------
-    locator : `matplotlib.ticker.Locator` subclass
-        Determines the positions of the ticks.
-    formatter : `matplotlib.ticker.Formatter` subclass
-        Determines the format of the tick labels.
-    """
-
-    def __init__(self):
-        self._locator = None
-        self._formatter = None
-
-    @property
-    def locator(self):
-        return self._locator
-
-    @locator.setter
-    def locator(self, locator):
-        if not isinstance(locator, mticker.Locator):
-            cbook.warn_deprecated(
-                "3.2", message="Support for locators that do not subclass "
-                "matplotlib.ticker.Locator is deprecated since %(since)s and "
-                "support for them will be removed %(removal)s.")
-        self._locator = locator
-
-    @property
-    def formatter(self):
-        return self._formatter
-
-    @formatter.setter
-    def formatter(self, formatter):
-        if not isinstance(formatter, mticker.Formatter):
-            cbook.warn_deprecated(
-                "3.2", message="Support for formatters that do not subclass "
-                "matplotlib.ticker.Formatter is deprecated since %(since)s "
-                "and support for them will be removed %(removal)s.")
-        self._formatter = formatter
-
-
-class _LazyTickList:
-    """
-    A descriptor for lazy instantiation of tick lists.
-
-    See comment above definition of the ``majorTicks`` and ``minorTicks``
-    attributes.
-    """
-
-    def __init__(self, major):
-        self._major = major
-
-    def __get__(self, instance, cls):
-        if instance is None:
-            return self
-        else:
-            # instance._get_tick() can itself try to access the majorTicks
-            # attribute (e.g. in certain projection classes which override
-            # e.g. get_xaxis_text1_transform).  In order to avoid infinite
-            # recursion, first set the majorTicks on the instance to an empty
-            # list, then create the tick and append it.
-            if self._major:
-                instance.majorTicks = []
-                tick = instance._get_tick(major=True)
-                instance.majorTicks.append(tick)
-                return instance.majorTicks
-            else:
-                instance.minorTicks = []
-                tick = instance._get_tick(major=False)
-                instance.minorTicks.append(tick)
-                return instance.minorTicks
-
-
-class Axis(martist.Artist):
-    """
-    Base class for `.XAxis` and `.YAxis`.
-
-    Attributes
-    ----------
-    isDefault_label : bool
-
-    axes : `matplotlib.axes.Axes`
-        The `~.axes.Axes` to which the Axis belongs.
-    major : `matplotlib.axis.Ticker`
-        Determines the major tick positions and their label format.
-    minor : `matplotlib.axis.Ticker`
-        Determines the minor tick positions and their label format.
-    callbacks : `matplotlib.cbook.CallbackRegistry`
-
-    label : `.Text`
-        The axis label.
-    labelpad : float
-        The distance between the axis label and the tick labels.
-        Defaults to :rc:`axes.labelpad` = 4.
-    offsetText : `.Text`
-        A `.Text` object containing the data offset of the ticks (if any).
-    pickradius : float
-        The acceptance radius for containment tests. See also `.Axis.contains`.
-    majorTicks : list of `.Tick`
-        The major ticks.
-    minorTicks : list of `.Tick`
-        The minor ticks.
-    """
-    OFFSETTEXTPAD = 3
-
-    def __str__(self):
-        return "{}({},{})".format(
-            type(self).__name__, *self.axes.transAxes.transform((0, 0)))
-
-    def __init__(self, axes, pickradius=15):
-        """
-        Parameters
-        ----------
-        axes : `matplotlib.axes.Axes`
-            The `~.axes.Axes` to which the created Axis belongs.
-        pickradius : float
-            The acceptance radius for containment tests. See also
-            `.Axis.contains`.
-        """
-        martist.Artist.__init__(self)
-        self._remove_overlapping_locs = True
-
-        self.set_figure(axes.figure)
-
-        self.isDefault_label = True
-
-        self.axes = axes
-        self.major = Ticker()
-        self.minor = Ticker()
-        self.callbacks = cbook.CallbackRegistry()
-
-        self._autolabelpos = True
-        self._smart_bounds = False  # Deprecated in 3.2
-
-        self.label = self._get_label()
-        self.labelpad = rcParams['axes.labelpad']
-        self.offsetText = self._get_offset_text()
-
-        self.pickradius = pickradius
-
-        # Initialize here for testing; later add API
-        self._major_tick_kw = dict()
-        self._minor_tick_kw = dict()
-
-        self.cla()
-        self._set_scale('linear')
-
-    # During initialization, Axis objects often create ticks that are later
-    # unused; this turns out to be a very slow step.  Instead, use a custom
-    # descriptor to make the tick lists lazy and instantiate them as needed.
-    majorTicks = _LazyTickList(major=True)
-    minorTicks = _LazyTickList(major=False)
-
-    def get_remove_overlapping_locs(self):
-        return self._remove_overlapping_locs
-
-    def set_remove_overlapping_locs(self, val):
-        self._remove_overlapping_locs = bool(val)
-
-    remove_overlapping_locs = property(
-        get_remove_overlapping_locs, set_remove_overlapping_locs,
-        doc=('If minor ticker locations that overlap with major '
-             'ticker locations should be trimmed.'))
-
-    def set_label_coords(self, x, y, transform=None):
-        """
-        Set the coordinates of the label.
-
-        By default, the x coordinate of the y label and the y coordinate of the
-        x label are determined by the tick label bounding boxes, but this can
-        lead to poor alignment of multiple labels if there are multiple axes.
-
-        You can also specify the coordinate system of the label with the
-        transform.  If None, the default coordinate system will be the axes
-        coordinate system: (0, 0) is bottom left, (0.5, 0.5) is center, etc.
-        """
-        self._autolabelpos = False
-        if transform is None:
-            transform = self.axes.transAxes
-
-        self.label.set_transform(transform)
-        self.label.set_position((x, y))
-        self.stale = True
-
-    def get_transform(self):
-        return self._scale.get_transform()
-
-    def get_scale(self):
-        return self._scale.name
-
-    def _set_scale(self, value, **kwargs):
-        self._scale = mscale.scale_factory(value, self, **kwargs)
-        self._scale.set_default_locators_and_formatters(self)
-
-        self.isDefault_majloc = True
-        self.isDefault_minloc = True
-        self.isDefault_majfmt = True
-        self.isDefault_minfmt = True
-
-    def limit_range_for_scale(self, vmin, vmax):
-        return self._scale.limit_range_for_scale(vmin, vmax, self.get_minpos())
-
-    def get_children(self):
-        return [self.label, self.offsetText,
-                *self.get_major_ticks(), *self.get_minor_ticks()]
-
-    def cla(self):
-        """Clear this axis."""
-
-        self.label.set_text('')  # self.set_label_text would change isDefault_
-
-        self._set_scale('linear')
-
-        # Clear the callback registry for this axis, or it may "leak"
-        self.callbacks = cbook.CallbackRegistry()
-
-        # whether the grids are on
-        self._gridOnMajor = (rcParams['axes.grid'] and
-                             rcParams['axes.grid.which'] in ('both', 'major'))
-        self._gridOnMinor = (rcParams['axes.grid'] and
-                             rcParams['axes.grid.which'] in ('both', 'minor'))
-
-        self.reset_ticks()
-
-        self.converter = None
-        self.units = None
-        self.set_units(None)
-        self.stale = True
-
-    def reset_ticks(self):
-        """
-        Re-initialize the major and minor Tick lists.
-
-        Each list starts with a single fresh Tick.
-        """
-        # Restore the lazy tick lists.
-        try:
-            del self.majorTicks
-        except AttributeError:
-            pass
-        try:
-            del self.minorTicks
-        except AttributeError:
-            pass
-        try:
-            self.set_clip_path(self.axes.patch)
-        except AttributeError:
-            pass
-
-    def set_tick_params(self, which='major', reset=False, **kw):
-        """
-        Set appearance parameters for ticks, ticklabels, and gridlines.
-
-        For documentation of keyword arguments, see
-        :meth:`matplotlib.axes.Axes.tick_params`.
-        """
-        dicts = []
-        if which == 'major' or which == 'both':
-            dicts.append(self._major_tick_kw)
-        if which == 'minor' or which == 'both':
-            dicts.append(self._minor_tick_kw)
-        kwtrans = self._translate_tick_kw(kw)
-
-        # this stashes the parameter changes so any new ticks will
-        # automatically get them
-        for d in dicts:
-            if reset:
-                d.clear()
-            d.update(kwtrans)
-
-        if reset:
-            self.reset_ticks()
-        else:
-            # apply the new kwargs to the existing ticks
-            if which == 'major' or which == 'both':
-                for tick in self.majorTicks:
-                    tick._apply_params(**kwtrans)
-            if which == 'minor' or which == 'both':
-                for tick in self.minorTicks:
-                    tick._apply_params(**kwtrans)
-            # special-case label color to also apply to the offset
-            # text
-            if 'labelcolor' in kwtrans:
-                self.offsetText.set_color(kwtrans['labelcolor'])
-
-        self.stale = True
-
-    @staticmethod
-    def _translate_tick_kw(kw):
-        # The following lists may be moved to a more accessible location.
-        kwkeys = ['size', 'width', 'color', 'tickdir', 'pad',
-                  'labelsize', 'labelcolor', 'zorder', 'gridOn',
-                  'tick1On', 'tick2On', 'label1On', 'label2On',
-                  'length', 'direction', 'left', 'bottom', 'right', 'top',
-                  'labelleft', 'labelbottom', 'labelright', 'labeltop',
-                  'labelrotation'] + _gridline_param_names
-        kwtrans = {}
-        if 'length' in kw:
-            kwtrans['size'] = kw.pop('length')
-        if 'direction' in kw:
-            kwtrans['tickdir'] = kw.pop('direction')
-        if 'rotation' in kw:
-            kwtrans['labelrotation'] = kw.pop('rotation')
-        if 'left' in kw:
-            kwtrans['tick1On'] = kw.pop('left')
-        if 'bottom' in kw:
-            kwtrans['tick1On'] = kw.pop('bottom')
-        if 'right' in kw:
-            kwtrans['tick2On'] = kw.pop('right')
-        if 'top' in kw:
-            kwtrans['tick2On'] = kw.pop('top')
-        if 'labelleft' in kw:
-            kwtrans['label1On'] = kw.pop('labelleft')
-        if 'labelbottom' in kw:
-            kwtrans['label1On'] = kw.pop('labelbottom')
-        if 'labelright' in kw:
-            kwtrans['label2On'] = kw.pop('labelright')
-        if 'labeltop' in kw:
-            kwtrans['label2On'] = kw.pop('labeltop')
-        if 'colors' in kw:
-            c = kw.pop('colors')
-            kwtrans['color'] = c
-            kwtrans['labelcolor'] = c
-        # Maybe move the checking up to the caller of this method.
-        for key in kw:
-            if key not in kwkeys:
-                raise ValueError(
-                    "keyword %s is not recognized; valid keywords are %s"
-                    % (key, kwkeys))
-            kwtrans.update(kw)
-        return kwtrans
-
-    def set_clip_path(self, clippath, transform=None):
-        martist.Artist.set_clip_path(self, clippath, transform)
-        for child in self.majorTicks + self.minorTicks:
-            child.set_clip_path(clippath, transform)
-        self.stale = True
-
-    def get_view_interval(self):
-        """Return the view limits ``(min, max)`` of this axis."""
-        raise NotImplementedError('Derived must override')
-
-    def set_view_interval(self, vmin, vmax, ignore=False):
-        """
-        Set the axis view limits.  This method is for internal use; Matplotlib
-        users should typically use e.g. `~Axes.set_xlim` and `~Axes.set_ylim`.
-
-        If *ignore* is False (the default), this method will never reduce the
-        preexisting view limits, only expand them if *vmin* or *vmax* are not
-        within them.  Moreover, the order of *vmin* and *vmax* does not matter;
-        the orientation of the axis will not change.
-
-        If *ignore* is True, the view limits will be set exactly to ``(vmin,
-        vmax)`` in that order.
-        """
-        raise NotImplementedError('Derived must override')
-
-    def get_data_interval(self):
-        """Return the Interval instance for this axis data limits."""
-        raise NotImplementedError('Derived must override')
-
-    def set_data_interval(self, vmin, vmax, ignore=False):
-        """
-        Set the axis data limits.  This method is for internal use.
-
-        If *ignore* is False (the default), this method will never reduce the
-        preexisting data limits, only expand them if *vmin* or *vmax* are not
-        within them.  Moreover, the order of *vmin* and *vmax* does not matter;
-        the orientation of the axis will not change.
-
-        If *ignore* is True, the data limits will be set exactly to ``(vmin,
-        vmax)`` in that order.
-        """
-        raise NotImplementedError('Derived must override')
-
-    def get_inverted(self):
-        """
-        Return whether the axis is oriented in the "inverse" direction.
-
-        The "normal" direction is increasing to the right for the x-axis and to
-        the top for the y-axis; the "inverse" direction is increasing to the
-        left for the x-axis and to the bottom for the y-axis.
-        """
-        low, high = self.get_view_interval()
-        return high < low
-
-    def set_inverted(self, inverted):
-        """
-        Set whether the axis is oriented in the "inverse" direction.
-
-        The "normal" direction is increasing to the right for the x-axis and to
-        the top for the y-axis; the "inverse" direction is increasing to the
-        left for the x-axis and to the bottom for the y-axis.
-        """
-        # Currently, must be implemented in subclasses using set_xlim/set_ylim
-        # rather than generically using set_view_interval, so that shared
-        # axes get updated as well.
-        raise NotImplementedError('Derived must override')
-
-    def set_default_intervals(self):
-        """
-        Set the default limits for the axis data and view interval if they
-        have not been not mutated yet.
-        """
-        # this is mainly in support of custom object plotting.  For
-        # example, if someone passes in a datetime object, we do not
-        # know automagically how to set the default min/max of the
-        # data and view limits.  The unit conversion AxisInfo
-        # interface provides a hook for custom types to register
-        # default limits through the AxisInfo.default_limits
-        # attribute, and the derived code below will check for that
-        # and use it if is available (else just use 0..1)
-
-    def _set_artist_props(self, a):
-        if a is None:
-            return
-        a.set_figure(self.figure)
-
-    @cbook.deprecated("3.1")
-    def iter_ticks(self):
-        """
-        Yield ``(Tick, location, label)`` tuples for major and minor ticks.
-        """
-        major_locs = self.get_majorticklocs()
-        major_labels = self.major.formatter.format_ticks(major_locs)
-        major_ticks = self.get_major_ticks(len(major_locs))
-        yield from zip(major_ticks, major_locs, major_labels)
-        minor_locs = self.get_minorticklocs()
-        minor_labels = self.minor.formatter.format_ticks(minor_locs)
-        minor_ticks = self.get_minor_ticks(len(minor_locs))
-        yield from zip(minor_ticks, minor_locs, minor_labels)
-
-    def get_ticklabel_extents(self, renderer):
-        """
-        Get the extents of the tick labels on either side
-        of the axes.
-        """
-
-        ticks_to_draw = self._update_ticks()
-        ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw,
-                                                                renderer)
-
-        if len(ticklabelBoxes):
-            bbox = mtransforms.Bbox.union(ticklabelBoxes)
-        else:
-            bbox = mtransforms.Bbox.from_extents(0, 0, 0, 0)
-        if len(ticklabelBoxes2):
-            bbox2 = mtransforms.Bbox.union(ticklabelBoxes2)
-        else:
-            bbox2 = mtransforms.Bbox.from_extents(0, 0, 0, 0)
-        return bbox, bbox2
-
-    @cbook.deprecated("3.2")
-    def set_smart_bounds(self, value):
-        """Set the axis to have smart bounds."""
-        self._smart_bounds = value
-        self.stale = True
-
-    @cbook.deprecated("3.2")
-    def get_smart_bounds(self):
-        """Return whether the axis has smart bounds."""
-        return self._smart_bounds
-
-    def _update_ticks(self):
-        """
-        Update ticks (position and labels) using the current data interval of
-        the axes.  Return the list of ticks that will be drawn.
-        """
-        major_locs = self.get_majorticklocs()
-        major_labels = self.major.formatter.format_ticks(major_locs)
-        major_ticks = self.get_major_ticks(len(major_locs))
-        self.major.formatter.set_locs(major_locs)
-        for tick, loc, label in zip(major_ticks, major_locs, major_labels):
-            tick.update_position(loc)
-            tick.set_label1(label)
-            tick.set_label2(label)
-        minor_locs = self.get_minorticklocs()
-        minor_labels = self.minor.formatter.format_ticks(minor_locs)
-        minor_ticks = self.get_minor_ticks(len(minor_locs))
-        self.minor.formatter.set_locs(minor_locs)
-        for tick, loc, label in zip(minor_ticks, minor_locs, minor_labels):
-            tick.update_position(loc)
-            tick.set_label1(label)
-            tick.set_label2(label)
-        ticks = [*major_ticks, *minor_ticks]
-
-        view_low, view_high = self.get_view_interval()
-        if view_low > view_high:
-            view_low, view_high = view_high, view_low
-
-        if self._smart_bounds and ticks:  # _smart_bounds is deprecated in 3.2
-            # handle inverted limits
-            data_low, data_high = sorted(self.get_data_interval())
-            locs = np.sort([tick.get_loc() for tick in ticks])
-            if data_low <= view_low:
-                # data extends beyond view, take view as limit
-                ilow = view_low
-            else:
-                # data stops within view, take best tick
-                good_locs = locs[locs <= data_low]
-                if len(good_locs):
-                    # last tick prior or equal to first data point
-                    ilow = good_locs[-1]
-                else:
-                    # No ticks (why not?), take first tick
-                    ilow = locs[0]
-            if data_high >= view_high:
-                # data extends beyond view, take view as limit
-                ihigh = view_high
-            else:
-                # data stops within view, take best tick
-                good_locs = locs[locs >= data_high]
-                if len(good_locs):
-                    # first tick after or equal to last data point
-                    ihigh = good_locs[0]
-                else:
-                    # No ticks (why not?), take last tick
-                    ihigh = locs[-1]
-            ticks = [tick for tick in ticks if ilow <= tick.get_loc() <= ihigh]
-
-        interval_t = self.get_transform().transform([view_low, view_high])
-
-        ticks_to_draw = []
-        for tick in ticks:
-            try:
-                loc_t = self.get_transform().transform(tick.get_loc())
-            except AssertionError:
-                # transforms.transform doesn't allow masked values but
-                # some scales might make them, so we need this try/except.
-                pass
-            else:
-                if mtransforms._interval_contains_close(interval_t, loc_t):
-                    ticks_to_draw.append(tick)
-
-        return ticks_to_draw
-
-    def _get_tick_bboxes(self, ticks, renderer):
-        """Return lists of bboxes for ticks' label1's and label2's."""
-        return ([tick.label1.get_window_extent(renderer)
-                 for tick in ticks if tick.label1.get_visible()],
-                [tick.label2.get_window_extent(renderer)
-                 for tick in ticks if tick.label2.get_visible()])
-
-    def get_tightbbox(self, renderer):
-        """
-        Return a bounding box that encloses the axis. It only accounts
-        tick labels, axis label, and offsetText.
-        """
-        if not self.get_visible():
-            return
-
-        ticks_to_draw = self._update_ticks()
-
-        self._update_label_position(renderer)
-
-        # go back to just this axis's tick labels
-        ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(
-                    ticks_to_draw, renderer)
-
-        self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2)
-        self.offsetText.set_text(self.major.formatter.get_offset())
-
-        bboxes = [
-            *(a.get_window_extent(renderer)
-              for a in [self.label, self.offsetText]
-              if a.get_visible()),
-            *ticklabelBoxes,
-            *ticklabelBoxes2,
-        ]
-        bboxes = [b for b in bboxes
-                  if 0 < b.width < np.inf and 0 < b.height < np.inf]
-        if bboxes:
-            return mtransforms.Bbox.union(bboxes)
-        else:
-            return None
-
-    def get_tick_padding(self):
-        values = []
-        if len(self.majorTicks):
-            values.append(self.majorTicks[0].get_tick_padding())
-        if len(self.minorTicks):
-            values.append(self.minorTicks[0].get_tick_padding())
-        return max(values, default=0)
-
-    @martist.allow_rasterization
-    def draw(self, renderer, *args, **kwargs):
-        'Draw the axis lines, grid lines, tick lines and labels'
-
-        if not self.get_visible():
-            return
-        renderer.open_group(__name__, gid=self.get_gid())
-
-        ticks_to_draw = self._update_ticks()
-        ticklabelBoxes, ticklabelBoxes2 = self._get_tick_bboxes(ticks_to_draw,
-                                                                renderer)
-
-        for tick in ticks_to_draw:
-            tick.draw(renderer)
-
-        # scale up the axis label box to also find the neighbors, not
-        # just the tick labels that actually overlap note we need a
-        # *copy* of the axis label box because we don't wan't to scale
-        # the actual bbox
-
-        self._update_label_position(renderer)
-
-        self.label.draw(renderer)
-
-        self._update_offset_text_position(ticklabelBoxes, ticklabelBoxes2)
-        self.offsetText.set_text(self.major.formatter.get_offset())
-        self.offsetText.draw(renderer)
-
-        renderer.close_group(__name__)
-        self.stale = False
-
-    def _get_label(self):
-        raise NotImplementedError('Derived must override')
-
-    def _get_offset_text(self):
-        raise NotImplementedError('Derived must override')
-
-    def get_gridlines(self):
-        'Return the grid lines as a list of Line2D instance'
-        ticks = self.get_major_ticks()
-        return cbook.silent_list('Line2D gridline',
-                                 [tick.gridline for tick in ticks])
-
-    def get_label(self):
-        'Return the axis label as a Text instance'
-        return self.label
-
-    def get_offset_text(self):
-        'Return the axis offsetText as a Text instance'
-        return self.offsetText
-
-    def get_pickradius(self):
-        'Return the depth of the axis used by the picker'
-        return self.pickradius
-
-    def get_majorticklabels(self):
-        'Return a list of Text instances for the major ticklabels.'
-        ticks = self.get_major_ticks()
-        labels1 = [tick.label1 for tick in ticks if tick.label1.get_visible()]
-        labels2 = [tick.label2 for tick in ticks if tick.label2.get_visible()]
-        return cbook.silent_list('Text major ticklabel', labels1 + labels2)
-
-    def get_minorticklabels(self):
-        'Return a list of Text instances for the minor ticklabels.'
-        ticks = self.get_minor_ticks()
-        labels1 = [tick.label1 for tick in ticks if tick.label1.get_visible()]
-        labels2 = [tick.label2 for tick in ticks if tick.label2.get_visible()]
-        return cbook.silent_list('Text minor ticklabel', labels1 + labels2)
-
-    def get_ticklabels(self, minor=False, which=None):
-        """
-        Get the tick labels as a list of `~matplotlib.text.Text` instances.
-
-        Parameters
-        ----------
-        minor : bool
-           If True return the minor ticklabels,
-           else return the major ticklabels
-
-        which : None, ('minor', 'major', 'both')
-           Overrides *minor*.
-
-           Selects which ticklabels to return
-
-        Returns
-        -------
-        ret : list
-           List of `~matplotlib.text.Text` instances.
-        """
-
-        if which is not None:
-            if which == 'minor':
-                return self.get_minorticklabels()
-            elif which == 'major':
-                return self.get_majorticklabels()
-            elif which == 'both':
-                return self.get_majorticklabels() + self.get_minorticklabels()
-            else:
-                cbook._check_in_list(['major', 'minor', 'both'], which=which)
-        if minor:
-            return self.get_minorticklabels()
-        return self.get_majorticklabels()
-
-    def get_majorticklines(self):
-        'Return the major tick lines as a list of Line2D instances'
-        lines = []
-        ticks = self.get_major_ticks()
-        for tick in ticks:
-            lines.append(tick.tick1line)
-            lines.append(tick.tick2line)
-        return cbook.silent_list('Line2D ticklines', lines)
-
-    def get_minorticklines(self):
-        'Return the minor tick lines as a list of Line2D instances'
-        lines = []
-        ticks = self.get_minor_ticks()
-        for tick in ticks:
-            lines.append(tick.tick1line)
-            lines.append(tick.tick2line)
-        return cbook.silent_list('Line2D ticklines', lines)
-
-    def get_ticklines(self, minor=False):
-        'Return the tick lines as a list of Line2D instances'
-        if minor:
-            return self.get_minorticklines()
-        return self.get_majorticklines()
-
-    def get_majorticklocs(self):
-        """Get the array of major tick locations in data coordinates."""
-        return self.major.locator()
-
-    def get_minorticklocs(self):
-        """Get the array of minor tick locations in data coordinates."""
-        # Remove minor ticks duplicating major ticks.
-        major_locs = self.major.locator()
-        minor_locs = self.minor.locator()
-        transform = self._scale.get_transform()
-        tr_minor_locs = transform.transform(minor_locs)
-        tr_major_locs = transform.transform(major_locs)
-        lo, hi = sorted(transform.transform(self.get_view_interval()))
-        # Use the transformed view limits as scale.  1e-5 is the default rtol
-        # for np.isclose.
-        tol = (hi - lo) * 1e-5
-        if self.remove_overlapping_locs:
-            minor_locs = [
-                loc for loc, tr_loc in zip(minor_locs, tr_minor_locs)
-                if ~np.isclose(tr_loc, tr_major_locs, atol=tol, rtol=0).any()]
-        return minor_locs
-
-    def get_ticklocs(self, minor=False):
-        """Get the array of tick locations in data coordinates."""
-        return self.get_minorticklocs() if minor else self.get_majorticklocs()
-
-    def get_ticks_direction(self, minor=False):
-        """
-        Get the tick directions as a numpy array
-
-        Parameters
-        ----------
-        minor : boolean
-            True to return the minor tick directions,
-            False to return the major tick directions,
-            Default is False
-
-        Returns
-        -------
-        numpy array of tick directions
-        """
-        if minor:
-            return np.array(
-                [tick._tickdir for tick in self.get_minor_ticks()])
-        else:
-            return np.array(
-                [tick._tickdir for tick in self.get_major_ticks()])
-
-    def _get_tick(self, major):
-        """Return the default tick instance."""
-        raise NotImplementedError('derived must override')
-
-    def _copy_tick_props(self, src, dest):
-        """Copy the properties from *src* tick to *dest* tick."""
-        if src is None or dest is None:
-            return
-        dest.label1.update_from(src.label1)
-        dest.label2.update_from(src.label2)
-        dest.tick1line.update_from(src.tick1line)
-        dest.tick2line.update_from(src.tick2line)
-        dest.gridline.update_from(src.gridline)
-
-    def get_label_text(self):
-        'Get the text of the label'
-        return self.label.get_text()
-
-    def get_major_locator(self):
-        'Get the locator of the major ticker'
-        return self.major.locator
-
-    def get_minor_locator(self):
-        'Get the locator of the minor ticker'
-        return self.minor.locator
-
-    def get_major_formatter(self):
-        'Get the formatter of the major ticker'
-        return self.major.formatter
-
-    def get_minor_formatter(self):
-        'Get the formatter of the minor ticker'
-        return self.minor.formatter
-
-    def get_major_ticks(self, numticks=None):
-        'Get the tick instances; grow as necessary.'
-        if numticks is None:
-            numticks = len(self.get_majorticklocs())
-
-        while len(self.majorTicks) < numticks:
-            # Update the new tick label properties from the old.
-            tick = self._get_tick(major=True)
-            self.majorTicks.append(tick)
-            tick.gridline.set_visible(self._gridOnMajor)
-            self._copy_tick_props(self.majorTicks[0], tick)
-
-        return self.majorTicks[:numticks]
-
-    def get_minor_ticks(self, numticks=None):
-        'Get the minor tick instances; grow as necessary.'
-        if numticks is None:
-            numticks = len(self.get_minorticklocs())
-
-        while len(self.minorTicks) < numticks:
-            # Update the new tick label properties from the old.
-            tick = self._get_tick(major=False)
-            self.minorTicks.append(tick)
-            tick.gridline.set_visible(self._gridOnMinor)
-            self._copy_tick_props(self.minorTicks[0], tick)
-
-        return self.minorTicks[:numticks]
-
-    def grid(self, b=None, which='major', **kwargs):
-        """
-        Configure the grid lines.
-
-        Parameters
-        ----------
-        b : bool or None
-            Whether to show the grid lines. If any *kwargs* are supplied,
-            it is assumed you want the grid on and *b* will be set to True.
-
-            If *b* is *None* and there are no *kwargs*, this toggles the
-            visibility of the lines.
-
-        which : {'major', 'minor', 'both'}
-            The grid lines to apply the changes on.
-
-        **kwargs : `.Line2D` properties
-            Define the line properties of the grid, e.g.::
-
-                grid(color='r', linestyle='-', linewidth=2)
-
-        """
-        if len(kwargs):
-            if not b and b is not None:  # something false-like but not None
-                cbook._warn_external('First parameter to grid() is false, '
-                                     'but line properties are supplied. The '
-                                     'grid will be enabled.')
-            b = True
-        which = which.lower()
-        cbook._check_in_list(['major', 'minor', 'both'], which=which)
-        gridkw = {'grid_' + item[0]: item[1] for item in kwargs.items()}
-
-        if which in ['minor', 'both']:
-            if b is None:
-                self._gridOnMinor = not self._gridOnMinor
-            else:
-                self._gridOnMinor = b
-            self.set_tick_params(which='minor', gridOn=self._gridOnMinor,
-                                 **gridkw)
-        if which in ['major', 'both']:
-            if b is None:
-                self._gridOnMajor = not self._gridOnMajor
-            else:
-                self._gridOnMajor = b
-            self.set_tick_params(which='major', gridOn=self._gridOnMajor,
-                                 **gridkw)
-        self.stale = True
-
-    def update_units(self, data):
-        """
-        Introspect *data* for units converter and update the
-        axis.converter instance if necessary. Return *True*
-        if *data* is registered for unit conversion.
-        """
-        converter = munits.registry.get_converter(data)
-        if converter is None:
-            return False
-
-        neednew = self.converter != converter
-        self.converter = converter
-        default = self.converter.default_units(data, self)
-        if default is not None and self.units is None:
-            self.set_units(default)
-
-        if neednew:
-            self._update_axisinfo()
-        self.stale = True
-        return True
-
-    def _update_axisinfo(self):
-        """
-        Check the axis converter for the stored units to see if the
-        axis info needs to be updated.
-        """
-        if self.converter is None:
-            return
-
-        info = self.converter.axisinfo(self.units, self)
-
-        if info is None:
-            return
-        if info.majloc is not None and \
-           self.major.locator != info.majloc and self.isDefault_majloc:
-            self.set_major_locator(info.majloc)
-            self.isDefault_majloc = True
-        if info.minloc is not None and \
-           self.minor.locator != info.minloc and self.isDefault_minloc:
-            self.set_minor_locator(info.minloc)
-            self.isDefault_minloc = True
-        if info.majfmt is not None and \
-           self.major.formatter != info.majfmt and self.isDefault_majfmt:
-            self.set_major_formatter(info.majfmt)
-            self.isDefault_majfmt = True
-        if info.minfmt is not None and \
-           self.minor.formatter != info.minfmt and self.isDefault_minfmt:
-            self.set_minor_formatter(info.minfmt)
-            self.isDefault_minfmt = True
-        if info.label is not None and self.isDefault_label:
-            self.set_label_text(info.label)
-            self.isDefault_label = True
-
-        self.set_default_intervals()
-
-    def have_units(self):
-        return self.converter is not None or self.units is not None
-
-    def convert_units(self, x):
-        # If x is natively supported by Matplotlib, doesn't need converting
-        if munits._is_natively_supported(x):
-            return x
-
-        if self.converter is None:
-            self.converter = munits.registry.get_converter(x)
-
-        if self.converter is None:
-            return x
-        try:
-            ret = self.converter.convert(x, self.units, self)
-        except Exception as e:
-            raise munits.ConversionError('Failed to convert value(s) to axis '
-                                         f'units: {x!r}') from e
-        return ret
-
-    def set_units(self, u):
-        """
-        Set the units for axis.
-
-        Parameters
-        ----------
-        u : units tag
-        """
-        if u == self.units:
-            return
-        self.units = u
-        self._update_axisinfo()
-        self.callbacks.process('units')
-        self.callbacks.process('units finalize')
-        self.stale = True
-
-    def get_units(self):
-        """Return the units for axis."""
-        return self.units
-
-    def set_label_text(self, label, fontdict=None, **kwargs):
-        """
-        Set the text value of the axis label.
-
-        Parameters
-        ----------
-        label : str
-            Text string.
-        fontdict : dict
-            Text properties.
-        **kwargs
-            Merged into fontdict.
-        """
-        self.isDefault_label = False
-        self.label.set_text(label)
-        if fontdict is not None:
-            self.label.update(fontdict)
-        self.label.update(kwargs)
-        self.stale = True
-        return self.label
-
-    def set_major_formatter(self, formatter):
-        """
-        Set the formatter of the major ticker.
-
-        Parameters
-        ----------
-        formatter : `~matplotlib.ticker.Formatter`
-        """
-        cbook._check_isinstance(mticker.Formatter, formatter=formatter)
-        self.isDefault_majfmt = False
-        self.major.formatter = formatter
-        formatter.set_axis(self)
-        self.stale = True
-
-    def set_minor_formatter(self, formatter):
-        """
-        Set the formatter of the minor ticker.
-
-        Parameters
-        ----------
-        formatter : `~matplotlib.ticker.Formatter`
-        """
-        cbook._check_isinstance(mticker.Formatter, formatter=formatter)
-        self.isDefault_minfmt = False
-        self.minor.formatter = formatter
-        formatter.set_axis(self)
-        self.stale = True
-
-    def set_major_locator(self, locator):
-        """
-        Set the locator of the major ticker.
-
-        Parameters
-        ----------
-        locator : `~matplotlib.ticker.Locator`
-        """
-        cbook._check_isinstance(mticker.Locator, locator=locator)
-        self.isDefault_majloc = False
-        self.major.locator = locator
-        if self.major.formatter:
-            self.major.formatter._set_locator(locator)
-        locator.set_axis(self)
-        self.stale = True
-
-    def set_minor_locator(self, locator):
-        """
-        Set the locator of the minor ticker.
-
-        Parameters
-        ----------
-        locator : `~matplotlib.ticker.Locator`
-        """
-        cbook._check_isinstance(mticker.Locator, locator=locator)
-        self.isDefault_minloc = False
-        self.minor.locator = locator
-        if self.minor.formatter:
-            self.minor.formatter._set_locator(locator)
-        locator.set_axis(self)
-        self.stale = True
-
-    def set_pickradius(self, pickradius):
-        """
-        Set the depth of the axis used by the picker.
-
-        Parameters
-        ----------
-        pickradius :  float
-        """
-        self.pickradius = pickradius
-
-    def set_ticklabels(self, ticklabels, *args, minor=False, **kwargs):
-        r"""
-        Set the text values of the tick labels.
-
-        Parameters
-        ----------
-        ticklabels : sequence of str or of `Text`\s
-            List of texts for tick labels; must include values for non-visible
-            labels.
-        minor : bool
-            If True, set minor ticks instead of major ticks.
-        **kwargs
-            Text properties.
-
-        Returns
-        -------
-        labels : list of `Text`\s
-            For each tick, includes ``tick.label1`` if it is visible, then
-            ``tick.label2`` if it is visible, in that order.
-        """
-        if args:
-            cbook.warn_deprecated(
-                "3.1", message="Additional positional arguments to "
-                "set_ticklabels are ignored, and deprecated since Matplotlib "
-                "3.1; passing them will raise a TypeError in Matplotlib 3.3.")
-        get_labels = []
-        for t in ticklabels:
-            # try calling get_text() to check whether it is Text object
-            # if it is Text, get label content
-            try:
-                get_labels.append(t.get_text())
-            # otherwise add the label to the list directly
-            except AttributeError:
-                get_labels.append(t)
-        # replace the ticklabels list with the processed one
-        ticklabels = get_labels
-
-        if minor:
-            self.set_minor_formatter(mticker.FixedFormatter(ticklabels))
-            ticks = self.get_minor_ticks()
-        else:
-            self.set_major_formatter(mticker.FixedFormatter(ticklabels))
-            ticks = self.get_major_ticks()
-        ret = []
-        for tick_label, tick in zip(ticklabels, ticks):
-            # deal with label1
-            tick.label1.set_text(tick_label)
-            tick.label1.update(kwargs)
-            # deal with label2
-            tick.label2.set_text(tick_label)
-            tick.label2.update(kwargs)
-            # only return visible tick labels
-            if tick.label1.get_visible():
-                ret.append(tick.label1)
-            if tick.label2.get_visible():
-                ret.append(tick.label2)
-
-        self.stale = True
-        return ret
-
-    @cbook._make_keyword_only("3.2", "minor")
-    def set_ticks(self, ticks, minor=False):
-        """
-        Set the locations of the tick marks from sequence ticks
-
-        Parameters
-        ----------
-        ticks : sequence of floats
-        minor : bool
-        """
-        # XXX if the user changes units, the information will be lost here
-        ticks = self.convert_units(ticks)
-        if len(ticks) > 1:
-            xleft, xright = self.get_view_interval()
-            if xright > xleft:
-                self.set_view_interval(min(ticks), max(ticks))
-            else:
-                self.set_view_interval(max(ticks), min(ticks))
-        if minor:
-            self.set_minor_locator(mticker.FixedLocator(ticks))
-            return self.get_minor_ticks(len(ticks))
-        else:
-            self.set_major_locator(mticker.FixedLocator(ticks))
-            return self.get_major_ticks(len(ticks))
-
-    def _get_tick_boxes_siblings(self, xdir, renderer):
-        """
-        Get the bounding boxes for this `.axis` and its siblings
-        as set by `.Figure.align_xlabels` or  `.Figure.align_ylablels`.
-
-        By default it just gets bboxes for self.
-        """
-        raise NotImplementedError('Derived must override')
-
-    def _update_label_position(self, renderer):
-        """
-        Update the label position based on the bounding box enclosing
-        all the ticklabels and axis spine.
-        """
-        raise NotImplementedError('Derived must override')
-
-    def _update_offset_text_position(self, bboxes, bboxes2):
-        """
-        Update the offset text position based on the sequence of bounding
-        boxes of all the ticklabels.
-        """
-        raise NotImplementedError('Derived must override')
-
-    def pan(self, numsteps):
-        """Pan by *numsteps* (can be positive or negative)."""
-        self.major.locator.pan(numsteps)
-
-    def zoom(self, direction):
-        """Zoom in/out on axis; if *direction* is >0 zoom in, else zoom out."""
-        self.major.locator.zoom(direction)
-
-    def axis_date(self, tz=None):
-        """
-        Sets up axis ticks and labels treating data along this axis as dates.
-
-        Parameters
-        ----------
-        tz : tzinfo or str or None
-            The timezone used to create date labels.
-        """
-        # By providing a sample datetime instance with the desired timezone,
-        # the registered converter can be selected, and the "units" attribute,
-        # which is the timezone, can be set.
-        if isinstance(tz, str):
-            import dateutil.tz
-            tz = dateutil.tz.gettz(tz)
-        self.update_units(datetime.datetime(2009, 1, 1, 0, 0, 0, 0, tz))
-
-    def get_tick_space(self):
-        """Return the estimated number of ticks that can fit on the axis."""
-        # Must be overridden in the subclass
-        raise NotImplementedError()
-
-    def _get_ticks_position(self):
-        """
-        Helper for `XAxis.get_ticks_position` and `YAxis.get_ticks_position`.
-
-        Check the visibility of tick1line, label1, tick2line, and label2 on
-        the first major and the first minor ticks, and return
-
-        - 1 if only tick1line and label1 are visible (which corresponds to
-          "bottom" for the x-axis and "left" for the y-axis);
-        - 2 if only tick2line and label2 are visible (which corresponds to
-          "top" for the x-axis and "right" for the y-axis);
-        - "default" if only tick1line, tick2line and label1 are visible;
-        - "unknown" otherwise.
-        """
-        major = self.majorTicks[0]
-        minor = self.minorTicks[0]
-        if all(tick.tick1line.get_visible()
-               and not tick.tick2line.get_visible()
-               and tick.label1.get_visible()
-               and not tick.label2.get_visible()
-               for tick in [major, minor]):
-            return 1
-        elif all(tick.tick2line.get_visible()
-                 and not tick.tick1line.get_visible()
-                 and tick.label2.get_visible()
-                 and not tick.label1.get_visible()
-                 for tick in [major, minor]):
-            return 2
-        elif all(tick.tick1line.get_visible()
-                 and tick.tick2line.get_visible()
-                 and tick.label1.get_visible()
-                 and not tick.label2.get_visible()
-                 for tick in [major, minor]):
-            return "default"
-        else:
-            return "unknown"
-
-    def get_label_position(self):
-        """
-        Return the label position (top or bottom)
-        """
-        return self.label_position
-
-    def set_label_position(self, position):
-        """
-        Set the label position (top or bottom)
-
-        Parameters
-        ----------
-        position : {'top', 'bottom'}
-        """
-        raise NotImplementedError()
-
-    def get_minpos(self):
-        raise NotImplementedError()
-
-
-def _make_getset_interval(method_name, lim_name, attr_name):
-    """
-    Helper to generate ``get_{data,view}_interval`` and
-    ``set_{data,view}_interval`` implementations.
-    """
-
-    def getter(self):
-        # docstring inherited.
-        return getattr(getattr(self.axes, lim_name), attr_name)
-
-    def setter(self, vmin, vmax, ignore=False):
-        # docstring inherited.
-        if ignore:
-            setattr(getattr(self.axes, lim_name), attr_name, (vmin, vmax))
-        else:
-            oldmin, oldmax = getter(self)
-            if oldmin < oldmax:
-                setter(self, min(vmin, vmax, oldmin), max(vmin, vmax, oldmax),
-                       ignore=True)
-            else:
-                setter(self, max(vmin, vmax, oldmin), min(vmin, vmax, oldmax),
-                       ignore=True)
-        self.stale = True
-
-    getter.__name__ = f"get_{method_name}_interval"
-    setter.__name__ = f"set_{method_name}_interval"
-
-    return getter, setter
-
-
-class XAxis(Axis):
-    __name__ = 'xaxis'
-    axis_name = 'x'  #: Read-only name identifying the axis.
-
-    def contains(self, mouseevent):
-        """Test whether the mouse event occurred in the x axis.
-        """
-        inside, info = self._default_contains(mouseevent)
-        if inside is not None:
-            return inside, info
-
-        x, y = mouseevent.x, mouseevent.y
-        try:
-            trans = self.axes.transAxes.inverted()
-            xaxes, yaxes = trans.transform((x, y))
-        except ValueError:
-            return False, {}
-        (l, b), (r, t) = self.axes.transAxes.transform([(0, 0), (1, 1)])
-        inaxis = 0 <= xaxes <= 1 and (
-            b - self.pickradius < y < b or
-            t < y < t + self.pickradius)
-        return inaxis, {}
-
-    def _get_tick(self, major):
-        if major:
-            tick_kw = self._major_tick_kw
-        else:
-            tick_kw = self._minor_tick_kw
-        return XTick(self.axes, 0, '', major=major, **tick_kw)
-
-    def _get_label(self):
-        # x in axes coords, y in display coords (to be updated at draw
-        # time by _update_label_positions)
-        label = mtext.Text(x=0.5, y=0,
-                           fontproperties=font_manager.FontProperties(
-                               size=rcParams['axes.labelsize'],
-                               weight=rcParams['axes.labelweight']),
-                           color=rcParams['axes.labelcolor'],
-                           verticalalignment='top',
-                           horizontalalignment='center')
-
-        label.set_transform(mtransforms.blended_transform_factory(
-            self.axes.transAxes, mtransforms.IdentityTransform()))
-
-        self._set_artist_props(label)
-        self.label_position = 'bottom'
-        return label
-
-    def _get_offset_text(self):
-        # x in axes coords, y in display coords (to be updated at draw time)
-        offsetText = mtext.Text(x=1, y=0,
-                                fontproperties=font_manager.FontProperties(
-                                    size=rcParams['xtick.labelsize']),
-                                color=rcParams['xtick.color'],
-                                verticalalignment='top',
-                                horizontalalignment='right')
-        offsetText.set_transform(mtransforms.blended_transform_factory(
-            self.axes.transAxes, mtransforms.IdentityTransform())
-        )
-        self._set_artist_props(offsetText)
-        self.offset_text_position = 'bottom'
-        return offsetText
-
-    def set_label_position(self, position):
-        """
-        Set the label position (top or bottom)
-
-        Parameters
-        ----------
-        position : {'top', 'bottom'}
-        """
-        self.label.set_verticalalignment(cbook._check_getitem({
-            'top': 'baseline', 'bottom': 'top',
-        }, position=position))
-        self.label_position = position
-        self.stale = True
-
-    def _get_tick_boxes_siblings(self, renderer):
-        """
-        Get the bounding boxes for this `.axis` and its siblings
-        as set by `.Figure.align_xlabels` or  `.Figure.align_ylablels`.
-
-        By default it just gets bboxes for self.
-        """
-        bboxes = []
-        bboxes2 = []
-        # get the Grouper that keeps track of x-label groups for this figure
-        grp = self.figure._align_xlabel_grp
-        # if we want to align labels from other axes:
-        for nn, axx in enumerate(grp.get_siblings(self.axes)):
-            ticks_to_draw = axx.xaxis._update_ticks()
-            tlb, tlb2 = axx.xaxis._get_tick_bboxes(ticks_to_draw, renderer)
-            bboxes.extend(tlb)
-            bboxes2.extend(tlb2)
-        return bboxes, bboxes2
-
-    def _update_label_position(self, renderer):
-        """
-        Update the label position based on the bounding box enclosing
-        all the ticklabels and axis spine
-        """
-        if not self._autolabelpos:
-            return
-
-        # get bounding boxes for this axis and any siblings
-        # that have been set by `fig.align_xlabels()`
-        bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer)
-
-        x, y = self.label.get_position()
-        if self.label_position == 'bottom':
-            try:
-                spine = self.axes.spines['bottom']
-                spinebbox = spine.get_transform().transform_path(
-                    spine.get_path()).get_extents()
-            except KeyError:
-                # use axes if spine doesn't exist
-                spinebbox = self.axes.bbox
-            bbox = mtransforms.Bbox.union(bboxes + [spinebbox])
-            bottom = bbox.y0
-
-            self.label.set_position(
-                (x, bottom - self.labelpad * self.figure.dpi / 72)
-            )
-
-        else:
-            try:
-                spine = self.axes.spines['top']
-                spinebbox = spine.get_transform().transform_path(
-                    spine.get_path()).get_extents()
-            except KeyError:
-                # use axes if spine doesn't exist
-                spinebbox = self.axes.bbox
-            bbox = mtransforms.Bbox.union(bboxes2 + [spinebbox])
-            top = bbox.y1
-
-            self.label.set_position(
-                (x, top + self.labelpad * self.figure.dpi / 72)
-            )
-
-    def _update_offset_text_position(self, bboxes, bboxes2):
-        """
-        Update the offset_text position based on the sequence of bounding
-        boxes of all the ticklabels
-        """
-        x, y = self.offsetText.get_position()
-        if not len(bboxes):
-            bottom = self.axes.bbox.ymin
-        else:
-            bbox = mtransforms.Bbox.union(bboxes)
-            bottom = bbox.y0
-        self.offsetText.set_position(
-            (x, bottom - self.OFFSETTEXTPAD * self.figure.dpi / 72)
-        )
-
-    def get_text_heights(self, renderer):
-        """
-        Returns the amount of space one should reserve for text
-        above and below the axes.  Returns a tuple (above, below)
-        """
-        bbox, bbox2 = self.get_ticklabel_extents(renderer)
-        # MGDTODO: Need a better way to get the pad
-        padPixels = self.majorTicks[0].get_pad_pixels()
-
-        above = 0.0
-        if bbox2.height:
-            above += bbox2.height + padPixels
-        below = 0.0
-        if bbox.height:
-            below += bbox.height + padPixels
-
-        if self.get_label_position() == 'top':
-            above += self.label.get_window_extent(renderer).height + padPixels
-        else:
-            below += self.label.get_window_extent(renderer).height + padPixels
-        return above, below
-
-    def set_ticks_position(self, position):
-        """
-        Set the ticks position (top, bottom, both, default or none)
-        both sets the ticks to appear on both positions, but does not
-        change the tick labels.  'default' resets the tick positions to
-        the default: ticks on both positions, labels at bottom.  'none'
-        can be used if you don't want any ticks. 'none' and 'both'
-        affect only the ticks, not the labels.
-
-        Parameters
-        ----------
-        position : {'top', 'bottom', 'both', 'default', 'none'}
-        """
-        if position == 'top':
-            self.set_tick_params(which='both', top=True, labeltop=True,
-                                 bottom=False, labelbottom=False)
-        elif position == 'bottom':
-            self.set_tick_params(which='both', top=False, labeltop=False,
-                                 bottom=True, labelbottom=True)
-        elif position == 'both':
-            self.set_tick_params(which='both', top=True,
-                                 bottom=True)
-        elif position == 'none':
-            self.set_tick_params(which='both', top=False,
-                                 bottom=False)
-        elif position == 'default':
-            self.set_tick_params(which='both', top=True, labeltop=False,
-                                 bottom=True, labelbottom=True)
-        else:
-            raise ValueError("invalid position: %s" % position)
-        self.stale = True
-
-    def tick_top(self):
-        """
-        Move ticks and ticklabels (if present) to the top of the axes.
-        """
-        label = True
-        if 'label1On' in self._major_tick_kw:
-            label = (self._major_tick_kw['label1On']
-                     or self._major_tick_kw['label2On'])
-        self.set_ticks_position('top')
-        # If labels were turned off before this was called, leave them off.
-        self.set_tick_params(which='both', labeltop=label)
-
-    def tick_bottom(self):
-        """
-        Move ticks and ticklabels (if present) to the bottom of the axes.
-        """
-        label = True
-        if 'label1On' in self._major_tick_kw:
-            label = (self._major_tick_kw['label1On']
-                     or self._major_tick_kw['label2On'])
-        self.set_ticks_position('bottom')
-        # If labels were turned off before this was called, leave them off.
-        self.set_tick_params(which='both', labelbottom=label)
-
-    def get_ticks_position(self):
-        """
-        Return the ticks position ("top", "bottom", "default", or "unknown").
-        """
-        return {1: "bottom", 2: "top",
-                "default": "default", "unknown": "unknown"}[
-                    self._get_ticks_position()]
-
-    get_view_interval, set_view_interval = _make_getset_interval(
-        "view", "viewLim", "intervalx")
-    get_data_interval, set_data_interval = _make_getset_interval(
-        "data", "dataLim", "intervalx")
-
-    def get_minpos(self):
-        return self.axes.dataLim.minposx
-
-    def set_inverted(self, inverted):
-        # docstring inherited
-        a, b = self.get_view_interval()
-        # cast to bool to avoid bad interaction between python 3.8 and np.bool_
-        self.axes.set_xlim(sorted((a, b), reverse=bool(inverted)), auto=None)
-
-    def set_default_intervals(self):
-        # docstring inherited
-        xmin, xmax = 0., 1.
-        dataMutated = self.axes.dataLim.mutatedx()
-        viewMutated = self.axes.viewLim.mutatedx()
-        if not dataMutated or not viewMutated:
-            if self.converter is not None:
-                info = self.converter.axisinfo(self.units, self)
-                if info.default_limits is not None:
-                    valmin, valmax = info.default_limits
-                    xmin = self.converter.convert(valmin, self.units, self)
-                    xmax = self.converter.convert(valmax, self.units, self)
-            if not dataMutated:
-                self.axes.dataLim.intervalx = xmin, xmax
-            if not viewMutated:
-                self.axes.viewLim.intervalx = xmin, xmax
-        self.stale = True
-
-    def get_tick_space(self):
-        ends = self.axes.transAxes.transform([[0, 0], [1, 0]])
-        length = ((ends[1][0] - ends[0][0]) / self.axes.figure.dpi) * 72
-        tick = self._get_tick(True)
-        # There is a heuristic here that the aspect ratio of tick text
-        # is no more than 3:1
-        size = tick.label1.get_size() * 3
-        if size > 0:
-            return int(np.floor(length / size))
-        else:
-            return 2**31 - 1
-
-
-class YAxis(Axis):
-    __name__ = 'yaxis'
-    axis_name = 'y'  #: Read-only name identifying the axis.
-
-    def contains(self, mouseevent):
-        """Test whether the mouse event occurred in the y axis.
-
-        Returns *True* | *False*
-        """
-        inside, info = self._default_contains(mouseevent)
-        if inside is not None:
-            return inside, info
-
-        x, y = mouseevent.x, mouseevent.y
-        try:
-            trans = self.axes.transAxes.inverted()
-            xaxes, yaxes = trans.transform((x, y))
-        except ValueError:
-            return False, {}
-        (l, b), (r, t) = self.axes.transAxes.transform([(0, 0), (1, 1)])
-        inaxis = 0 <= yaxes <= 1 and (
-            l - self.pickradius < x < l or
-            r < x < r + self.pickradius)
-        return inaxis, {}
-
-    def _get_tick(self, major):
-        if major:
-            tick_kw = self._major_tick_kw
-        else:
-            tick_kw = self._minor_tick_kw
-        return YTick(self.axes, 0, '', major=major, **tick_kw)
-
-    def _get_label(self):
-        # x in display coords (updated by _update_label_position)
-        # y in axes coords
-        label = mtext.Text(x=0, y=0.5,
-                           # todo: get the label position
-                           fontproperties=font_manager.FontProperties(
-                               size=rcParams['axes.labelsize'],
-                               weight=rcParams['axes.labelweight']),
-                           color=rcParams['axes.labelcolor'],
-                           verticalalignment='bottom',
-                           horizontalalignment='center',
-                           rotation='vertical',
-                           rotation_mode='anchor')
-        label.set_transform(mtransforms.blended_transform_factory(
-            mtransforms.IdentityTransform(), self.axes.transAxes))
-
-        self._set_artist_props(label)
-        self.label_position = 'left'
-        return label
-
-    def _get_offset_text(self):
-        # x in display coords, y in axes coords (to be updated at draw time)
-        offsetText = mtext.Text(x=0, y=0.5,
-                                fontproperties=font_manager.FontProperties(
-                                    size=rcParams['ytick.labelsize']
-                                ),
-                                color=rcParams['ytick.color'],
-                                verticalalignment='baseline',
-                                horizontalalignment='left')
-        offsetText.set_transform(mtransforms.blended_transform_factory(
-            self.axes.transAxes, mtransforms.IdentityTransform())
-        )
-        self._set_artist_props(offsetText)
-        self.offset_text_position = 'left'
-        return offsetText
-
-    def set_label_position(self, position):
-        """
-        Set the label position (left or right)
-
-        Parameters
-        ----------
-        position : {'left', 'right'}
-        """
-        self.label.set_rotation_mode('anchor')
-        self.label.set_horizontalalignment('center')
-        self.label.set_verticalalignment(cbook._check_getitem({
-            'left': 'bottom', 'right': 'top',
-        }, position=position))
-        self.label_position = position
-        self.stale = True
-
-    def _get_tick_boxes_siblings(self, renderer):
-        """
-        Get the bounding boxes for this `.axis` and its siblings
-        as set by `.Figure.align_xlabels` or  `.Figure.align_ylablels`.
-
-        By default it just gets bboxes for self.
-        """
-        bboxes = []
-        bboxes2 = []
-        # get the Grouper that keeps track of y-label groups for this figure
-        grp = self.figure._align_ylabel_grp
-        # if we want to align labels from other axes:
-        for axx in grp.get_siblings(self.axes):
-            ticks_to_draw = axx.yaxis._update_ticks()
-            tlb, tlb2 = axx.yaxis._get_tick_bboxes(ticks_to_draw, renderer)
-            bboxes.extend(tlb)
-            bboxes2.extend(tlb2)
-        return bboxes, bboxes2
-
-    def _update_label_position(self, renderer):
-        """
-        Update the label position based on the bounding box enclosing
-        all the ticklabels and axis spine
-        """
-        if not self._autolabelpos:
-            return
-
-        # get bounding boxes for this axis and any siblings
-        # that have been set by `fig.align_ylabels()`
-        bboxes, bboxes2 = self._get_tick_boxes_siblings(renderer=renderer)
-
-        x, y = self.label.get_position()
-        if self.label_position == 'left':
-            try:
-                spine = self.axes.spines['left']
-                spinebbox = spine.get_transform().transform_path(
-                    spine.get_path()).get_extents()
-            except KeyError:
-                # use axes if spine doesn't exist
-                spinebbox = self.axes.bbox
-            bbox = mtransforms.Bbox.union(bboxes + [spinebbox])
-            left = bbox.x0
-            self.label.set_position(
-                (left - self.labelpad * self.figure.dpi / 72, y)
-            )
-
-        else:
-            try:
-                spine = self.axes.spines['right']
-                spinebbox = spine.get_transform().transform_path(
-                    spine.get_path()).get_extents()
-            except KeyError:
-                # use axes if spine doesn't exist
-                spinebbox = self.axes.bbox
-            bbox = mtransforms.Bbox.union(bboxes2 + [spinebbox])
-            right = bbox.x1
-
-            self.label.set_position(
-                (right + self.labelpad * self.figure.dpi / 72, y)
-            )
-
-    def _update_offset_text_position(self, bboxes, bboxes2):
-        """
-        Update the offset_text position based on the sequence of bounding
-        boxes of all the ticklabels
-        """
-        x, y = self.offsetText.get_position()
-        top = self.axes.bbox.ymax
-        self.offsetText.set_position(
-            (x, top + self.OFFSETTEXTPAD * self.figure.dpi / 72)
-        )
-
-    def set_offset_position(self, position):
-        """
-        Parameters
-        ----------
-        position : {'left', 'right'}
-        """
-        x, y = self.offsetText.get_position()
-        x = cbook._check_getitem({'left': 0, 'right': 1}, position=position)
-
-        self.offsetText.set_ha(position)
-        self.offsetText.set_position((x, y))
-        self.stale = True
-
-    def get_text_widths(self, renderer):
-        bbox, bbox2 = self.get_ticklabel_extents(renderer)
-        # MGDTODO: Need a better way to get the pad
-        padPixels = self.majorTicks[0].get_pad_pixels()
-
-        left = 0.0
-        if bbox.width:
-            left += bbox.width + padPixels
-        right = 0.0
-        if bbox2.width:
-            right += bbox2.width + padPixels
-
-        if self.get_label_position() == 'left':
-            left += self.label.get_window_extent(renderer).width + padPixels
-        else:
-            right += self.label.get_window_extent(renderer).width + padPixels
-        return left, right
-
-    def set_ticks_position(self, position):
-        """
-        Set the ticks position (left, right, both, default or none)
-        'both' sets the ticks to appear on both positions, but does not
-        change the tick labels.  'default' resets the tick positions to
-        the default: ticks on both positions, labels at left.  'none'
-        can be used if you don't want any ticks. 'none' and 'both'
-        affect only the ticks, not the labels.
-
-        Parameters
-        ----------
-        position : {'left', 'right', 'both', 'default', 'none'}
-        """
-        if position == 'right':
-            self.set_tick_params(which='both', right=True, labelright=True,
-                                 left=False, labelleft=False)
-            self.set_offset_position(position)
-        elif position == 'left':
-            self.set_tick_params(which='both', right=False, labelright=False,
-                                 left=True, labelleft=True)
-            self.set_offset_position(position)
-        elif position == 'both':
-            self.set_tick_params(which='both', right=True,
-                                 left=True)
-        elif position == 'none':
-            self.set_tick_params(which='both', right=False,
-                                 left=False)
-        elif position == 'default':
-            self.set_tick_params(which='both', right=True, labelright=False,
-                                 left=True, labelleft=True)
-        else:
-            raise ValueError("invalid position: %s" % position)
-        self.stale = True
-
-    def tick_right(self):
-        """
-        Move ticks and ticklabels (if present) to the right of the axes.
-        """
-        label = True
-        if 'label1On' in self._major_tick_kw:
-            label = (self._major_tick_kw['label1On']
-                     or self._major_tick_kw['label2On'])
-        self.set_ticks_position('right')
-        # if labels were turned off before this was called
-        # leave them off
-        self.set_tick_params(which='both', labelright=label)
-
-    def tick_left(self):
-        """
-        Move ticks and ticklabels (if present) to the left of the axes.
-        """
-        label = True
-        if 'label1On' in self._major_tick_kw:
-            label = (self._major_tick_kw['label1On']
-                     or self._major_tick_kw['label2On'])
-        self.set_ticks_position('left')
-        # if labels were turned off before this was called
-        # leave them off
-        self.set_tick_params(which='both', labelleft=label)
-
-    def get_ticks_position(self):
-        """
-        Return the ticks position ("left", "right", "default", or "unknown").
-        """
-        return {1: "left", 2: "right",
-                "default": "default", "unknown": "unknown"}[
-                    self._get_ticks_position()]
-
-    get_view_interval, set_view_interval = _make_getset_interval(
-        "view", "viewLim", "intervaly")
-    get_data_interval, set_data_interval = _make_getset_interval(
-        "data", "dataLim", "intervaly")
-
-    def get_minpos(self):
-        return self.axes.dataLim.minposy
-
-    def set_inverted(self, inverted):
-        # docstring inherited
-        a, b = self.get_view_interval()
-        # cast to bool to avoid bad interaction between python 3.8 and np.bool_
-        self.axes.set_ylim(sorted((a, b), reverse=bool(inverted)), auto=None)
-
-    def set_default_intervals(self):
-        # docstring inherited
-        ymin, ymax = 0., 1.
-        dataMutated = self.axes.dataLim.mutatedy()
-        viewMutated = self.axes.viewLim.mutatedy()
-        if not dataMutated or not viewMutated:
-            if self.converter is not None:
-                info = self.converter.axisinfo(self.units, self)
-                if info.default_limits is not None:
-                    valmin, valmax = info.default_limits
-                    ymin = self.converter.convert(valmin, self.units, self)
-                    ymax = self.converter.convert(valmax, self.units, self)
-            if not dataMutated:
-                self.axes.dataLim.intervaly = ymin, ymax
-            if not viewMutated:
-                self.axes.viewLim.intervaly = ymin, ymax
-        self.stale = True
-
-    def get_tick_space(self):
-        ends = self.axes.transAxes.transform([[0, 0], [0, 1]])
-        length = ((ends[1][1] - ends[0][1]) / self.axes.figure.dpi) * 72
-        tick = self._get_tick(True)
-        # Having a spacing of at least 2 just looks good.
-        size = tick.label1.get_size() * 2.0
-        if size > 0:
-            return int(np.floor(length / size))
-        else:
-            return 2**31 - 1

+ 0 - 3421
venv/lib/python3.8/site-packages/matplotlib/backend_bases.py

@@ -1,3421 +0,0 @@
-"""
-Abstract base classes define the primitives that renderers and
-graphics contexts must implement to serve as a matplotlib backend
-
-:class:`RendererBase`
-    An abstract base class to handle drawing/rendering operations.
-
-:class:`FigureCanvasBase`
-    The abstraction layer that separates the
-    :class:`matplotlib.figure.Figure` from the backend specific
-    details like a user interface drawing area
-
-:class:`GraphicsContextBase`
-    An abstract base class that provides color, line styles, etc...
-
-:class:`Event`
-    The base class for all of the matplotlib event
-    handling.  Derived classes such as :class:`KeyEvent` and
-    :class:`MouseEvent` store the meta data like keys and buttons
-    pressed, x and y locations in pixel and
-    :class:`~matplotlib.axes.Axes` coordinates.
-
-:class:`ShowBase`
-    The base class for the Show class of each interactive backend;
-    the 'show' callable is then set to Show.__call__, inherited from
-    ShowBase.
-
-:class:`ToolContainerBase`
-     The base class for the Toolbar class of each interactive backend.
-
-:class:`StatusbarBase`
-    The base class for the messaging area.
-"""
-
-from contextlib import contextmanager
-from enum import IntEnum
-import functools
-import importlib
-import io
-import logging
-import os
-import sys
-import time
-from weakref import WeakKeyDictionary
-
-import numpy as np
-
-import matplotlib as mpl
-from matplotlib import (
-    backend_tools as tools, cbook, colors, textpath, tight_bbox, transforms,
-    widgets, get_backend, is_interactive, rcParams)
-from matplotlib._pylab_helpers import Gcf
-from matplotlib.transforms import Affine2D
-from matplotlib.path import Path
-
-try:
-    from PIL import __version__ as PILLOW_VERSION
-    from distutils.version import LooseVersion
-    if LooseVersion(PILLOW_VERSION) >= "3.4":
-        _has_pil = True
-    else:
-        _has_pil = False
-    del PILLOW_VERSION
-except ImportError:
-    _has_pil = False
-
-_log = logging.getLogger(__name__)
-
-_default_filetypes = {
-    'ps': 'Postscript',
-    'eps': 'Encapsulated Postscript',
-    'pdf': 'Portable Document Format',
-    'pgf': 'PGF code for LaTeX',
-    'png': 'Portable Network Graphics',
-    'raw': 'Raw RGBA bitmap',
-    'rgba': 'Raw RGBA bitmap',
-    'svg': 'Scalable Vector Graphics',
-    'svgz': 'Scalable Vector Graphics'
-}
-
-
-_default_backends = {
-    'ps': 'matplotlib.backends.backend_ps',
-    'eps': 'matplotlib.backends.backend_ps',
-    'pdf': 'matplotlib.backends.backend_pdf',
-    'pgf': 'matplotlib.backends.backend_pgf',
-    'png': 'matplotlib.backends.backend_agg',
-    'raw': 'matplotlib.backends.backend_agg',
-    'rgba': 'matplotlib.backends.backend_agg',
-    'svg': 'matplotlib.backends.backend_svg',
-    'svgz': 'matplotlib.backends.backend_svg',
-}
-
-
-def register_backend(format, backend, description=None):
-    """
-    Register a backend for saving to a given file format.
-
-    Parameters
-    ----------
-    format : str
-        File extension
-
-    backend : module string or canvas class
-        Backend for handling file output
-
-    description : str, default: ""
-        Description of the file type.
-    """
-    if description is None:
-        description = ''
-    _default_backends[format] = backend
-    _default_filetypes[format] = description
-
-
-def get_registered_canvas_class(format):
-    """
-    Return the registered default canvas for given file format.
-    Handles deferred import of required backend.
-    """
-    if format not in _default_backends:
-        return None
-    backend_class = _default_backends[format]
-    if isinstance(backend_class, str):
-        backend_class = importlib.import_module(backend_class).FigureCanvas
-        _default_backends[format] = backend_class
-    return backend_class
-
-
-class RendererBase:
-    """An abstract base class to handle drawing/rendering operations.
-
-    The following methods must be implemented in the backend for full
-    functionality (though just implementing :meth:`draw_path` alone would
-    give a highly capable backend):
-
-    * :meth:`draw_path`
-    * :meth:`draw_image`
-    * :meth:`draw_gouraud_triangle`
-
-    The following methods *should* be implemented in the backend for
-    optimization reasons:
-
-    * :meth:`draw_text`
-    * :meth:`draw_markers`
-    * :meth:`draw_path_collection`
-    * :meth:`draw_quad_mesh`
-    """
-
-    def __init__(self):
-        self._texmanager = None
-        self._text2path = textpath.TextToPath()
-
-    def open_group(self, s, gid=None):
-        """
-        Open a grouping element with label *s* and *gid* (if set) as id.
-
-        Only used by the SVG renderer.
-        """
-
-    def close_group(self, s):
-        """
-        Close a grouping element with label *s*.
-
-        Only used by the SVG renderer.
-        """
-
-    def draw_path(self, gc, path, transform, rgbFace=None):
-        """Draw a `~.path.Path` instance using the given affine transform."""
-        raise NotImplementedError
-
-    def draw_markers(self, gc, marker_path, marker_trans, path,
-                     trans, rgbFace=None):
-        """
-        Draw a marker at each of the vertices in path.
-
-        This includes all vertices, including control points on curves.
-        To avoid that behavior, those vertices should be removed before
-        calling this function.
-
-        This provides a fallback implementation of draw_markers that
-        makes multiple calls to :meth:`draw_path`.  Some backends may
-        want to override this method in order to draw the marker only
-        once and reuse it multiple times.
-
-        Parameters
-        ----------
-        gc : `GraphicsContextBase`
-            The graphics context.
-
-        marker_trans : `matplotlib.transforms.Transform`
-            An affine transform applied to the marker.
-
-        trans : `matplotlib.transforms.Transform`
-            An affine transform applied to the path.
-
-        """
-        for vertices, codes in path.iter_segments(trans, simplify=False):
-            if len(vertices):
-                x, y = vertices[-2:]
-                self.draw_path(gc, marker_path,
-                               marker_trans +
-                               transforms.Affine2D().translate(x, y),
-                               rgbFace)
-
-    def draw_path_collection(self, gc, master_transform, paths, all_transforms,
-                             offsets, offsetTrans, facecolors, edgecolors,
-                             linewidths, linestyles, antialiaseds, urls,
-                             offset_position):
-        """
-        Draw a collection of paths selecting drawing properties from
-        the lists *facecolors*, *edgecolors*, *linewidths*,
-        *linestyles* and *antialiaseds*. *offsets* is a list of
-        offsets to apply to each of the paths.  The offsets in
-        *offsets* are first transformed by *offsetTrans* before being
-        applied.  *offset_position* may be either "screen" or "data"
-        depending on the space that the offsets are in.
-
-        This provides a fallback implementation of
-        :meth:`draw_path_collection` that makes multiple calls to
-        :meth:`draw_path`.  Some backends may want to override this in
-        order to render each set of path data only once, and then
-        reference that path multiple times with the different offsets,
-        colors, styles etc.  The generator methods
-        :meth:`_iter_collection_raw_paths` and
-        :meth:`_iter_collection` are provided to help with (and
-        standardize) the implementation across backends.  It is highly
-        recommended to use those generators, so that changes to the
-        behavior of :meth:`draw_path_collection` can be made globally.
-        """
-        path_ids = [
-            (path, transforms.Affine2D(transform))
-            for path, transform in self._iter_collection_raw_paths(
-                    master_transform, paths, all_transforms)]
-
-        for xo, yo, path_id, gc0, rgbFace in self._iter_collection(
-                gc, master_transform, all_transforms, path_ids, offsets,
-                offsetTrans, facecolors, edgecolors, linewidths, linestyles,
-                antialiaseds, urls, offset_position):
-            path, transform = path_id
-            transform = transforms.Affine2D(
-                            transform.get_matrix()).translate(xo, yo)
-            self.draw_path(gc0, path, transform, rgbFace)
-
-    def draw_quad_mesh(self, gc, master_transform, meshWidth, meshHeight,
-                       coordinates, offsets, offsetTrans, facecolors,
-                       antialiased, edgecolors):
-        """
-        This provides a fallback implementation of
-        :meth:`draw_quad_mesh` that generates paths and then calls
-        :meth:`draw_path_collection`.
-        """
-
-        from matplotlib.collections import QuadMesh
-        paths = QuadMesh.convert_mesh_to_paths(
-            meshWidth, meshHeight, coordinates)
-
-        if edgecolors is None:
-            edgecolors = facecolors
-        linewidths = np.array([gc.get_linewidth()], float)
-
-        return self.draw_path_collection(
-            gc, master_transform, paths, [], offsets, offsetTrans, facecolors,
-            edgecolors, linewidths, [], [antialiased], [None], 'screen')
-
-    def draw_gouraud_triangle(self, gc, points, colors, transform):
-        """
-        Draw a Gouraud-shaded triangle.
-
-        Parameters
-        ----------
-        points : array-like, shape=(3, 2)
-            Array of (x, y) points for the triangle.
-
-        colors : array-like, shape=(3, 4)
-            RGBA colors for each point of the triangle.
-
-        transform : `matplotlib.transforms.Transform`
-            An affine transform to apply to the points.
-
-        """
-        raise NotImplementedError
-
-    def draw_gouraud_triangles(self, gc, triangles_array, colors_array,
-                               transform):
-        """
-        Draw a series of Gouraud triangles.
-
-        Parameters
-        ----------
-        points : array-like, shape=(N, 3, 2)
-            Array of *N* (x, y) points for the triangles.
-
-        colors : array-like, shape=(N, 3, 4)
-            Array of *N* RGBA colors for each point of the triangles.
-
-        transform : `matplotlib.transforms.Transform`
-            An affine transform to apply to the points.
-        """
-        transform = transform.frozen()
-        for tri, col in zip(triangles_array, colors_array):
-            self.draw_gouraud_triangle(gc, tri, col, transform)
-
-    def _iter_collection_raw_paths(self, master_transform, paths,
-                                   all_transforms):
-        """
-        This is a helper method (along with :meth:`_iter_collection`) to make
-        it easier to write a space-efficient :meth:`draw_path_collection`
-        implementation in a backend.
-
-        This method yields all of the base path/transform
-        combinations, given a master transform, a list of paths and
-        list of transforms.
-
-        The arguments should be exactly what is passed in to
-        :meth:`draw_path_collection`.
-
-        The backend should take each yielded path and transform and
-        create an object that can be referenced (reused) later.
-        """
-        Npaths = len(paths)
-        Ntransforms = len(all_transforms)
-        N = max(Npaths, Ntransforms)
-
-        if Npaths == 0:
-            return
-
-        transform = transforms.IdentityTransform()
-        for i in range(N):
-            path = paths[i % Npaths]
-            if Ntransforms:
-                transform = Affine2D(all_transforms[i % Ntransforms])
-            yield path, transform + master_transform
-
-    def _iter_collection_uses_per_path(self, paths, all_transforms,
-                                       offsets, facecolors, edgecolors):
-        """
-        Compute how many times each raw path object returned by
-        _iter_collection_raw_paths would be used when calling
-        _iter_collection. This is intended for the backend to decide
-        on the tradeoff between using the paths in-line and storing
-        them once and reusing. Rounds up in case the number of uses
-        is not the same for every path.
-        """
-        Npaths = len(paths)
-        if Npaths == 0 or len(facecolors) == len(edgecolors) == 0:
-            return 0
-        Npath_ids = max(Npaths, len(all_transforms))
-        N = max(Npath_ids, len(offsets))
-        return (N + Npath_ids - 1) // Npath_ids
-
-    def _iter_collection(self, gc, master_transform, all_transforms,
-                         path_ids, offsets, offsetTrans, facecolors,
-                         edgecolors, linewidths, linestyles,
-                         antialiaseds, urls, offset_position):
-        """
-        This is a helper method (along with
-        :meth:`_iter_collection_raw_paths`) to make it easier to write
-        a space-efficient :meth:`draw_path_collection` implementation in a
-        backend.
-
-        This method yields all of the path, offset and graphics
-        context combinations to draw the path collection.  The caller
-        should already have looped over the results of
-        :meth:`_iter_collection_raw_paths` to draw this collection.
-
-        The arguments should be the same as that passed into
-        :meth:`draw_path_collection`, with the exception of
-        *path_ids*, which is a list of arbitrary objects that the
-        backend will use to reference one of the paths created in the
-        :meth:`_iter_collection_raw_paths` stage.
-
-        Each yielded result is of the form::
-
-           xo, yo, path_id, gc, rgbFace
-
-        where *xo*, *yo* is an offset; *path_id* is one of the elements of
-        *path_ids*; *gc* is a graphics context and *rgbFace* is a color to
-        use for filling the path.
-        """
-        Ntransforms = len(all_transforms)
-        Npaths = len(path_ids)
-        Noffsets = len(offsets)
-        N = max(Npaths, Noffsets)
-        Nfacecolors = len(facecolors)
-        Nedgecolors = len(edgecolors)
-        Nlinewidths = len(linewidths)
-        Nlinestyles = len(linestyles)
-        Naa = len(antialiaseds)
-        Nurls = len(urls)
-
-        if (Nfacecolors == 0 and Nedgecolors == 0) or Npaths == 0:
-            return
-        if Noffsets:
-            toffsets = offsetTrans.transform(offsets)
-
-        gc0 = self.new_gc()
-        gc0.copy_properties(gc)
-
-        if Nfacecolors == 0:
-            rgbFace = None
-
-        if Nedgecolors == 0:
-            gc0.set_linewidth(0.0)
-
-        xo, yo = 0, 0
-        for i in range(N):
-            path_id = path_ids[i % Npaths]
-            if Noffsets:
-                xo, yo = toffsets[i % Noffsets]
-                if offset_position == 'data':
-                    if Ntransforms:
-                        transform = (
-                            Affine2D(all_transforms[i % Ntransforms]) +
-                            master_transform)
-                    else:
-                        transform = master_transform
-                    (xo, yo), (xp, yp) = transform.transform(
-                        [(xo, yo), (0, 0)])
-                    xo = -(xp - xo)
-                    yo = -(yp - yo)
-            if not (np.isfinite(xo) and np.isfinite(yo)):
-                continue
-            if Nfacecolors:
-                rgbFace = facecolors[i % Nfacecolors]
-            if Nedgecolors:
-                if Nlinewidths:
-                    gc0.set_linewidth(linewidths[i % Nlinewidths])
-                if Nlinestyles:
-                    gc0.set_dashes(*linestyles[i % Nlinestyles])
-                fg = edgecolors[i % Nedgecolors]
-                if len(fg) == 4:
-                    if fg[3] == 0.0:
-                        gc0.set_linewidth(0)
-                    else:
-                        gc0.set_foreground(fg)
-                else:
-                    gc0.set_foreground(fg)
-            if rgbFace is not None and len(rgbFace) == 4:
-                if rgbFace[3] == 0:
-                    rgbFace = None
-            gc0.set_antialiased(antialiaseds[i % Naa])
-            if Nurls:
-                gc0.set_url(urls[i % Nurls])
-
-            yield xo, yo, path_id, gc0, rgbFace
-        gc0.restore()
-
-    def get_image_magnification(self):
-        """
-        Get the factor by which to magnify images passed to :meth:`draw_image`.
-        Allows a backend to have images at a different resolution to other
-        artists.
-        """
-        return 1.0
-
-    def draw_image(self, gc, x, y, im, transform=None):
-        """
-        Draw an RGBA image.
-
-        Parameters
-        ----------
-        gc : `GraphicsContextBase`
-            A graphics context with clipping information.
-
-        x : scalar
-            The distance in physical units (i.e., dots or pixels) from the left
-            hand side of the canvas.
-
-        y : scalar
-            The distance in physical units (i.e., dots or pixels) from the
-            bottom side of the canvas.
-
-        im : array-like, shape=(N, M, 4), dtype=np.uint8
-            An array of RGBA pixels.
-
-        transform : `matplotlib.transforms.Affine2DBase`
-            If and only if the concrete backend is written such that
-            :meth:`option_scale_image` returns ``True``, an affine
-            transformation *may* be passed to :meth:`draw_image`. It takes the
-            form of a :class:`~matplotlib.transforms.Affine2DBase` instance.
-            The translation vector of the transformation is given in physical
-            units (i.e., dots or pixels). Note that the transformation does not
-            override *x* and *y*, and has to be applied *before* translating
-            the result by *x* and *y* (this can be accomplished by adding *x*
-            and *y* to the translation vector defined by *transform*).
-        """
-        raise NotImplementedError
-
-    def option_image_nocomposite(self):
-        """
-        Return whether image composition by Matplotlib should be skipped.
-
-        Raster backends should usually return False (letting the C-level
-        rasterizer take care of image composition); vector backends should
-        usually return ``not rcParams["image.composite_image"]``.
-        """
-        return False
-
-    def option_scale_image(self):
-        """
-        Return whether arbitrary affine transformations in :meth:`draw_image`
-        are supported (True for most vector backends).
-        """
-        return False
-
-    def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
-        """
-        """
-        self._draw_text_as_path(gc, x, y, s, prop, angle, ismath="TeX")
-
-    def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
-        """
-        Draw the text instance.
-
-        Parameters
-        ----------
-        gc : `GraphicsContextBase`
-            The graphics context.
-        x : float
-            The x location of the text in display coords.
-        y : float
-            The y location of the text baseline in display coords.
-        s : str
-            The text string.
-        prop : `matplotlib.font_manager.FontProperties`
-            The font properties.
-        angle : float
-            The rotation angle in degrees anti-clockwise.
-        mtext : `matplotlib.text.Text`
-            The original text object to be rendered.
-
-        Notes
-        -----
-        **Note for backend implementers:**
-
-        When you are trying to determine if you have gotten your bounding box
-        right (which is what enables the text layout/alignment to work
-        properly), it helps to change the line in text.py::
-
-            if 0: bbox_artist(self, renderer)
-
-        to if 1, and then the actual bounding box will be plotted along with
-        your text.
-        """
-
-        self._draw_text_as_path(gc, x, y, s, prop, angle, ismath)
-
-    def _get_text_path_transform(self, x, y, s, prop, angle, ismath):
-        """
-        Return the text path and transform.
-
-        Parameters
-        ----------
-        prop : `matplotlib.font_manager.FontProperties`
-            The font property.
-        s : str
-            The text to be converted.
-        ismath : bool or "TeX"
-            If True, use mathtext parser. If "TeX", use *usetex* mode.
-        """
-
-        text2path = self._text2path
-        fontsize = self.points_to_pixels(prop.get_size_in_points())
-        verts, codes = text2path.get_text_path(prop, s, ismath=ismath)
-
-        path = Path(verts, codes)
-        angle = np.deg2rad(angle)
-        if self.flipy():
-            width, height = self.get_canvas_width_height()
-            transform = (Affine2D()
-                         .scale(fontsize / text2path.FONT_SCALE)
-                         .rotate(angle)
-                         .translate(x, height - y))
-        else:
-            transform = (Affine2D()
-                         .scale(fontsize / text2path.FONT_SCALE)
-                         .rotate(angle)
-                         .translate(x, y))
-
-        return path, transform
-
-    def _draw_text_as_path(self, gc, x, y, s, prop, angle, ismath):
-        """
-        Draw the text by converting them to paths using textpath module.
-
-        Parameters
-        ----------
-        prop : `matplotlib.font_manager.FontProperties`
-            The font property.
-        s : str
-            The text to be converted.
-        usetex : bool
-            Whether to use matplotlib usetex mode.
-        ismath : bool or "TeX"
-            If True, use mathtext parser. If "TeX", use *usetex* mode.
-        """
-        path, transform = self._get_text_path_transform(
-            x, y, s, prop, angle, ismath)
-        color = gc.get_rgb()
-        gc.set_linewidth(0.0)
-        self.draw_path(gc, path, transform, rgbFace=color)
-
-    def get_text_width_height_descent(self, s, prop, ismath):
-        """
-        Get the width, height, and descent (offset from the bottom
-        to the baseline), in display coords, of the string *s* with
-        :class:`~matplotlib.font_manager.FontProperties` *prop*
-        """
-        if ismath == 'TeX':
-            # todo: handle props
-            texmanager = self._text2path.get_texmanager()
-            fontsize = prop.get_size_in_points()
-            w, h, d = texmanager.get_text_width_height_descent(
-                s, fontsize, renderer=self)
-            return w, h, d
-
-        dpi = self.points_to_pixels(72)
-        if ismath:
-            dims = self._text2path.mathtext_parser.parse(s, dpi, prop)
-            return dims[0:3]  # return width, height, descent
-
-        flags = self._text2path._get_hinting_flag()
-        font = self._text2path._get_font(prop)
-        size = prop.get_size_in_points()
-        font.set_size(size, dpi)
-        # the width and height of unrotated string
-        font.set_text(s, 0.0, flags=flags)
-        w, h = font.get_width_height()
-        d = font.get_descent()
-        w /= 64.0  # convert from subpixels
-        h /= 64.0
-        d /= 64.0
-        return w, h, d
-
-    def flipy(self):
-        """
-        Return whether y values increase from top to bottom.
-
-        Note that this only affects drawing of texts and images.
-        """
-        return True
-
-    def get_canvas_width_height(self):
-        """Return the canvas width and height in display coords."""
-        return 1, 1
-
-    def get_texmanager(self):
-        """Return the `.TexManager` instance."""
-        if self._texmanager is None:
-            from matplotlib.texmanager import TexManager
-            self._texmanager = TexManager()
-        return self._texmanager
-
-    def new_gc(self):
-        """Return an instance of a `GraphicsContextBase`."""
-        return GraphicsContextBase()
-
-    def points_to_pixels(self, points):
-        """
-        Convert points to display units.
-
-        You need to override this function (unless your backend
-        doesn't have a dpi, e.g., postscript or svg).  Some imaging
-        systems assume some value for pixels per inch::
-
-            points to pixels = points * pixels_per_inch/72 * dpi/72
-
-        Parameters
-        ----------
-        points : float or array-like
-            a float or a numpy array of float
-
-        Returns
-        -------
-        Points converted to pixels
-        """
-        return points
-
-    @cbook.deprecated("3.1", alternative="cbook.strip_math")
-    def strip_math(self, s):
-        return cbook.strip_math(s)
-
-    def start_rasterizing(self):
-        """
-        Switch to the raster renderer.
-
-        Used by `MixedModeRenderer`.
-        """
-
-    def stop_rasterizing(self):
-        """
-        Switch back to the vector renderer and draw the contents of the raster
-        renderer as an image on the vector renderer.
-
-        Used by `MixedModeRenderer`.
-        """
-
-    def start_filter(self):
-        """
-        Switch to a temporary renderer for image filtering effects.
-
-        Currently only supported by the agg renderer.
-        """
-
-    def stop_filter(self, filter_func):
-        """
-        Switch back to the original renderer.  The contents of the temporary
-        renderer is processed with the *filter_func* and is drawn on the
-        original renderer as an image.
-
-        Currently only supported by the agg renderer.
-        """
-
-
-class GraphicsContextBase:
-    """An abstract base class that provides color, line styles, etc."""
-
-    def __init__(self):
-        self._alpha = 1.0
-        self._forced_alpha = False  # if True, _alpha overrides A from RGBA
-        self._antialiased = 1  # use 0, 1 not True, False for extension code
-        self._capstyle = 'butt'
-        self._cliprect = None
-        self._clippath = None
-        self._dashes = None, None
-        self._joinstyle = 'round'
-        self._linestyle = 'solid'
-        self._linewidth = 1
-        self._rgb = (0.0, 0.0, 0.0, 1.0)
-        self._hatch = None
-        self._hatch_color = colors.to_rgba(rcParams['hatch.color'])
-        self._hatch_linewidth = rcParams['hatch.linewidth']
-        self._url = None
-        self._gid = None
-        self._snap = None
-        self._sketch = None
-
-    def copy_properties(self, gc):
-        'Copy properties from gc to self'
-        self._alpha = gc._alpha
-        self._forced_alpha = gc._forced_alpha
-        self._antialiased = gc._antialiased
-        self._capstyle = gc._capstyle
-        self._cliprect = gc._cliprect
-        self._clippath = gc._clippath
-        self._dashes = gc._dashes
-        self._joinstyle = gc._joinstyle
-        self._linestyle = gc._linestyle
-        self._linewidth = gc._linewidth
-        self._rgb = gc._rgb
-        self._hatch = gc._hatch
-        self._hatch_color = gc._hatch_color
-        self._hatch_linewidth = gc._hatch_linewidth
-        self._url = gc._url
-        self._gid = gc._gid
-        self._snap = gc._snap
-        self._sketch = gc._sketch
-
-    def restore(self):
-        """
-        Restore the graphics context from the stack - needed only
-        for backends that save graphics contexts on a stack.
-        """
-
-    def get_alpha(self):
-        """
-        Return the alpha value used for blending - not supported on
-        all backends.
-        """
-        return self._alpha
-
-    def get_antialiased(self):
-        "Return whether the object should try to do antialiased rendering."
-        return self._antialiased
-
-    def get_capstyle(self):
-        """
-        Return the capstyle as a string in ('butt', 'round', 'projecting').
-        """
-        return self._capstyle
-
-    def get_clip_rectangle(self):
-        """
-        Return the clip rectangle as a `~matplotlib.transforms.Bbox` instance.
-        """
-        return self._cliprect
-
-    def get_clip_path(self):
-        """
-        Return the clip path in the form (path, transform), where path
-        is a :class:`~matplotlib.path.Path` instance, and transform is
-        an affine transform to apply to the path before clipping.
-        """
-        if self._clippath is not None:
-            return self._clippath.get_transformed_path_and_affine()
-        return None, None
-
-    def get_dashes(self):
-        """
-        Return the dash style as an (offset, dash-list) pair.
-
-        The dash list is a even-length list that gives the ink on, ink off in
-        points.  See p. 107 of to PostScript `blue book`_ for more info.
-
-        Default value is (None, None).
-
-        .. _blue book: https://www-cdf.fnal.gov/offline/PostScript/BLUEBOOK.PDF
-        """
-        return self._dashes
-
-    def get_forced_alpha(self):
-        """
-        Return whether the value given by get_alpha() should be used to
-        override any other alpha-channel values.
-        """
-        return self._forced_alpha
-
-    def get_joinstyle(self):
-        """Return the line join style as one of ('miter', 'round', 'bevel')."""
-        return self._joinstyle
-
-    def get_linewidth(self):
-        """Return the line width in points."""
-        return self._linewidth
-
-    def get_rgb(self):
-        """Return a tuple of three or four floats from 0-1."""
-        return self._rgb
-
-    def get_url(self):
-        """Return a url if one is set, None otherwise."""
-        return self._url
-
-    def get_gid(self):
-        """Return the object identifier if one is set, None otherwise."""
-        return self._gid
-
-    def get_snap(self):
-        """
-        Returns the snap setting, which can be:
-
-        * True: snap vertices to the nearest pixel center
-        * False: leave vertices as-is
-        * None: (auto) If the path contains only rectilinear line segments,
-          round to the nearest pixel center
-        """
-        return self._snap
-
-    def set_alpha(self, alpha):
-        """
-        Set the alpha value used for blending - not supported on all backends.
-
-        If ``alpha=None`` (the default), the alpha components of the
-        foreground and fill colors will be used to set their respective
-        transparencies (where applicable); otherwise, ``alpha`` will override
-        them.
-        """
-        if alpha is not None:
-            self._alpha = alpha
-            self._forced_alpha = True
-        else:
-            self._alpha = 1.0
-            self._forced_alpha = False
-        self.set_foreground(self._rgb, isRGBA=True)
-
-    def set_antialiased(self, b):
-        """Set whether object should be drawn with antialiased rendering."""
-        # Use ints to make life easier on extension code trying to read the gc.
-        self._antialiased = int(bool(b))
-
-    def set_capstyle(self, cs):
-        """Set the capstyle to be one of ('butt', 'round', 'projecting')."""
-        cbook._check_in_list(['butt', 'round', 'projecting'], cs=cs)
-        self._capstyle = cs
-
-    def set_clip_rectangle(self, rectangle):
-        """
-        Set the clip rectangle with sequence (left, bottom, width, height)
-        """
-        self._cliprect = rectangle
-
-    def set_clip_path(self, path):
-        """
-        Set the clip path and transformation.
-
-        Parameters
-        ----------
-        path : `~matplotlib.transforms.TransformedPath` or None
-        """
-        cbook._check_isinstance((transforms.TransformedPath, None), path=path)
-        self._clippath = path
-
-    def set_dashes(self, dash_offset, dash_list):
-        """
-        Set the dash style for the gc.
-
-        Parameters
-        ----------
-        dash_offset : float or None
-            The offset (usually 0).
-        dash_list : array-like or None
-            The on-off sequence as points.
-
-        Notes
-        -----
-        ``(None, None)`` specifies a solid line.
-
-        See p. 107 of to PostScript `blue book`_ for more info.
-
-        .. _blue book: https://www-cdf.fnal.gov/offline/PostScript/BLUEBOOK.PDF
-        """
-        if dash_list is not None:
-            dl = np.asarray(dash_list)
-            if np.any(dl < 0.0):
-                raise ValueError(
-                    "All values in the dash list must be positive")
-        self._dashes = dash_offset, dash_list
-
-    def set_foreground(self, fg, isRGBA=False):
-        """
-        Set the foreground color.
-
-        Parameters
-        ----------
-        fg : color
-        isRGBA : bool
-            If *fg* is known to be an ``(r, g, b, a)`` tuple, *isRGBA* can be
-            set to True to improve performance.
-        """
-        if self._forced_alpha and isRGBA:
-            self._rgb = fg[:3] + (self._alpha,)
-        elif self._forced_alpha:
-            self._rgb = colors.to_rgba(fg, self._alpha)
-        elif isRGBA:
-            self._rgb = fg
-        else:
-            self._rgb = colors.to_rgba(fg)
-
-    def set_joinstyle(self, js):
-        """Set the join style to be one of ('miter', 'round', 'bevel')."""
-        cbook._check_in_list(['miter', 'round', 'bevel'], js=js)
-        self._joinstyle = js
-
-    def set_linewidth(self, w):
-        """Set the linewidth in points."""
-        self._linewidth = float(w)
-
-    def set_url(self, url):
-        """Set the url for links in compatible backends."""
-        self._url = url
-
-    def set_gid(self, id):
-        """Set the id."""
-        self._gid = id
-
-    def set_snap(self, snap):
-        """
-        Set the snap setting which may be:
-
-        * True: snap vertices to the nearest pixel center
-        * False: leave vertices as-is
-        * None: (auto) If the path contains only rectilinear line segments,
-          round to the nearest pixel center
-        """
-        self._snap = snap
-
-    def set_hatch(self, hatch):
-        """Set the hatch style (for fills)."""
-        self._hatch = hatch
-
-    def get_hatch(self):
-        """Get the current hatch style."""
-        return self._hatch
-
-    def get_hatch_path(self, density=6.0):
-        """Return a `Path` for the current hatch."""
-        hatch = self.get_hatch()
-        if hatch is None:
-            return None
-        return Path.hatch(hatch, density)
-
-    def get_hatch_color(self):
-        """Get the hatch color."""
-        return self._hatch_color
-
-    def set_hatch_color(self, hatch_color):
-        """Set the hatch color."""
-        self._hatch_color = hatch_color
-
-    def get_hatch_linewidth(self):
-        """Get the hatch linewidth."""
-        return self._hatch_linewidth
-
-    def get_sketch_params(self):
-        """
-        Return the sketch parameters for the artist.
-
-        Returns
-        -------
-        sketch_params : tuple or `None`
-
-            A 3-tuple with the following elements:
-
-            * ``scale``: The amplitude of the wiggle perpendicular to the
-              source line.
-            * ``length``: The length of the wiggle along the line.
-            * ``randomness``: The scale factor by which the length is
-              shrunken or expanded.
-
-            May return `None` if no sketch parameters were set.
-        """
-        return self._sketch
-
-    def set_sketch_params(self, scale=None, length=None, randomness=None):
-        """
-        Set the sketch parameters.
-
-        Parameters
-        ----------
-        scale : float, optional
-            The amplitude of the wiggle perpendicular to the source line, in
-            pixels.  If scale is `None`, or not provided, no sketch filter will
-            be provided.
-        length : float, default: 128
-             The length of the wiggle along the line, in pixels.
-        randomness : float, default: 16
-            The scale factor by which the length is shrunken or expanded.
-        """
-        self._sketch = (
-            None if scale is None
-            else (scale, length or 128., randomness or 16.))
-
-
-class TimerBase:
-    """
-    A base class for providing timer events, useful for things animations.
-    Backends need to implement a few specific methods in order to use their
-    own timing mechanisms so that the timer events are integrated into their
-    event loops.
-
-    Subclasses must override the following methods:
-
-    - ``_timer_start``: Backend-specific code for starting the timer.
-    - ``_timer_stop``: Backend-specific code for stopping the timer.
-
-    Subclasses may additionally override the following methods:
-
-    - ``_timer_set_single_shot``: Code for setting the timer to single shot
-      operating mode, if supported by the timer object.  If not, the `Timer`
-      class itself will store the flag and the ``_on_timer`` method should be
-      overridden to support such behavior.
-
-    - ``_timer_set_interval``: Code for setting the interval on the timer, if
-      there is a method for doing so on the timer object.
-
-    - ``_on_timer``: The internal function that any timer object should call,
-      which will handle the task of running all callbacks that have been set.
-
-    Attributes
-    ----------
-    interval : scalar
-        The time between timer events in milliseconds. Default is 1000 ms.
-
-    single_shot : bool
-        Boolean flag indicating whether this timer should operate as single
-        shot (run once and then stop). Defaults to `False`.
-
-    callbacks : List[Tuple[callable, Tuple, Dict]]
-        Stores list of (func, args, kwargs) tuples that will be called upon
-        timer events. This list can be manipulated directly, or the
-        functions `add_callback` and `remove_callback` can be used.
-    """
-    def __init__(self, interval=None, callbacks=None):
-        #Initialize empty callbacks list and setup default settings if necssary
-        if callbacks is None:
-            self.callbacks = []
-        else:
-            self.callbacks = callbacks[:]  # Create a copy
-
-        if interval is None:
-            self._interval = 1000
-        else:
-            self._interval = interval
-
-        self._single = False
-
-        # Default attribute for holding the GUI-specific timer object
-        self._timer = None
-
-    def __del__(self):
-        """Need to stop timer and possibly disconnect timer."""
-        self._timer_stop()
-
-    def start(self, interval=None):
-        """
-        Start the timer object.
-
-        Parameters
-        ----------
-        interval : int, optional
-            Timer interval in milliseconds; overrides a previously set interval
-            if provided.
-        """
-        if interval is not None:
-            self.interval = interval
-        self._timer_start()
-
-    def stop(self):
-        """Stop the timer."""
-        self._timer_stop()
-
-    def _timer_start(self):
-        pass
-
-    def _timer_stop(self):
-        pass
-
-    @property
-    def interval(self):
-        return self._interval
-
-    @interval.setter
-    def interval(self, interval):
-        # Force to int since none of the backends actually support fractional
-        # milliseconds, and some error or give warnings.
-        interval = int(interval)
-        self._interval = interval
-        self._timer_set_interval()
-
-    @property
-    def single_shot(self):
-        return self._single
-
-    @single_shot.setter
-    def single_shot(self, ss):
-        self._single = ss
-        self._timer_set_single_shot()
-
-    def add_callback(self, func, *args, **kwargs):
-        """
-        Register *func* to be called by timer when the event fires. Any
-        additional arguments provided will be passed to *func*.
-
-        This function returns *func*, which makes it possible to use it as a
-        decorator.
-        """
-        self.callbacks.append((func, args, kwargs))
-        return func
-
-    def remove_callback(self, func, *args, **kwargs):
-        """
-        Remove *func* from list of callbacks.
-
-        *args* and *kwargs* are optional and used to distinguish between copies
-        of the same function registered to be called with different arguments.
-        This behavior is deprecated.  In the future, `*args, **kwargs` won't be
-        considered anymore; to keep a specific callback removable by itself,
-        pass it to `add_callback` as a `functools.partial` object.
-        """
-        if args or kwargs:
-            cbook.warn_deprecated(
-                "3.1", message="In a future version, Timer.remove_callback "
-                "will not take *args, **kwargs anymore, but remove all "
-                "callbacks where the callable matches; to keep a specific "
-                "callback removable by itself, pass it to add_callback as a "
-                "functools.partial object.")
-            self.callbacks.remove((func, args, kwargs))
-        else:
-            funcs = [c[0] for c in self.callbacks]
-            if func in funcs:
-                self.callbacks.pop(funcs.index(func))
-
-    def _timer_set_interval(self):
-        """Used to set interval on underlying timer object."""
-
-    def _timer_set_single_shot(self):
-        """Used to set single shot on underlying timer object."""
-
-    def _on_timer(self):
-        """
-        Runs all function that have been registered as callbacks. Functions
-        can return False (or 0) if they should not be called any more. If there
-        are no callbacks, the timer is automatically stopped.
-        """
-        for func, args, kwargs in self.callbacks:
-            ret = func(*args, **kwargs)
-            # docstring above explains why we use `if ret == 0` here,
-            # instead of `if not ret`.
-            # This will also catch `ret == False` as `False == 0`
-            # but does not annoy the linters
-            # https://docs.python.org/3/library/stdtypes.html#boolean-values
-            if ret == 0:
-                self.callbacks.remove((func, args, kwargs))
-
-        if len(self.callbacks) == 0:
-            self.stop()
-
-
-class Event:
-    """
-    A matplotlib event.  Attach additional attributes as defined in
-    :meth:`FigureCanvasBase.mpl_connect`.  The following attributes
-    are defined and shown with their default values
-
-    Attributes
-    ----------
-    name : str
-        the event name
-
-    canvas : `FigureCanvasBase`
-        the backend-specific canvas instance generating the event
-
-    guiEvent
-        the GUI event that triggered the matplotlib event
-
-    """
-    def __init__(self, name, canvas, guiEvent=None):
-        self.name = name
-        self.canvas = canvas
-        self.guiEvent = guiEvent
-
-
-class DrawEvent(Event):
-    """
-    An event triggered by a draw operation on the canvas
-
-    In most backends callbacks subscribed to this callback will be
-    fired after the rendering is complete but before the screen is
-    updated.  Any extra artists drawn to the canvas's renderer will
-    be reflected without an explicit call to ``blit``.
-
-    .. warning::
-
-       Calling ``canvas.draw`` and ``canvas.blit`` in these callbacks may
-       not be safe with all backends and may cause infinite recursion.
-
-    In addition to the :class:`Event` attributes, the following event
-    attributes are defined:
-
-    Attributes
-    ----------
-    renderer : `RendererBase`
-        the renderer for the draw event
-
-    """
-    def __init__(self, name, canvas, renderer):
-        Event.__init__(self, name, canvas)
-        self.renderer = renderer
-
-
-class ResizeEvent(Event):
-    """
-    An event triggered by a canvas resize
-
-    In addition to the :class:`Event` attributes, the following event
-    attributes are defined:
-
-    Attributes
-    ----------
-    width : int
-        Width of the canvas in pixels.
-    height : int
-        Height of the canvas in pixels.
-    """
-    def __init__(self, name, canvas):
-        Event.__init__(self, name, canvas)
-        self.width, self.height = canvas.get_width_height()
-
-
-class CloseEvent(Event):
-    """An event triggered by a figure being closed."""
-
-
-class LocationEvent(Event):
-    """
-    An event that has a screen location.
-
-    The following additional attributes are defined and shown with
-    their default values.
-
-    In addition to the :class:`Event` attributes, the following
-    event attributes are defined:
-
-    Attributes
-    ----------
-    x : int
-        x position - pixels from left of canvas.
-    y : int
-        y position - pixels from bottom of canvas.
-    inaxes : `~.axes.Axes` or None
-        The `~.axes.Axes` instance over which the mouse is, if any.
-    xdata : float or None
-        x data coordinate of the mouse.
-    ydata : float or None
-        y data coordinate of the mouse.
-    """
-
-    lastevent = None  # the last event that was triggered before this one
-
-    def __init__(self, name, canvas, x, y, guiEvent=None):
-        """
-        (*x*, *y*) in figure coords ((0, 0) = bottom left).
-        """
-        Event.__init__(self, name, canvas, guiEvent=guiEvent)
-        # x position - pixels from left of canvas
-        self.x = int(x) if x is not None else x
-        # y position - pixels from right of canvas
-        self.y = int(y) if y is not None else y
-        self.inaxes = None  # the Axes instance if mouse us over axes
-        self.xdata = None   # x coord of mouse in data coords
-        self.ydata = None   # y coord of mouse in data coords
-
-        if x is None or y is None:
-            # cannot check if event was in axes if no (x, y) info
-            self._update_enter_leave()
-            return
-
-        if self.canvas.mouse_grabber is None:
-            self.inaxes = self.canvas.inaxes((x, y))
-        else:
-            self.inaxes = self.canvas.mouse_grabber
-
-        if self.inaxes is not None:
-            try:
-                trans = self.inaxes.transData.inverted()
-                xdata, ydata = trans.transform((x, y))
-            except ValueError:
-                pass
-            else:
-                self.xdata = xdata
-                self.ydata = ydata
-
-        self._update_enter_leave()
-
-    def _update_enter_leave(self):
-        'process the figure/axes enter leave events'
-        if LocationEvent.lastevent is not None:
-            last = LocationEvent.lastevent
-            if last.inaxes != self.inaxes:
-                # process axes enter/leave events
-                try:
-                    if last.inaxes is not None:
-                        last.canvas.callbacks.process('axes_leave_event', last)
-                except Exception:
-                    pass
-                    # See ticket 2901582.
-                    # I think this is a valid exception to the rule
-                    # against catching all exceptions; if anything goes
-                    # wrong, we simply want to move on and process the
-                    # current event.
-                if self.inaxes is not None:
-                    self.canvas.callbacks.process('axes_enter_event', self)
-
-        else:
-            # process a figure enter event
-            if self.inaxes is not None:
-                self.canvas.callbacks.process('axes_enter_event', self)
-
-        LocationEvent.lastevent = self
-
-
-class MouseButton(IntEnum):
-    LEFT = 1
-    MIDDLE = 2
-    RIGHT = 3
-    BACK = 8
-    FORWARD = 9
-
-
-class MouseEvent(LocationEvent):
-    """
-    A mouse event ('button_press_event',
-                   'button_release_event',
-                   'scroll_event',
-                   'motion_notify_event').
-
-    In addition to the :class:`Event` and :class:`LocationEvent`
-    attributes, the following attributes are defined:
-
-    Attributes
-    ----------
-    button : {None, MouseButton.LEFT, MouseButton.MIDDLE, MouseButton.RIGHT, \
-'up', 'down'}
-        The button pressed. 'up' and 'down' are used for scroll events.
-        Note that in the nbagg backend, both the middle and right clicks
-        return RIGHT since right clicking will bring up the context menu in
-        some browsers.
-        Note that LEFT and RIGHT actually refer to the "primary" and
-        "secondary" buttons, i.e. if the user inverts their left and right
-        buttons ("left-handed setting") then the LEFT button will be the one
-        physically on the right.
-
-    key : None or str
-        The key pressed when the mouse event triggered, e.g. 'shift'.
-        See `KeyEvent`.
-
-    step : int
-        The number of scroll steps (positive for 'up', negative for 'down').
-        This applies only to 'scroll_event' and defaults to 0 otherwise.
-
-    dblclick : bool
-        Whether the event is a double-click. This applies only to
-        'button_press_event' and is False otherwise. In particular, it's
-        not used in 'button_release_event'.
-
-    Examples
-    --------
-    ::
-
-        def on_press(event):
-            print('you pressed', event.button, event.xdata, event.ydata)
-
-        cid = fig.canvas.mpl_connect('button_press_event', on_press)
-    """
-
-    def __init__(self, name, canvas, x, y, button=None, key=None,
-                 step=0, dblclick=False, guiEvent=None):
-        """
-        (*x*, *y*) in figure coords ((0, 0) = bottom left)
-        button pressed None, 1, 2, 3, 'up', 'down'
-        """
-        LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent)
-        if button in MouseButton.__members__.values():
-            button = MouseButton(button)
-        self.button = button
-        self.key = key
-        self.step = step
-        self.dblclick = dblclick
-
-    def __str__(self):
-        return (f"{self.name}: "
-                f"xy=({self.x}, {self.y}) xydata=({self.xdata}, {self.ydata}) "
-                f"button={self.button} dblclick={self.dblclick} "
-                f"inaxes={self.inaxes}")
-
-
-class PickEvent(Event):
-    """
-    a pick event, fired when the user picks a location on the canvas
-    sufficiently close to an artist.
-
-    Attrs: all the :class:`Event` attributes plus
-
-    Attributes
-    ----------
-    mouseevent : `MouseEvent`
-        the mouse event that generated the pick
-
-    artist : `matplotlib.artist.Artist`
-        the picked artist
-
-    other
-        extra class dependent attrs -- e.g., a
-        :class:`~matplotlib.lines.Line2D` pick may define different
-        extra attributes than a
-        :class:`~matplotlib.collections.PatchCollection` pick event
-
-    Examples
-    --------
-    ::
-        ax.plot(np.rand(100), 'o', picker=5)  # 5 points tolerance
-
-        def on_pick(event):
-            line = event.artist
-            xdata, ydata = line.get_data()
-            ind = event.ind
-            print('on pick line:', np.array([xdata[ind], ydata[ind]]).T)
-
-        cid = fig.canvas.mpl_connect('pick_event', on_pick)
-    """
-    def __init__(self, name, canvas, mouseevent, artist,
-                 guiEvent=None, **kwargs):
-        Event.__init__(self, name, canvas, guiEvent)
-        self.mouseevent = mouseevent
-        self.artist = artist
-        self.__dict__.update(kwargs)
-
-
-class KeyEvent(LocationEvent):
-    """
-    A key event (key press, key release).
-
-    Attach additional attributes as defined in
-    :meth:`FigureCanvasBase.mpl_connect`.
-
-    In addition to the :class:`Event` and :class:`LocationEvent`
-    attributes, the following attributes are defined:
-
-    Attributes
-    ----------
-    key : None or str
-        the key(s) pressed. Could be **None**, a single case sensitive ascii
-        character ("g", "G", "#", etc.), a special key
-        ("control", "shift", "f1", "up", etc.) or a
-        combination of the above (e.g., "ctrl+alt+g", "ctrl+alt+G").
-
-    Notes
-    -----
-    Modifier keys will be prefixed to the pressed key and will be in the order
-    "ctrl", "alt", "super". The exception to this rule is when the pressed key
-    is itself a modifier key, therefore "ctrl+alt" and "alt+control" can both
-    be valid key values.
-
-    Examples
-    --------
-    ::
-
-        def on_key(event):
-            print('you pressed', event.key, event.xdata, event.ydata)
-
-        cid = fig.canvas.mpl_connect('key_press_event', on_key)
-    """
-    def __init__(self, name, canvas, key, x=0, y=0, guiEvent=None):
-        LocationEvent.__init__(self, name, canvas, x, y, guiEvent=guiEvent)
-        self.key = key
-
-
-def _get_renderer(figure, print_method, *, draw_disabled=False):
-    """
-    Get the renderer that would be used to save a `~.Figure`, and cache it on
-    the figure.
-
-    If *draw_disabled* is True, additionally replace draw_foo methods on
-    *renderer* by no-ops.  This is used by the tight-bbox-saving renderer,
-    which needs to walk through the artist tree to compute the tight-bbox, but
-    for which the output file may be closed early.
-    """
-    # This is implemented by triggering a draw, then immediately jumping out of
-    # Figure.draw() by raising an exception.
-
-    class Done(Exception):
-        pass
-
-    def _draw(renderer): raise Done(renderer)
-
-    with cbook._setattr_cm(figure, draw=_draw):
-        try:
-            print_method(io.BytesIO())
-        except Done as exc:
-            renderer, = figure._cachedRenderer, = exc.args
-
-    if draw_disabled:
-        for meth_name in dir(RendererBase):
-            if meth_name.startswith("draw_"):
-                setattr(renderer, meth_name, lambda *args, **kwargs: None)
-
-    return renderer
-
-
-def _is_non_interactive_terminal_ipython(ip):
-    """
-    Return whether we are in a a terminal IPython, but non interactive.
-
-    When in _terminal_ IPython, ip.parent will have and `interact` attribute,
-    if this attribute is False we do not setup eventloop integration as the
-    user will _not_ interact with IPython. In all other case (ZMQKernel, or is
-    interactive), we do.
-    """
-    return (hasattr(ip, 'parent')
-        and (ip.parent is not None)
-        and getattr(ip.parent, 'interact', None) is False)
-
-
-class FigureCanvasBase:
-    """
-    The canvas the figure renders into.
-
-    Public attributes
-
-    Attributes
-    ----------
-    figure : `matplotlib.figure.Figure`
-        A high-level figure instance
-    """
-
-    # Set to one of {"qt5", "qt4", "gtk3", "wx", "tk", "macosx"} if an
-    # interactive framework is required, or None otherwise.
-    required_interactive_framework = None
-
-    events = [
-        'resize_event',
-        'draw_event',
-        'key_press_event',
-        'key_release_event',
-        'button_press_event',
-        'button_release_event',
-        'scroll_event',
-        'motion_notify_event',
-        'pick_event',
-        'idle_event',
-        'figure_enter_event',
-        'figure_leave_event',
-        'axes_enter_event',
-        'axes_leave_event',
-        'close_event'
-    ]
-
-    fixed_dpi = None
-
-    filetypes = _default_filetypes
-    if _has_pil:
-        # JPEG support
-        register_backend('jpg', 'matplotlib.backends.backend_agg',
-                         'Joint Photographic Experts Group')
-        register_backend('jpeg', 'matplotlib.backends.backend_agg',
-                         'Joint Photographic Experts Group')
-        # TIFF support
-        register_backend('tif', 'matplotlib.backends.backend_agg',
-                         'Tagged Image File Format')
-        register_backend('tiff', 'matplotlib.backends.backend_agg',
-                         'Tagged Image File Format')
-
-    @cbook._classproperty
-    def supports_blit(cls):
-        return (hasattr(cls, "copy_from_bbox")
-                and hasattr(cls, "restore_region"))
-
-    def __init__(self, figure):
-        self._fix_ipython_backend2gui()
-        self._is_idle_drawing = True
-        self._is_saving = False
-        figure.set_canvas(self)
-        self.figure = figure
-        # a dictionary from event name to a dictionary that maps cid->func
-        self.callbacks = cbook.CallbackRegistry()
-        self.widgetlock = widgets.LockDraw()
-        self._button = None  # the button pressed
-        self._key = None  # the key pressed
-        self._lastx, self._lasty = None, None
-        self.button_pick_id = self.mpl_connect('button_press_event', self.pick)
-        self.scroll_pick_id = self.mpl_connect('scroll_event', self.pick)
-        self.mouse_grabber = None  # the axes currently grabbing mouse
-        self.toolbar = None  # NavigationToolbar2 will set me
-        self._is_idle_drawing = False
-
-    @classmethod
-    @functools.lru_cache()
-    def _fix_ipython_backend2gui(cls):
-        # Fix hard-coded module -> toolkit mapping in IPython (used for
-        # `ipython --auto`).  This cannot be done at import time due to
-        # ordering issues, so we do it when creating a canvas, and should only
-        # be done once per class (hence the `lru_cache(1)`).
-        if "IPython" not in sys.modules:
-            return
-        import IPython
-        ip = IPython.get_ipython()
-        if not ip:
-            return
-        from IPython.core import pylabtools as pt
-        if (not hasattr(pt, "backend2gui")
-                or not hasattr(ip, "enable_matplotlib")):
-            # In case we ever move the patch to IPython and remove these APIs,
-            # don't break on our side.
-            return
-        rif = getattr(cls, "required_interactive_framework", None)
-        backend2gui_rif = {"qt5": "qt", "qt4": "qt", "gtk3": "gtk3",
-                           "wx": "wx", "macosx": "osx"}.get(rif)
-        if backend2gui_rif:
-            if _is_non_interactive_terminal_ipython(ip):
-                ip.enable_gui(backend2gui_rif)
-
-    @contextmanager
-    def _idle_draw_cntx(self):
-        self._is_idle_drawing = True
-        try:
-            yield
-        finally:
-            self._is_idle_drawing = False
-
-    def is_saving(self):
-        """
-        Returns whether the renderer is in the process of saving
-        to a file, rather than rendering for an on-screen buffer.
-        """
-        return self._is_saving
-
-    def pick(self, mouseevent):
-        if not self.widgetlock.locked():
-            self.figure.pick(mouseevent)
-
-    def blit(self, bbox=None):
-        """Blit the canvas in bbox (default entire canvas)."""
-
-    def resize(self, w, h):
-        """Set the canvas size in pixels."""
-
-    def draw_event(self, renderer):
-        """Pass a `DrawEvent` to all functions connected to ``draw_event``."""
-        s = 'draw_event'
-        event = DrawEvent(s, self, renderer)
-        self.callbacks.process(s, event)
-
-    def resize_event(self):
-        """
-        Pass a `ResizeEvent` to all functions connected to ``resize_event``.
-        """
-        s = 'resize_event'
-        event = ResizeEvent(s, self)
-        self.callbacks.process(s, event)
-        self.draw_idle()
-
-    def close_event(self, guiEvent=None):
-        """
-        Pass a `CloseEvent` to all functions connected to ``close_event``.
-        """
-        s = 'close_event'
-        try:
-            event = CloseEvent(s, self, guiEvent=guiEvent)
-            self.callbacks.process(s, event)
-        except (TypeError, AttributeError):
-            pass
-            # Suppress the TypeError when the python session is being killed.
-            # It may be that a better solution would be a mechanism to
-            # disconnect all callbacks upon shutdown.
-            # AttributeError occurs on OSX with qt4agg upon exiting
-            # with an open window; 'callbacks' attribute no longer exists.
-
-    def key_press_event(self, key, guiEvent=None):
-        """
-        Pass a `KeyEvent` to all functions connected to ``key_press_event``.
-        """
-        self._key = key
-        s = 'key_press_event'
-        event = KeyEvent(
-            s, self, key, self._lastx, self._lasty, guiEvent=guiEvent)
-        self.callbacks.process(s, event)
-
-    def key_release_event(self, key, guiEvent=None):
-        """
-        Pass a `KeyEvent` to all functions connected to ``key_release_event``.
-        """
-        s = 'key_release_event'
-        event = KeyEvent(
-            s, self, key, self._lastx, self._lasty, guiEvent=guiEvent)
-        self.callbacks.process(s, event)
-        self._key = None
-
-    def pick_event(self, mouseevent, artist, **kwargs):
-        """
-        This method will be called by artists who are picked and will
-        fire off :class:`PickEvent` callbacks registered listeners
-        """
-        s = 'pick_event'
-        event = PickEvent(s, self, mouseevent, artist,
-                          guiEvent=mouseevent.guiEvent,
-                          **kwargs)
-        self.callbacks.process(s, event)
-
-    def scroll_event(self, x, y, step, guiEvent=None):
-        """
-        Backend derived classes should call this function on any
-        scroll wheel event.  (*x*, *y*) are the canvas coords ((0, 0) is lower
-        left).  button and key are as defined in MouseEvent.
-
-        This method will be call all functions connected to the
-        'scroll_event' with a :class:`MouseEvent` instance.
-        """
-        if step >= 0:
-            self._button = 'up'
-        else:
-            self._button = 'down'
-        s = 'scroll_event'
-        mouseevent = MouseEvent(s, self, x, y, self._button, self._key,
-                                step=step, guiEvent=guiEvent)
-        self.callbacks.process(s, mouseevent)
-
-    def button_press_event(self, x, y, button, dblclick=False, guiEvent=None):
-        """
-        Backend derived classes should call this function on any mouse
-        button press.  (*x*, *y*) are the canvas coords ((0, 0) is lower left).
-        button and key are as defined in :class:`MouseEvent`.
-
-        This method will be call all functions connected to the
-        'button_press_event' with a :class:`MouseEvent` instance.
-        """
-        self._button = button
-        s = 'button_press_event'
-        mouseevent = MouseEvent(s, self, x, y, button, self._key,
-                                dblclick=dblclick, guiEvent=guiEvent)
-        self.callbacks.process(s, mouseevent)
-
-    def button_release_event(self, x, y, button, guiEvent=None):
-        """
-        Backend derived classes should call this function on any mouse
-        button release.
-
-        This method will call all functions connected to the
-        'button_release_event' with a :class:`MouseEvent` instance.
-
-        Parameters
-        ----------
-        x : float
-            The canvas coordinates where 0=left.
-        y : float
-            The canvas coordinates where 0=bottom.
-        guiEvent
-            The native UI event that generated the Matplotlib event.
-        """
-        s = 'button_release_event'
-        event = MouseEvent(s, self, x, y, button, self._key, guiEvent=guiEvent)
-        self.callbacks.process(s, event)
-        self._button = None
-
-    def motion_notify_event(self, x, y, guiEvent=None):
-        """
-        Backend derived classes should call this function on any
-        motion-notify-event.
-
-        This method will call all functions connected to the
-        'motion_notify_event' with a :class:`MouseEvent` instance.
-
-        Parameters
-        ----------
-        x : float
-            The canvas coordinates where 0=left.
-        y : float
-            The canvas coordinates where 0=bottom.
-        guiEvent
-            The native UI event that generated the Matplotlib event.
-        """
-        self._lastx, self._lasty = x, y
-        s = 'motion_notify_event'
-        event = MouseEvent(s, self, x, y, self._button, self._key,
-                           guiEvent=guiEvent)
-        self.callbacks.process(s, event)
-
-    def leave_notify_event(self, guiEvent=None):
-        """
-        Backend derived classes should call this function when leaving
-        canvas
-
-        Parameters
-        ----------
-        guiEvent
-            The native UI event that generated the Matplotlib event.
-        """
-        self.callbacks.process('figure_leave_event', LocationEvent.lastevent)
-        LocationEvent.lastevent = None
-        self._lastx, self._lasty = None, None
-
-    def enter_notify_event(self, guiEvent=None, xy=None):
-        """
-        Backend derived classes should call this function when entering
-        canvas
-
-        Parameters
-        ----------
-        guiEvent
-            The native UI event that generated the Matplotlib event.
-        xy : (float, float)
-            The coordinate location of the pointer when the canvas is entered.
-        """
-        if xy is not None:
-            x, y = xy
-            self._lastx, self._lasty = x, y
-        else:
-            x = None
-            y = None
-            cbook.warn_deprecated(
-                '3.0', message='enter_notify_event expects a location but '
-                'your backend did not pass one.')
-
-        event = LocationEvent('figure_enter_event', self, x, y, guiEvent)
-        self.callbacks.process('figure_enter_event', event)
-
-    def inaxes(self, xy):
-        """
-        Return the topmost visible `~.axes.Axes` containing the point *xy*.
-
-        Parameters
-        ----------
-        xy : tuple or list
-            (x, y) coordinates.
-            x position - pixels from left of canvas.
-            y position - pixels from bottom of canvas.
-
-        Returns
-        -------
-        axes : `~matplotlib.axes.Axes` or None
-            The topmost visible axes containing the point, or None if no axes.
-        """
-        axes_list = [a for a in self.figure.get_axes()
-                     if a.patch.contains_point(xy) and a.get_visible()]
-        if axes_list:
-            axes = cbook._topmost_artist(axes_list)
-        else:
-            axes = None
-
-        return axes
-
-    def grab_mouse(self, ax):
-        """
-        Set the child axes which are currently grabbing the mouse events.
-        Usually called by the widgets themselves.
-        It is an error to call this if the mouse is already grabbed by
-        another axes.
-        """
-        if self.mouse_grabber not in (None, ax):
-            raise RuntimeError("Another Axes already grabs mouse input")
-        self.mouse_grabber = ax
-
-    def release_mouse(self, ax):
-        """
-        Release the mouse grab held by the axes, ax.
-        Usually called by the widgets.
-        It is ok to call this even if you ax doesn't have the mouse
-        grab currently.
-        """
-        if self.mouse_grabber is ax:
-            self.mouse_grabber = None
-
-    def draw(self, *args, **kwargs):
-        """Render the :class:`~matplotlib.figure.Figure`."""
-
-    def draw_idle(self, *args, **kwargs):
-        """
-        Request a widget redraw once control returns to the GUI event loop.
-
-        Even if multiple calls to `draw_idle` occur before control returns
-        to the GUI event loop, the figure will only be rendered once.
-
-        Notes
-        -----
-        Backends may choose to override the method and implement their own
-        strategy to prevent multiple renderings.
-
-        """
-        if not self._is_idle_drawing:
-            with self._idle_draw_cntx():
-                self.draw(*args, **kwargs)
-
-    @cbook.deprecated("3.2")
-    def draw_cursor(self, event):
-        """
-        Draw a cursor in the event.axes if inaxes is not None.  Use
-        native GUI drawing for efficiency if possible
-        """
-
-    def get_width_height(self):
-        """
-        Return the figure width and height in points or pixels
-        (depending on the backend), truncated to integers
-        """
-        return int(self.figure.bbox.width), int(self.figure.bbox.height)
-
-    @classmethod
-    def get_supported_filetypes(cls):
-        """Return dict of savefig file formats supported by this backend."""
-        return cls.filetypes
-
-    @classmethod
-    def get_supported_filetypes_grouped(cls):
-        """
-        Return a dict of savefig file formats supported by this backend,
-        where the keys are a file type name, such as 'Joint Photographic
-        Experts Group', and the values are a list of filename extensions used
-        for that filetype, such as ['jpg', 'jpeg'].
-        """
-        groupings = {}
-        for ext, name in cls.filetypes.items():
-            groupings.setdefault(name, []).append(ext)
-            groupings[name].sort()
-        return groupings
-
-    def _get_output_canvas(self, fmt):
-        """
-        Return a canvas suitable for saving figures to a specified file format.
-
-        If necessary, this function will switch to a registered backend that
-        supports the format.
-        """
-        # Return the current canvas if it supports the requested format.
-        if hasattr(self, 'print_{}'.format(fmt)):
-            return self
-        # Return a default canvas for the requested format, if it exists.
-        canvas_class = get_registered_canvas_class(fmt)
-        if canvas_class:
-            return self.switch_backends(canvas_class)
-        # Else report error for unsupported format.
-        raise ValueError(
-            "Format {!r} is not supported (supported formats: {})"
-            .format(fmt, ", ".join(sorted(self.get_supported_filetypes()))))
-
-    def print_figure(self, filename, dpi=None, facecolor=None, edgecolor=None,
-                     orientation='portrait', format=None,
-                     *, bbox_inches=None, **kwargs):
-        """
-        Render the figure to hardcopy. Set the figure patch face and edge
-        colors.  This is useful because some of the GUIs have a gray figure
-        face color background and you'll probably want to override this on
-        hardcopy.
-
-        Parameters
-        ----------
-        filename
-            can also be a file object on image backends
-
-        orientation : {'landscape', 'portrait'}, default: 'portrait'
-            only currently applies to PostScript printing.
-
-        dpi : scalar, optional
-            the dots per inch to save the figure in; if None, use savefig.dpi
-
-        facecolor : color, default: :rc:`savefig.facecolor`
-            The facecolor of the figure.
-
-        edgecolor : color, default: :rc:`savefig.edgecolor`
-            The edgecolor of the figure.
-
-        format : str, optional
-            Force a specific file format. If not given, the format is inferred
-            from the *filename* extension, and if that fails from
-            :rc:`savefig.format`.
-
-        bbox_inches : 'tight' or `~matplotlib.transforms.Bbox`, \
-default: :rc:`savefig.bbox`
-            Bbox in inches. Only the given portion of the figure is
-            saved. If 'tight', try to figure out the tight bbox of
-            the figure.
-
-        pad_inches : float, default: :rc:`savefig.pad_inches`
-            Amount of padding around the figure when *bbox_inches* is 'tight'.
-
-        bbox_extra_artists : list of `~matplotlib.artist.Artist`, optional
-            A list of extra artists that will be considered when the
-            tight bbox is calculated.
-
-        """
-        if format is None:
-            # get format from filename, or from backend's default filetype
-            if isinstance(filename, os.PathLike):
-                filename = os.fspath(filename)
-            if isinstance(filename, str):
-                format = os.path.splitext(filename)[1][1:]
-            if format is None or format == '':
-                format = self.get_default_filetype()
-                if isinstance(filename, str):
-                    filename = filename.rstrip('.') + '.' + format
-        format = format.lower()
-
-        # get canvas object and print method for format
-        canvas = self._get_output_canvas(format)
-        print_method = getattr(canvas, 'print_%s' % format)
-
-        if dpi is None:
-            dpi = rcParams['savefig.dpi']
-        if dpi == 'figure':
-            dpi = getattr(self.figure, '_original_dpi', self.figure.dpi)
-
-        # Remove the figure manager, if any, to avoid resizing the GUI widget.
-        # Some code (e.g. Figure.show) differentiates between having *no*
-        # manager and a *None* manager, which should be fixed at some point,
-        # but this should be fine.
-        with cbook._setattr_cm(self, _is_saving=True, manager=None), \
-                cbook._setattr_cm(self.figure, dpi=dpi):
-
-            if facecolor is None:
-                facecolor = rcParams['savefig.facecolor']
-            if edgecolor is None:
-                edgecolor = rcParams['savefig.edgecolor']
-
-            origfacecolor = self.figure.get_facecolor()
-            origedgecolor = self.figure.get_edgecolor()
-
-            self.figure.set_facecolor(facecolor)
-            self.figure.set_edgecolor(edgecolor)
-
-            if bbox_inches is None:
-                bbox_inches = rcParams['savefig.bbox']
-
-            if bbox_inches:
-                if bbox_inches == "tight":
-                    renderer = _get_renderer(
-                        self.figure,
-                        functools.partial(
-                            print_method, dpi=dpi, orientation=orientation),
-                        draw_disabled=True)
-                    self.figure.draw(renderer)
-                    bbox_artists = kwargs.pop("bbox_extra_artists", None)
-                    bbox_inches = self.figure.get_tightbbox(renderer,
-                            bbox_extra_artists=bbox_artists)
-                    pad = kwargs.pop("pad_inches", None)
-                    if pad is None:
-                        pad = rcParams['savefig.pad_inches']
-
-                    bbox_inches = bbox_inches.padded(pad)
-
-                # call adjust_bbox to save only the given area
-                restore_bbox = tight_bbox.adjust_bbox(self.figure, bbox_inches,
-                                                      canvas.fixed_dpi)
-
-                _bbox_inches_restore = (bbox_inches, restore_bbox)
-            else:
-                _bbox_inches_restore = None
-
-            try:
-                result = print_method(
-                    filename,
-                    dpi=dpi,
-                    facecolor=facecolor,
-                    edgecolor=edgecolor,
-                    orientation=orientation,
-                    bbox_inches_restore=_bbox_inches_restore,
-                    **kwargs)
-            finally:
-                if bbox_inches and restore_bbox:
-                    restore_bbox()
-
-                self.figure.set_facecolor(origfacecolor)
-                self.figure.set_edgecolor(origedgecolor)
-                self.figure.set_canvas(self)
-            return result
-
-    @classmethod
-    def get_default_filetype(cls):
-        """
-        Get the default savefig file format as specified in rcParam
-        ``savefig.format``. Returned string excludes period. Overridden
-        in backends that only support a single file type.
-        """
-        return rcParams['savefig.format']
-
-    def get_window_title(self):
-        """
-        Get the title text of the window containing the figure.
-        Return None if there is no window (e.g., a PS backend).
-        """
-        if hasattr(self, "manager"):
-            return self.manager.get_window_title()
-
-    def set_window_title(self, title):
-        """
-        Set the title text of the window containing the figure.  Note that
-        this has no effect if there is no window (e.g., a PS backend).
-        """
-        if hasattr(self, "manager"):
-            self.manager.set_window_title(title)
-
-    def get_default_filename(self):
-        """
-        Return a string, which includes extension, suitable for use as
-        a default filename.
-        """
-        default_basename = self.get_window_title() or 'image'
-        default_basename = default_basename.replace(' ', '_')
-        default_filetype = self.get_default_filetype()
-        default_filename = default_basename + '.' + default_filetype
-        return default_filename
-
-    def switch_backends(self, FigureCanvasClass):
-        """
-        Instantiate an instance of FigureCanvasClass
-
-        This is used for backend switching, e.g., to instantiate a
-        FigureCanvasPS from a FigureCanvasGTK.  Note, deep copying is
-        not done, so any changes to one of the instances (e.g., setting
-        figure size or line props), will be reflected in the other
-        """
-        newCanvas = FigureCanvasClass(self.figure)
-        newCanvas._is_saving = self._is_saving
-        return newCanvas
-
-    def mpl_connect(self, s, func):
-        """
-        Bind function *func* to event *s*.
-
-        Parameters
-        ----------
-        s : str
-            One of the following events ids:
-
-            - 'button_press_event'
-            - 'button_release_event'
-            - 'draw_event'
-            - 'key_press_event'
-            - 'key_release_event'
-            - 'motion_notify_event'
-            - 'pick_event'
-            - 'resize_event'
-            - 'scroll_event'
-            - 'figure_enter_event',
-            - 'figure_leave_event',
-            - 'axes_enter_event',
-            - 'axes_leave_event'
-            - 'close_event'.
-
-        func : callable
-            The callback function to be executed, which must have the
-            signature::
-
-                def func(event: Event) -> Any
-
-            For the location events (button and key press/release), if the
-            mouse is over the axes, the ``inaxes`` attribute of the event will
-            be set to the `~matplotlib.axes.Axes` the event occurs is over, and
-            additionally, the variables ``xdata`` and ``ydata`` attributes will
-            be set to the mouse location in data coordinates.  See `.KeyEvent`
-            and `.MouseEvent` for more info.
-
-        Returns
-        -------
-        cid
-            A connection id that can be used with
-            `.FigureCanvasBase.mpl_disconnect`.
-
-        Examples
-        --------
-        ::
-
-            def on_press(event):
-                print('you pressed', event.button, event.xdata, event.ydata)
-
-            cid = canvas.mpl_connect('button_press_event', on_press)
-        """
-
-        return self.callbacks.connect(s, func)
-
-    def mpl_disconnect(self, cid):
-        """
-        Disconnect the callback with id *cid*.
-
-        Examples
-        --------
-        ::
-
-            cid = canvas.mpl_connect('button_press_event', on_press)
-            # ... later
-            canvas.mpl_disconnect(cid)
-        """
-        return self.callbacks.disconnect(cid)
-
-    def new_timer(self, *args, **kwargs):
-        """
-        Create a new backend-specific subclass of `.Timer`.
-
-        This is useful for getting periodic events through the backend's native
-        event loop.  Implemented only for backends with GUIs.
-
-        Other Parameters
-        ----------------
-        interval : scalar
-            Timer interval in milliseconds
-
-        callbacks : List[Tuple[callable, Tuple, Dict]]
-            Sequence of (func, args, kwargs) where ``func(*args, **kwargs)``
-            will be executed by the timer every *interval*.
-
-            Callbacks which return ``False`` or ``0`` will be removed from the
-            timer.
-
-        Examples
-        --------
-        >>> timer = fig.canvas.new_timer(callbacks=[(f1, (1, ), {'a': 3}),])
-        """
-        return TimerBase(*args, **kwargs)
-
-    def flush_events(self):
-        """
-        Flush the GUI events for the figure.
-
-        Interactive backends need to reimplement this method.
-        """
-
-    def start_event_loop(self, timeout=0):
-        """
-        Start a blocking event loop.
-
-        Such an event loop is used by interactive functions, such as `ginput`
-        and `waitforbuttonpress`, to wait for events.
-
-        The event loop blocks until a callback function triggers
-        `stop_event_loop`, or *timeout* is reached.
-
-        If *timeout* is negative, never timeout.
-
-        Only interactive backends need to reimplement this method and it relies
-        on `flush_events` being properly implemented.
-
-        Interactive backends should implement this in a more native way.
-        """
-        if timeout <= 0:
-            timeout = np.inf
-        timestep = 0.01
-        counter = 0
-        self._looping = True
-        while self._looping and counter * timestep < timeout:
-            self.flush_events()
-            time.sleep(timestep)
-            counter += 1
-
-    def stop_event_loop(self):
-        """
-        Stop the current blocking event loop.
-
-        Interactive backends need to reimplement this to match
-        `start_event_loop`
-        """
-        self._looping = False
-
-
-def key_press_handler(event, canvas, toolbar=None):
-    """
-    Implement the default Matplotlib key bindings for the canvas and toolbar
-    described at :ref:`key-event-handling`.
-
-    Parameters
-    ----------
-    event : :class:`KeyEvent`
-        a key press/release event
-    canvas : :class:`FigureCanvasBase`
-        the backend-specific canvas instance
-    toolbar : :class:`NavigationToolbar2`
-        the navigation cursor toolbar
-    """
-    # these bindings happen whether you are over an axes or not
-
-    if event.key is None:
-        return
-
-    # Load key-mappings from rcParams.
-    fullscreen_keys = rcParams['keymap.fullscreen']
-    home_keys = rcParams['keymap.home']
-    back_keys = rcParams['keymap.back']
-    forward_keys = rcParams['keymap.forward']
-    pan_keys = rcParams['keymap.pan']
-    zoom_keys = rcParams['keymap.zoom']
-    save_keys = rcParams['keymap.save']
-    quit_keys = rcParams['keymap.quit']
-    grid_keys = rcParams['keymap.grid']
-    grid_minor_keys = rcParams['keymap.grid_minor']
-    toggle_yscale_keys = rcParams['keymap.yscale']
-    toggle_xscale_keys = rcParams['keymap.xscale']
-    all_keys = rcParams['keymap.all_axes']
-
-    # toggle fullscreen mode ('f', 'ctrl + f')
-    if event.key in fullscreen_keys:
-        try:
-            canvas.manager.full_screen_toggle()
-        except AttributeError:
-            pass
-
-    # quit the figure (default key 'ctrl+w')
-    if event.key in quit_keys:
-        Gcf.destroy_fig(canvas.figure)
-
-    if toolbar is not None:
-        # home or reset mnemonic  (default key 'h', 'home' and 'r')
-        if event.key in home_keys:
-            toolbar.home()
-        # forward / backward keys to enable left handed quick navigation
-        # (default key for backward: 'left', 'backspace' and 'c')
-        elif event.key in back_keys:
-            toolbar.back()
-        # (default key for forward: 'right' and 'v')
-        elif event.key in forward_keys:
-            toolbar.forward()
-        # pan mnemonic (default key 'p')
-        elif event.key in pan_keys:
-            toolbar.pan()
-            toolbar._update_cursor(event)
-        # zoom mnemonic (default key 'o')
-        elif event.key in zoom_keys:
-            toolbar.zoom()
-            toolbar._update_cursor(event)
-        # saving current figure (default key 's')
-        elif event.key in save_keys:
-            toolbar.save_figure()
-
-    if event.inaxes is None:
-        return
-
-    # these bindings require the mouse to be over an axes to trigger
-    def _get_uniform_gridstate(ticks):
-        # Return True/False if all grid lines are on or off, None if they are
-        # not all in the same state.
-        if all(tick.gridline.get_visible() for tick in ticks):
-            return True
-        elif not any(tick.gridline.get_visible() for tick in ticks):
-            return False
-        else:
-            return None
-
-    ax = event.inaxes
-    # toggle major grids in current axes (default key 'g')
-    # Both here and below (for 'G'), we do nothing if *any* grid (major or
-    # minor, x or y) is not in a uniform state, to avoid messing up user
-    # customization.
-    if (event.key in grid_keys
-            # Exclude minor grids not in a uniform state.
-            and None not in [_get_uniform_gridstate(ax.xaxis.minorTicks),
-                             _get_uniform_gridstate(ax.yaxis.minorTicks)]):
-        x_state = _get_uniform_gridstate(ax.xaxis.majorTicks)
-        y_state = _get_uniform_gridstate(ax.yaxis.majorTicks)
-        cycle = [(False, False), (True, False), (True, True), (False, True)]
-        try:
-            x_state, y_state = (
-                cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)])
-        except ValueError:
-            # Exclude major grids not in a uniform state.
-            pass
-        else:
-            # If turning major grids off, also turn minor grids off.
-            ax.grid(x_state, which="major" if x_state else "both", axis="x")
-            ax.grid(y_state, which="major" if y_state else "both", axis="y")
-            canvas.draw_idle()
-    # toggle major and minor grids in current axes (default key 'G')
-    if (event.key in grid_minor_keys
-            # Exclude major grids not in a uniform state.
-            and None not in [_get_uniform_gridstate(ax.xaxis.majorTicks),
-                             _get_uniform_gridstate(ax.yaxis.majorTicks)]):
-        x_state = _get_uniform_gridstate(ax.xaxis.minorTicks)
-        y_state = _get_uniform_gridstate(ax.yaxis.minorTicks)
-        cycle = [(False, False), (True, False), (True, True), (False, True)]
-        try:
-            x_state, y_state = (
-                cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)])
-        except ValueError:
-            # Exclude minor grids not in a uniform state.
-            pass
-        else:
-            ax.grid(x_state, which="both", axis="x")
-            ax.grid(y_state, which="both", axis="y")
-            canvas.draw_idle()
-    # toggle scaling of y-axes between 'log and 'linear' (default key 'l')
-    elif event.key in toggle_yscale_keys:
-        scale = ax.get_yscale()
-        if scale == 'log':
-            ax.set_yscale('linear')
-            ax.figure.canvas.draw_idle()
-        elif scale == 'linear':
-            try:
-                ax.set_yscale('log')
-            except ValueError as exc:
-                _log.warning(str(exc))
-                ax.set_yscale('linear')
-            ax.figure.canvas.draw_idle()
-    # toggle scaling of x-axes between 'log and 'linear' (default key 'k')
-    elif event.key in toggle_xscale_keys:
-        scalex = ax.get_xscale()
-        if scalex == 'log':
-            ax.set_xscale('linear')
-            ax.figure.canvas.draw_idle()
-        elif scalex == 'linear':
-            try:
-                ax.set_xscale('log')
-            except ValueError as exc:
-                _log.warning(str(exc))
-                ax.set_xscale('linear')
-            ax.figure.canvas.draw_idle()
-    # enable nagivation for all axes that contain the event (default key 'a')
-    elif event.key in all_keys:
-        for a in canvas.figure.get_axes():
-            if (event.x is not None and event.y is not None
-                    and a.in_axes(event)):  # FIXME: Why only these?
-                a.set_navigate(True)
-    # enable navigation only for axes with this index (if such an axes exist,
-    # otherwise do nothing)
-    elif event.key.isdigit() and event.key != '0':
-        n = int(event.key) - 1
-        if n < len(canvas.figure.get_axes()):
-            for i, a in enumerate(canvas.figure.get_axes()):
-                if (event.x is not None and event.y is not None
-                        and a.in_axes(event)):  # FIXME: Why only these?
-                    a.set_navigate(i == n)
-
-
-def button_press_handler(event, canvas, toolbar=None):
-    """
-    The default Matplotlib button actions for extra mouse buttons.
-    """
-    if toolbar is not None:
-        button_name = str(MouseButton(event.button))
-        if button_name in rcParams['keymap.back']:
-            toolbar.back()
-        elif button_name in rcParams['keymap.forward']:
-            toolbar.forward()
-
-
-class NonGuiException(Exception):
-    """Raised when trying show a figure in a non-GUI backend."""
-    pass
-
-
-class FigureManagerBase:
-    """
-    A backend-independent abstraction of a figure container and controller.
-
-    The figure manager is used by pyplot to interact with the window in a
-    backend-independent way. It's an adapter for the real (GUI) framework that
-    represents the visual figure on screen.
-
-    GUI backends define from this class to translate common operations such
-    as *show* or *resize* to the GUI-specific code. Non-GUI backends do not
-    support these operations an can just use the base class.
-
-    This following basic operations are accessible:
-
-    **Window operations**
-
-    - `~.FigureManagerBase.show`
-    - `~.FigureManagerBase.destroy`
-    - `~.FigureManagerBase.full_screen_toggle`
-    - `~.FigureManagerBase.resize`
-    - `~.FigureManagerBase.get_window_title`
-    - `~.FigureManagerBase.set_window_title`
-
-    **Key and mouse button press handling**
-
-    The figure manager sets up default key and mouse button press handling by
-    hooking up the `.key_press_handler` to the matplotlib event system. This
-    ensures the same shortcuts and mouse actions across backends.
-
-    **Other operations**
-
-    Subclasses will have additional attributes and functions to access
-    additional functionality. This is of course backend-specific. For example,
-    most GUI backends have ``window`` and ``toolbar`` attributes that give
-    access to the native GUI widgets of the respective framework.
-
-    Attributes
-    ----------
-    canvas : :class:`FigureCanvasBase`
-        The backend-specific canvas instance.
-
-    num : int or str
-        The figure number.
-
-    key_press_handler_id : int
-        The default key handler cid, when using the toolmanager.
-        To disable the default key press handling use::
-
-            figure.canvas.mpl_disconnect(
-                figure.canvas.manager.key_press_handler_id)
-
-    button_press_handler_id : int
-        The default mouse button handler cid, when using the toolmanager.
-        To disable the default button press handling use::
-
-            figure.canvas.mpl_disconnect(
-                figure.canvas.manager.button_press_handler_id)
-    """
-    def __init__(self, canvas, num):
-        self.canvas = canvas
-        canvas.manager = self  # store a pointer to parent
-        self.num = num
-
-        self.key_press_handler_id = None
-        self.button_press_handler_id = None
-        if rcParams['toolbar'] != 'toolmanager':
-            self.key_press_handler_id = self.canvas.mpl_connect(
-                'key_press_event',
-                self.key_press)
-            self.button_press_handler_id = self.canvas.mpl_connect(
-                'button_press_event',
-                self.button_press)
-
-        self.toolmanager = None
-        self.toolbar = None
-
-        @self.canvas.figure.add_axobserver
-        def notify_axes_change(fig):
-            # Called whenever the current axes is changed.
-            if self.toolmanager is None and self.toolbar is not None:
-                self.toolbar.update()
-
-    def show(self):
-        """
-        For GUI backends, show the figure window and redraw.
-        For non-GUI backends, raise an exception to be caught
-        by :meth:`~matplotlib.figure.Figure.show`, for an
-        optional warning.
-        """
-        raise NonGuiException()
-
-    def destroy(self):
-        pass
-
-    def full_screen_toggle(self):
-        pass
-
-    def resize(self, w, h):
-        """For GUI backends, resize the window (in pixels)."""
-
-    def key_press(self, event):
-        """
-        Implement the default Matplotlib key bindings defined at
-        :ref:`key-event-handling`.
-        """
-        if rcParams['toolbar'] != 'toolmanager':
-            key_press_handler(event, self.canvas, self.canvas.toolbar)
-
-    def button_press(self, event):
-        """The default Matplotlib button actions for extra mouse buttons."""
-        if rcParams['toolbar'] != 'toolmanager':
-            button_press_handler(event, self.canvas, self.canvas.toolbar)
-
-    def get_window_title(self):
-        """
-        Get the title text of the window containing the figure.
-
-        Return None for non-GUI (e.g., PS) backends.
-        """
-        return 'image'
-
-    def set_window_title(self, title):
-        """
-        Set the title text of the window containing the figure.
-
-        This has no effect for non-GUI (e.g., PS) backends.
-        """
-
-
-cursors = tools.cursors
-
-
-class NavigationToolbar2:
-    """
-    Base class for the navigation cursor, version 2
-
-    backends must implement a canvas that handles connections for
-    'button_press_event' and 'button_release_event'.  See
-    :meth:`FigureCanvasBase.mpl_connect` for more information
-
-
-    They must also define
-
-      :meth:`save_figure`
-         save the current figure
-
-      :meth:`set_cursor`
-         if you want the pointer icon to change
-
-      :meth:`_init_toolbar`
-         create your toolbar widget
-
-      :meth:`draw_rubberband` (optional)
-         draw the zoom to rect "rubberband" rectangle
-
-      :meth:`press`  (optional)
-         whenever a mouse button is pressed, you'll be notified with
-         the event
-
-      :meth:`release` (optional)
-         whenever a mouse button is released, you'll be notified with
-         the event
-
-      :meth:`set_message` (optional)
-         display message
-
-      :meth:`set_history_buttons` (optional)
-         you can change the history back / forward buttons to
-         indicate disabled / enabled state.
-
-    That's it, we'll do the rest!
-    """
-
-    # list of toolitems to add to the toolbar, format is:
-    # (
-    #   text, # the text of the button (often not visible to users)
-    #   tooltip_text, # the tooltip shown on hover (where possible)
-    #   image_file, # name of the image for the button (without the extension)
-    #   name_of_method, # name of the method in NavigationToolbar2 to call
-    # )
-    toolitems = (
-        ('Home', 'Reset original view', 'home', 'home'),
-        ('Back', 'Back to previous view', 'back', 'back'),
-        ('Forward', 'Forward to next view', 'forward', 'forward'),
-        (None, None, None, None),
-        ('Pan', 'Pan axes with left mouse, zoom with right', 'move', 'pan'),
-        ('Zoom', 'Zoom to rectangle', 'zoom_to_rect', 'zoom'),
-        ('Subplots', 'Configure subplots', 'subplots', 'configure_subplots'),
-        (None, None, None, None),
-        ('Save', 'Save the figure', 'filesave', 'save_figure'),
-      )
-
-    def __init__(self, canvas):
-        self.canvas = canvas
-        canvas.toolbar = self
-        self._nav_stack = cbook.Stack()
-        self._xypress = None  # location and axis info at the time of the press
-        self._idPress = None
-        self._idRelease = None
-        self._active = None
-        # This cursor will be set after the initial draw.
-        self._lastCursor = cursors.POINTER
-        self._init_toolbar()
-        self._idDrag = self.canvas.mpl_connect(
-            'motion_notify_event', self.mouse_move)
-
-        self._ids_zoom = []
-        self._zoom_mode = None
-
-        self._button_pressed = None  # determined by button pressed at start
-
-        self.mode = ''  # a mode string for the status bar
-        self.set_history_buttons()
-
-    def set_message(self, s):
-        """Display a message on toolbar or in status bar."""
-
-    def back(self, *args):
-        """Move back up the view lim stack."""
-        self._nav_stack.back()
-        self.set_history_buttons()
-        self._update_view()
-
-    def draw_rubberband(self, event, x0, y0, x1, y1):
-        """
-        Draw a rectangle rubberband to indicate zoom limits.
-
-        Note that it is not guaranteed that ``x0 <= x1`` and ``y0 <= y1``.
-        """
-
-    def remove_rubberband(self):
-        """Remove the rubberband."""
-
-    def forward(self, *args):
-        """Move forward in the view lim stack."""
-        self._nav_stack.forward()
-        self.set_history_buttons()
-        self._update_view()
-
-    def home(self, *args):
-        """Restore the original view."""
-        self._nav_stack.home()
-        self.set_history_buttons()
-        self._update_view()
-
-    def _init_toolbar(self):
-        """
-        This is where you actually build the GUI widgets (called by
-        __init__).  The icons ``home.xpm``, ``back.xpm``, ``forward.xpm``,
-        ``hand.xpm``, ``zoom_to_rect.xpm`` and ``filesave.xpm`` are standard
-        across backends (there are ppm versions in CVS also).
-
-        You just need to set the callbacks
-
-        home         : self.home
-        back         : self.back
-        forward      : self.forward
-        hand         : self.pan
-        zoom_to_rect : self.zoom
-        filesave     : self.save_figure
-
-        You only need to define the last one - the others are in the base
-        class implementation.
-
-        """
-        raise NotImplementedError
-
-    def _update_cursor(self, event):
-        """
-        Update the cursor after a mouse move event or a tool (de)activation.
-        """
-        if not event.inaxes or not self._active:
-            if self._lastCursor != cursors.POINTER:
-                self.set_cursor(cursors.POINTER)
-                self._lastCursor = cursors.POINTER
-        else:
-            if (self._active == 'ZOOM'
-                    and self._lastCursor != cursors.SELECT_REGION):
-                self.set_cursor(cursors.SELECT_REGION)
-                self._lastCursor = cursors.SELECT_REGION
-            elif (self._active == 'PAN' and
-                  self._lastCursor != cursors.MOVE):
-                self.set_cursor(cursors.MOVE)
-                self._lastCursor = cursors.MOVE
-
-    @contextmanager
-    def _wait_cursor_for_draw_cm(self):
-        """
-        Set the cursor to a wait cursor when drawing the canvas.
-
-        In order to avoid constantly changing the cursor when the canvas
-        changes frequently, do nothing if this context was triggered during the
-        last second.  (Optimally we'd prefer only setting the wait cursor if
-        the *current* draw takes too long, but the current draw blocks the GUI
-        thread).
-        """
-        self._draw_time, last_draw_time = (
-            time.time(), getattr(self, "_draw_time", -np.inf))
-        if self._draw_time - last_draw_time > 1:
-            try:
-                self.set_cursor(cursors.WAIT)
-                yield
-            finally:
-                self.set_cursor(self._lastCursor)
-        else:
-            yield
-
-    def mouse_move(self, event):
-        self._update_cursor(event)
-
-        if event.inaxes and event.inaxes.get_navigate():
-
-            try:
-                s = event.inaxes.format_coord(event.xdata, event.ydata)
-            except (ValueError, OverflowError):
-                pass
-            else:
-                artists = [a for a in event.inaxes._mouseover_set
-                           if a.contains(event)[0] and a.get_visible()]
-
-                if artists:
-                    a = cbook._topmost_artist(artists)
-                    if a is not event.inaxes.patch:
-                        data = a.get_cursor_data(event)
-                        if data is not None:
-                            data_str = a.format_cursor_data(data)
-                            if data_str is not None:
-                                s = s + ' ' + data_str
-
-                if len(self.mode):
-                    self.set_message('%s, %s' % (self.mode, s))
-                else:
-                    self.set_message(s)
-        else:
-            self.set_message(self.mode)
-
-    def pan(self, *args):
-        """
-        Activate the pan/zoom tool.
-
-        Pan with left button, zoom with right.
-        """
-        # set the pointer icon and button press funcs to the
-        # appropriate callbacks
-
-        if self._active == 'PAN':
-            self._active = None
-        else:
-            self._active = 'PAN'
-        if self._idPress is not None:
-            self._idPress = self.canvas.mpl_disconnect(self._idPress)
-            self.mode = ''
-
-        if self._idRelease is not None:
-            self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
-            self.mode = ''
-
-        if self._active:
-            self._idPress = self.canvas.mpl_connect(
-                'button_press_event', self.press_pan)
-            self._idRelease = self.canvas.mpl_connect(
-                'button_release_event', self.release_pan)
-            self.mode = 'pan/zoom'
-            self.canvas.widgetlock(self)
-        else:
-            self.canvas.widgetlock.release(self)
-
-        for a in self.canvas.figure.get_axes():
-            a.set_navigate_mode(self._active)
-
-        self.set_message(self.mode)
-
-    def press(self, event):
-        """Called whenever a mouse button is pressed."""
-
-    def press_pan(self, event):
-        """Callback for mouse button press in pan/zoom mode."""
-
-        if event.button == 1:
-            self._button_pressed = 1
-        elif event.button == 3:
-            self._button_pressed = 3
-        else:
-            self._button_pressed = None
-            return
-
-        if self._nav_stack() is None:
-            # set the home button to this view
-            self.push_current()
-
-        x, y = event.x, event.y
-        self._xypress = []
-        for i, a in enumerate(self.canvas.figure.get_axes()):
-            if (x is not None and y is not None and a.in_axes(event) and
-                    a.get_navigate() and a.can_pan()):
-                a.start_pan(x, y, event.button)
-                self._xypress.append((a, i))
-                self.canvas.mpl_disconnect(self._idDrag)
-                self._idDrag = self.canvas.mpl_connect('motion_notify_event',
-                                                       self.drag_pan)
-
-        self.press(event)
-
-    def press_zoom(self, event):
-        """Callback for mouse button press in zoom to rect mode."""
-        # If we're already in the middle of a zoom, pressing another
-        # button works to "cancel"
-        if self._ids_zoom != []:
-            for zoom_id in self._ids_zoom:
-                self.canvas.mpl_disconnect(zoom_id)
-            self.release(event)
-            self.draw()
-            self._xypress = None
-            self._button_pressed = None
-            self._ids_zoom = []
-            return
-
-        if event.button == 1:
-            self._button_pressed = 1
-        elif event.button == 3:
-            self._button_pressed = 3
-        else:
-            self._button_pressed = None
-            return
-
-        if self._nav_stack() is None:
-            # set the home button to this view
-            self.push_current()
-
-        x, y = event.x, event.y
-        self._xypress = []
-        for i, a in enumerate(self.canvas.figure.get_axes()):
-            if (x is not None and y is not None and a.in_axes(event) and
-                    a.get_navigate() and a.can_zoom()):
-                self._xypress.append((x, y, a, i, a._get_view()))
-
-        id1 = self.canvas.mpl_connect('motion_notify_event', self.drag_zoom)
-        id2 = self.canvas.mpl_connect('key_press_event',
-                                      self._switch_on_zoom_mode)
-        id3 = self.canvas.mpl_connect('key_release_event',
-                                      self._switch_off_zoom_mode)
-
-        self._ids_zoom = id1, id2, id3
-        self._zoom_mode = event.key
-
-        self.press(event)
-
-    def _switch_on_zoom_mode(self, event):
-        self._zoom_mode = event.key
-        self.mouse_move(event)
-
-    def _switch_off_zoom_mode(self, event):
-        self._zoom_mode = None
-        self.mouse_move(event)
-
-    def push_current(self):
-        """Push the current view limits and position onto the stack."""
-        self._nav_stack.push(
-            WeakKeyDictionary(
-                {ax: (ax._get_view(),
-                      # Store both the original and modified positions.
-                      (ax.get_position(True).frozen(),
-                       ax.get_position().frozen()))
-                 for ax in self.canvas.figure.axes}))
-        self.set_history_buttons()
-
-    def release(self, event):
-        """Callback for mouse button release."""
-
-    def release_pan(self, event):
-        """Callback for mouse button release in pan/zoom mode."""
-
-        if self._button_pressed is None:
-            return
-        self.canvas.mpl_disconnect(self._idDrag)
-        self._idDrag = self.canvas.mpl_connect(
-            'motion_notify_event', self.mouse_move)
-        for a, ind in self._xypress:
-            a.end_pan()
-        if not self._xypress:
-            return
-        self._xypress = []
-        self._button_pressed = None
-        self.push_current()
-        self.release(event)
-        self.draw()
-
-    def drag_pan(self, event):
-        """Callback for dragging in pan/zoom mode."""
-        for a, ind in self._xypress:
-            #safer to use the recorded button at the press than current button:
-            #multiple button can get pressed during motion...
-            a.drag_pan(self._button_pressed, event.key, event.x, event.y)
-        self.canvas.draw_idle()
-
-    def drag_zoom(self, event):
-        """Callback for dragging in zoom mode."""
-        if self._xypress:
-            x, y = event.x, event.y
-            lastx, lasty, a, ind, view = self._xypress[0]
-            (x1, y1), (x2, y2) = np.clip(
-                [[lastx, lasty], [x, y]], a.bbox.min, a.bbox.max)
-            if self._zoom_mode == "x":
-                y1, y2 = a.bbox.intervaly
-            elif self._zoom_mode == "y":
-                x1, x2 = a.bbox.intervalx
-            self.draw_rubberband(event, x1, y1, x2, y2)
-
-    def release_zoom(self, event):
-        """Callback for mouse button release in zoom to rect mode."""
-        for zoom_id in self._ids_zoom:
-            self.canvas.mpl_disconnect(zoom_id)
-        self._ids_zoom = []
-
-        self.remove_rubberband()
-
-        if not self._xypress:
-            return
-
-        last_a = []
-
-        for cur_xypress in self._xypress:
-            x, y = event.x, event.y
-            lastx, lasty, a, ind, view = cur_xypress
-            # ignore singular clicks - 5 pixels is a threshold
-            # allows the user to "cancel" a zoom action
-            # by zooming by less than 5 pixels
-            if ((abs(x - lastx) < 5 and self._zoom_mode != "y") or
-                    (abs(y - lasty) < 5 and self._zoom_mode != "x")):
-                self._xypress = None
-                self.release(event)
-                self.draw()
-                return
-
-            # detect twinx, twiny axes and avoid double zooming
-            twinx, twiny = False, False
-            if last_a:
-                for la in last_a:
-                    if a.get_shared_x_axes().joined(a, la):
-                        twinx = True
-                    if a.get_shared_y_axes().joined(a, la):
-                        twiny = True
-            last_a.append(a)
-
-            if self._button_pressed == 1:
-                direction = 'in'
-            elif self._button_pressed == 3:
-                direction = 'out'
-            else:
-                continue
-
-            a._set_view_from_bbox((lastx, lasty, x, y), direction,
-                                  self._zoom_mode, twinx, twiny)
-
-        self.draw()
-        self._xypress = None
-        self._button_pressed = None
-
-        self._zoom_mode = None
-
-        self.push_current()
-        self.release(event)
-
-    def draw(self):
-        """Redraw the canvases, update the locators."""
-        for a in self.canvas.figure.get_axes():
-            xaxis = getattr(a, 'xaxis', None)
-            yaxis = getattr(a, 'yaxis', None)
-            locators = []
-            if xaxis is not None:
-                locators.append(xaxis.get_major_locator())
-                locators.append(xaxis.get_minor_locator())
-            if yaxis is not None:
-                locators.append(yaxis.get_major_locator())
-                locators.append(yaxis.get_minor_locator())
-
-            for loc in locators:
-                loc.refresh()
-        self.canvas.draw_idle()
-
-    def _update_view(self):
-        """
-        Update the viewlim and position from the view and position stack for
-        each axes.
-        """
-        nav_info = self._nav_stack()
-        if nav_info is None:
-            return
-        # Retrieve all items at once to avoid any risk of GC deleting an Axes
-        # while in the middle of the loop below.
-        items = list(nav_info.items())
-        for ax, (view, (pos_orig, pos_active)) in items:
-            ax._set_view(view)
-            # Restore both the original and modified positions
-            ax._set_position(pos_orig, 'original')
-            ax._set_position(pos_active, 'active')
-        self.canvas.draw_idle()
-
-    def save_figure(self, *args):
-        """Save the current figure."""
-        raise NotImplementedError
-
-    def set_cursor(self, cursor):
-        """
-        Set the current cursor to one of the :class:`Cursors` enums values.
-
-        If required by the backend, this method should trigger an update in
-        the backend event loop after the cursor is set, as this method may be
-        called e.g. before a long-running task during which the GUI is not
-        updated.
-        """
-
-    def update(self):
-        """Reset the axes stack."""
-        self._nav_stack.clear()
-        self.set_history_buttons()
-
-    def zoom(self, *args):
-        """Activate zoom to rect mode."""
-        if self._active == 'ZOOM':
-            self._active = None
-        else:
-            self._active = 'ZOOM'
-
-        if self._idPress is not None:
-            self._idPress = self.canvas.mpl_disconnect(self._idPress)
-            self.mode = ''
-
-        if self._idRelease is not None:
-            self._idRelease = self.canvas.mpl_disconnect(self._idRelease)
-            self.mode = ''
-
-        if self._active:
-            self._idPress = self.canvas.mpl_connect('button_press_event',
-                                                    self.press_zoom)
-            self._idRelease = self.canvas.mpl_connect('button_release_event',
-                                                      self.release_zoom)
-            self.mode = 'zoom rect'
-            self.canvas.widgetlock(self)
-        else:
-            self.canvas.widgetlock.release(self)
-
-        for a in self.canvas.figure.get_axes():
-            a.set_navigate_mode(self._active)
-
-        self.set_message(self.mode)
-
-    def set_history_buttons(self):
-        """Enable or disable the back/forward button."""
-
-
-class ToolContainerBase:
-    """
-    Base class for all tool containers, e.g. toolbars.
-
-    Attributes
-    ----------
-    toolmanager : `ToolManager`
-        The tools with which this `ToolContainer` wants to communicate.
-    """
-
-    _icon_extension = '.png'
-    """
-    Toolcontainer button icon image format extension
-
-    **String**: Image extension
-    """
-
-    def __init__(self, toolmanager):
-        self.toolmanager = toolmanager
-        self.toolmanager.toolmanager_connect('tool_removed_event',
-                                             self._remove_tool_cbk)
-
-    def _tool_toggled_cbk(self, event):
-        """
-        Captures the 'tool_trigger_[name]'
-
-        This only gets used for toggled tools
-        """
-        self.toggle_toolitem(event.tool.name, event.tool.toggled)
-
-    def add_tool(self, tool, group, position=-1):
-        """
-        Adds a tool to this container
-
-        Parameters
-        ----------
-        tool : tool_like
-            The tool to add, see `ToolManager.get_tool`.
-        group : str
-            The name of the group to add this tool to.
-        position : int (optional)
-            The position within the group to place this tool.  Defaults to end.
-        """
-        tool = self.toolmanager.get_tool(tool)
-        image = self._get_image_filename(tool.image)
-        toggle = getattr(tool, 'toggled', None) is not None
-        self.add_toolitem(tool.name, group, position,
-                          image, tool.description, toggle)
-        if toggle:
-            self.toolmanager.toolmanager_connect('tool_trigger_%s' % tool.name,
-                                                 self._tool_toggled_cbk)
-            # If initially toggled
-            if tool.toggled:
-                self.toggle_toolitem(tool.name, True)
-
-    def _remove_tool_cbk(self, event):
-        """Captures the 'tool_removed_event' signal and removes the tool."""
-        self.remove_toolitem(event.tool.name)
-
-    def _get_image_filename(self, image):
-        """Find the image based on its name."""
-        if not image:
-            return None
-
-        basedir = cbook._get_data_path("images")
-        for fname in [
-            image,
-            image + self._icon_extension,
-            str(basedir / image),
-            str(basedir / (image + self._icon_extension)),
-        ]:
-            if os.path.isfile(fname):
-                return fname
-
-    def trigger_tool(self, name):
-        """
-        Trigger the tool
-
-        Parameters
-        ----------
-        name : str
-            Name (id) of the tool triggered from within the container.
-        """
-        self.toolmanager.trigger_tool(name, sender=self)
-
-    def add_toolitem(self, name, group, position, image, description, toggle):
-        """
-        Add a toolitem to the container
-
-        This method must get implemented per backend
-
-        The callback associated with the button click event,
-        must be **EXACTLY** `self.trigger_tool(name)`
-
-        Parameters
-        ----------
-        name : str
-            Name of the tool to add, this gets used as the tool's ID and as the
-            default label of the buttons
-        group : String
-            Name of the group that this tool belongs to
-        position : Int
-            Position of the tool within its group, if -1 it goes at the End
-        image_file : String
-            Filename of the image for the button or `None`
-        description : String
-            Description of the tool, used for the tooltips
-        toggle : Bool
-            * `True` : The button is a toggle (change the pressed/unpressed
-              state between consecutive clicks)
-            * `False` : The button is a normal button (returns to unpressed
-              state after release)
-        """
-        raise NotImplementedError
-
-    def toggle_toolitem(self, name, toggled):
-        """
-        Toggle the toolitem without firing event
-
-        Parameters
-        ----------
-        name : String
-            Id of the tool to toggle
-        toggled : bool
-            Whether to set this tool as toggled or not.
-        """
-        raise NotImplementedError
-
-    def remove_toolitem(self, name):
-        """
-        Remove a toolitem from the `ToolContainer`.
-
-        This method must get implemented per backend.
-
-        Called when `ToolManager` emits a `tool_removed_event`.
-
-        Parameters
-        ----------
-        name : str
-            Name of the tool to remove.
-        """
-        raise NotImplementedError
-
-
-class StatusbarBase:
-    """Base class for the statusbar."""
-    def __init__(self, toolmanager):
-        self.toolmanager = toolmanager
-        self.toolmanager.toolmanager_connect('tool_message_event',
-                                             self._message_cbk)
-
-    def _message_cbk(self, event):
-        """Capture the 'tool_message_event' and set the message."""
-        self.set_message(event.message)
-
-    def set_message(self, s):
-        """
-        Display a message on toolbar or in status bar.
-
-        Parameters
-        ----------
-        s : str
-            Message text.
-        """
-        pass
-
-
-class _Backend:
-    # A backend can be defined by using the following pattern:
-    #
-    # @_Backend.export
-    # class FooBackend(_Backend):
-    #     # override the attributes and methods documented below.
-
-    # `backend_version` may be overridden by the subclass.
-    backend_version = "unknown"
-
-    # The `FigureCanvas` class must be defined.
-    FigureCanvas = None
-
-    # For interactive backends, the `FigureManager` class must be overridden.
-    FigureManager = FigureManagerBase
-
-    # The following methods must be left as None for non-interactive backends.
-    # For interactive backends, `trigger_manager_draw` should be a function
-    # taking a manager as argument and triggering a canvas draw, and `mainloop`
-    # should be a function taking no argument and starting the backend main
-    # loop.
-    trigger_manager_draw = None
-    mainloop = None
-
-    # The following methods will be automatically defined and exported, but
-    # can be overridden.
-
-    @classmethod
-    def new_figure_manager(cls, num, *args, **kwargs):
-        """Create a new figure manager instance."""
-        # This import needs to happen here due to circular imports.
-        from matplotlib.figure import Figure
-        fig_cls = kwargs.pop('FigureClass', Figure)
-        fig = fig_cls(*args, **kwargs)
-        return cls.new_figure_manager_given_figure(num, fig)
-
-    @classmethod
-    def new_figure_manager_given_figure(cls, num, figure):
-        """Create a new figure manager instance for the given figure."""
-        canvas = cls.FigureCanvas(figure)
-        manager = cls.FigureManager(canvas, num)
-        return manager
-
-    @classmethod
-    def draw_if_interactive(cls):
-        if cls.trigger_manager_draw is not None and is_interactive():
-            manager = Gcf.get_active()
-            if manager:
-                cls.trigger_manager_draw(manager)
-
-    @classmethod
-    @cbook._make_keyword_only("3.1", "block")
-    def show(cls, block=None):
-        """
-        Show all figures.
-
-        `show` blocks by calling `mainloop` if *block* is ``True``, or if it
-        is ``None`` and we are neither in IPython's ``%pylab`` mode, nor in
-        `interactive` mode.
-        """
-        managers = Gcf.get_all_fig_managers()
-        if not managers:
-            return
-        for manager in managers:
-            # Emits a warning if the backend is non-interactive.
-            manager.canvas.figure.show()
-        if cls.mainloop is None:
-            return
-        if block is None:
-            # Hack: Are we in IPython's pylab mode?
-            from matplotlib import pyplot
-            try:
-                # IPython versions >= 0.10 tack the _needmain attribute onto
-                # pyplot.show, and always set it to False, when in %pylab mode.
-                ipython_pylab = not pyplot.show._needmain
-            except AttributeError:
-                ipython_pylab = False
-            block = not ipython_pylab and not is_interactive()
-            # TODO: The above is a hack to get the WebAgg backend working with
-            # ipython's `%pylab` mode until proper integration is implemented.
-            if get_backend() == "WebAgg":
-                block = True
-        if block:
-            cls.mainloop()
-
-    # This method is the one actually exporting the required methods.
-
-    @staticmethod
-    def export(cls):
-        for name in [
-                "backend_version",
-                "FigureCanvas",
-                "FigureManager",
-                "new_figure_manager",
-                "new_figure_manager_given_figure",
-                "draw_if_interactive",
-                "show",
-        ]:
-            setattr(sys.modules[cls.__module__], name, getattr(cls, name))
-
-        # For back-compatibility, generate a shim `Show` class.
-
-        class Show(ShowBase):
-            def mainloop(self):
-                return cls.mainloop()
-
-        setattr(sys.modules[cls.__module__], "Show", Show)
-        return cls
-
-
-class ShowBase(_Backend):
-    """
-    Simple base class to generate a ``show()`` function in backends.
-
-    Subclass must override ``mainloop()`` method.
-    """
-
-    def __call__(self, block=None):
-        return self.show(block=block)

+ 0 - 423
venv/lib/python3.8/site-packages/matplotlib/backend_managers.py

@@ -1,423 +0,0 @@
-import logging
-
-import matplotlib.cbook as cbook
-import matplotlib.widgets as widgets
-from matplotlib.rcsetup import validate_stringlist
-import matplotlib.backend_tools as tools
-
-_log = logging.getLogger(__name__)
-
-
-class ToolEvent:
-    """Event for tool manipulation (add/remove)."""
-    def __init__(self, name, sender, tool, data=None):
-        self.name = name
-        self.sender = sender
-        self.tool = tool
-        self.data = data
-
-
-class ToolTriggerEvent(ToolEvent):
-    """Event to inform that a tool has been triggered."""
-    def __init__(self, name, sender, tool, canvasevent=None, data=None):
-        ToolEvent.__init__(self, name, sender, tool, data)
-        self.canvasevent = canvasevent
-
-
-class ToolManagerMessageEvent:
-    """
-    Event carrying messages from toolmanager.
-
-    Messages usually get displayed to the user by the toolbar.
-    """
-    def __init__(self, name, sender, message):
-        self.name = name
-        self.sender = sender
-        self.message = message
-
-
-class ToolManager:
-    """
-    Manager for actions triggered by user interactions (key press, toolbar
-    clicks, ...) on a Figure.
-
-    Attributes
-    ----------
-    figure : `Figure`
-    keypresslock : `widgets.LockDraw`
-        `LockDraw` object to know if the `canvas` key_press_event is locked
-    messagelock : `widgets.LockDraw`
-        `LockDraw` object to know if the message is available to write
-    """
-
-    def __init__(self, figure=None):
-        _log.warning('Treat the new Tool classes introduced in v1.5 as '
-                     'experimental for now, the API will likely change in '
-                     'version 2.1 and perhaps the rcParam as well')
-
-        self._key_press_handler_id = None
-
-        self._tools = {}
-        self._keys = {}
-        self._toggled = {}
-        self._callbacks = cbook.CallbackRegistry()
-
-        # to process keypress event
-        self.keypresslock = widgets.LockDraw()
-        self.messagelock = widgets.LockDraw()
-
-        self._figure = None
-        self.set_figure(figure)
-
-    @property
-    def canvas(self):
-        """Canvas managed by FigureManager."""
-        if not self._figure:
-            return None
-        return self._figure.canvas
-
-    @property
-    def figure(self):
-        """Figure that holds the canvas."""
-        return self._figure
-
-    @figure.setter
-    def figure(self, figure):
-        self.set_figure(figure)
-
-    def set_figure(self, figure, update_tools=True):
-        """
-        Bind the given figure to the tools.
-
-        Parameters
-        ----------
-        figure : `.Figure`
-        update_tools : bool
-            Force tools to update figure
-        """
-        if self._key_press_handler_id:
-            self.canvas.mpl_disconnect(self._key_press_handler_id)
-        self._figure = figure
-        if figure:
-            self._key_press_handler_id = self.canvas.mpl_connect(
-                'key_press_event', self._key_press)
-        if update_tools:
-            for tool in self._tools.values():
-                tool.figure = figure
-
-    def toolmanager_connect(self, s, func):
-        """
-        Connect event with string *s* to *func*.
-
-        Parameters
-        ----------
-        s : String
-            Name of the event
-
-            The following events are recognized
-
-            - 'tool_message_event'
-            - 'tool_removed_event'
-            - 'tool_added_event'
-
-            For every tool added a new event is created
-
-            - 'tool_trigger_TOOLNAME`
-              Where TOOLNAME is the id of the tool.
-
-        func : function
-            Function to be called with signature
-            def func(event)
-        """
-        return self._callbacks.connect(s, func)
-
-    def toolmanager_disconnect(self, cid):
-        """
-        Disconnect callback id *cid*.
-
-        Example usage::
-
-            cid = toolmanager.toolmanager_connect('tool_trigger_zoom', onpress)
-            #...later
-            toolmanager.toolmanager_disconnect(cid)
-        """
-        return self._callbacks.disconnect(cid)
-
-    def message_event(self, message, sender=None):
-        """Emit a `ToolManagerMessageEvent`."""
-        if sender is None:
-            sender = self
-
-        s = 'tool_message_event'
-        event = ToolManagerMessageEvent(s, sender, message)
-        self._callbacks.process(s, event)
-
-    @property
-    def active_toggle(self):
-        """Currently toggled tools."""
-        return self._toggled
-
-    def get_tool_keymap(self, name):
-        """
-        Get the keymap associated with the specified tool.
-
-        Parameters
-        ----------
-        name : str
-            Name of the Tool.
-
-        Returns
-        -------
-        list : list of keys associated with the Tool
-        """
-
-        keys = [k for k, i in self._keys.items() if i == name]
-        return keys
-
-    def _remove_keys(self, name):
-        for k in self.get_tool_keymap(name):
-            del self._keys[k]
-
-    def update_keymap(self, name, *keys):
-        """
-        Set the keymap to associate with the specified tool.
-
-        Parameters
-        ----------
-        name : str
-            Name of the Tool.
-        keys : keys to associate with the Tool
-        """
-
-        if name not in self._tools:
-            raise KeyError('%s not in Tools' % name)
-
-        self._remove_keys(name)
-
-        for key in keys:
-            for k in validate_stringlist(key):
-                if k in self._keys:
-                    cbook._warn_external('Key %s changed from %s to %s' %
-                                         (k, self._keys[k], name))
-                self._keys[k] = name
-
-    def remove_tool(self, name):
-        """
-        Remove tool named *name*.
-
-        Parameters
-        ----------
-        name : str
-            Name of the Tool.
-        """
-
-        tool = self.get_tool(name)
-        tool.destroy()
-
-        # If is a toggle tool and toggled, untoggle
-        if getattr(tool, 'toggled', False):
-            self.trigger_tool(tool, 'toolmanager')
-
-        self._remove_keys(name)
-
-        s = 'tool_removed_event'
-        event = ToolEvent(s, self, tool)
-        self._callbacks.process(s, event)
-
-        del self._tools[name]
-
-    def add_tool(self, name, tool, *args, **kwargs):
-        """
-        Add *tool* to `ToolManager`.
-
-        If successful, adds a new event ``tool_trigger_{name}`` where
-        ``{name}`` is the *name* of the tool; the event is fired everytime the
-        tool is triggered.
-
-        Parameters
-        ----------
-        name : str
-            Name of the tool, treated as the ID, has to be unique.
-        tool : class_like, i.e. str or type
-            Reference to find the class of the Tool to added.
-
-        Notes
-        -----
-        args and kwargs get passed directly to the tools constructor.
-
-        See Also
-        --------
-        matplotlib.backend_tools.ToolBase : The base class for tools.
-        """
-
-        tool_cls = self._get_cls_to_instantiate(tool)
-        if not tool_cls:
-            raise ValueError('Impossible to find class for %s' % str(tool))
-
-        if name in self._tools:
-            cbook._warn_external('A "Tool class" with the same name already '
-                                 'exists, not added')
-            return self._tools[name]
-
-        tool_obj = tool_cls(self, name, *args, **kwargs)
-        self._tools[name] = tool_obj
-
-        if tool_cls.default_keymap is not None:
-            self.update_keymap(name, tool_cls.default_keymap)
-
-        # For toggle tools init the radio_group in self._toggled
-        if isinstance(tool_obj, tools.ToolToggleBase):
-            # None group is not mutually exclusive, a set is used to keep track
-            # of all toggled tools in this group
-            if tool_obj.radio_group is None:
-                self._toggled.setdefault(None, set())
-            else:
-                self._toggled.setdefault(tool_obj.radio_group, None)
-
-            # If initially toggled
-            if tool_obj.toggled:
-                self._handle_toggle(tool_obj, None, None, None)
-        tool_obj.set_figure(self.figure)
-
-        self._tool_added_event(tool_obj)
-        return tool_obj
-
-    def _tool_added_event(self, tool):
-        s = 'tool_added_event'
-        event = ToolEvent(s, self, tool)
-        self._callbacks.process(s, event)
-
-    def _handle_toggle(self, tool, sender, canvasevent, data):
-        """
-        Toggle tools, need to untoggle prior to using other Toggle tool.
-        Called from trigger_tool.
-
-        Parameters
-        ----------
-        tool : Tool object
-        sender : object
-            Object that wishes to trigger the tool
-        canvasevent : Event
-            Original Canvas event or None
-        data : Object
-            Extra data to pass to the tool when triggering
-        """
-
-        radio_group = tool.radio_group
-        # radio_group None is not mutually exclusive
-        # just keep track of toggled tools in this group
-        if radio_group is None:
-            if tool.name in self._toggled[None]:
-                self._toggled[None].remove(tool.name)
-            else:
-                self._toggled[None].add(tool.name)
-            return
-
-        # If the tool already has a toggled state, untoggle it
-        if self._toggled[radio_group] == tool.name:
-            toggled = None
-        # If no tool was toggled in the radio_group
-        # toggle it
-        elif self._toggled[radio_group] is None:
-            toggled = tool.name
-        # Other tool in the radio_group is toggled
-        else:
-            # Untoggle previously toggled tool
-            self.trigger_tool(self._toggled[radio_group],
-                              self,
-                              canvasevent,
-                              data)
-            toggled = tool.name
-
-        # Keep track of the toggled tool in the radio_group
-        self._toggled[radio_group] = toggled
-
-    def _get_cls_to_instantiate(self, callback_class):
-        # Find the class that corresponds to the tool
-        if isinstance(callback_class, str):
-            # FIXME: make more complete searching structure
-            if callback_class in globals():
-                callback_class = globals()[callback_class]
-            else:
-                mod = 'backend_tools'
-                current_module = __import__(mod,
-                                            globals(), locals(), [mod], 1)
-
-                callback_class = getattr(current_module, callback_class, False)
-        if callable(callback_class):
-            return callback_class
-        else:
-            return None
-
-    def trigger_tool(self, name, sender=None, canvasevent=None, data=None):
-        """
-        Trigger a tool and emit the ``tool_trigger_{name}`` event.
-
-        Parameters
-        ----------
-        name : str
-            Name of the tool.
-        sender : object
-            Object that wishes to trigger the tool
-        canvasevent : Event
-            Original Canvas event or None
-        data : Object
-            Extra data to pass to the tool when triggering
-        """
-        tool = self.get_tool(name)
-        if tool is None:
-            return
-
-        if sender is None:
-            sender = self
-
-        self._trigger_tool(name, sender, canvasevent, data)
-
-        s = 'tool_trigger_%s' % name
-        event = ToolTriggerEvent(s, sender, tool, canvasevent, data)
-        self._callbacks.process(s, event)
-
-    def _trigger_tool(self, name, sender=None, canvasevent=None, data=None):
-        """Actually trigger a tool."""
-        tool = self.get_tool(name)
-
-        if isinstance(tool, tools.ToolToggleBase):
-            self._handle_toggle(tool, sender, canvasevent, data)
-
-        # Important!!!
-        # This is where the Tool object gets triggered
-        tool.trigger(sender, canvasevent, data)
-
-    def _key_press(self, event):
-        if event.key is None or self.keypresslock.locked():
-            return
-
-        name = self._keys.get(event.key, None)
-        if name is None:
-            return
-        self.trigger_tool(name, canvasevent=event)
-
-    @property
-    def tools(self):
-        """A dict mapping tool name -> controlled tool."""
-        return self._tools
-
-    def get_tool(self, name, warn=True):
-        """
-        Return the tool object, also accepts the actual tool for convenience.
-
-        Parameters
-        ----------
-        name : str, ToolBase
-            Name of the tool, or the tool itself
-        warn : bool, optional
-            If this method should give warnings.
-        """
-        if isinstance(name, tools.ToolBase) and name.name in self._tools:
-            return name
-        if name not in self._tools:
-            if warn:
-                cbook._warn_external("ToolManager does not control tool "
-                                     "%s" % name)
-            return None
-        return self._tools[name]

+ 0 - 1146
venv/lib/python3.8/site-packages/matplotlib/backend_tools.py

@@ -1,1146 +0,0 @@
-"""
-Abstract base classes define the primitives for Tools.
-These tools are used by `matplotlib.backend_managers.ToolManager`
-
-:class:`ToolBase`
-    Simple stateless tool
-
-:class:`ToolToggleBase`
-    Tool that has two states, only one Toggle tool can be
-    active at any given time for the same
-    `matplotlib.backend_managers.ToolManager`
-"""
-
-from enum import IntEnum
-import logging
-import re
-import time
-from types import SimpleNamespace
-from weakref import WeakKeyDictionary
-
-import numpy as np
-
-from matplotlib import rcParams
-from matplotlib._pylab_helpers import Gcf
-import matplotlib.cbook as cbook
-
-_log = logging.getLogger(__name__)
-
-
-class Cursors(IntEnum):  # Must subclass int for the macOS backend.
-    """Backend-independent cursor types."""
-    HAND, POINTER, SELECT_REGION, MOVE, WAIT = range(5)
-cursors = Cursors  # Backcompat.
-
-# Views positions tool
-_views_positions = 'viewpos'
-
-
-class ToolBase:
-    """
-    Base tool class
-
-    A base tool, only implements `trigger` method or not method at all.
-    The tool is instantiated by `matplotlib.backend_managers.ToolManager`
-
-    Attributes
-    ----------
-    toolmanager : `matplotlib.backend_managers.ToolManager`
-        ToolManager that controls this Tool
-    figure : `FigureCanvas`
-        Figure instance that is affected by this Tool
-    name : str
-        Used as **Id** of the tool, has to be unique among tools of the same
-        ToolManager
-    """
-
-    default_keymap = None
-    """
-    Keymap to associate with this tool
-
-    **String**: List of comma separated keys that will be used to call this
-    tool when the keypress event of *self.figure.canvas* is emitted
-    """
-
-    description = None
-    """
-    Description of the Tool
-
-    **String**: If the Tool is included in the Toolbar this text is used
-    as a Tooltip
-    """
-
-    image = None
-    """
-    Filename of the image
-
-    **String**: Filename of the image to use in the toolbar. If None, the
-    *name* is used as a label in the toolbar button
-    """
-
-    def __init__(self, toolmanager, name):
-        cbook._warn_external(
-            'The new Tool classes introduced in v1.5 are experimental; their '
-            'API (including names) will likely change in future versions.')
-        self._name = name
-        self._toolmanager = toolmanager
-        self._figure = None
-
-    @property
-    def figure(self):
-        return self._figure
-
-    @figure.setter
-    def figure(self, figure):
-        self.set_figure(figure)
-
-    @property
-    def canvas(self):
-        if not self._figure:
-            return None
-        return self._figure.canvas
-
-    @property
-    def toolmanager(self):
-        return self._toolmanager
-
-    def _make_classic_style_pseudo_toolbar(self):
-        """
-        Return a placeholder object with a single `canvas` attribute.
-
-        This is useful to reuse the implementations of tools already provided
-        by the classic Toolbars.
-        """
-        return SimpleNamespace(canvas=self.canvas)
-
-    def set_figure(self, figure):
-        """
-        Assign a figure to the tool
-
-        Parameters
-        ----------
-        figure : `Figure`
-        """
-        self._figure = figure
-
-    def trigger(self, sender, event, data=None):
-        """
-        Called when this tool gets used
-
-        This method is called by
-        `matplotlib.backend_managers.ToolManager.trigger_tool`
-
-        Parameters
-        ----------
-        event : `Event`
-            The Canvas event that caused this tool to be called
-        sender : object
-            Object that requested the tool to be triggered
-        data : object
-            Extra data
-        """
-
-        pass
-
-    @property
-    def name(self):
-        """Tool Id"""
-        return self._name
-
-    def destroy(self):
-        """
-        Destroy the tool
-
-        This method is called when the tool is removed by
-        `matplotlib.backend_managers.ToolManager.remove_tool`
-        """
-        pass
-
-
-class ToolToggleBase(ToolBase):
-    """
-    Toggleable tool
-
-    Every time it is triggered, it switches between enable and disable
-
-    Parameters
-    ----------
-    ``*args``
-        Variable length argument to be used by the Tool
-    ``**kwargs``
-        `toggled` if present and True, sets the initial state of the Tool
-        Arbitrary keyword arguments to be consumed by the Tool
-    """
-
-    radio_group = None
-    """Attribute to group 'radio' like tools (mutually exclusive)
-
-    **String** that identifies the group or **None** if not belonging to a
-    group
-    """
-
-    cursor = None
-    """Cursor to use when the tool is active"""
-
-    default_toggled = False
-    """Default of toggled state"""
-
-    def __init__(self, *args, **kwargs):
-        self._toggled = kwargs.pop('toggled', self.default_toggled)
-        ToolBase.__init__(self, *args, **kwargs)
-
-    def trigger(self, sender, event, data=None):
-        """Calls `enable` or `disable` based on `toggled` value"""
-        if self._toggled:
-            self.disable(event)
-        else:
-            self.enable(event)
-        self._toggled = not self._toggled
-
-    def enable(self, event=None):
-        """
-        Enable the toggle tool
-
-        `trigger` calls this method when `toggled` is False
-        """
-        pass
-
-    def disable(self, event=None):
-        """
-        Disable the toggle tool
-
-        `trigger` call this method when `toggled` is True.
-
-        This can happen in different circumstances
-
-        * Click on the toolbar tool button
-        * Call to `matplotlib.backend_managers.ToolManager.trigger_tool`
-        * Another `ToolToggleBase` derived tool is triggered
-          (from the same `ToolManager`)
-        """
-        pass
-
-    @property
-    def toggled(self):
-        """State of the toggled tool"""
-
-        return self._toggled
-
-    def set_figure(self, figure):
-        toggled = self.toggled
-        if toggled:
-            if self.figure:
-                self.trigger(self, None)
-            else:
-                # if no figure the internal state is not changed
-                # we change it here so next call to trigger will change it back
-                self._toggled = False
-        ToolBase.set_figure(self, figure)
-        if toggled:
-            if figure:
-                self.trigger(self, None)
-            else:
-                # if there is no figure, trigger won't change the internal
-                # state we change it back
-                self._toggled = True
-
-
-class SetCursorBase(ToolBase):
-    """
-    Change to the current cursor while inaxes
-
-    This tool, keeps track of all `ToolToggleBase` derived tools, and calls
-    set_cursor when a tool gets triggered
-    """
-    def __init__(self, *args, **kwargs):
-        ToolBase.__init__(self, *args, **kwargs)
-        self._idDrag = None
-        self._cursor = None
-        self._default_cursor = cursors.POINTER
-        self._last_cursor = self._default_cursor
-        self.toolmanager.toolmanager_connect('tool_added_event',
-                                             self._add_tool_cbk)
-
-        # process current tools
-        for tool in self.toolmanager.tools.values():
-            self._add_tool(tool)
-
-    def set_figure(self, figure):
-        if self._idDrag:
-            self.canvas.mpl_disconnect(self._idDrag)
-        ToolBase.set_figure(self, figure)
-        if figure:
-            self._idDrag = self.canvas.mpl_connect(
-                'motion_notify_event', self._set_cursor_cbk)
-
-    def _tool_trigger_cbk(self, event):
-        if event.tool.toggled:
-            self._cursor = event.tool.cursor
-        else:
-            self._cursor = None
-
-        self._set_cursor_cbk(event.canvasevent)
-
-    def _add_tool(self, tool):
-        """Set the cursor when the tool is triggered."""
-        if getattr(tool, 'cursor', None) is not None:
-            self.toolmanager.toolmanager_connect('tool_trigger_%s' % tool.name,
-                                                 self._tool_trigger_cbk)
-
-    def _add_tool_cbk(self, event):
-        """Process every newly added tool."""
-        if event.tool is self:
-            return
-        self._add_tool(event.tool)
-
-    def _set_cursor_cbk(self, event):
-        if not event:
-            return
-
-        if not getattr(event, 'inaxes', False) or not self._cursor:
-            if self._last_cursor != self._default_cursor:
-                self.set_cursor(self._default_cursor)
-                self._last_cursor = self._default_cursor
-        elif self._cursor:
-            cursor = self._cursor
-            if cursor and self._last_cursor != cursor:
-                self.set_cursor(cursor)
-                self._last_cursor = cursor
-
-    def set_cursor(self, cursor):
-        """
-        Set the cursor
-
-        This method has to be implemented per backend
-        """
-        raise NotImplementedError
-
-
-class ToolCursorPosition(ToolBase):
-    """
-    Send message with the current pointer position
-
-    This tool runs in the background reporting the position of the cursor
-    """
-    def __init__(self, *args, **kwargs):
-        self._idDrag = None
-        ToolBase.__init__(self, *args, **kwargs)
-
-    def set_figure(self, figure):
-        if self._idDrag:
-            self.canvas.mpl_disconnect(self._idDrag)
-        ToolBase.set_figure(self, figure)
-        if figure:
-            self._idDrag = self.canvas.mpl_connect(
-                'motion_notify_event', self.send_message)
-
-    def send_message(self, event):
-        """Call `matplotlib.backend_managers.ToolManager.message_event`"""
-        if self.toolmanager.messagelock.locked():
-            return
-
-        message = ' '
-
-        if event.inaxes and event.inaxes.get_navigate():
-            try:
-                s = event.inaxes.format_coord(event.xdata, event.ydata)
-            except (ValueError, OverflowError):
-                pass
-            else:
-                artists = [a for a in event.inaxes._mouseover_set
-                           if a.contains(event) and a.get_visible()]
-
-                if artists:
-                    a = cbook._topmost_artist(artists)
-                    if a is not event.inaxes.patch:
-                        data = a.get_cursor_data(event)
-                        if data is not None:
-                            data_str = a.format_cursor_data(data)
-                            if data_str is not None:
-                                s = s + ' ' + data_str
-
-                message = s
-        self.toolmanager.message_event(message, self)
-
-
-class RubberbandBase(ToolBase):
-    """Draw and remove rubberband"""
-    def trigger(self, sender, event, data):
-        """Call `draw_rubberband` or `remove_rubberband` based on data"""
-        if not self.figure.canvas.widgetlock.available(sender):
-            return
-        if data is not None:
-            self.draw_rubberband(*data)
-        else:
-            self.remove_rubberband()
-
-    def draw_rubberband(self, *data):
-        """
-        Draw rubberband
-
-        This method must get implemented per backend
-        """
-        raise NotImplementedError
-
-    def remove_rubberband(self):
-        """
-        Remove rubberband
-
-        This method should get implemented per backend
-        """
-        pass
-
-
-class ToolQuit(ToolBase):
-    """Tool to call the figure manager destroy method"""
-
-    description = 'Quit the figure'
-    default_keymap = rcParams['keymap.quit']
-
-    def trigger(self, sender, event, data=None):
-        Gcf.destroy_fig(self.figure)
-
-
-class ToolQuitAll(ToolBase):
-    """Tool to call the figure manager destroy method"""
-
-    description = 'Quit all figures'
-    default_keymap = rcParams['keymap.quit_all']
-
-    def trigger(self, sender, event, data=None):
-        Gcf.destroy_all()
-
-
-class ToolEnableAllNavigation(ToolBase):
-    """Tool to enable all axes for toolmanager interaction"""
-
-    description = 'Enable all axes toolmanager'
-    default_keymap = rcParams['keymap.all_axes']
-
-    def trigger(self, sender, event, data=None):
-        if event.inaxes is None:
-            return
-
-        for a in self.figure.get_axes():
-            if (event.x is not None and event.y is not None
-                    and a.in_axes(event)):
-                a.set_navigate(True)
-
-
-class ToolEnableNavigation(ToolBase):
-    """Tool to enable a specific axes for toolmanager interaction"""
-
-    description = 'Enable one axes toolmanager'
-    default_keymap = (1, 2, 3, 4, 5, 6, 7, 8, 9)
-
-    def trigger(self, sender, event, data=None):
-        if event.inaxes is None:
-            return
-
-        n = int(event.key) - 1
-        if n < len(self.figure.get_axes()):
-            for i, a in enumerate(self.figure.get_axes()):
-                if (event.x is not None and event.y is not None
-                        and a.in_axes(event)):
-                    a.set_navigate(i == n)
-
-
-class _ToolGridBase(ToolBase):
-    """Common functionality between ToolGrid and ToolMinorGrid."""
-
-    _cycle = [(False, False), (True, False), (True, True), (False, True)]
-
-    def trigger(self, sender, event, data=None):
-        ax = event.inaxes
-        if ax is None:
-            return
-        try:
-            x_state, x_which, y_state, y_which = self._get_next_grid_states(ax)
-        except ValueError:
-            pass
-        else:
-            ax.grid(x_state, which=x_which, axis="x")
-            ax.grid(y_state, which=y_which, axis="y")
-            ax.figure.canvas.draw_idle()
-
-    @staticmethod
-    def _get_uniform_grid_state(ticks):
-        """
-        Check whether all grid lines are in the same visibility state.
-
-        Returns True/False if all grid lines are on or off, None if they are
-        not all in the same state.
-        """
-        if all(tick.gridline.get_visible() for tick in ticks):
-            return True
-        elif not any(tick.gridline.get_visible() for tick in ticks):
-            return False
-        else:
-            return None
-
-
-class ToolGrid(_ToolGridBase):
-    """Tool to toggle the major grids of the figure"""
-
-    description = 'Toggle major grids'
-    default_keymap = rcParams['keymap.grid']
-
-    def _get_next_grid_states(self, ax):
-        if None in map(self._get_uniform_grid_state,
-                       [ax.xaxis.minorTicks, ax.yaxis.minorTicks]):
-            # Bail out if minor grids are not in a uniform state.
-            raise ValueError
-        x_state, y_state = map(self._get_uniform_grid_state,
-                               [ax.xaxis.majorTicks, ax.yaxis.majorTicks])
-        cycle = self._cycle
-        # Bail out (via ValueError) if major grids are not in a uniform state.
-        x_state, y_state = (
-            cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)])
-        return (x_state, "major" if x_state else "both",
-                y_state, "major" if y_state else "both")
-
-
-class ToolMinorGrid(_ToolGridBase):
-    """Tool to toggle the major and minor grids of the figure"""
-
-    description = 'Toggle major and minor grids'
-    default_keymap = rcParams['keymap.grid_minor']
-
-    def _get_next_grid_states(self, ax):
-        if None in map(self._get_uniform_grid_state,
-                       [ax.xaxis.majorTicks, ax.yaxis.majorTicks]):
-            # Bail out if major grids are not in a uniform state.
-            raise ValueError
-        x_state, y_state = map(self._get_uniform_grid_state,
-                               [ax.xaxis.minorTicks, ax.yaxis.minorTicks])
-        cycle = self._cycle
-        # Bail out (via ValueError) if minor grids are not in a uniform state.
-        x_state, y_state = (
-            cycle[(cycle.index((x_state, y_state)) + 1) % len(cycle)])
-        return x_state, "both", y_state, "both"
-
-
-class ToolFullScreen(ToolToggleBase):
-    """Tool to toggle full screen"""
-
-    description = 'Toggle fullscreen mode'
-    default_keymap = rcParams['keymap.fullscreen']
-
-    def enable(self, event):
-        self.figure.canvas.manager.full_screen_toggle()
-
-    def disable(self, event):
-        self.figure.canvas.manager.full_screen_toggle()
-
-
-class AxisScaleBase(ToolToggleBase):
-    """Base Tool to toggle between linear and logarithmic"""
-
-    def trigger(self, sender, event, data=None):
-        if event.inaxes is None:
-            return
-        ToolToggleBase.trigger(self, sender, event, data)
-
-    def enable(self, event):
-        self.set_scale(event.inaxes, 'log')
-        self.figure.canvas.draw_idle()
-
-    def disable(self, event):
-        self.set_scale(event.inaxes, 'linear')
-        self.figure.canvas.draw_idle()
-
-
-class ToolYScale(AxisScaleBase):
-    """Tool to toggle between linear and logarithmic scales on the Y axis"""
-
-    description = 'Toggle scale Y axis'
-    default_keymap = rcParams['keymap.yscale']
-
-    def set_scale(self, ax, scale):
-        ax.set_yscale(scale)
-
-
-class ToolXScale(AxisScaleBase):
-    """Tool to toggle between linear and logarithmic scales on the X axis"""
-
-    description = 'Toggle scale X axis'
-    default_keymap = rcParams['keymap.xscale']
-
-    def set_scale(self, ax, scale):
-        ax.set_xscale(scale)
-
-
-class ToolViewsPositions(ToolBase):
-    """
-    Auxiliary Tool to handle changes in views and positions
-
-    Runs in the background and should get used by all the tools that
-    need to access the figure's history of views and positions, e.g.
-
-    * `ToolZoom`
-    * `ToolPan`
-    * `ToolHome`
-    * `ToolBack`
-    * `ToolForward`
-    """
-
-    def __init__(self, *args, **kwargs):
-        self.views = WeakKeyDictionary()
-        self.positions = WeakKeyDictionary()
-        self.home_views = WeakKeyDictionary()
-        ToolBase.__init__(self, *args, **kwargs)
-
-    def add_figure(self, figure):
-        """Add the current figure to the stack of views and positions"""
-
-        if figure not in self.views:
-            self.views[figure] = cbook.Stack()
-            self.positions[figure] = cbook.Stack()
-            self.home_views[figure] = WeakKeyDictionary()
-            # Define Home
-            self.push_current(figure)
-            # Make sure we add a home view for new axes as they're added
-            figure.add_axobserver(lambda fig: self.update_home_views(fig))
-
-    def clear(self, figure):
-        """Reset the axes stack"""
-        if figure in self.views:
-            self.views[figure].clear()
-            self.positions[figure].clear()
-            self.home_views[figure].clear()
-            self.update_home_views()
-
-    def update_view(self):
-        """
-        Update the view limits and position for each axes from the current
-        stack position. If any axes are present in the figure that aren't in
-        the current stack position, use the home view limits for those axes and
-        don't update *any* positions.
-        """
-
-        views = self.views[self.figure]()
-        if views is None:
-            return
-        pos = self.positions[self.figure]()
-        if pos is None:
-            return
-        home_views = self.home_views[self.figure]
-        all_axes = self.figure.get_axes()
-        for a in all_axes:
-            if a in views:
-                cur_view = views[a]
-            else:
-                cur_view = home_views[a]
-            a._set_view(cur_view)
-
-        if set(all_axes).issubset(pos):
-            for a in all_axes:
-                # Restore both the original and modified positions
-                a._set_position(pos[a][0], 'original')
-                a._set_position(pos[a][1], 'active')
-
-        self.figure.canvas.draw_idle()
-
-    def push_current(self, figure=None):
-        """
-        Push the current view limits and position onto their respective stacks
-        """
-        if not figure:
-            figure = self.figure
-        views = WeakKeyDictionary()
-        pos = WeakKeyDictionary()
-        for a in figure.get_axes():
-            views[a] = a._get_view()
-            pos[a] = self._axes_pos(a)
-        self.views[figure].push(views)
-        self.positions[figure].push(pos)
-
-    def _axes_pos(self, ax):
-        """
-        Return the original and modified positions for the specified axes
-
-        Parameters
-        ----------
-        ax : (matplotlib.axes.AxesSubplot)
-        The axes to get the positions for
-
-        Returns
-        -------
-        limits : (tuple)
-        A tuple of the original and modified positions
-        """
-
-        return (ax.get_position(True).frozen(),
-                ax.get_position().frozen())
-
-    def update_home_views(self, figure=None):
-        """
-        Make sure that self.home_views has an entry for all axes present in the
-        figure
-        """
-
-        if not figure:
-            figure = self.figure
-        for a in figure.get_axes():
-            if a not in self.home_views[figure]:
-                self.home_views[figure][a] = a._get_view()
-
-    def refresh_locators(self):
-        """Redraw the canvases, update the locators"""
-        for a in self.figure.get_axes():
-            xaxis = getattr(a, 'xaxis', None)
-            yaxis = getattr(a, 'yaxis', None)
-            zaxis = getattr(a, 'zaxis', None)
-            locators = []
-            if xaxis is not None:
-                locators.append(xaxis.get_major_locator())
-                locators.append(xaxis.get_minor_locator())
-            if yaxis is not None:
-                locators.append(yaxis.get_major_locator())
-                locators.append(yaxis.get_minor_locator())
-            if zaxis is not None:
-                locators.append(zaxis.get_major_locator())
-                locators.append(zaxis.get_minor_locator())
-
-            for loc in locators:
-                loc.refresh()
-        self.figure.canvas.draw_idle()
-
-    def home(self):
-        """Recall the first view and position from the stack"""
-        self.views[self.figure].home()
-        self.positions[self.figure].home()
-
-    def back(self):
-        """Back one step in the stack of views and positions"""
-        self.views[self.figure].back()
-        self.positions[self.figure].back()
-
-    def forward(self):
-        """Forward one step in the stack of views and positions"""
-        self.views[self.figure].forward()
-        self.positions[self.figure].forward()
-
-
-class ViewsPositionsBase(ToolBase):
-    """Base class for `ToolHome`, `ToolBack` and `ToolForward`"""
-
-    _on_trigger = None
-
-    def trigger(self, sender, event, data=None):
-        self.toolmanager.get_tool(_views_positions).add_figure(self.figure)
-        getattr(self.toolmanager.get_tool(_views_positions),
-                self._on_trigger)()
-        self.toolmanager.get_tool(_views_positions).update_view()
-
-
-class ToolHome(ViewsPositionsBase):
-    """Restore the original view lim"""
-
-    description = 'Reset original view'
-    image = 'home'
-    default_keymap = rcParams['keymap.home']
-    _on_trigger = 'home'
-
-
-class ToolBack(ViewsPositionsBase):
-    """Move back up the view lim stack"""
-
-    description = 'Back to previous view'
-    image = 'back'
-    default_keymap = rcParams['keymap.back']
-    _on_trigger = 'back'
-
-
-class ToolForward(ViewsPositionsBase):
-    """Move forward in the view lim stack"""
-
-    description = 'Forward to next view'
-    image = 'forward'
-    default_keymap = rcParams['keymap.forward']
-    _on_trigger = 'forward'
-
-
-class ConfigureSubplotsBase(ToolBase):
-    """Base tool for the configuration of subplots"""
-
-    description = 'Configure subplots'
-    image = 'subplots'
-
-
-class SaveFigureBase(ToolBase):
-    """Base tool for figure saving"""
-
-    description = 'Save the figure'
-    image = 'filesave'
-    default_keymap = rcParams['keymap.save']
-
-
-class ZoomPanBase(ToolToggleBase):
-    """Base class for `ToolZoom` and `ToolPan`"""
-    def __init__(self, *args):
-        ToolToggleBase.__init__(self, *args)
-        self._button_pressed = None
-        self._xypress = None
-        self._idPress = None
-        self._idRelease = None
-        self._idScroll = None
-        self.base_scale = 2.
-        self.scrollthresh = .5  # .5 second scroll threshold
-        self.lastscroll = time.time()-self.scrollthresh
-
-    def enable(self, event):
-        """Connect press/release events and lock the canvas"""
-        self.figure.canvas.widgetlock(self)
-        self._idPress = self.figure.canvas.mpl_connect(
-            'button_press_event', self._press)
-        self._idRelease = self.figure.canvas.mpl_connect(
-            'button_release_event', self._release)
-        self._idScroll = self.figure.canvas.mpl_connect(
-            'scroll_event', self.scroll_zoom)
-
-    def disable(self, event):
-        """Release the canvas and disconnect press/release events"""
-        self._cancel_action()
-        self.figure.canvas.widgetlock.release(self)
-        self.figure.canvas.mpl_disconnect(self._idPress)
-        self.figure.canvas.mpl_disconnect(self._idRelease)
-        self.figure.canvas.mpl_disconnect(self._idScroll)
-
-    def trigger(self, sender, event, data=None):
-        self.toolmanager.get_tool(_views_positions).add_figure(self.figure)
-        ToolToggleBase.trigger(self, sender, event, data)
-
-    def scroll_zoom(self, event):
-        # https://gist.github.com/tacaswell/3144287
-        if event.inaxes is None:
-            return
-
-        if event.button == 'up':
-            # deal with zoom in
-            scl = self.base_scale
-        elif event.button == 'down':
-            # deal with zoom out
-            scl = 1/self.base_scale
-        else:
-            # deal with something that should never happen
-            scl = 1
-
-        ax = event.inaxes
-        ax._set_view_from_bbox([event.x, event.y, scl])
-
-        # If last scroll was done within the timing threshold, delete the
-        # previous view
-        if (time.time()-self.lastscroll) < self.scrollthresh:
-            self.toolmanager.get_tool(_views_positions).back()
-
-        self.figure.canvas.draw_idle()  # force re-draw
-
-        self.lastscroll = time.time()
-        self.toolmanager.get_tool(_views_positions).push_current()
-
-
-class ToolZoom(ZoomPanBase):
-    """Zoom to rectangle"""
-
-    description = 'Zoom to rectangle'
-    image = 'zoom_to_rect'
-    default_keymap = rcParams['keymap.zoom']
-    cursor = cursors.SELECT_REGION
-    radio_group = 'default'
-
-    def __init__(self, *args):
-        ZoomPanBase.__init__(self, *args)
-        self._ids_zoom = []
-
-    def _cancel_action(self):
-        for zoom_id in self._ids_zoom:
-            self.figure.canvas.mpl_disconnect(zoom_id)
-        self.toolmanager.trigger_tool('rubberband', self)
-        self.toolmanager.get_tool(_views_positions).refresh_locators()
-        self._xypress = None
-        self._button_pressed = None
-        self._ids_zoom = []
-        return
-
-    def _press(self, event):
-        """Callback for mouse button presses in zoom-to-rectangle mode."""
-
-        # If we're already in the middle of a zoom, pressing another
-        # button works to "cancel"
-        if self._ids_zoom != []:
-            self._cancel_action()
-
-        if event.button == 1:
-            self._button_pressed = 1
-        elif event.button == 3:
-            self._button_pressed = 3
-        else:
-            self._cancel_action()
-            return
-
-        x, y = event.x, event.y
-
-        self._xypress = []
-        for i, a in enumerate(self.figure.get_axes()):
-            if (x is not None and y is not None and a.in_axes(event) and
-                    a.get_navigate() and a.can_zoom()):
-                self._xypress.append((x, y, a, i, a._get_view()))
-
-        id1 = self.figure.canvas.mpl_connect(
-            'motion_notify_event', self._mouse_move)
-        id2 = self.figure.canvas.mpl_connect(
-            'key_press_event', self._switch_on_zoom_mode)
-        id3 = self.figure.canvas.mpl_connect(
-            'key_release_event', self._switch_off_zoom_mode)
-
-        self._ids_zoom = id1, id2, id3
-        self._zoom_mode = event.key
-
-    def _switch_on_zoom_mode(self, event):
-        self._zoom_mode = event.key
-        self._mouse_move(event)
-
-    def _switch_off_zoom_mode(self, event):
-        self._zoom_mode = None
-        self._mouse_move(event)
-
-    def _mouse_move(self, event):
-        """Callback for mouse moves in zoom-to-rectangle mode."""
-
-        if self._xypress:
-            x, y = event.x, event.y
-            lastx, lasty, a, ind, view = self._xypress[0]
-            (x1, y1), (x2, y2) = np.clip(
-                [[lastx, lasty], [x, y]], a.bbox.min, a.bbox.max)
-            if self._zoom_mode == "x":
-                y1, y2 = a.bbox.intervaly
-            elif self._zoom_mode == "y":
-                x1, x2 = a.bbox.intervalx
-            self.toolmanager.trigger_tool(
-                'rubberband', self, data=(x1, y1, x2, y2))
-
-    def _release(self, event):
-        """Callback for mouse button releases in zoom-to-rectangle mode."""
-
-        for zoom_id in self._ids_zoom:
-            self.figure.canvas.mpl_disconnect(zoom_id)
-        self._ids_zoom = []
-
-        if not self._xypress:
-            self._cancel_action()
-            return
-
-        last_a = []
-
-        for cur_xypress in self._xypress:
-            x, y = event.x, event.y
-            lastx, lasty, a, _ind, view = cur_xypress
-            # ignore singular clicks - 5 pixels is a threshold
-            if abs(x - lastx) < 5 or abs(y - lasty) < 5:
-                self._cancel_action()
-                return
-
-            # detect twinx, twiny axes and avoid double zooming
-            twinx, twiny = False, False
-            if last_a:
-                for la in last_a:
-                    if a.get_shared_x_axes().joined(a, la):
-                        twinx = True
-                    if a.get_shared_y_axes().joined(a, la):
-                        twiny = True
-            last_a.append(a)
-
-            if self._button_pressed == 1:
-                direction = 'in'
-            elif self._button_pressed == 3:
-                direction = 'out'
-            else:
-                continue
-
-            a._set_view_from_bbox((lastx, lasty, x, y), direction,
-                                  self._zoom_mode, twinx, twiny)
-
-        self._zoom_mode = None
-        self.toolmanager.get_tool(_views_positions).push_current()
-        self._cancel_action()
-
-
-class ToolPan(ZoomPanBase):
-    """Pan axes with left mouse, zoom with right"""
-
-    default_keymap = rcParams['keymap.pan']
-    description = 'Pan axes with left mouse, zoom with right'
-    image = 'move'
-    cursor = cursors.MOVE
-    radio_group = 'default'
-
-    def __init__(self, *args):
-        ZoomPanBase.__init__(self, *args)
-        self._idDrag = None
-
-    def _cancel_action(self):
-        self._button_pressed = None
-        self._xypress = []
-        self.figure.canvas.mpl_disconnect(self._idDrag)
-        self.toolmanager.messagelock.release(self)
-        self.toolmanager.get_tool(_views_positions).refresh_locators()
-
-    def _press(self, event):
-        if event.button == 1:
-            self._button_pressed = 1
-        elif event.button == 3:
-            self._button_pressed = 3
-        else:
-            self._cancel_action()
-            return
-
-        x, y = event.x, event.y
-
-        self._xypress = []
-        for i, a in enumerate(self.figure.get_axes()):
-            if (x is not None and y is not None and a.in_axes(event) and
-                    a.get_navigate() and a.can_pan()):
-                a.start_pan(x, y, event.button)
-                self._xypress.append((a, i))
-                self.toolmanager.messagelock(self)
-                self._idDrag = self.figure.canvas.mpl_connect(
-                    'motion_notify_event', self._mouse_move)
-
-    def _release(self, event):
-        if self._button_pressed is None:
-            self._cancel_action()
-            return
-
-        self.figure.canvas.mpl_disconnect(self._idDrag)
-        self.toolmanager.messagelock.release(self)
-
-        for a, _ind in self._xypress:
-            a.end_pan()
-        if not self._xypress:
-            self._cancel_action()
-            return
-
-        self.toolmanager.get_tool(_views_positions).push_current()
-        self._cancel_action()
-
-    def _mouse_move(self, event):
-        for a, _ind in self._xypress:
-            # safer to use the recorded button at the _press than current
-            # button: # multiple button can get pressed during motion...
-            a.drag_pan(self._button_pressed, event.key, event.x, event.y)
-        self.toolmanager.canvas.draw_idle()
-
-
-class ToolHelpBase(ToolBase):
-    description = 'Print tool list, shortcuts and description'
-    default_keymap = rcParams['keymap.help']
-    image = 'help.png'
-
-    @staticmethod
-    def format_shortcut(key_sequence):
-        """
-        Converts a shortcut string from the notation used in rc config to the
-        standard notation for displaying shortcuts, e.g. 'ctrl+a' -> 'Ctrl+A'.
-        """
-        return (key_sequence if len(key_sequence) == 1 else
-                re.sub(r"\+[A-Z]", r"+Shift\g<0>", key_sequence).title())
-
-    def _format_tool_keymap(self, name):
-        keymaps = self.toolmanager.get_tool_keymap(name)
-        return ", ".join(self.format_shortcut(keymap) for keymap in keymaps)
-
-    def _get_help_entries(self):
-        return [(name, self._format_tool_keymap(name), tool.description)
-                for name, tool in sorted(self.toolmanager.tools.items())
-                if tool.description]
-
-    def _get_help_text(self):
-        entries = self._get_help_entries()
-        entries = ["{}: {}\n\t{}".format(*entry) for entry in entries]
-        return "\n".join(entries)
-
-    def _get_help_html(self):
-        fmt = "<tr><td>{}</td><td>{}</td><td>{}</td></tr>"
-        rows = [fmt.format(
-            "<b>Action</b>", "<b>Shortcuts</b>", "<b>Description</b>")]
-        rows += [fmt.format(*row) for row in self._get_help_entries()]
-        return ("<style>td {padding: 0px 4px}</style>"
-                "<table><thead>" + rows[0] + "</thead>"
-                "<tbody>".join(rows[1:]) + "</tbody></table>")
-
-
-class ToolCopyToClipboardBase(ToolBase):
-    """Tool to copy the figure to the clipboard"""
-
-    description = 'Copy the canvas figure to clipboard'
-    default_keymap = rcParams['keymap.copy']
-
-    def trigger(self, *args, **kwargs):
-        message = "Copy tool is not available"
-        self.toolmanager.message_event(message, self)
-
-
-default_tools = {'home': ToolHome, 'back': ToolBack, 'forward': ToolForward,
-                 'zoom': ToolZoom, 'pan': ToolPan,
-                 'subplots': 'ToolConfigureSubplots',
-                 'save': 'ToolSaveFigure',
-                 'grid': ToolGrid,
-                 'grid_minor': ToolMinorGrid,
-                 'fullscreen': ToolFullScreen,
-                 'quit': ToolQuit,
-                 'quit_all': ToolQuitAll,
-                 'allnav': ToolEnableAllNavigation,
-                 'nav': ToolEnableNavigation,
-                 'xscale': ToolXScale,
-                 'yscale': ToolYScale,
-                 'position': ToolCursorPosition,
-                 _views_positions: ToolViewsPositions,
-                 'cursor': 'ToolSetCursor',
-                 'rubberband': 'ToolRubberband',
-                 'help': 'ToolHelp',
-                 'copy': 'ToolCopyToClipboard',
-                 }
-"""Default tools"""
-
-default_toolbar_tools = [['navigation', ['home', 'back', 'forward']],
-                         ['zoompan', ['pan', 'zoom', 'subplots']],
-                         ['io', ['save', 'help']]]
-"""Default tools in the toolbar"""
-
-
-def add_tools_to_manager(toolmanager, tools=default_tools):
-    """
-    Add multiple tools to `ToolManager`
-
-    Parameters
-    ----------
-    toolmanager : ToolManager
-        `backend_managers.ToolManager` object that will get the tools added
-    tools : {str: class_like}, optional
-        The tools to add in a {name: tool} dict, see `add_tool` for more
-        info.
-    """
-
-    for name, tool in tools.items():
-        toolmanager.add_tool(name, tool)
-
-
-def add_tools_to_container(container, tools=default_toolbar_tools):
-    """
-    Add multiple tools to the container.
-
-    Parameters
-    ----------
-    container : Container
-        `backend_bases.ToolContainerBase` object that will get the tools added
-    tools : list, optional
-        List in the form
-        [[group1, [tool1, tool2 ...]], [group2, [...]]]
-        Where the tools given by tool1, and tool2 will display in group1.
-        See `add_tool` for details.
-    """
-
-    for group, grouptools in tools:
-        for position, tool in enumerate(grouptools):
-            container.add_tool(tool, group, position)

+ 0 - 54
venv/lib/python3.8/site-packages/matplotlib/backends/__init__.py

@@ -1,54 +0,0 @@
-import importlib
-import logging
-import os
-import sys
-
-import matplotlib
-from matplotlib import cbook
-from matplotlib.backend_bases import _Backend
-
-_log = logging.getLogger(__name__)
-
-
-# NOTE: plt.switch_backend() (called at import time) will add a "backend"
-# attribute here for backcompat.
-
-
-def _get_running_interactive_framework():
-    """
-    Return the interactive framework whose event loop is currently running, if
-    any, or "headless" if no event loop can be started, or None.
-
-    Returns
-    -------
-    Optional[str]
-        One of the following values: "qt5", "qt4", "gtk3", "wx", "tk",
-        "macosx", "headless", ``None``.
-    """
-    QtWidgets = (sys.modules.get("PyQt5.QtWidgets")
-                 or sys.modules.get("PySide2.QtWidgets"))
-    if QtWidgets and QtWidgets.QApplication.instance():
-        return "qt5"
-    QtGui = (sys.modules.get("PyQt4.QtGui")
-             or sys.modules.get("PySide.QtGui"))
-    if QtGui and QtGui.QApplication.instance():
-        return "qt4"
-    Gtk = sys.modules.get("gi.repository.Gtk")
-    if Gtk and Gtk.main_level():
-        return "gtk3"
-    wx = sys.modules.get("wx")
-    if wx and wx.GetApp():
-        return "wx"
-    tkinter = sys.modules.get("tkinter")
-    if tkinter:
-        for frame in sys._current_frames().values():
-            while frame:
-                if frame.f_code == tkinter.mainloop.__code__:
-                    return "tk"
-                frame = frame.f_back
-    if 'matplotlib.backends._macosx' in sys.modules:
-        if sys.modules["matplotlib.backends._macosx"].event_loop_is_running():
-            return "macosx"
-    if sys.platform.startswith("linux") and not os.environ.get("DISPLAY"):
-        return "headless"
-    return None

BIN
venv/lib/python3.8/site-packages/matplotlib/backends/_backend_agg.cpython-38-x86_64-linux-gnu.so


+ 0 - 84
venv/lib/python3.8/site-packages/matplotlib/backends/_backend_pdf_ps.py

@@ -1,84 +0,0 @@
-"""
-Common functionality between the PDF and PS backends.
-"""
-
-import functools
-
-import matplotlib as mpl
-from .. import font_manager, ft2font
-from ..afm import AFM
-from ..backend_bases import RendererBase
-
-
-@functools.lru_cache(50)
-def _cached_get_afm_from_fname(fname):
-    with open(fname, "rb") as fh:
-        return AFM(fh)
-
-
-class RendererPDFPSBase(RendererBase):
-    # The following attributes must be defined by the subclasses:
-    # - _afm_font_dir
-    # - _use_afm_rc_name
-
-    def flipy(self):
-        # docstring inherited
-        return False  # y increases from bottom to top.
-
-    def option_scale_image(self):
-        # docstring inherited
-        return True  # PDF and PS support arbitrary image scaling.
-
-    def option_image_nocomposite(self):
-        # docstring inherited
-        # Decide whether to composite image based on rcParam value.
-        return not mpl.rcParams["image.composite_image"]
-
-    def get_canvas_width_height(self):
-        # docstring inherited
-        return self.width * 72.0, self.height * 72.0
-
-    def get_text_width_height_descent(self, s, prop, ismath):
-        # docstring inherited
-        if mpl.rcParams["text.usetex"]:
-            texmanager = self.get_texmanager()
-            fontsize = prop.get_size_in_points()
-            w, h, d = texmanager.get_text_width_height_descent(
-                s, fontsize, renderer=self)
-            return w, h, d
-        elif ismath:
-            parse = self.mathtext_parser.parse(s, 72, prop)
-            return parse.width, parse.height, parse.depth
-        elif mpl.rcParams[self._use_afm_rc_name]:
-            font = self._get_font_afm(prop)
-            l, b, w, h, d = font.get_str_bbox_and_descent(s)
-            scale = prop.get_size_in_points() / 1000
-            w *= scale
-            h *= scale
-            d *= scale
-            return w, h, d
-        else:
-            font = self._get_font_ttf(prop)
-            font.set_text(s, 0.0, flags=ft2font.LOAD_NO_HINTING)
-            w, h = font.get_width_height()
-            d = font.get_descent()
-            scale = 1 / 64
-            w *= scale
-            h *= scale
-            d *= scale
-            return w, h, d
-
-    def _get_font_afm(self, prop):
-        fname = (
-            font_manager.findfont(
-                prop, fontext="afm", directory=self._afm_font_dir)
-            or font_manager.findfont(
-                "Helvetica", fontext="afm", directory=self._afm_font_dir))
-        return _cached_get_afm_from_fname(fname)
-
-    def _get_font_ttf(self, prop):
-        fname = font_manager.findfont(prop)
-        font = font_manager.get_font(fname)
-        font.clear()
-        font.set_size(prop.get_size_in_points(), 72)
-        return font

+ 0 - 907
venv/lib/python3.8/site-packages/matplotlib/backends/_backend_tk.py

@@ -1,907 +0,0 @@
-from contextlib import contextmanager
-import logging
-import math
-import os.path
-import sys
-import tkinter as tk
-from tkinter.simpledialog import SimpleDialog
-import tkinter.filedialog
-import tkinter.messagebox
-
-import numpy as np
-
-import matplotlib
-from matplotlib import backend_tools, cbook, rcParams
-from matplotlib.backend_bases import (
-    _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2,
-    StatusbarBase, TimerBase, ToolContainerBase, cursors)
-from matplotlib.backend_managers import ToolManager
-from matplotlib._pylab_helpers import Gcf
-from matplotlib.figure import Figure
-from matplotlib.widgets import SubplotTool
-from . import _tkagg
-
-try:
-    from ._tkagg import Win32_GetForegroundWindow, Win32_SetForegroundWindow
-except ImportError:
-    @contextmanager
-    def _restore_foreground_window_at_end():
-        yield
-else:
-    @contextmanager
-    def _restore_foreground_window_at_end():
-        foreground = Win32_GetForegroundWindow()
-        try:
-            yield
-        finally:
-            if rcParams['tk.window_focus']:
-                Win32_SetForegroundWindow(foreground)
-
-
-_log = logging.getLogger(__name__)
-
-backend_version = tk.TkVersion
-
-cursord = {
-    cursors.MOVE: "fleur",
-    cursors.HAND: "hand2",
-    cursors.POINTER: "arrow",
-    cursors.SELECT_REGION: "tcross",
-    cursors.WAIT: "watch",
-    }
-
-
-def blit(photoimage, aggimage, offsets, bbox=None):
-    """
-    Blit *aggimage* to *photoimage*.
-
-    *offsets* is a tuple describing how to fill the ``offset`` field of the
-    ``Tk_PhotoImageBlock`` struct: it should be (0, 1, 2, 3) for RGBA8888 data,
-    (2, 1, 0, 3) for little-endian ARBG32 (i.e. GBRA8888) data and (1, 2, 3, 0)
-    for big-endian ARGB32 (i.e. ARGB8888) data.
-
-    If *bbox* is passed, it defines the region that gets blitted.
-    """
-    data = np.asarray(aggimage)
-    height, width = data.shape[:2]
-    dataptr = (height, width, data.ctypes.data)
-    if bbox is not None:
-        (x1, y1), (x2, y2) = bbox.__array__()
-        x1 = max(math.floor(x1), 0)
-        x2 = min(math.ceil(x2), width)
-        y1 = max(math.floor(y1), 0)
-        y2 = min(math.ceil(y2), height)
-        bboxptr = (x1, x2, y1, y2)
-    else:
-        photoimage.blank()
-        bboxptr = (0, width, 0, height)
-    _tkagg.blit(
-        photoimage.tk.interpaddr(), str(photoimage), dataptr, offsets, bboxptr)
-
-
-class TimerTk(TimerBase):
-    '''
-    Subclass of :class:`backend_bases.TimerBase` that uses Tk's timer events.
-
-    Attributes
-    ----------
-    interval : int
-        The time between timer events in milliseconds. Default is 1000 ms.
-    single_shot : bool
-        Boolean flag indicating whether this timer should operate as single
-        shot (run once and then stop). Defaults to False.
-    callbacks : list
-        Stores list of (func, args) tuples that will be called upon timer
-        events. This list can be manipulated directly, or the functions
-        `add_callback` and `remove_callback` can be used.
-
-    '''
-    def __init__(self, parent, *args, **kwargs):
-        TimerBase.__init__(self, *args, **kwargs)
-        self.parent = parent
-        self._timer = None
-
-    def _timer_start(self):
-        self._timer_stop()
-        self._timer = self.parent.after(self._interval, self._on_timer)
-
-    def _timer_stop(self):
-        if self._timer is not None:
-            self.parent.after_cancel(self._timer)
-        self._timer = None
-
-    def _on_timer(self):
-        TimerBase._on_timer(self)
-
-        # Tk after() is only a single shot, so we need to add code here to
-        # reset the timer if we're not operating in single shot mode.  However,
-        # if _timer is None, this means that _timer_stop has been called; so
-        # don't recreate the timer in that case.
-        if not self._single and self._timer:
-            self._timer = self.parent.after(self._interval, self._on_timer)
-        else:
-            self._timer = None
-
-
-class FigureCanvasTk(FigureCanvasBase):
-    required_interactive_framework = "tk"
-
-    keyvald = {65507: 'control',
-               65505: 'shift',
-               65513: 'alt',
-               65515: 'super',
-               65508: 'control',
-               65506: 'shift',
-               65514: 'alt',
-               65361: 'left',
-               65362: 'up',
-               65363: 'right',
-               65364: 'down',
-               65307: 'escape',
-               65470: 'f1',
-               65471: 'f2',
-               65472: 'f3',
-               65473: 'f4',
-               65474: 'f5',
-               65475: 'f6',
-               65476: 'f7',
-               65477: 'f8',
-               65478: 'f9',
-               65479: 'f10',
-               65480: 'f11',
-               65481: 'f12',
-               65300: 'scroll_lock',
-               65299: 'break',
-               65288: 'backspace',
-               65293: 'enter',
-               65379: 'insert',
-               65535: 'delete',
-               65360: 'home',
-               65367: 'end',
-               65365: 'pageup',
-               65366: 'pagedown',
-               65438: '0',
-               65436: '1',
-               65433: '2',
-               65435: '3',
-               65430: '4',
-               65437: '5',
-               65432: '6',
-               65429: '7',
-               65431: '8',
-               65434: '9',
-               65451: '+',
-               65453: '-',
-               65450: '*',
-               65455: '/',
-               65439: 'dec',
-               65421: 'enter',
-               }
-
-    _keycode_lookup = {
-                       262145: 'control',
-                       524320: 'alt',
-                       524352: 'alt',
-                       1048584: 'super',
-                       1048592: 'super',
-                       131074: 'shift',
-                       131076: 'shift',
-                       }
-    """_keycode_lookup is used for badly mapped (i.e. no event.key_sym set)
-       keys on apple keyboards."""
-
-    def __init__(self, figure, master=None, resize_callback=None):
-        super(FigureCanvasTk, self).__init__(figure)
-        self._idle = True
-        self._idle_callback = None
-        t1, t2, w, h = self.figure.bbox.bounds
-        w, h = int(w), int(h)
-        self._tkcanvas = tk.Canvas(
-            master=master, background="white",
-            width=w, height=h, borderwidth=0, highlightthickness=0)
-        self._tkphoto = tk.PhotoImage(
-            master=self._tkcanvas, width=w, height=h)
-        self._tkcanvas.create_image(w//2, h//2, image=self._tkphoto)
-        self._resize_callback = resize_callback
-        self._tkcanvas.bind("<Configure>", self.resize)
-        self._tkcanvas.bind("<Key>", self.key_press)
-        self._tkcanvas.bind("<Motion>", self.motion_notify_event)
-        self._tkcanvas.bind("<Enter>", self.enter_notify_event)
-        self._tkcanvas.bind("<Leave>", self.leave_notify_event)
-        self._tkcanvas.bind("<KeyRelease>", self.key_release)
-        for name in ["<Button-1>", "<Button-2>", "<Button-3>"]:
-            self._tkcanvas.bind(name, self.button_press_event)
-        for name in [
-                "<Double-Button-1>", "<Double-Button-2>", "<Double-Button-3>"]:
-            self._tkcanvas.bind(name, self.button_dblclick_event)
-        for name in [
-                "<ButtonRelease-1>", "<ButtonRelease-2>", "<ButtonRelease-3>"]:
-            self._tkcanvas.bind(name, self.button_release_event)
-
-        # Mouse wheel on Linux generates button 4/5 events
-        for name in "<Button-4>", "<Button-5>":
-            self._tkcanvas.bind(name, self.scroll_event)
-        # Mouse wheel for windows goes to the window with the focus.
-        # Since the canvas won't usually have the focus, bind the
-        # event to the window containing the canvas instead.
-        # See http://wiki.tcl.tk/3893 (mousewheel) for details
-        root = self._tkcanvas.winfo_toplevel()
-        root.bind("<MouseWheel>", self.scroll_event_windows, "+")
-
-        # Can't get destroy events by binding to _tkcanvas. Therefore, bind
-        # to the window and filter.
-        def filter_destroy(evt):
-            if evt.widget is self._tkcanvas:
-                self._master.update_idletasks()
-                self.close_event()
-        root.bind("<Destroy>", filter_destroy, "+")
-
-        self._master = master
-        self._tkcanvas.focus_set()
-
-    def resize(self, event):
-        width, height = event.width, event.height
-        if self._resize_callback is not None:
-            self._resize_callback(event)
-
-        # compute desired figure size in inches
-        dpival = self.figure.dpi
-        winch = width / dpival
-        hinch = height / dpival
-        self.figure.set_size_inches(winch, hinch, forward=False)
-
-        self._tkcanvas.delete(self._tkphoto)
-        self._tkphoto = tk.PhotoImage(
-            master=self._tkcanvas, width=int(width), height=int(height))
-        self._tkcanvas.create_image(
-            int(width / 2), int(height / 2), image=self._tkphoto)
-        self.resize_event()
-        self.draw()
-
-    def draw_idle(self):
-        # docstring inherited
-        if not self._idle:
-            return
-
-        self._idle = False
-
-        def idle_draw(*args):
-            try:
-                self.draw()
-            finally:
-                self._idle = True
-
-        self._idle_callback = self._tkcanvas.after_idle(idle_draw)
-
-    def get_tk_widget(self):
-        """Return the Tk widget used to implement FigureCanvasTkAgg.
-        Although the initial implementation uses a Tk canvas,  this routine
-        is intended to hide that fact.
-        """
-        return self._tkcanvas
-
-    def motion_notify_event(self, event):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.figure.bbox.height - event.y
-        FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event)
-
-    def enter_notify_event(self, event):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.figure.bbox.height - event.y
-        FigureCanvasBase.enter_notify_event(self, guiEvent=event, xy=(x, y))
-
-    def button_press_event(self, event, dblclick=False):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.figure.bbox.height - event.y
-        num = getattr(event, 'num', None)
-
-        if sys.platform == 'darwin':
-            # 2 and 3 were reversed on the OSX platform I tested under tkagg.
-            if num == 2:
-                num = 3
-            elif num == 3:
-                num = 2
-
-        FigureCanvasBase.button_press_event(
-            self, x, y, num, dblclick=dblclick, guiEvent=event)
-
-    def button_dblclick_event(self, event):
-        self.button_press_event(event, dblclick=True)
-
-    def button_release_event(self, event):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.figure.bbox.height - event.y
-
-        num = getattr(event, 'num', None)
-
-        if sys.platform == 'darwin':
-            # 2 and 3 were reversed on the OSX platform I tested under tkagg.
-            if num == 2:
-                num = 3
-            elif num == 3:
-                num = 2
-
-        FigureCanvasBase.button_release_event(self, x, y, num, guiEvent=event)
-
-    def scroll_event(self, event):
-        x = event.x
-        y = self.figure.bbox.height - event.y
-        num = getattr(event, 'num', None)
-        step = 1 if num == 4 else -1 if num == 5 else 0
-        FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=event)
-
-    def scroll_event_windows(self, event):
-        """MouseWheel event processor"""
-        # need to find the window that contains the mouse
-        w = event.widget.winfo_containing(event.x_root, event.y_root)
-        if w == self._tkcanvas:
-            x = event.x_root - w.winfo_rootx()
-            y = event.y_root - w.winfo_rooty()
-            y = self.figure.bbox.height - y
-            step = event.delta/120.
-            FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=event)
-
-    def _get_key(self, event):
-        val = event.keysym_num
-        if val in self.keyvald:
-            key = self.keyvald[val]
-        elif (val == 0 and sys.platform == 'darwin'
-              and event.keycode in self._keycode_lookup):
-            key = self._keycode_lookup[event.keycode]
-        elif val < 256:
-            key = chr(val)
-        else:
-            key = None
-
-        # add modifier keys to the key string. Bit details originate from
-        # http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
-        # BIT_SHIFT = 0x001; BIT_CAPSLOCK = 0x002; BIT_CONTROL = 0x004;
-        # BIT_LEFT_ALT = 0x008; BIT_NUMLOCK = 0x010; BIT_RIGHT_ALT = 0x080;
-        # BIT_MB_1 = 0x100; BIT_MB_2 = 0x200; BIT_MB_3 = 0x400;
-        # In general, the modifier key is excluded from the modifier flag,
-        # however this is not the case on "darwin", so double check that
-        # we aren't adding repeat modifier flags to a modifier key.
-        if sys.platform == 'win32':
-            modifiers = [(17, 'alt', 'alt'),
-                         (2, 'ctrl', 'control'),
-                         ]
-        elif sys.platform == 'darwin':
-            modifiers = [(3, 'super', 'super'),
-                         (4, 'alt', 'alt'),
-                         (2, 'ctrl', 'control'),
-                         ]
-        else:
-            modifiers = [(6, 'super', 'super'),
-                         (3, 'alt', 'alt'),
-                         (2, 'ctrl', 'control'),
-                         ]
-
-        if key is not None:
-            # shift is not added to the keys as this is already accounted for
-            for bitmask, prefix, key_name in modifiers:
-                if event.state & (1 << bitmask) and key_name not in key:
-                    key = '{0}+{1}'.format(prefix, key)
-
-        return key
-
-    def key_press(self, event):
-        key = self._get_key(event)
-        FigureCanvasBase.key_press_event(self, key, guiEvent=event)
-
-    def key_release(self, event):
-        key = self._get_key(event)
-        FigureCanvasBase.key_release_event(self, key, guiEvent=event)
-
-    def new_timer(self, *args, **kwargs):
-        # docstring inherited
-        return TimerTk(self._tkcanvas, *args, **kwargs)
-
-    def flush_events(self):
-        # docstring inherited
-        self._master.update()
-
-
-class FigureManagerTk(FigureManagerBase):
-    """
-    Attributes
-    ----------
-    canvas : `FigureCanvas`
-        The FigureCanvas instance
-    num : int or str
-        The Figure number
-    toolbar : tk.Toolbar
-        The tk.Toolbar
-    window : tk.Window
-        The tk.Window
-
-    """
-    def __init__(self, canvas, num, window):
-        FigureManagerBase.__init__(self, canvas, num)
-        self.window = window
-        self.window.withdraw()
-        self.set_window_title("Figure %d" % num)
-        self.canvas = canvas
-        # If using toolmanager it has to be present when initializing the
-        # toolbar
-        self.toolmanager = self._get_toolmanager()
-        # packing toolbar first, because if space is getting low, last packed
-        # widget is getting shrunk first (-> the canvas)
-        self.toolbar = self._get_toolbar()
-        self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
-
-        self.statusbar = None
-
-        if self.toolmanager:
-            backend_tools.add_tools_to_manager(self.toolmanager)
-            if self.toolbar:
-                backend_tools.add_tools_to_container(self.toolbar)
-                self.statusbar = StatusbarTk(self.window, self.toolmanager)
-
-        self._shown = False
-
-    def _get_toolbar(self):
-        if matplotlib.rcParams['toolbar'] == 'toolbar2':
-            toolbar = NavigationToolbar2Tk(self.canvas, self.window)
-        elif matplotlib.rcParams['toolbar'] == 'toolmanager':
-            toolbar = ToolbarTk(self.toolmanager, self.window)
-        else:
-            toolbar = None
-        return toolbar
-
-    def _get_toolmanager(self):
-        if rcParams['toolbar'] == 'toolmanager':
-            toolmanager = ToolManager(self.canvas.figure)
-        else:
-            toolmanager = None
-        return toolmanager
-
-    def resize(self, width, height):
-        self.canvas._tkcanvas.master.geometry("%dx%d" % (width, height))
-
-        if self.toolbar is not None:
-            self.toolbar.configure(width=width)
-
-    def show(self):
-        with _restore_foreground_window_at_end():
-            if not self._shown:
-                def destroy(*args):
-                    self.window = None
-                    Gcf.destroy(self.num)
-                self.canvas._tkcanvas.bind("<Destroy>", destroy)
-                self.window.deiconify()
-            else:
-                self.canvas.draw_idle()
-            # Raise the new window.
-            self.canvas.manager.window.attributes('-topmost', 1)
-            self.canvas.manager.window.attributes('-topmost', 0)
-            self._shown = True
-
-    def destroy(self, *args):
-        if self.window is not None:
-            #self.toolbar.destroy()
-            if self.canvas._idle_callback:
-                self.canvas._tkcanvas.after_cancel(self.canvas._idle_callback)
-            self.window.destroy()
-        if Gcf.get_num_fig_managers() == 0:
-            if self.window is not None:
-                self.window.quit()
-        self.window = None
-
-    def get_window_title(self):
-        return self.window.wm_title()
-
-    def set_window_title(self, title):
-        self.window.wm_title(title)
-
-    def full_screen_toggle(self):
-        is_fullscreen = bool(self.window.attributes('-fullscreen'))
-        self.window.attributes('-fullscreen', not is_fullscreen)
-
-
-class NavigationToolbar2Tk(NavigationToolbar2, tk.Frame):
-    """
-    Attributes
-    ----------
-    canvas : `FigureCanvas`
-        the figure canvas on which to operate
-    win : tk.Window
-        the tk.Window which owns this toolbar
-
-    """
-    def __init__(self, canvas, window):
-        self.canvas = canvas
-        # Avoid using self.window (prefer self.canvas.get_tk_widget().master),
-        # so that Tool implementations can reuse the methods.
-        self.window = window
-        NavigationToolbar2.__init__(self, canvas)
-
-    def destroy(self, *args):
-        del self.message
-        tk.Frame.destroy(self, *args)
-
-    def set_message(self, s):
-        self.message.set(s)
-
-    def draw_rubberband(self, event, x0, y0, x1, y1):
-        height = self.canvas.figure.bbox.height
-        y0 = height - y0
-        y1 = height - y1
-        if hasattr(self, "lastrect"):
-            self.canvas._tkcanvas.delete(self.lastrect)
-        self.lastrect = self.canvas._tkcanvas.create_rectangle(x0, y0, x1, y1)
-
-    def release(self, event):
-        if hasattr(self, "lastrect"):
-            self.canvas._tkcanvas.delete(self.lastrect)
-            del self.lastrect
-
-    def set_cursor(self, cursor):
-        window = self.canvas.get_tk_widget().master
-        window.configure(cursor=cursord[cursor])
-        window.update_idletasks()
-
-    def _Button(self, text, file, command, extension='.gif'):
-        img_file = str(cbook._get_data_path('images', file + extension))
-        im = tk.PhotoImage(master=self, file=img_file)
-        b = tk.Button(
-            master=self, text=text, padx=2, pady=2, image=im, command=command)
-        b._ntimage = im
-        b.pack(side=tk.LEFT)
-        return b
-
-    def _Spacer(self):
-        # Buttons are 30px high. Make this 26px tall +2px padding to center it.
-        s = tk.Frame(
-            master=self, height=26, relief=tk.RIDGE, pady=2, bg="DarkGray")
-        s.pack(side=tk.LEFT, padx=5)
-        return s
-
-    def _init_toolbar(self):
-        xmin, xmax = self.canvas.figure.bbox.intervalx
-        height, width = 50, xmax-xmin
-        tk.Frame.__init__(self, master=self.window,
-                          width=int(width), height=int(height),
-                          borderwidth=2)
-
-        self.update()  # Make axes menu
-
-        for text, tooltip_text, image_file, callback in self.toolitems:
-            if text is None:
-                # Add a spacer; return value is unused.
-                self._Spacer()
-            else:
-                button = self._Button(text=text, file=image_file,
-                                      command=getattr(self, callback))
-                if tooltip_text is not None:
-                    ToolTip.createToolTip(button, tooltip_text)
-
-        self.message = tk.StringVar(master=self)
-        self._message_label = tk.Label(master=self, textvariable=self.message)
-        self._message_label.pack(side=tk.RIGHT)
-        self.pack(side=tk.BOTTOM, fill=tk.X)
-
-    def configure_subplots(self):
-        toolfig = Figure(figsize=(6, 3))
-        window = tk.Toplevel()
-        canvas = type(self.canvas)(toolfig, master=window)
-        toolfig.subplots_adjust(top=0.9)
-        canvas.tool = SubplotTool(self.canvas.figure, toolfig)
-        canvas.draw()
-        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
-        window.grab_set()
-
-    def save_figure(self, *args):
-        filetypes = self.canvas.get_supported_filetypes().copy()
-        default_filetype = self.canvas.get_default_filetype()
-
-        # Tk doesn't provide a way to choose a default filetype,
-        # so we just have to put it first
-        default_filetype_name = filetypes.pop(default_filetype)
-        sorted_filetypes = ([(default_filetype, default_filetype_name)]
-                            + sorted(filetypes.items()))
-        tk_filetypes = [(name, '*.%s' % ext) for ext, name in sorted_filetypes]
-
-        # adding a default extension seems to break the
-        # asksaveasfilename dialog when you choose various save types
-        # from the dropdown.  Passing in the empty string seems to
-        # work - JDH!
-        #defaultextension = self.canvas.get_default_filetype()
-        defaultextension = ''
-        initialdir = os.path.expanduser(rcParams['savefig.directory'])
-        initialfile = self.canvas.get_default_filename()
-        fname = tkinter.filedialog.asksaveasfilename(
-            master=self.canvas.get_tk_widget().master,
-            title='Save the figure',
-            filetypes=tk_filetypes,
-            defaultextension=defaultextension,
-            initialdir=initialdir,
-            initialfile=initialfile,
-            )
-
-        if fname in ["", ()]:
-            return
-        # Save dir for next time, unless empty str (i.e., use cwd).
-        if initialdir != "":
-            rcParams['savefig.directory'] = (
-                os.path.dirname(str(fname)))
-        try:
-            # This method will handle the delegation to the correct type
-            self.canvas.figure.savefig(fname)
-        except Exception as e:
-            tkinter.messagebox.showerror("Error saving file", str(e))
-
-    @cbook.deprecated("3.1")
-    def set_active(self, ind):
-        self._ind = ind
-        self._active = [self._axes[i] for i in self._ind]
-
-    def update(self):
-        self._axes = self.canvas.figure.axes
-        with _restore_foreground_window_at_end():
-            NavigationToolbar2.update(self)
-
-
-class ToolTip:
-    """
-    Tooltip recipe from
-    http://www.voidspace.org.uk/python/weblog/arch_d7_2006_07_01.shtml#e387
-    """
-    @staticmethod
-    def createToolTip(widget, text):
-        toolTip = ToolTip(widget)
-        def enter(event):
-            toolTip.showtip(text)
-        def leave(event):
-            toolTip.hidetip()
-        widget.bind('<Enter>', enter)
-        widget.bind('<Leave>', leave)
-
-    def __init__(self, widget):
-        self.widget = widget
-        self.tipwindow = None
-        self.id = None
-        self.x = self.y = 0
-
-    def showtip(self, text):
-        "Display text in tooltip window"
-        self.text = text
-        if self.tipwindow or not self.text:
-            return
-        x, y, _, _ = self.widget.bbox("insert")
-        x = x + self.widget.winfo_rootx() + 27
-        y = y + self.widget.winfo_rooty()
-        self.tipwindow = tw = tk.Toplevel(self.widget)
-        tw.wm_overrideredirect(1)
-        tw.wm_geometry("+%d+%d" % (x, y))
-        try:
-            # For Mac OS
-            tw.tk.call("::tk::unsupported::MacWindowStyle",
-                       "style", tw._w,
-                       "help", "noActivates")
-        except tk.TclError:
-            pass
-        label = tk.Label(tw, text=self.text, justify=tk.LEFT,
-                         background="#ffffe0", relief=tk.SOLID, borderwidth=1)
-        label.pack(ipadx=1)
-
-    def hidetip(self):
-        tw = self.tipwindow
-        self.tipwindow = None
-        if tw:
-            tw.destroy()
-
-
-class RubberbandTk(backend_tools.RubberbandBase):
-    def draw_rubberband(self, x0, y0, x1, y1):
-        height = self.figure.canvas.figure.bbox.height
-        y0 = height - y0
-        y1 = height - y1
-        if hasattr(self, "lastrect"):
-            self.figure.canvas._tkcanvas.delete(self.lastrect)
-        self.lastrect = self.figure.canvas._tkcanvas.create_rectangle(
-            x0, y0, x1, y1)
-
-    def remove_rubberband(self):
-        if hasattr(self, "lastrect"):
-            self.figure.canvas._tkcanvas.delete(self.lastrect)
-            del self.lastrect
-
-
-class SetCursorTk(backend_tools.SetCursorBase):
-    def set_cursor(self, cursor):
-        NavigationToolbar2Tk.set_cursor(
-            self._make_classic_style_pseudo_toolbar(), cursor)
-
-
-class ToolbarTk(ToolContainerBase, tk.Frame):
-    _icon_extension = '.gif'
-
-    def __init__(self, toolmanager, window):
-        ToolContainerBase.__init__(self, toolmanager)
-        xmin, xmax = self.toolmanager.canvas.figure.bbox.intervalx
-        height, width = 50, xmax - xmin
-        tk.Frame.__init__(self, master=window,
-                          width=int(width), height=int(height),
-                          borderwidth=2)
-        self._toolitems = {}
-        self.pack(side=tk.TOP, fill=tk.X)
-        self._groups = {}
-
-    def add_toolitem(
-            self, name, group, position, image_file, description, toggle):
-        frame = self._get_groupframe(group)
-        button = self._Button(name, image_file, toggle, frame)
-        if description is not None:
-            ToolTip.createToolTip(button, description)
-        self._toolitems.setdefault(name, [])
-        self._toolitems[name].append(button)
-
-    def _get_groupframe(self, group):
-        if group not in self._groups:
-            if self._groups:
-                self._add_separator()
-            frame = tk.Frame(master=self, borderwidth=0)
-            frame.pack(side=tk.LEFT, fill=tk.Y)
-            self._groups[group] = frame
-        return self._groups[group]
-
-    def _add_separator(self):
-        separator = tk.Frame(master=self, bd=5, width=1, bg='black')
-        separator.pack(side=tk.LEFT, fill=tk.Y, padx=2)
-
-    def _Button(self, text, image_file, toggle, frame):
-        if image_file is not None:
-            im = tk.PhotoImage(master=self, file=image_file)
-        else:
-            im = None
-
-        if not toggle:
-            b = tk.Button(master=frame, text=text, padx=2, pady=2, image=im,
-                          command=lambda: self._button_click(text))
-        else:
-            # There is a bug in tkinter included in some python 3.6 versions
-            # that without this variable, produces a "visual" toggling of
-            # other near checkbuttons
-            # https://bugs.python.org/issue29402
-            # https://bugs.python.org/issue25684
-            var = tk.IntVar()
-            b = tk.Checkbutton(master=frame, text=text, padx=2, pady=2,
-                               image=im, indicatoron=False,
-                               command=lambda: self._button_click(text),
-                               variable=var)
-        b._ntimage = im
-        b.pack(side=tk.LEFT)
-        return b
-
-    def _button_click(self, name):
-        self.trigger_tool(name)
-
-    def toggle_toolitem(self, name, toggled):
-        if name not in self._toolitems:
-            return
-        for toolitem in self._toolitems[name]:
-            if toggled:
-                toolitem.select()
-            else:
-                toolitem.deselect()
-
-    def remove_toolitem(self, name):
-        for toolitem in self._toolitems[name]:
-            toolitem.pack_forget()
-        del self._toolitems[name]
-
-
-class StatusbarTk(StatusbarBase, tk.Frame):
-    def __init__(self, window, *args, **kwargs):
-        StatusbarBase.__init__(self, *args, **kwargs)
-        xmin, xmax = self.toolmanager.canvas.figure.bbox.intervalx
-        height, width = 50, xmax - xmin
-        tk.Frame.__init__(self, master=window,
-                          width=int(width), height=int(height),
-                          borderwidth=2)
-        self._message = tk.StringVar(master=self)
-        self._message_label = tk.Label(master=self, textvariable=self._message)
-        self._message_label.pack(side=tk.RIGHT)
-        self.pack(side=tk.TOP, fill=tk.X)
-
-    def set_message(self, s):
-        self._message.set(s)
-
-
-class SaveFigureTk(backend_tools.SaveFigureBase):
-    def trigger(self, *args):
-        NavigationToolbar2Tk.save_figure(
-            self._make_classic_style_pseudo_toolbar())
-
-
-class ConfigureSubplotsTk(backend_tools.ConfigureSubplotsBase):
-    def __init__(self, *args, **kwargs):
-        backend_tools.ConfigureSubplotsBase.__init__(self, *args, **kwargs)
-        self.window = None
-
-    def trigger(self, *args):
-        self.init_window()
-        self.window.lift()
-
-    def init_window(self):
-        if self.window:
-            return
-
-        toolfig = Figure(figsize=(6, 3))
-        self.window = tk.Tk()
-
-        canvas = type(self.canvas)(toolfig, master=self.window)
-        toolfig.subplots_adjust(top=0.9)
-        SubplotTool(self.figure, toolfig)
-        canvas.draw()
-        canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
-        self.window.protocol("WM_DELETE_WINDOW", self.destroy)
-
-    def destroy(self, *args, **kwargs):
-        if self.window is not None:
-            self.window.destroy()
-            self.window = None
-
-
-class HelpTk(backend_tools.ToolHelpBase):
-    def trigger(self, *args):
-        dialog = SimpleDialog(
-            self.figure.canvas._tkcanvas, self._get_help_text(), ["OK"])
-        dialog.done = lambda num: dialog.frame.master.withdraw()
-
-
-backend_tools.ToolSaveFigure = SaveFigureTk
-backend_tools.ToolConfigureSubplots = ConfigureSubplotsTk
-backend_tools.ToolSetCursor = SetCursorTk
-backend_tools.ToolRubberband = RubberbandTk
-backend_tools.ToolHelp = HelpTk
-backend_tools.ToolCopyToClipboard = backend_tools.ToolCopyToClipboardBase
-Toolbar = ToolbarTk
-
-
-@_Backend.export
-class _BackendTk(_Backend):
-    FigureManager = FigureManagerTk
-
-    @classmethod
-    def new_figure_manager_given_figure(cls, num, figure):
-        """
-        Create a new figure manager instance for the given figure.
-        """
-        with _restore_foreground_window_at_end():
-            window = tk.Tk(className="matplotlib")
-            window.withdraw()
-
-            # Put a Matplotlib icon on the window rather than the default tk
-            # icon.  Tkinter doesn't allow colour icons on linux systems, but
-            # tk>=8.5 has a iconphoto command which we call directly.  See
-            # http://mail.python.org/pipermail/tkinter-discuss/2006-November/000954.html
-            icon_fname = str(cbook._get_data_path(
-                'images/matplotlib_128.ppm'))
-            icon_img = tk.PhotoImage(file=icon_fname, master=window)
-            try:
-                window.iconphoto(False, icon_img)
-            except Exception as exc:
-                # log the failure (due e.g. to Tk version), but carry on
-                _log.info('Could not load matplotlib icon: %s', exc)
-
-            canvas = cls.FigureCanvas(figure, master=window)
-            manager = cls.FigureManager(canvas, num, window)
-            if matplotlib.is_interactive():
-                manager.show()
-                canvas.draw_idle()
-            return manager
-
-    @staticmethod
-    def trigger_manager_draw(manager):
-        manager.show()
-
-    @staticmethod
-    def mainloop():
-        managers = Gcf.get_all_fig_managers()
-        if managers:
-            managers[0].window.mainloop()

BIN
venv/lib/python3.8/site-packages/matplotlib/backends/_tkagg.cpython-38-x86_64-linux-gnu.so


+ 0 - 622
venv/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py

@@ -1,622 +0,0 @@
-"""
-An agg http://antigrain.com/ backend
-
-Features that are implemented
-
- * capstyles and join styles
- * dashes
- * linewidth
- * lines, rectangles, ellipses
- * clipping to a rectangle
- * output to RGBA and PNG, optionally JPEG and TIFF
- * alpha blending
- * DPI scaling properly - everything scales properly (dashes, linewidths, etc)
- * draw polygon
- * freetype2 w/ ft2font
-
-TODO:
-
-  * integrate screen dpi w/ ppi and text
-
-"""
-try:
-    import threading
-except ImportError:
-    import dummy_threading as threading
-try:
-    from contextlib import nullcontext
-except ImportError:
-    from contextlib import ExitStack as nullcontext  # Py 3.6.
-from math import radians, cos, sin
-
-import numpy as np
-
-from matplotlib import cbook, rcParams, __version__
-from matplotlib.backend_bases import (
-    _Backend, FigureCanvasBase, FigureManagerBase, RendererBase)
-from matplotlib.font_manager import findfont, get_font
-from matplotlib.ft2font import (LOAD_FORCE_AUTOHINT, LOAD_NO_HINTING,
-                                LOAD_DEFAULT, LOAD_NO_AUTOHINT)
-from matplotlib.mathtext import MathTextParser
-from matplotlib.path import Path
-from matplotlib.transforms import Bbox, BboxBase
-from matplotlib import colors as mcolors
-
-from matplotlib.backends._backend_agg import RendererAgg as _RendererAgg
-
-from matplotlib.backend_bases import _has_pil
-
-if _has_pil:
-    from PIL import Image
-
-backend_version = 'v2.2'
-
-
-def get_hinting_flag():
-    mapping = {
-        True: LOAD_FORCE_AUTOHINT,
-        False: LOAD_NO_HINTING,
-        'either': LOAD_DEFAULT,
-        'native': LOAD_NO_AUTOHINT,
-        'auto': LOAD_FORCE_AUTOHINT,
-        'none': LOAD_NO_HINTING
-        }
-    return mapping[rcParams['text.hinting']]
-
-
-class RendererAgg(RendererBase):
-    """
-    The renderer handles all the drawing primitives using a graphics
-    context instance that controls the colors/styles
-    """
-
-    # we want to cache the fonts at the class level so that when
-    # multiple figures are created we can reuse them.  This helps with
-    # a bug on windows where the creation of too many figures leads to
-    # too many open file handles.  However, storing them at the class
-    # level is not thread safe.  The solution here is to let the
-    # FigureCanvas acquire a lock on the fontd at the start of the
-    # draw, and release it when it is done.  This allows multiple
-    # renderers to share the cached fonts, but only one figure can
-    # draw at time and so the font cache is used by only one
-    # renderer at a time.
-
-    lock = threading.RLock()
-
-    def __init__(self, width, height, dpi):
-        RendererBase.__init__(self)
-
-        self.dpi = dpi
-        self.width = width
-        self.height = height
-        self._renderer = _RendererAgg(int(width), int(height), dpi)
-        self._filter_renderers = []
-
-        self._update_methods()
-        self.mathtext_parser = MathTextParser('Agg')
-
-        self.bbox = Bbox.from_bounds(0, 0, self.width, self.height)
-
-    def __getstate__(self):
-        # We only want to preserve the init keywords of the Renderer.
-        # Anything else can be re-created.
-        return {'width': self.width, 'height': self.height, 'dpi': self.dpi}
-
-    def __setstate__(self, state):
-        self.__init__(state['width'], state['height'], state['dpi'])
-
-    def _update_methods(self):
-        self.draw_gouraud_triangle = self._renderer.draw_gouraud_triangle
-        self.draw_gouraud_triangles = self._renderer.draw_gouraud_triangles
-        self.draw_image = self._renderer.draw_image
-        self.draw_markers = self._renderer.draw_markers
-        self.draw_path_collection = self._renderer.draw_path_collection
-        self.draw_quad_mesh = self._renderer.draw_quad_mesh
-        self.copy_from_bbox = self._renderer.copy_from_bbox
-        self.get_content_extents = self._renderer.get_content_extents
-
-    def tostring_rgba_minimized(self):
-        extents = self.get_content_extents()
-        bbox = [[extents[0], self.height - (extents[1] + extents[3])],
-                [extents[0] + extents[2], self.height - extents[1]]]
-        region = self.copy_from_bbox(bbox)
-        return np.array(region), extents
-
-    def draw_path(self, gc, path, transform, rgbFace=None):
-        # docstring inherited
-        nmax = rcParams['agg.path.chunksize']  # here at least for testing
-        npts = path.vertices.shape[0]
-
-        if (nmax > 100 and npts > nmax and path.should_simplify and
-                rgbFace is None and gc.get_hatch() is None):
-            nch = np.ceil(npts / nmax)
-            chsize = int(np.ceil(npts / nch))
-            i0 = np.arange(0, npts, chsize)
-            i1 = np.zeros_like(i0)
-            i1[:-1] = i0[1:] - 1
-            i1[-1] = npts
-            for ii0, ii1 in zip(i0, i1):
-                v = path.vertices[ii0:ii1, :]
-                c = path.codes
-                if c is not None:
-                    c = c[ii0:ii1]
-                    c[0] = Path.MOVETO  # move to end of last chunk
-                p = Path(v, c)
-                try:
-                    self._renderer.draw_path(gc, p, transform, rgbFace)
-                except OverflowError:
-                    raise OverflowError("Exceeded cell block limit (set "
-                                        "'agg.path.chunksize' rcparam)")
-        else:
-            try:
-                self._renderer.draw_path(gc, path, transform, rgbFace)
-            except OverflowError:
-                raise OverflowError("Exceeded cell block limit (set "
-                                    "'agg.path.chunksize' rcparam)")
-
-    def draw_mathtext(self, gc, x, y, s, prop, angle):
-        """
-        Draw the math text using matplotlib.mathtext
-        """
-        ox, oy, width, height, descent, font_image, used_characters = \
-            self.mathtext_parser.parse(s, self.dpi, prop)
-
-        xd = descent * sin(radians(angle))
-        yd = descent * cos(radians(angle))
-        x = round(x + ox + xd)
-        y = round(y - oy + yd)
-        self._renderer.draw_text_image(font_image, x, y + 1, angle, gc)
-
-    def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
-        # docstring inherited
-
-        if ismath:
-            return self.draw_mathtext(gc, x, y, s, prop, angle)
-
-        flags = get_hinting_flag()
-        font = self._get_agg_font(prop)
-
-        if font is None:
-            return None
-        # We pass '0' for angle here, since it will be rotated (in raster
-        # space) in the following call to draw_text_image).
-        font.set_text(s, 0, flags=flags)
-        font.draw_glyphs_to_bitmap(antialiased=rcParams['text.antialiased'])
-        d = font.get_descent() / 64.0
-        # The descent needs to be adjusted for the angle.
-        xo, yo = font.get_bitmap_offset()
-        xo /= 64.0
-        yo /= 64.0
-        xd = d * sin(radians(angle))
-        yd = d * cos(radians(angle))
-        x = round(x + xo + xd)
-        y = round(y + yo + yd)
-        self._renderer.draw_text_image(font, x, y + 1, angle, gc)
-
-    def get_text_width_height_descent(self, s, prop, ismath):
-        # docstring inherited
-
-        if ismath in ["TeX", "TeX!"]:
-            # todo: handle props
-            texmanager = self.get_texmanager()
-            fontsize = prop.get_size_in_points()
-            w, h, d = texmanager.get_text_width_height_descent(
-                s, fontsize, renderer=self)
-            return w, h, d
-
-        if ismath:
-            ox, oy, width, height, descent, fonts, used_characters = \
-                self.mathtext_parser.parse(s, self.dpi, prop)
-            return width, height, descent
-
-        flags = get_hinting_flag()
-        font = self._get_agg_font(prop)
-        font.set_text(s, 0.0, flags=flags)
-        w, h = font.get_width_height()  # width and height of unrotated string
-        d = font.get_descent()
-        w /= 64.0  # convert from subpixels
-        h /= 64.0
-        d /= 64.0
-        return w, h, d
-
-    def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!', mtext=None):
-        # docstring inherited
-        # todo, handle props, angle, origins
-        size = prop.get_size_in_points()
-
-        texmanager = self.get_texmanager()
-
-        Z = texmanager.get_grey(s, size, self.dpi)
-        Z = np.array(Z * 255.0, np.uint8)
-
-        w, h, d = self.get_text_width_height_descent(s, prop, ismath)
-        xd = d * sin(radians(angle))
-        yd = d * cos(radians(angle))
-        x = round(x + xd)
-        y = round(y + yd)
-        self._renderer.draw_text_image(Z, x, y, angle, gc)
-
-    def get_canvas_width_height(self):
-        # docstring inherited
-        return self.width, self.height
-
-    def _get_agg_font(self, prop):
-        """
-        Get the font for text instance t, caching for efficiency
-        """
-        fname = findfont(prop)
-        font = get_font(fname)
-
-        font.clear()
-        size = prop.get_size_in_points()
-        font.set_size(size, self.dpi)
-
-        return font
-
-    def points_to_pixels(self, points):
-        # docstring inherited
-        return points * self.dpi / 72
-
-    def buffer_rgba(self):
-        return memoryview(self._renderer)
-
-    def tostring_argb(self):
-        return np.asarray(self._renderer).take([3, 0, 1, 2], axis=2).tobytes()
-
-    def tostring_rgb(self):
-        return np.asarray(self._renderer).take([0, 1, 2], axis=2).tobytes()
-
-    def clear(self):
-        self._renderer.clear()
-
-    def option_image_nocomposite(self):
-        # docstring inherited
-
-        # It is generally faster to composite each image directly to
-        # the Figure, and there's no file size benefit to compositing
-        # with the Agg backend
-        return True
-
-    def option_scale_image(self):
-        # docstring inherited
-        return False
-
-    def restore_region(self, region, bbox=None, xy=None):
-        """
-        Restore the saved region. If bbox (instance of BboxBase, or
-        its extents) is given, only the region specified by the bbox
-        will be restored. *xy* (a pair of floats) optionally
-        specifies the new position (the LLC of the original region,
-        not the LLC of the bbox) where the region will be restored.
-
-        >>> region = renderer.copy_from_bbox()
-        >>> x1, y1, x2, y2 = region.get_extents()
-        >>> renderer.restore_region(region, bbox=(x1+dx, y1, x2, y2),
-        ...                         xy=(x1-dx, y1))
-
-        """
-        if bbox is not None or xy is not None:
-            if bbox is None:
-                x1, y1, x2, y2 = region.get_extents()
-            elif isinstance(bbox, BboxBase):
-                x1, y1, x2, y2 = bbox.extents
-            else:
-                x1, y1, x2, y2 = bbox
-
-            if xy is None:
-                ox, oy = x1, y1
-            else:
-                ox, oy = xy
-
-            # The incoming data is float, but the _renderer type-checking wants
-            # to see integers.
-            self._renderer.restore_region(region, int(x1), int(y1),
-                                          int(x2), int(y2), int(ox), int(oy))
-
-        else:
-            self._renderer.restore_region(region)
-
-    def start_filter(self):
-        """
-        Start filtering. It simply create a new canvas (the old one is saved).
-        """
-        self._filter_renderers.append(self._renderer)
-        self._renderer = _RendererAgg(int(self.width), int(self.height),
-                                      self.dpi)
-        self._update_methods()
-
-    def stop_filter(self, post_processing):
-        """
-        Save the plot in the current canvas as a image and apply
-        the *post_processing* function.
-
-           def post_processing(image, dpi):
-             # ny, nx, depth = image.shape
-             # image (numpy array) has RGBA channels and has a depth of 4.
-             ...
-             # create a new_image (numpy array of 4 channels, size can be
-             # different). The resulting image may have offsets from
-             # lower-left corner of the original image
-             return new_image, offset_x, offset_y
-
-        The saved renderer is restored and the returned image from
-        post_processing is plotted (using draw_image) on it.
-        """
-
-        width, height = int(self.width), int(self.height)
-
-        buffer, (l, b, w, h) = self.tostring_rgba_minimized()
-
-        self._renderer = self._filter_renderers.pop()
-        self._update_methods()
-
-        if w > 0 and h > 0:
-            img = np.frombuffer(buffer, np.uint8)
-            img, ox, oy = post_processing(img.reshape((h, w, 4)) / 255.,
-                                          self.dpi)
-            gc = self.new_gc()
-            if img.dtype.kind == 'f':
-                img = np.asarray(img * 255., np.uint8)
-            img = img[::-1]
-            self._renderer.draw_image(gc, l + ox, height - b - h + oy, img)
-
-
-class FigureCanvasAgg(FigureCanvasBase):
-    """
-    The canvas the figure renders into.  Calls the draw and print fig
-    methods, creates the renderers, etc...
-
-    Attributes
-    ----------
-    figure : `matplotlib.figure.Figure`
-        A high-level Figure instance
-
-    """
-
-    def copy_from_bbox(self, bbox):
-        renderer = self.get_renderer()
-        return renderer.copy_from_bbox(bbox)
-
-    def restore_region(self, region, bbox=None, xy=None):
-        renderer = self.get_renderer()
-        return renderer.restore_region(region, bbox, xy)
-
-    def draw(self):
-        """
-        Draw the figure using the renderer.
-        """
-        self.renderer = self.get_renderer(cleared=True)
-        # Acquire a lock on the shared font cache.
-        with RendererAgg.lock, \
-             (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
-              else nullcontext()):
-            self.figure.draw(self.renderer)
-            # A GUI class may be need to update a window using this draw, so
-            # don't forget to call the superclass.
-            super().draw()
-
-    def get_renderer(self, cleared=False):
-        l, b, w, h = self.figure.bbox.bounds
-        key = w, h, self.figure.dpi
-        reuse_renderer = (hasattr(self, "renderer")
-                          and getattr(self, "_lastKey", None) == key)
-        if not reuse_renderer:
-            self.renderer = RendererAgg(w, h, self.figure.dpi)
-            self._lastKey = key
-        elif cleared:
-            self.renderer.clear()
-        return self.renderer
-
-    def tostring_rgb(self):
-        """Get the image as an RGB byte string.
-
-        `draw` must be called at least once before this function will work and
-        to update the renderer for any subsequent changes to the Figure.
-
-        Returns
-        -------
-        bytes
-        """
-        return self.renderer.tostring_rgb()
-
-    def tostring_argb(self):
-        """Get the image as an ARGB byte string.
-
-        `draw` must be called at least once before this function will work and
-        to update the renderer for any subsequent changes to the Figure.
-
-        Returns
-        -------
-        bytes
-        """
-        return self.renderer.tostring_argb()
-
-    def buffer_rgba(self):
-        """Get the image as a memoryview to the renderer's buffer.
-
-        `draw` must be called at least once before this function will work and
-        to update the renderer for any subsequent changes to the Figure.
-
-        Returns
-        -------
-        memoryview
-        """
-        return self.renderer.buffer_rgba()
-
-    def print_raw(self, filename_or_obj, *args, **kwargs):
-        FigureCanvasAgg.draw(self)
-        renderer = self.get_renderer()
-        with cbook.open_file_cm(filename_or_obj, "wb") as fh:
-            fh.write(renderer.buffer_rgba())
-
-    print_rgba = print_raw
-
-    def print_png(self, filename_or_obj, *args,
-                  metadata=None, pil_kwargs=None,
-                  **kwargs):
-        """
-        Write the figure to a PNG file.
-
-        Parameters
-        ----------
-        filename_or_obj : str or PathLike or file-like object
-            The file to write to.
-
-        metadata : dict, optional
-            Metadata in the PNG file as key-value pairs of bytes or latin-1
-            encodable strings.
-            According to the PNG specification, keys must be shorter than 79
-            chars.
-
-            The `PNG specification`_ defines some common keywords that may be
-            used as appropriate:
-
-            - Title: Short (one line) title or caption for image.
-            - Author: Name of image's creator.
-            - Description: Description of image (possibly long).
-            - Copyright: Copyright notice.
-            - Creation Time: Time of original image creation
-              (usually RFC 1123 format).
-            - Software: Software used to create the image.
-            - Disclaimer: Legal disclaimer.
-            - Warning: Warning of nature of content.
-            - Source: Device used to create the image.
-            - Comment: Miscellaneous comment;
-              conversion from other image format.
-
-            Other keywords may be invented for other purposes.
-
-            If 'Software' is not given, an autogenerated value for matplotlib
-            will be used.
-
-            For more details see the `PNG specification`_.
-
-            .. _PNG specification: \
-                https://www.w3.org/TR/2003/REC-PNG-20031110/#11keywords
-
-        pil_kwargs : dict, optional
-            If set to a non-None value, use Pillow to save the figure instead
-            of Matplotlib's builtin PNG support, and pass these keyword
-            arguments to `PIL.Image.save`.
-
-            If the 'pnginfo' key is present, it completely overrides
-            *metadata*, including the default 'Software' key.
-        """
-        from matplotlib import _png
-
-        if metadata is None:
-            metadata = {}
-        default_metadata = {
-            "Software":
-                f"matplotlib version{__version__}, http://matplotlib.org/",
-        }
-
-        FigureCanvasAgg.draw(self)
-        if pil_kwargs is not None:
-            from PIL import Image
-            from PIL.PngImagePlugin import PngInfo
-            # Only use the metadata kwarg if pnginfo is not set, because the
-            # semantics of duplicate keys in pnginfo is unclear.
-            if "pnginfo" in pil_kwargs:
-                if metadata:
-                    cbook._warn_external("'metadata' is overridden by the "
-                                         "'pnginfo' entry in 'pil_kwargs'.")
-            else:
-                pnginfo = PngInfo()
-                for k, v in {**default_metadata, **metadata}.items():
-                    pnginfo.add_text(k, v)
-                pil_kwargs["pnginfo"] = pnginfo
-            pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
-            (Image.fromarray(np.asarray(self.buffer_rgba()))
-             .save(filename_or_obj, format="png", **pil_kwargs))
-
-        else:
-            renderer = self.get_renderer()
-            with cbook.open_file_cm(filename_or_obj, "wb") as fh:
-                _png.write_png(renderer._renderer, fh, self.figure.dpi,
-                               metadata={**default_metadata, **metadata})
-
-    def print_to_buffer(self):
-        FigureCanvasAgg.draw(self)
-        renderer = self.get_renderer()
-        return (bytes(renderer.buffer_rgba()),
-                (int(renderer.width), int(renderer.height)))
-
-    if _has_pil:
-
-        # Note that these methods should typically be called via savefig() and
-        # print_figure(), and the latter ensures that `self.figure.dpi` already
-        # matches the dpi kwarg (if any).
-
-        @cbook._delete_parameter("3.2", "dryrun")
-        def print_jpg(self, filename_or_obj, *args, dryrun=False,
-                      pil_kwargs=None, **kwargs):
-            """
-            Write the figure to a JPEG file.
-
-            Parameters
-            ----------
-            filename_or_obj : str or PathLike or file-like object
-                The file to write to.
-
-            Other Parameters
-            ----------------
-            quality : int
-                The image quality, on a scale from 1 (worst) to 100 (best).
-                The default is :rc:`savefig.jpeg_quality`.  Values above
-                95 should be avoided; 100 completely disables the JPEG
-                quantization stage.
-
-            optimize : bool
-                If present, indicates that the encoder should
-                make an extra pass over the image in order to select
-                optimal encoder settings.
-
-            progressive : bool
-                If present, indicates that this image
-                should be stored as a progressive JPEG file.
-
-            pil_kwargs : dict, optional
-                Additional keyword arguments that are passed to
-                `PIL.Image.save` when saving the figure.  These take precedence
-                over *quality*, *optimize* and *progressive*.
-            """
-            FigureCanvasAgg.draw(self)
-            if dryrun:
-                return
-            # The image is pasted onto a white background image to handle
-            # transparency.
-            image = Image.fromarray(np.asarray(self.buffer_rgba()))
-            background = Image.new('RGB', image.size, "white")
-            background.paste(image, image)
-            if pil_kwargs is None:
-                pil_kwargs = {}
-            for k in ["quality", "optimize", "progressive"]:
-                if k in kwargs:
-                    pil_kwargs.setdefault(k, kwargs[k])
-            pil_kwargs.setdefault("quality", rcParams["savefig.jpeg_quality"])
-            pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
-            return background.save(
-                filename_or_obj, format='jpeg', **pil_kwargs)
-
-        print_jpeg = print_jpg
-
-        @cbook._delete_parameter("3.2", "dryrun")
-        def print_tif(self, filename_or_obj, *args, dryrun=False,
-                      pil_kwargs=None, **kwargs):
-            FigureCanvasAgg.draw(self)
-            if dryrun:
-                return
-            if pil_kwargs is None:
-                pil_kwargs = {}
-            pil_kwargs.setdefault("dpi", (self.figure.dpi, self.figure.dpi))
-            return (Image.fromarray(np.asarray(self.buffer_rgba()))
-                    .save(filename_or_obj, format='tiff', **pil_kwargs))
-
-        print_tiff = print_tif
-
-
-@_Backend.export
-class _BackendAgg(_Backend):
-    FigureCanvas = FigureCanvasAgg
-    FigureManager = FigureManagerBase

+ 0 - 484
venv/lib/python3.8/site-packages/matplotlib/backends/backend_cairo.py

@@ -1,484 +0,0 @@
-"""
-A Cairo backend for matplotlib
-==============================
-:Author: Steve Chaplin and others
-
-This backend depends on cairocffi or pycairo.
-"""
-
-import gzip
-
-import numpy as np
-
-try:
-    import cairo
-    if cairo.version_info < (1, 11, 0):
-        # Introduced create_for_data for Py3.
-        raise ImportError
-except ImportError:
-    try:
-        import cairocffi as cairo
-    except ImportError:
-        raise ImportError(
-            "cairo backend requires that pycairo>=1.11.0 or cairocffi"
-            "is installed")
-
-from .. import cbook
-from matplotlib.backend_bases import (
-    _Backend, FigureCanvasBase, FigureManagerBase, GraphicsContextBase,
-    RendererBase)
-from matplotlib.font_manager import ttfFontProperty
-from matplotlib.mathtext import MathTextParser
-from matplotlib.path import Path
-from matplotlib.transforms import Affine2D
-
-
-backend_version = cairo.version
-
-
-if cairo.__name__ == "cairocffi":
-    # Convert a pycairo context to a cairocffi one.
-    def _to_context(ctx):
-        if not isinstance(ctx, cairo.Context):
-            ctx = cairo.Context._from_pointer(
-                cairo.ffi.cast(
-                    'cairo_t **',
-                    id(ctx) + object.__basicsize__)[0],
-                incref=True)
-        return ctx
-else:
-    # Pass-through a pycairo context.
-    def _to_context(ctx):
-        return ctx
-
-
-def _append_path(ctx, path, transform, clip=None):
-    for points, code in path.iter_segments(
-            transform, remove_nans=True, clip=clip):
-        if code == Path.MOVETO:
-            ctx.move_to(*points)
-        elif code == Path.CLOSEPOLY:
-            ctx.close_path()
-        elif code == Path.LINETO:
-            ctx.line_to(*points)
-        elif code == Path.CURVE3:
-            cur = np.asarray(ctx.get_current_point())
-            a = points[:2]
-            b = points[-2:]
-            ctx.curve_to(*(cur / 3 + a * 2 / 3), *(a * 2 / 3 + b / 3), *b)
-        elif code == Path.CURVE4:
-            ctx.curve_to(*points)
-
-
-class RendererCairo(RendererBase):
-    fontweights = {
-        100:          cairo.FONT_WEIGHT_NORMAL,
-        200:          cairo.FONT_WEIGHT_NORMAL,
-        300:          cairo.FONT_WEIGHT_NORMAL,
-        400:          cairo.FONT_WEIGHT_NORMAL,
-        500:          cairo.FONT_WEIGHT_NORMAL,
-        600:          cairo.FONT_WEIGHT_BOLD,
-        700:          cairo.FONT_WEIGHT_BOLD,
-        800:          cairo.FONT_WEIGHT_BOLD,
-        900:          cairo.FONT_WEIGHT_BOLD,
-        'ultralight': cairo.FONT_WEIGHT_NORMAL,
-        'light':      cairo.FONT_WEIGHT_NORMAL,
-        'normal':     cairo.FONT_WEIGHT_NORMAL,
-        'medium':     cairo.FONT_WEIGHT_NORMAL,
-        'regular':    cairo.FONT_WEIGHT_NORMAL,
-        'semibold':   cairo.FONT_WEIGHT_BOLD,
-        'bold':       cairo.FONT_WEIGHT_BOLD,
-        'heavy':      cairo.FONT_WEIGHT_BOLD,
-        'ultrabold':  cairo.FONT_WEIGHT_BOLD,
-        'black':      cairo.FONT_WEIGHT_BOLD,
-    }
-    fontangles = {
-        'italic':  cairo.FONT_SLANT_ITALIC,
-        'normal':  cairo.FONT_SLANT_NORMAL,
-        'oblique': cairo.FONT_SLANT_OBLIQUE,
-    }
-
-    def __init__(self, dpi):
-        self.dpi = dpi
-        self.gc = GraphicsContextCairo(renderer=self)
-        self.text_ctx = cairo.Context(
-           cairo.ImageSurface(cairo.FORMAT_ARGB32, 1, 1))
-        self.mathtext_parser = MathTextParser('Cairo')
-        RendererBase.__init__(self)
-
-    def set_ctx_from_surface(self, surface):
-        self.gc.ctx = cairo.Context(surface)
-        # Although it may appear natural to automatically call
-        # `self.set_width_height(surface.get_width(), surface.get_height())`
-        # here (instead of having the caller do so separately), this would fail
-        # for PDF/PS/SVG surfaces, which have no way to report their extents.
-
-    def set_width_height(self, width, height):
-        self.width = width
-        self.height = height
-
-    def _fill_and_stroke(self, ctx, fill_c, alpha, alpha_overrides):
-        if fill_c is not None:
-            ctx.save()
-            if len(fill_c) == 3 or alpha_overrides:
-                ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], alpha)
-            else:
-                ctx.set_source_rgba(fill_c[0], fill_c[1], fill_c[2], fill_c[3])
-            ctx.fill_preserve()
-            ctx.restore()
-        ctx.stroke()
-
-    def draw_path(self, gc, path, transform, rgbFace=None):
-        # docstring inherited
-        ctx = gc.ctx
-        # Clip the path to the actual rendering extents if it isn't filled.
-        clip = (ctx.clip_extents()
-                if rgbFace is None and gc.get_hatch() is None
-                else None)
-        transform = (transform
-                     + Affine2D().scale(1, -1).translate(0, self.height))
-        ctx.new_path()
-        _append_path(ctx, path, transform, clip)
-        self._fill_and_stroke(
-            ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha())
-
-    def draw_markers(self, gc, marker_path, marker_trans, path, transform,
-                     rgbFace=None):
-        # docstring inherited
-
-        ctx = gc.ctx
-        ctx.new_path()
-        # Create the path for the marker; it needs to be flipped here already!
-        _append_path(ctx, marker_path, marker_trans + Affine2D().scale(1, -1))
-        marker_path = ctx.copy_path_flat()
-
-        # Figure out whether the path has a fill
-        x1, y1, x2, y2 = ctx.fill_extents()
-        if x1 == 0 and y1 == 0 and x2 == 0 and y2 == 0:
-            filled = False
-            # No fill, just unset this (so we don't try to fill it later on)
-            rgbFace = None
-        else:
-            filled = True
-
-        transform = (transform
-                     + Affine2D().scale(1, -1).translate(0, self.height))
-
-        ctx.new_path()
-        for i, (vertices, codes) in enumerate(
-                path.iter_segments(transform, simplify=False)):
-            if len(vertices):
-                x, y = vertices[-2:]
-                ctx.save()
-
-                # Translate and apply path
-                ctx.translate(x, y)
-                ctx.append_path(marker_path)
-
-                ctx.restore()
-
-                # Slower code path if there is a fill; we need to draw
-                # the fill and stroke for each marker at the same time.
-                # Also flush out the drawing every once in a while to
-                # prevent the paths from getting way too long.
-                if filled or i % 1000 == 0:
-                    self._fill_and_stroke(
-                        ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha())
-
-        # Fast path, if there is no fill, draw everything in one step
-        if not filled:
-            self._fill_and_stroke(
-                ctx, rgbFace, gc.get_alpha(), gc.get_forced_alpha())
-
-    def draw_image(self, gc, x, y, im):
-        im = cbook._unmultiplied_rgba8888_to_premultiplied_argb32(im[::-1])
-        surface = cairo.ImageSurface.create_for_data(
-            im.ravel().data, cairo.FORMAT_ARGB32,
-            im.shape[1], im.shape[0], im.shape[1] * 4)
-        ctx = gc.ctx
-        y = self.height - y - im.shape[0]
-
-        ctx.save()
-        ctx.set_source_surface(surface, float(x), float(y))
-        ctx.paint()
-        ctx.restore()
-
-    def draw_text(self, gc, x, y, s, prop, angle, ismath=False, mtext=None):
-        # docstring inherited
-
-        # Note: (x, y) are device/display coords, not user-coords, unlike other
-        # draw_* methods
-        if ismath:
-            self._draw_mathtext(gc, x, y, s, prop, angle)
-
-        else:
-            ctx = gc.ctx
-            ctx.new_path()
-            ctx.move_to(x, y)
-            ctx.select_font_face(prop.get_name(),
-                                 self.fontangles[prop.get_style()],
-                                 self.fontweights[prop.get_weight()])
-
-            size = prop.get_size_in_points() * self.dpi / 72.0
-
-            ctx.save()
-            if angle:
-                ctx.rotate(np.deg2rad(-angle))
-            ctx.set_font_size(size)
-
-            ctx.show_text(s)
-            ctx.restore()
-
-    def _draw_mathtext(self, gc, x, y, s, prop, angle):
-        ctx = gc.ctx
-        width, height, descent, glyphs, rects = self.mathtext_parser.parse(
-            s, self.dpi, prop)
-
-        ctx.save()
-        ctx.translate(x, y)
-        if angle:
-            ctx.rotate(np.deg2rad(-angle))
-
-        for font, fontsize, s, ox, oy in glyphs:
-            ctx.new_path()
-            ctx.move_to(ox, oy)
-
-            fontProp = ttfFontProperty(font)
-            ctx.select_font_face(fontProp.name,
-                                 self.fontangles[fontProp.style],
-                                 self.fontweights[fontProp.weight])
-
-            size = fontsize * self.dpi / 72.0
-            ctx.set_font_size(size)
-            ctx.show_text(s)
-
-        for ox, oy, w, h in rects:
-            ctx.new_path()
-            ctx.rectangle(ox, oy, w, h)
-            ctx.set_source_rgb(0, 0, 0)
-            ctx.fill_preserve()
-
-        ctx.restore()
-
-    def get_canvas_width_height(self):
-        # docstring inherited
-        return self.width, self.height
-
-    def get_text_width_height_descent(self, s, prop, ismath):
-        # docstring inherited
-
-        if ismath:
-            width, height, descent, fonts, used_characters = \
-                self.mathtext_parser.parse(s, self.dpi, prop)
-            return width, height, descent
-
-        ctx = self.text_ctx
-        ctx.save()
-        ctx.select_font_face(prop.get_name(),
-                             self.fontangles[prop.get_style()],
-                             self.fontweights[prop.get_weight()])
-
-        # Cairo (says it) uses 1/96 inch user space units, ref: cairo_gstate.c
-        # but if /96.0 is used the font is too small
-        size = prop.get_size_in_points() * self.dpi / 72
-
-        # problem - scale remembers last setting and font can become
-        # enormous causing program to crash
-        # save/restore prevents the problem
-        ctx.set_font_size(size)
-
-        y_bearing, w, h = ctx.text_extents(s)[1:4]
-        ctx.restore()
-
-        return w, h, h + y_bearing
-
-    def new_gc(self):
-        # docstring inherited
-        self.gc.ctx.save()
-        self.gc._alpha = 1
-        self.gc._forced_alpha = False  # if True, _alpha overrides A from RGBA
-        return self.gc
-
-    def points_to_pixels(self, points):
-        # docstring inherited
-        return points / 72 * self.dpi
-
-
-class GraphicsContextCairo(GraphicsContextBase):
-    _joind = {
-        'bevel':  cairo.LINE_JOIN_BEVEL,
-        'miter':  cairo.LINE_JOIN_MITER,
-        'round':  cairo.LINE_JOIN_ROUND,
-    }
-
-    _capd = {
-        'butt':        cairo.LINE_CAP_BUTT,
-        'projecting':  cairo.LINE_CAP_SQUARE,
-        'round':       cairo.LINE_CAP_ROUND,
-    }
-
-    def __init__(self, renderer):
-        GraphicsContextBase.__init__(self)
-        self.renderer = renderer
-
-    def restore(self):
-        self.ctx.restore()
-
-    def set_alpha(self, alpha):
-        GraphicsContextBase.set_alpha(self, alpha)
-        _alpha = self.get_alpha()
-        rgb = self._rgb
-        if self.get_forced_alpha():
-            self.ctx.set_source_rgba(rgb[0], rgb[1], rgb[2], _alpha)
-        else:
-            self.ctx.set_source_rgba(rgb[0], rgb[1], rgb[2], rgb[3])
-
-    # def set_antialiased(self, b):
-        # cairo has many antialiasing modes, we need to pick one for True and
-        # one for False.
-
-    def set_capstyle(self, cs):
-        self.ctx.set_line_cap(cbook._check_getitem(self._capd, capstyle=cs))
-        self._capstyle = cs
-
-    def set_clip_rectangle(self, rectangle):
-        if not rectangle:
-            return
-        x, y, w, h = np.round(rectangle.bounds)
-        ctx = self.ctx
-        ctx.new_path()
-        ctx.rectangle(x, self.renderer.height - h - y, w, h)
-        ctx.clip()
-
-    def set_clip_path(self, path):
-        if not path:
-            return
-        tpath, affine = path.get_transformed_path_and_affine()
-        ctx = self.ctx
-        ctx.new_path()
-        affine = (affine
-                  + Affine2D().scale(1, -1).translate(0, self.renderer.height))
-        _append_path(ctx, tpath, affine)
-        ctx.clip()
-
-    def set_dashes(self, offset, dashes):
-        self._dashes = offset, dashes
-        if dashes is None:
-            self.ctx.set_dash([], 0)  # switch dashes off
-        else:
-            self.ctx.set_dash(
-                list(self.renderer.points_to_pixels(np.asarray(dashes))),
-                offset)
-
-    def set_foreground(self, fg, isRGBA=None):
-        GraphicsContextBase.set_foreground(self, fg, isRGBA)
-        if len(self._rgb) == 3:
-            self.ctx.set_source_rgb(*self._rgb)
-        else:
-            self.ctx.set_source_rgba(*self._rgb)
-
-    def get_rgb(self):
-        return self.ctx.get_source().get_rgba()[:3]
-
-    def set_joinstyle(self, js):
-        self.ctx.set_line_join(cbook._check_getitem(self._joind, joinstyle=js))
-        self._joinstyle = js
-
-    def set_linewidth(self, w):
-        self._linewidth = float(w)
-        self.ctx.set_line_width(self.renderer.points_to_pixels(w))
-
-
-class FigureCanvasCairo(FigureCanvasBase):
-
-    def print_png(self, fobj, *args, **kwargs):
-        self._get_printed_image_surface().write_to_png(fobj)
-
-    def print_rgba(self, fobj, *args, **kwargs):
-        width, height = self.get_width_height()
-        buf = self._get_printed_image_surface().get_data()
-        fobj.write(cbook._premultiplied_argb32_to_unmultiplied_rgba8888(
-            np.asarray(buf).reshape((width, height, 4))))
-
-    print_raw = print_rgba
-
-    def _get_printed_image_surface(self):
-        width, height = self.get_width_height()
-        renderer = RendererCairo(self.figure.dpi)
-        renderer.set_width_height(width, height)
-        surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height)
-        renderer.set_ctx_from_surface(surface)
-        self.figure.draw(renderer)
-        return surface
-
-    def print_pdf(self, fobj, *args, **kwargs):
-        return self._save(fobj, 'pdf', *args, **kwargs)
-
-    def print_ps(self, fobj, *args, **kwargs):
-        return self._save(fobj, 'ps', *args, **kwargs)
-
-    def print_svg(self, fobj, *args, **kwargs):
-        return self._save(fobj, 'svg', *args, **kwargs)
-
-    def print_svgz(self, fobj, *args, **kwargs):
-        return self._save(fobj, 'svgz', *args, **kwargs)
-
-    def _save(self, fo, fmt, **kwargs):
-        # save PDF/PS/SVG
-        orientation = kwargs.get('orientation', 'portrait')
-
-        dpi = 72
-        self.figure.dpi = dpi
-        w_in, h_in = self.figure.get_size_inches()
-        width_in_points, height_in_points = w_in * dpi, h_in * dpi
-
-        if orientation == 'landscape':
-            width_in_points, height_in_points = (
-                height_in_points, width_in_points)
-
-        if fmt == 'ps':
-            if not hasattr(cairo, 'PSSurface'):
-                raise RuntimeError('cairo has not been compiled with PS '
-                                   'support enabled')
-            surface = cairo.PSSurface(fo, width_in_points, height_in_points)
-        elif fmt == 'pdf':
-            if not hasattr(cairo, 'PDFSurface'):
-                raise RuntimeError('cairo has not been compiled with PDF '
-                                   'support enabled')
-            surface = cairo.PDFSurface(fo, width_in_points, height_in_points)
-        elif fmt in ('svg', 'svgz'):
-            if not hasattr(cairo, 'SVGSurface'):
-                raise RuntimeError('cairo has not been compiled with SVG '
-                                   'support enabled')
-            if fmt == 'svgz':
-                if isinstance(fo, str):
-                    fo = gzip.GzipFile(fo, 'wb')
-                else:
-                    fo = gzip.GzipFile(None, 'wb', fileobj=fo)
-            surface = cairo.SVGSurface(fo, width_in_points, height_in_points)
-        else:
-            raise ValueError("Unknown format: {!r}".format(fmt))
-
-        # surface.set_dpi() can be used
-        renderer = RendererCairo(self.figure.dpi)
-        renderer.set_width_height(width_in_points, height_in_points)
-        renderer.set_ctx_from_surface(surface)
-        ctx = renderer.gc.ctx
-
-        if orientation == 'landscape':
-            ctx.rotate(np.pi / 2)
-            ctx.translate(0, -height_in_points)
-            # Perhaps add an '%%Orientation: Landscape' comment?
-
-        self.figure.draw(renderer)
-
-        ctx.show_page()
-        surface.finish()
-        if fmt == 'svgz':
-            fo.close()
-
-
-@_Backend.export
-class _BackendCairo(_Backend):
-    FigureCanvas = FigureCanvasCairo
-    FigureManager = FigureManagerBase

+ 0 - 1000
venv/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3.py

@@ -1,1000 +0,0 @@
-import functools
-import logging
-import os
-from pathlib import Path
-import sys
-
-import matplotlib
-from matplotlib import backend_tools, cbook, rcParams
-from matplotlib._pylab_helpers import Gcf
-from matplotlib.backend_bases import (
-    _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2,
-    StatusbarBase, TimerBase, ToolContainerBase, cursors)
-from matplotlib.backend_managers import ToolManager
-from matplotlib.figure import Figure
-from matplotlib.widgets import SubplotTool
-
-try:
-    import gi
-except ImportError:
-    raise ImportError("The GTK3 backends require PyGObject")
-
-try:
-    # :raises ValueError: If module/version is already loaded, already
-    # required, or unavailable.
-    gi.require_version("Gtk", "3.0")
-except ValueError as e:
-    # in this case we want to re-raise as ImportError so the
-    # auto-backend selection logic correctly skips.
-    raise ImportError from e
-
-from gi.repository import GLib, GObject, Gtk, Gdk
-
-
-_log = logging.getLogger(__name__)
-
-backend_version = "%s.%s.%s" % (
-    Gtk.get_major_version(), Gtk.get_micro_version(), Gtk.get_minor_version())
-
-try:
-    cursord = {
-        cursors.MOVE:          Gdk.Cursor.new(Gdk.CursorType.FLEUR),
-        cursors.HAND:          Gdk.Cursor.new(Gdk.CursorType.HAND2),
-        cursors.POINTER:       Gdk.Cursor.new(Gdk.CursorType.LEFT_PTR),
-        cursors.SELECT_REGION: Gdk.Cursor.new(Gdk.CursorType.TCROSS),
-        cursors.WAIT:          Gdk.Cursor.new(Gdk.CursorType.WATCH),
-    }
-except TypeError as exc:
-    # Happens when running headless.  Convert to ImportError to cooperate with
-    # backend switching.
-    raise ImportError(exc)
-
-
-class TimerGTK3(TimerBase):
-    """
-    Subclass of `.TimerBase` using GTK3 for timer events.
-
-    Attributes
-    ----------
-    interval : int
-        The time between timer events in milliseconds. Default is 1000 ms.
-    single_shot : bool
-        Boolean flag indicating whether this timer should operate as single
-        shot (run once and then stop). Defaults to False.
-    callbacks : list
-        Stores list of (func, args) tuples that will be called upon timer
-        events. This list can be manipulated directly, or the functions
-        `add_callback` and `remove_callback` can be used.
-    """
-
-    def _timer_start(self):
-        # Need to stop it, otherwise we potentially leak a timer id that will
-        # never be stopped.
-        self._timer_stop()
-        self._timer = GLib.timeout_add(self._interval, self._on_timer)
-
-    def _timer_stop(self):
-        if self._timer is not None:
-            GLib.source_remove(self._timer)
-            self._timer = None
-
-    def _timer_set_interval(self):
-        # Only stop and restart it if the timer has already been started
-        if self._timer is not None:
-            self._timer_stop()
-            self._timer_start()
-
-    def _on_timer(self):
-        TimerBase._on_timer(self)
-
-        # Gtk timeout_add() requires that the callback returns True if it
-        # is to be called again.
-        if self.callbacks and not self._single:
-            return True
-        else:
-            self._timer = None
-            return False
-
-
-class FigureCanvasGTK3(Gtk.DrawingArea, FigureCanvasBase):
-    required_interactive_framework = "gtk3"
-
-    keyvald = {65507: 'control',
-               65505: 'shift',
-               65513: 'alt',
-               65508: 'control',
-               65506: 'shift',
-               65514: 'alt',
-               65361: 'left',
-               65362: 'up',
-               65363: 'right',
-               65364: 'down',
-               65307: 'escape',
-               65470: 'f1',
-               65471: 'f2',
-               65472: 'f3',
-               65473: 'f4',
-               65474: 'f5',
-               65475: 'f6',
-               65476: 'f7',
-               65477: 'f8',
-               65478: 'f9',
-               65479: 'f10',
-               65480: 'f11',
-               65481: 'f12',
-               65300: 'scroll_lock',
-               65299: 'break',
-               65288: 'backspace',
-               65293: 'enter',
-               65379: 'insert',
-               65535: 'delete',
-               65360: 'home',
-               65367: 'end',
-               65365: 'pageup',
-               65366: 'pagedown',
-               65438: '0',
-               65436: '1',
-               65433: '2',
-               65435: '3',
-               65430: '4',
-               65437: '5',
-               65432: '6',
-               65429: '7',
-               65431: '8',
-               65434: '9',
-               65451: '+',
-               65453: '-',
-               65450: '*',
-               65455: '/',
-               65439: 'dec',
-               65421: 'enter',
-               }
-
-    # Setting this as a static constant prevents
-    # this resulting expression from leaking
-    event_mask = (Gdk.EventMask.BUTTON_PRESS_MASK
-                  | Gdk.EventMask.BUTTON_RELEASE_MASK
-                  | Gdk.EventMask.EXPOSURE_MASK
-                  | Gdk.EventMask.KEY_PRESS_MASK
-                  | Gdk.EventMask.KEY_RELEASE_MASK
-                  | Gdk.EventMask.ENTER_NOTIFY_MASK
-                  | Gdk.EventMask.LEAVE_NOTIFY_MASK
-                  | Gdk.EventMask.POINTER_MOTION_MASK
-                  | Gdk.EventMask.POINTER_MOTION_HINT_MASK
-                  | Gdk.EventMask.SCROLL_MASK)
-
-    def __init__(self, figure):
-        FigureCanvasBase.__init__(self, figure)
-        GObject.GObject.__init__(self)
-
-        self._idle_draw_id = 0
-        self._lastCursor = None
-
-        self.connect('scroll_event',         self.scroll_event)
-        self.connect('button_press_event',   self.button_press_event)
-        self.connect('button_release_event', self.button_release_event)
-        self.connect('configure_event',      self.configure_event)
-        self.connect('draw',                 self.on_draw_event)
-        self.connect('key_press_event',      self.key_press_event)
-        self.connect('key_release_event',    self.key_release_event)
-        self.connect('motion_notify_event',  self.motion_notify_event)
-        self.connect('leave_notify_event',   self.leave_notify_event)
-        self.connect('enter_notify_event',   self.enter_notify_event)
-        self.connect('size_allocate',        self.size_allocate)
-
-        self.set_events(self.__class__.event_mask)
-
-        self.set_double_buffered(True)
-        self.set_can_focus(True)
-        self._renderer_init()
-
-    def destroy(self):
-        #Gtk.DrawingArea.destroy(self)
-        self.close_event()
-        if self._idle_draw_id != 0:
-            GLib.source_remove(self._idle_draw_id)
-
-    def scroll_event(self, widget, event):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.get_allocation().height - event.y
-        step = 1 if event.direction == Gdk.ScrollDirection.UP else -1
-        FigureCanvasBase.scroll_event(self, x, y, step, guiEvent=event)
-        return False  # finish event propagation?
-
-    def button_press_event(self, widget, event):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.get_allocation().height - event.y
-        FigureCanvasBase.button_press_event(
-            self, x, y, event.button, guiEvent=event)
-        return False  # finish event propagation?
-
-    def button_release_event(self, widget, event):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.get_allocation().height - event.y
-        FigureCanvasBase.button_release_event(
-            self, x, y, event.button, guiEvent=event)
-        return False  # finish event propagation?
-
-    def key_press_event(self, widget, event):
-        key = self._get_key(event)
-        FigureCanvasBase.key_press_event(self, key, guiEvent=event)
-        return True  # stop event propagation
-
-    def key_release_event(self, widget, event):
-        key = self._get_key(event)
-        FigureCanvasBase.key_release_event(self, key, guiEvent=event)
-        return True  # stop event propagation
-
-    def motion_notify_event(self, widget, event):
-        if event.is_hint:
-            t, x, y, state = event.window.get_pointer()
-        else:
-            x, y = event.x, event.y
-
-        # flipy so y=0 is bottom of canvas
-        y = self.get_allocation().height - y
-        FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event)
-        return False  # finish event propagation?
-
-    def leave_notify_event(self, widget, event):
-        FigureCanvasBase.leave_notify_event(self, event)
-
-    def enter_notify_event(self, widget, event):
-        x = event.x
-        # flipy so y=0 is bottom of canvas
-        y = self.get_allocation().height - event.y
-        FigureCanvasBase.enter_notify_event(self, guiEvent=event, xy=(x, y))
-
-    def size_allocate(self, widget, allocation):
-        dpival = self.figure.dpi
-        winch = allocation.width / dpival
-        hinch = allocation.height / dpival
-        self.figure.set_size_inches(winch, hinch, forward=False)
-        FigureCanvasBase.resize_event(self)
-        self.draw_idle()
-
-    def _get_key(self, event):
-        if event.keyval in self.keyvald:
-            key = self.keyvald[event.keyval]
-        elif event.keyval < 256:
-            key = chr(event.keyval)
-        else:
-            key = None
-
-        modifiers = [
-                     (Gdk.ModifierType.MOD4_MASK, 'super'),
-                     (Gdk.ModifierType.MOD1_MASK, 'alt'),
-                     (Gdk.ModifierType.CONTROL_MASK, 'ctrl'),
-                    ]
-        for key_mask, prefix in modifiers:
-            if event.state & key_mask:
-                key = '{0}+{1}'.format(prefix, key)
-
-        return key
-
-    def configure_event(self, widget, event):
-        if widget.get_property("window") is None:
-            return
-        w, h = event.width, event.height
-        if w < 3 or h < 3:
-            return  # empty fig
-        # resize the figure (in inches)
-        dpi = self.figure.dpi
-        self.figure.set_size_inches(w / dpi, h / dpi, forward=False)
-        return False  # finish event propagation?
-
-    def on_draw_event(self, widget, ctx):
-        # to be overwritten by GTK3Agg or GTK3Cairo
-        pass
-
-    def draw(self):
-        # docstring inherited
-        if self.is_drawable():
-            self.queue_draw()
-
-    def draw_idle(self):
-        # docstring inherited
-        if self._idle_draw_id != 0:
-            return
-        def idle_draw(*args):
-            try:
-                self.draw()
-            finally:
-                self._idle_draw_id = 0
-            return False
-        self._idle_draw_id = GLib.idle_add(idle_draw)
-
-    def new_timer(self, *args, **kwargs):
-        # docstring inherited
-        return TimerGTK3(*args, **kwargs)
-
-    def flush_events(self):
-        # docstring inherited
-        Gdk.threads_enter()
-        while Gtk.events_pending():
-            Gtk.main_iteration()
-        Gdk.flush()
-        Gdk.threads_leave()
-
-
-class FigureManagerGTK3(FigureManagerBase):
-    """
-    Attributes
-    ----------
-    canvas : `FigureCanvas`
-        The FigureCanvas instance
-    num : int or str
-        The Figure number
-    toolbar : Gtk.Toolbar
-        The Gtk.Toolbar
-    vbox : Gtk.VBox
-        The Gtk.VBox containing the canvas and toolbar
-    window : Gtk.Window
-        The Gtk.Window
-
-    """
-    def __init__(self, canvas, num):
-        FigureManagerBase.__init__(self, canvas, num)
-
-        self.window = Gtk.Window()
-        self.window.set_wmclass("matplotlib", "Matplotlib")
-        self.set_window_title("Figure %d" % num)
-        try:
-            self.window.set_icon_from_file(window_icon)
-        except Exception:
-            # Some versions of gtk throw a glib.GError but not all, so I am not
-            # sure how to catch it.  I am unhappy doing a blanket catch here,
-            # but am not sure what a better way is - JDH
-            _log.info('Could not load matplotlib icon: %s', sys.exc_info()[1])
-
-        self.vbox = Gtk.Box()
-        self.vbox.set_property("orientation", Gtk.Orientation.VERTICAL)
-        self.window.add(self.vbox)
-        self.vbox.show()
-
-        self.canvas.show()
-
-        self.vbox.pack_start(self.canvas, True, True, 0)
-        # calculate size for window
-        w = int(self.canvas.figure.bbox.width)
-        h = int(self.canvas.figure.bbox.height)
-
-        self.toolmanager = self._get_toolmanager()
-        self.toolbar = self._get_toolbar()
-        self.statusbar = None
-
-        def add_widget(child, expand, fill, padding):
-            child.show()
-            self.vbox.pack_end(child, False, False, 0)
-            size_request = child.size_request()
-            return size_request.height
-
-        if self.toolmanager:
-            backend_tools.add_tools_to_manager(self.toolmanager)
-            if self.toolbar:
-                backend_tools.add_tools_to_container(self.toolbar)
-                self.statusbar = StatusbarGTK3(self.toolmanager)
-                h += add_widget(self.statusbar, False, False, 0)
-                h += add_widget(Gtk.HSeparator(), False, False, 0)
-
-        if self.toolbar is not None:
-            self.toolbar.show()
-            h += add_widget(self.toolbar, False, False, 0)
-
-        self.window.set_default_size(w, h)
-
-        def destroy(*args):
-            Gcf.destroy(num)
-        self.window.connect("destroy", destroy)
-        self.window.connect("delete_event", destroy)
-        if matplotlib.is_interactive():
-            self.window.show()
-            self.canvas.draw_idle()
-
-        self.canvas.grab_focus()
-
-    def destroy(self, *args):
-        self.vbox.destroy()
-        self.window.destroy()
-        self.canvas.destroy()
-        if self.toolbar:
-            self.toolbar.destroy()
-
-        if (Gcf.get_num_fig_managers() == 0 and
-                not matplotlib.is_interactive() and
-                Gtk.main_level() >= 1):
-            Gtk.main_quit()
-
-    def show(self):
-        # show the figure window
-        self.window.show()
-        self.window.present()
-
-    def full_screen_toggle(self):
-        self._full_screen_flag = not self._full_screen_flag
-        if self._full_screen_flag:
-            self.window.fullscreen()
-        else:
-            self.window.unfullscreen()
-    _full_screen_flag = False
-
-    def _get_toolbar(self):
-        # must be inited after the window, drawingArea and figure
-        # attrs are set
-        if rcParams['toolbar'] == 'toolbar2':
-            toolbar = NavigationToolbar2GTK3(self.canvas, self.window)
-        elif rcParams['toolbar'] == 'toolmanager':
-            toolbar = ToolbarGTK3(self.toolmanager)
-        else:
-            toolbar = None
-        return toolbar
-
-    def _get_toolmanager(self):
-        # must be initialised after toolbar has been set
-        if rcParams['toolbar'] == 'toolmanager':
-            toolmanager = ToolManager(self.canvas.figure)
-        else:
-            toolmanager = None
-        return toolmanager
-
-    def get_window_title(self):
-        return self.window.get_title()
-
-    def set_window_title(self, title):
-        self.window.set_title(title)
-
-    def resize(self, width, height):
-        'set the canvas size in pixels'
-        #_, _, cw, ch = self.canvas.allocation
-        #_, _, ww, wh = self.window.allocation
-        #self.window.resize (width-cw+ww, height-ch+wh)
-        self.window.resize(width, height)
-
-
-class NavigationToolbar2GTK3(NavigationToolbar2, Gtk.Toolbar):
-    def __init__(self, canvas, window):
-        self.win = window
-        GObject.GObject.__init__(self)
-        NavigationToolbar2.__init__(self, canvas)
-        self.ctx = None
-
-    def set_message(self, s):
-        self.message.set_label(s)
-
-    def set_cursor(self, cursor):
-        self.canvas.get_property("window").set_cursor(cursord[cursor])
-        Gtk.main_iteration()
-
-    def draw_rubberband(self, event, x0, y0, x1, y1):
-        # adapted from
-        # http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/189744
-        self.ctx = self.canvas.get_property("window").cairo_create()
-
-        # todo: instead of redrawing the entire figure, copy the part of
-        # the figure that was covered by the previous rubberband rectangle
-        self.canvas.draw()
-
-        height = self.canvas.figure.bbox.height
-        y1 = height - y1
-        y0 = height - y0
-        w = abs(x1 - x0)
-        h = abs(y1 - y0)
-        rect = [int(val) for val in (min(x0, x1), min(y0, y1), w, h)]
-
-        self.ctx.new_path()
-        self.ctx.set_line_width(0.5)
-        self.ctx.rectangle(rect[0], rect[1], rect[2], rect[3])
-        self.ctx.set_source_rgb(0, 0, 0)
-        self.ctx.stroke()
-
-    def _init_toolbar(self):
-        self.set_style(Gtk.ToolbarStyle.ICONS)
-
-        self._gtk_ids = {}
-        for text, tooltip_text, image_file, callback in self.toolitems:
-            if text is None:
-                self.insert(Gtk.SeparatorToolItem(), -1)
-                continue
-            image = Gtk.Image()
-            image.set_from_file(
-                str(cbook._get_data_path('images', image_file + '.png')))
-            self._gtk_ids[text] = tbutton = Gtk.ToolButton()
-            tbutton.set_label(text)
-            tbutton.set_icon_widget(image)
-            self.insert(tbutton, -1)
-            tbutton.connect('clicked', getattr(self, callback))
-            tbutton.set_tooltip_text(tooltip_text)
-
-        toolitem = Gtk.SeparatorToolItem()
-        self.insert(toolitem, -1)
-        toolitem.set_draw(False)
-        toolitem.set_expand(True)
-
-        toolitem = Gtk.ToolItem()
-        self.insert(toolitem, -1)
-        self.message = Gtk.Label()
-        toolitem.add(self.message)
-
-        self.show_all()
-
-    @cbook.deprecated("3.1")
-    def get_filechooser(self):
-        fc = FileChooserDialog(
-            title='Save the figure',
-            parent=self.win,
-            path=os.path.expanduser(rcParams['savefig.directory']),
-            filetypes=self.canvas.get_supported_filetypes(),
-            default_filetype=self.canvas.get_default_filetype())
-        fc.set_current_name(self.canvas.get_default_filename())
-        return fc
-
-    def save_figure(self, *args):
-        dialog = Gtk.FileChooserDialog(
-            title="Save the figure",
-            parent=self.canvas.get_toplevel(),
-            action=Gtk.FileChooserAction.SAVE,
-            buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                     Gtk.STOCK_SAVE,   Gtk.ResponseType.OK),
-        )
-        for name, fmts \
-                in self.canvas.get_supported_filetypes_grouped().items():
-            ff = Gtk.FileFilter()
-            ff.set_name(name)
-            for fmt in fmts:
-                ff.add_pattern("*." + fmt)
-            dialog.add_filter(ff)
-            if self.canvas.get_default_filetype() in fmts:
-                dialog.set_filter(ff)
-
-        @functools.partial(dialog.connect, "notify::filter")
-        def on_notify_filter(*args):
-            name = dialog.get_filter().get_name()
-            fmt = self.canvas.get_supported_filetypes_grouped()[name][0]
-            dialog.set_current_name(
-                str(Path(dialog.get_current_name()).with_suffix("." + fmt)))
-
-        dialog.set_current_folder(rcParams["savefig.directory"])
-        dialog.set_current_name(self.canvas.get_default_filename())
-        dialog.set_do_overwrite_confirmation(True)
-
-        response = dialog.run()
-        fname = dialog.get_filename()
-        ff = dialog.get_filter()  # Doesn't autoadjust to filename :/
-        fmt = self.canvas.get_supported_filetypes_grouped()[ff.get_name()][0]
-        dialog.destroy()
-        if response == Gtk.ResponseType.CANCEL:
-            return
-        # Save dir for next time, unless empty str (which means use cwd).
-        if rcParams['savefig.directory']:
-            rcParams['savefig.directory'] = os.path.dirname(fname)
-        try:
-            self.canvas.figure.savefig(fname, format=fmt)
-        except Exception as e:
-            error_msg_gtk(str(e), parent=self)
-
-    def configure_subplots(self, button):
-        toolfig = Figure(figsize=(6, 3))
-        canvas = type(self.canvas)(toolfig)
-        toolfig.subplots_adjust(top=0.9)
-        # Need to keep a reference to the tool.
-        _tool = SubplotTool(self.canvas.figure, toolfig)
-
-        w = int(toolfig.bbox.width)
-        h = int(toolfig.bbox.height)
-
-        window = Gtk.Window()
-        try:
-            window.set_icon_from_file(window_icon)
-        except Exception:
-            # we presumably already logged a message on the
-            # failure of the main plot, don't keep reporting
-            pass
-        window.set_title("Subplot Configuration Tool")
-        window.set_default_size(w, h)
-        vbox = Gtk.Box()
-        vbox.set_property("orientation", Gtk.Orientation.VERTICAL)
-        window.add(vbox)
-        vbox.show()
-
-        canvas.show()
-        vbox.pack_start(canvas, True, True, 0)
-        window.show()
-
-    def set_history_buttons(self):
-        can_backward = self._nav_stack._pos > 0
-        can_forward = self._nav_stack._pos < len(self._nav_stack._elements) - 1
-        if 'Back' in self._gtk_ids:
-            self._gtk_ids['Back'].set_sensitive(can_backward)
-        if 'Forward' in self._gtk_ids:
-            self._gtk_ids['Forward'].set_sensitive(can_forward)
-
-
-@cbook.deprecated("3.1")
-class FileChooserDialog(Gtk.FileChooserDialog):
-    """GTK+ file selector which remembers the last file/directory
-    selected and presents the user with a menu of supported image formats
-    """
-    def __init__(self,
-                 title='Save file',
-                 parent=None,
-                 action=Gtk.FileChooserAction.SAVE,
-                 buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                          Gtk.STOCK_SAVE, Gtk.ResponseType.OK),
-                 path=None,
-                 filetypes=[],
-                 default_filetype=None,
-                 ):
-        super().__init__(title, parent, action, buttons)
-        self.set_default_response(Gtk.ResponseType.OK)
-        self.set_do_overwrite_confirmation(True)
-
-        if not path:
-            path = os.getcwd()
-
-        # create an extra widget to list supported image formats
-        self.set_current_folder(path)
-        self.set_current_name('image.' + default_filetype)
-
-        hbox = Gtk.Box(spacing=10)
-        hbox.pack_start(Gtk.Label(label="File Format:"), False, False, 0)
-
-        liststore = Gtk.ListStore(GObject.TYPE_STRING)
-        cbox = Gtk.ComboBox()
-        cbox.set_model(liststore)
-        cell = Gtk.CellRendererText()
-        cbox.pack_start(cell, True)
-        cbox.add_attribute(cell, 'text', 0)
-        hbox.pack_start(cbox, False, False, 0)
-
-        self.filetypes = filetypes
-        sorted_filetypes = sorted(filetypes.items())
-        default = 0
-        for i, (ext, name) in enumerate(sorted_filetypes):
-            liststore.append(["%s (*.%s)" % (name, ext)])
-            if ext == default_filetype:
-                default = i
-        cbox.set_active(default)
-        self.ext = default_filetype
-
-        def cb_cbox_changed(cbox, data=None):
-            """File extension changed"""
-            head, filename = os.path.split(self.get_filename())
-            root, ext = os.path.splitext(filename)
-            ext = ext[1:]
-            new_ext = sorted_filetypes[cbox.get_active()][0]
-            self.ext = new_ext
-
-            if ext in self.filetypes:
-                filename = root + '.' + new_ext
-            elif ext == '':
-                filename = filename.rstrip('.') + '.' + new_ext
-
-            self.set_current_name(filename)
-        cbox.connect("changed", cb_cbox_changed)
-
-        hbox.show_all()
-        self.set_extra_widget(hbox)
-
-    def get_filename_from_user(self):
-        if self.run() == int(Gtk.ResponseType.OK):
-            return self.get_filename(), self.ext
-        else:
-            return None, self.ext
-
-
-class ToolbarGTK3(ToolContainerBase, Gtk.Box):
-    _icon_extension = '.png'
-
-    def __init__(self, toolmanager):
-        ToolContainerBase.__init__(self, toolmanager)
-        Gtk.Box.__init__(self)
-        self.set_property("orientation", Gtk.Orientation.VERTICAL)
-
-        self._toolarea = Gtk.Box()
-        self._toolarea.set_property('orientation', Gtk.Orientation.HORIZONTAL)
-        self.pack_start(self._toolarea, False, False, 0)
-        self._toolarea.show_all()
-        self._groups = {}
-        self._toolitems = {}
-
-    def add_toolitem(self, name, group, position, image_file, description,
-                     toggle):
-        if toggle:
-            tbutton = Gtk.ToggleToolButton()
-        else:
-            tbutton = Gtk.ToolButton()
-        tbutton.set_label(name)
-
-        if image_file is not None:
-            image = Gtk.Image()
-            image.set_from_file(image_file)
-            tbutton.set_icon_widget(image)
-
-        if position is None:
-            position = -1
-
-        self._add_button(tbutton, group, position)
-        signal = tbutton.connect('clicked', self._call_tool, name)
-        tbutton.set_tooltip_text(description)
-        tbutton.show_all()
-        self._toolitems.setdefault(name, [])
-        self._toolitems[name].append((tbutton, signal))
-
-    def _add_button(self, button, group, position):
-        if group not in self._groups:
-            if self._groups:
-                self._add_separator()
-            toolbar = Gtk.Toolbar()
-            toolbar.set_style(Gtk.ToolbarStyle.ICONS)
-            self._toolarea.pack_start(toolbar, False, False, 0)
-            toolbar.show_all()
-            self._groups[group] = toolbar
-        self._groups[group].insert(button, position)
-
-    def _call_tool(self, btn, name):
-        self.trigger_tool(name)
-
-    def toggle_toolitem(self, name, toggled):
-        if name not in self._toolitems:
-            return
-        for toolitem, signal in self._toolitems[name]:
-            toolitem.handler_block(signal)
-            toolitem.set_active(toggled)
-            toolitem.handler_unblock(signal)
-
-    def remove_toolitem(self, name):
-        if name not in self._toolitems:
-            self.toolmanager.message_event('%s Not in toolbar' % name, self)
-            return
-
-        for group in self._groups:
-            for toolitem, _signal in self._toolitems[name]:
-                if toolitem in self._groups[group]:
-                    self._groups[group].remove(toolitem)
-        del self._toolitems[name]
-
-    def _add_separator(self):
-        sep = Gtk.Separator()
-        sep.set_property("orientation", Gtk.Orientation.VERTICAL)
-        self._toolarea.pack_start(sep, False, True, 0)
-        sep.show_all()
-
-
-class StatusbarGTK3(StatusbarBase, Gtk.Statusbar):
-    def __init__(self, *args, **kwargs):
-        StatusbarBase.__init__(self, *args, **kwargs)
-        Gtk.Statusbar.__init__(self)
-        self._context = self.get_context_id('message')
-
-    def set_message(self, s):
-        self.pop(self._context)
-        self.push(self._context, s)
-
-
-class RubberbandGTK3(backend_tools.RubberbandBase):
-    def draw_rubberband(self, x0, y0, x1, y1):
-        NavigationToolbar2GTK3.draw_rubberband(
-            self._make_classic_style_pseudo_toolbar(), None, x0, y0, x1, y1)
-
-
-class SaveFigureGTK3(backend_tools.SaveFigureBase):
-
-    @cbook.deprecated("3.1")
-    def get_filechooser(self):
-        fc = FileChooserDialog(
-            title='Save the figure',
-            parent=self.figure.canvas.manager.window,
-            path=os.path.expanduser(rcParams['savefig.directory']),
-            filetypes=self.figure.canvas.get_supported_filetypes(),
-            default_filetype=self.figure.canvas.get_default_filetype())
-        fc.set_current_name(self.figure.canvas.get_default_filename())
-        return fc
-
-    def trigger(self, *args, **kwargs):
-
-        class PseudoToolbar:
-            canvas = self.figure.canvas
-
-        return NavigationToolbar2GTK3.save_figure(PseudoToolbar())
-
-
-class SetCursorGTK3(backend_tools.SetCursorBase):
-    def set_cursor(self, cursor):
-        NavigationToolbar2GTK3.set_cursor(
-            self._make_classic_style_pseudo_toolbar(), cursor)
-
-
-class ConfigureSubplotsGTK3(backend_tools.ConfigureSubplotsBase, Gtk.Window):
-    @cbook.deprecated("3.2")
-    @property
-    def window(self):
-        if not hasattr(self, "_window"):
-            self._window = None
-        return self._window
-
-    @window.setter
-    @cbook.deprecated("3.2")
-    def window(self, window):
-        self._window = window
-
-    @cbook.deprecated("3.2")
-    def init_window(self):
-        if self.window:
-            return
-        self.window = Gtk.Window(title="Subplot Configuration Tool")
-
-        try:
-            self.window.window.set_icon_from_file(window_icon)
-        except Exception:
-            # we presumably already logged a message on the
-            # failure of the main plot, don't keep reporting
-            pass
-
-        self.vbox = Gtk.Box()
-        self.vbox.set_property("orientation", Gtk.Orientation.VERTICAL)
-        self.window.add(self.vbox)
-        self.vbox.show()
-        self.window.connect('destroy', self.destroy)
-
-        toolfig = Figure(figsize=(6, 3))
-        canvas = self.figure.canvas.__class__(toolfig)
-
-        toolfig.subplots_adjust(top=0.9)
-        SubplotTool(self.figure, toolfig)
-
-        w = int(toolfig.bbox.width)
-        h = int(toolfig.bbox.height)
-
-        self.window.set_default_size(w, h)
-
-        canvas.show()
-        self.vbox.pack_start(canvas, True, True, 0)
-        self.window.show()
-
-    @cbook.deprecated("3.2")
-    def destroy(self, *args):
-        self.window.destroy()
-        self.window = None
-
-    def _get_canvas(self, fig):
-        return self.canvas.__class__(fig)
-
-    def trigger(self, *args):
-        NavigationToolbar2GTK3.configure_subplots(
-            self._make_classic_style_pseudo_toolbar(), None)
-
-
-class HelpGTK3(backend_tools.ToolHelpBase):
-    def _normalize_shortcut(self, key):
-        """
-        Convert Matplotlib key presses to GTK+ accelerator identifiers.
-
-        Related to `FigureCanvasGTK3._get_key`.
-        """
-        special = {
-            'backspace': 'BackSpace',
-            'pagedown': 'Page_Down',
-            'pageup': 'Page_Up',
-            'scroll_lock': 'Scroll_Lock',
-        }
-
-        parts = key.split('+')
-        mods = ['<' + mod + '>' for mod in parts[:-1]]
-        key = parts[-1]
-
-        if key in special:
-            key = special[key]
-        elif len(key) > 1:
-            key = key.capitalize()
-        elif key.isupper():
-            mods += ['<shift>']
-
-        return ''.join(mods) + key
-
-    def _show_shortcuts_window(self):
-        section = Gtk.ShortcutsSection()
-
-        for name, tool in sorted(self.toolmanager.tools.items()):
-            if not tool.description:
-                continue
-
-            # Putting everything in a separate group allows GTK to
-            # automatically split them into separate columns/pages, which is
-            # useful because we have lots of shortcuts, some with many keys
-            # that are very wide.
-            group = Gtk.ShortcutsGroup()
-            section.add(group)
-            # A hack to remove the title since we have no group naming.
-            group.forall(lambda widget, data: widget.set_visible(False), None)
-
-            shortcut = Gtk.ShortcutsShortcut(
-                accelerator=' '.join(
-                    self._normalize_shortcut(key)
-                    for key in self.toolmanager.get_tool_keymap(name)
-                    # Will never be sent:
-                    if 'cmd+' not in key),
-                title=tool.name,
-                subtitle=tool.description)
-            group.add(shortcut)
-
-        window = Gtk.ShortcutsWindow(
-            title='Help',
-            modal=True,
-            transient_for=self._figure.canvas.get_toplevel())
-        section.show()  # Must be done explicitly before add!
-        window.add(section)
-
-        window.show_all()
-
-    def _show_shortcuts_dialog(self):
-        dialog = Gtk.MessageDialog(
-            self._figure.canvas.get_toplevel(),
-            0, Gtk.MessageType.INFO, Gtk.ButtonsType.OK, self._get_help_text(),
-            title="Help")
-        dialog.run()
-        dialog.destroy()
-
-    def trigger(self, *args):
-        if Gtk.check_version(3, 20, 0) is None:
-            self._show_shortcuts_window()
-        else:
-            self._show_shortcuts_dialog()
-
-
-class ToolCopyToClipboardGTK3(backend_tools.ToolCopyToClipboardBase):
-    def trigger(self, *args, **kwargs):
-        clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD)
-        window = self.canvas.get_window()
-        x, y, width, height = window.get_geometry()
-        pb = Gdk.pixbuf_get_from_window(window, x, y, width, height)
-        clipboard.set_image(pb)
-
-
-# Define the file to use as the GTk icon
-if sys.platform == 'win32':
-    icon_filename = 'matplotlib.png'
-else:
-    icon_filename = 'matplotlib.svg'
-window_icon = str(cbook._get_data_path('images', icon_filename))
-
-
-def error_msg_gtk(msg, parent=None):
-    if parent is not None:  # find the toplevel Gtk.Window
-        parent = parent.get_toplevel()
-        if not parent.is_toplevel():
-            parent = None
-    if not isinstance(msg, str):
-        msg = ','.join(map(str, msg))
-    dialog = Gtk.MessageDialog(
-        parent=parent, type=Gtk.MessageType.ERROR, buttons=Gtk.ButtonsType.OK,
-        message_format=msg)
-    dialog.run()
-    dialog.destroy()
-
-
-backend_tools.ToolSaveFigure = SaveFigureGTK3
-backend_tools.ToolConfigureSubplots = ConfigureSubplotsGTK3
-backend_tools.ToolSetCursor = SetCursorGTK3
-backend_tools.ToolRubberband = RubberbandGTK3
-backend_tools.ToolHelp = HelpGTK3
-backend_tools.ToolCopyToClipboard = ToolCopyToClipboardGTK3
-
-Toolbar = ToolbarGTK3
-
-
-@_Backend.export
-class _BackendGTK3(_Backend):
-    FigureCanvas = FigureCanvasGTK3
-    FigureManager = FigureManagerGTK3
-
-    @staticmethod
-    def trigger_manager_draw(manager):
-        manager.canvas.draw_idle()
-
-    @staticmethod
-    def mainloop():
-        if Gtk.main_level() == 0:
-            Gtk.main()

+ 0 - 95
venv/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3agg.py

@@ -1,95 +0,0 @@
-import numpy as np
-
-from .. import cbook
-try:
-    from . import backend_cairo
-except ImportError as e:
-    raise ImportError('backend Gtk3Agg requires cairo') from e
-from . import backend_agg, backend_gtk3
-from .backend_cairo import cairo
-from .backend_gtk3 import Gtk, _BackendGTK3
-from matplotlib import transforms
-
-
-class FigureCanvasGTK3Agg(backend_gtk3.FigureCanvasGTK3,
-                          backend_agg.FigureCanvasAgg):
-    def __init__(self, figure):
-        backend_gtk3.FigureCanvasGTK3.__init__(self, figure)
-        self._bbox_queue = []
-
-    def _renderer_init(self):
-        pass
-
-    def _render_figure(self, width, height):
-        backend_agg.FigureCanvasAgg.draw(self)
-
-    def on_draw_event(self, widget, ctx):
-        """GtkDrawable draw event, like expose_event in GTK 2.X.
-        """
-        allocation = self.get_allocation()
-        w, h = allocation.width, allocation.height
-
-        if not len(self._bbox_queue):
-            Gtk.render_background(
-                self.get_style_context(), ctx,
-                allocation.x, allocation.y,
-                allocation.width, allocation.height)
-            bbox_queue = [transforms.Bbox([[0, 0], [w, h]])]
-        else:
-            bbox_queue = self._bbox_queue
-
-        ctx = backend_cairo._to_context(ctx)
-
-        for bbox in bbox_queue:
-            x = int(bbox.x0)
-            y = h - int(bbox.y1)
-            width = int(bbox.x1) - int(bbox.x0)
-            height = int(bbox.y1) - int(bbox.y0)
-
-            buf = cbook._unmultiplied_rgba8888_to_premultiplied_argb32(
-                np.asarray(self.copy_from_bbox(bbox)))
-            image = cairo.ImageSurface.create_for_data(
-                buf.ravel().data, cairo.FORMAT_ARGB32, width, height)
-            ctx.set_source_surface(image, x, y)
-            ctx.paint()
-
-        if len(self._bbox_queue):
-            self._bbox_queue = []
-
-        return False
-
-    def blit(self, bbox=None):
-        # If bbox is None, blit the entire canvas to gtk. Otherwise
-        # blit only the area defined by the bbox.
-        if bbox is None:
-            bbox = self.figure.bbox
-
-        allocation = self.get_allocation()
-        x = int(bbox.x0)
-        y = allocation.height - int(bbox.y1)
-        width = int(bbox.x1) - int(bbox.x0)
-        height = int(bbox.y1) - int(bbox.y0)
-
-        self._bbox_queue.append(bbox)
-        self.queue_draw_area(x, y, width, height)
-
-    def draw(self):
-        if self.get_visible() and self.get_mapped():
-            allocation = self.get_allocation()
-            self._render_figure(allocation.width, allocation.height)
-        super().draw()
-
-    def print_png(self, filename, *args, **kwargs):
-        # Do this so we can save the resolution of figure in the PNG file
-        agg = self.switch_backends(backend_agg.FigureCanvasAgg)
-        return agg.print_png(filename, *args, **kwargs)
-
-
-class FigureManagerGTK3Agg(backend_gtk3.FigureManagerGTK3):
-    pass
-
-
-@_BackendGTK3.export
-class _BackendGTK3Cairo(_BackendGTK3):
-    FigureCanvas = FigureCanvasGTK3Agg
-    FigureManager = FigureManagerGTK3Agg

+ 0 - 48
venv/lib/python3.8/site-packages/matplotlib/backends/backend_gtk3cairo.py

@@ -1,48 +0,0 @@
-try:
-    from contextlib import nullcontext
-except ImportError:
-    from contextlib import ExitStack as nullcontext  # Py 3.6.
-
-from . import backend_cairo, backend_gtk3
-from .backend_gtk3 import Gtk, _BackendGTK3
-from matplotlib import cbook
-from matplotlib.backend_bases import cursors
-
-
-class RendererGTK3Cairo(backend_cairo.RendererCairo):
-    def set_context(self, ctx):
-        self.gc.ctx = backend_cairo._to_context(ctx)
-
-
-class FigureCanvasGTK3Cairo(backend_gtk3.FigureCanvasGTK3,
-                            backend_cairo.FigureCanvasCairo):
-
-    def _renderer_init(self):
-        """Use cairo renderer."""
-        self._renderer = RendererGTK3Cairo(self.figure.dpi)
-
-    def _render_figure(self, width, height):
-        self._renderer.set_width_height(width, height)
-        self.figure.draw(self._renderer)
-
-    def on_draw_event(self, widget, ctx):
-        """GtkDrawable draw event."""
-        with (self.toolbar._wait_cursor_for_draw_cm() if self.toolbar
-              else nullcontext()):
-            self._renderer.set_context(ctx)
-            allocation = self.get_allocation()
-            Gtk.render_background(
-                self.get_style_context(), ctx,
-                allocation.x, allocation.y,
-                allocation.width, allocation.height)
-            self._render_figure(allocation.width, allocation.height)
-
-
-@cbook.deprecated("3.1", alternative="backend_gtk3.FigureManagerGTK3")
-class FigureManagerGTK3Cairo(backend_gtk3.FigureManagerGTK3):
-    pass
-
-
-@_BackendGTK3.export
-class _BackendGTK3Cairo(_BackendGTK3):
-    FigureCanvas = FigureCanvasGTK3Cairo

+ 0 - 184
venv/lib/python3.8/site-packages/matplotlib/backends/backend_macosx.py

@@ -1,184 +0,0 @@
-import matplotlib
-from matplotlib import cbook, rcParams
-from matplotlib._pylab_helpers import Gcf
-from matplotlib.backends import _macosx
-from matplotlib.backends.backend_agg import FigureCanvasAgg
-from matplotlib.backend_bases import (
-    _Backend, FigureCanvasBase, FigureManagerBase, NavigationToolbar2,
-    TimerBase)
-from matplotlib.figure import Figure
-from matplotlib.widgets import SubplotTool
-
-
-########################################################################
-#
-# The following functions and classes are for pylab and implement
-# window/figure managers, etc...
-#
-########################################################################
-
-
-class TimerMac(_macosx.Timer, TimerBase):
-    """
-    Subclass of `.TimerBase` that uses CoreFoundation run loops for timer
-    events.
-
-    Attributes
-    ----------
-    interval : int
-        The time between timer events in milliseconds. Default is 1000 ms.
-    single_shot : bool
-        Boolean flag indicating whether this timer should operate as single
-        shot (run once and then stop). Defaults to False.
-    callbacks : list
-        Stores list of (func, args) tuples that will be called upon timer
-        events. This list can be manipulated directly, or the functions
-        `add_callback` and `remove_callback` can be used.
-    """
-    # completely implemented at the C-level (in _macosx.Timer)
-
-
-class FigureCanvasMac(_macosx.FigureCanvas, FigureCanvasAgg):
-    """
-    The canvas the figure renders into.  Calls the draw and print fig
-    methods, creates the renderers, etc...
-
-    Events such as button presses, mouse movements, and key presses
-    are handled in the C code and the base class methods
-    button_press_event, button_release_event, motion_notify_event,
-    key_press_event, and key_release_event are called from there.
-
-    Attributes
-    ----------
-    figure : `matplotlib.figure.Figure`
-        A high-level Figure instance
-    """
-
-    required_interactive_framework = "macosx"
-
-    def __init__(self, figure):
-        FigureCanvasBase.__init__(self, figure)
-        width, height = self.get_width_height()
-        _macosx.FigureCanvas.__init__(self, width, height)
-        self._device_scale = 1.0
-
-    def _set_device_scale(self, value):
-        if self._device_scale != value:
-            self.figure.dpi = self.figure.dpi / self._device_scale * value
-            self._device_scale = value
-
-    def _draw(self):
-        renderer = self.get_renderer(cleared=self.figure.stale)
-
-        if self.figure.stale:
-            self.figure.draw(renderer)
-
-        return renderer
-
-    def draw(self):
-        # docstring inherited
-        self.draw_idle()
-        self.flush_events()
-
-    # draw_idle is provided by _macosx.FigureCanvas
-
-    @cbook.deprecated("3.2", alternative="draw_idle()")
-    def invalidate(self):
-        return self.draw_idle()
-
-    def blit(self, bbox=None):
-        self.draw_idle()
-
-    def resize(self, width, height):
-        dpi = self.figure.dpi
-        width /= dpi
-        height /= dpi
-        self.figure.set_size_inches(width * self._device_scale,
-                                    height * self._device_scale,
-                                    forward=False)
-        FigureCanvasBase.resize_event(self)
-        self.draw_idle()
-
-    def new_timer(self, *args, **kwargs):
-        # docstring inherited
-        return TimerMac(*args, **kwargs)
-
-
-class FigureManagerMac(_macosx.FigureManager, FigureManagerBase):
-    """
-    Wrap everything up into a window for the pylab interface
-    """
-    def __init__(self, canvas, num):
-        FigureManagerBase.__init__(self, canvas, num)
-        title = "Figure %d" % num
-        _macosx.FigureManager.__init__(self, canvas, title)
-        if rcParams['toolbar'] == 'toolbar2':
-            self.toolbar = NavigationToolbar2Mac(canvas)
-        else:
-            self.toolbar = None
-        if self.toolbar is not None:
-            self.toolbar.update()
-
-        if matplotlib.is_interactive():
-            self.show()
-            self.canvas.draw_idle()
-
-    def close(self):
-        Gcf.destroy(self.num)
-
-
-class NavigationToolbar2Mac(_macosx.NavigationToolbar2, NavigationToolbar2):
-
-    def __init__(self, canvas):
-        NavigationToolbar2.__init__(self, canvas)
-
-    def _init_toolbar(self):
-        _macosx.NavigationToolbar2.__init__(
-            self, str(cbook._get_data_path('images')))
-
-    def draw_rubberband(self, event, x0, y0, x1, y1):
-        self.canvas.set_rubberband(int(x0), int(y0), int(x1), int(y1))
-
-    def release(self, event):
-        self.canvas.remove_rubberband()
-
-    def set_cursor(self, cursor):
-        _macosx.set_cursor(cursor)
-
-    def save_figure(self, *args):
-        filename = _macosx.choose_save_file('Save the figure',
-                                            self.canvas.get_default_filename())
-        if filename is None:  # Cancel
-            return
-        self.canvas.figure.savefig(filename)
-
-    def prepare_configure_subplots(self):
-        toolfig = Figure(figsize=(6, 3))
-        canvas = FigureCanvasMac(toolfig)
-        toolfig.subplots_adjust(top=0.9)
-        # Need to keep a reference to the tool.
-        _tool = SubplotTool(self.canvas.figure, toolfig)
-        return canvas
-
-    def set_message(self, message):
-        _macosx.NavigationToolbar2.set_message(self, message.encode('utf-8'))
-
-
-########################################################################
-#
-# Now just provide the standard names that backend.__init__ is expecting
-#
-########################################################################
-
-@_Backend.export
-class _BackendMac(_Backend):
-    FigureCanvas = FigureCanvasMac
-    FigureManager = FigureManagerMac
-
-    @staticmethod
-    def trigger_manager_draw(manager):
-        manager.canvas.draw_idle()
-
-    @staticmethod
-    def mainloop():
-        _macosx.show()

+ 0 - 139
venv/lib/python3.8/site-packages/matplotlib/backends/backend_mixed.py

@@ -1,139 +0,0 @@
-import numpy as np
-
-from matplotlib.backends.backend_agg import RendererAgg
-from matplotlib.tight_bbox import process_figure_for_rasterizing
-
-
-class MixedModeRenderer:
-    """
-    A helper class to implement a renderer that switches between
-    vector and raster drawing.  An example may be a PDF writer, where
-    most things are drawn with PDF vector commands, but some very
-    complex objects, such as quad meshes, are rasterised and then
-    output as images.
-    """
-    def __init__(self, figure, width, height, dpi, vector_renderer,
-                 raster_renderer_class=None,
-                 bbox_inches_restore=None):
-        """
-        Parameters
-        ----------
-        figure : `matplotlib.figure.Figure`
-            The figure instance.
-
-        width : scalar
-            The width of the canvas in logical units
-
-        height : scalar
-            The height of the canvas in logical units
-
-        dpi : scalar
-            The dpi of the canvas
-
-        vector_renderer : `matplotlib.backend_bases.RendererBase`
-            An instance of a subclass of
-            `~matplotlib.backend_bases.RendererBase` that will be used for the
-            vector drawing.
-
-        raster_renderer_class : `matplotlib.backend_bases.RendererBase`
-            The renderer class to use for the raster drawing.  If not provided,
-            this will use the Agg backend (which is currently the only viable
-            option anyway.)
-
-        """
-        if raster_renderer_class is None:
-            raster_renderer_class = RendererAgg
-
-        self._raster_renderer_class = raster_renderer_class
-        self._width = width
-        self._height = height
-        self.dpi = dpi
-
-        self._vector_renderer = vector_renderer
-
-        self._raster_renderer = None
-        self._rasterizing = 0
-
-        # A reference to the figure is needed as we need to change
-        # the figure dpi before and after the rasterization. Although
-        # this looks ugly, I couldn't find a better solution. -JJL
-        self.figure = figure
-        self._figdpi = figure.get_dpi()
-
-        self._bbox_inches_restore = bbox_inches_restore
-
-        self._renderer = vector_renderer
-
-    def __getattr__(self, attr):
-        # Proxy everything that hasn't been overridden to the base
-        # renderer. Things that *are* overridden can call methods
-        # on self._renderer directly, but must not cache/store
-        # methods (because things like RendererAgg change their
-        # methods on the fly in order to optimise proxying down
-        # to the underlying C implementation).
-        return getattr(self._renderer, attr)
-
-    def start_rasterizing(self):
-        """
-        Enter "raster" mode.  All subsequent drawing commands (until
-        stop_rasterizing is called) will be drawn with the raster
-        backend.
-
-        If start_rasterizing is called multiple times before
-        stop_rasterizing is called, this method has no effect.
-        """
-
-        # change the dpi of the figure temporarily.
-        self.figure.set_dpi(self.dpi)
-
-        if self._bbox_inches_restore:  # when tight bbox is used
-            r = process_figure_for_rasterizing(self.figure,
-                                               self._bbox_inches_restore)
-            self._bbox_inches_restore = r
-
-        if self._rasterizing == 0:
-            self._raster_renderer = self._raster_renderer_class(
-                self._width*self.dpi, self._height*self.dpi, self.dpi)
-            self._renderer = self._raster_renderer
-        self._rasterizing += 1
-
-    def stop_rasterizing(self):
-        """
-        Exit "raster" mode.  All of the drawing that was done since
-        the last start_rasterizing command will be copied to the
-        vector backend by calling draw_image.
-
-        If stop_rasterizing is called multiple times before
-        start_rasterizing is called, this method has no effect.
-        """
-        self._rasterizing -= 1
-        if self._rasterizing == 0:
-            self._renderer = self._vector_renderer
-
-            height = self._height * self.dpi
-            buffer, bounds = self._raster_renderer.tostring_rgba_minimized()
-            l, b, w, h = bounds
-            if w > 0 and h > 0:
-                image = np.frombuffer(buffer, dtype=np.uint8)
-                image = image.reshape((h, w, 4))
-                image = image[::-1]
-                gc = self._renderer.new_gc()
-                # TODO: If the mixedmode resolution differs from the figure's
-                #       dpi, the image must be scaled (dpi->_figdpi). Not all
-                #       backends support this.
-                self._renderer.draw_image(
-                    gc,
-                    l * self._figdpi / self.dpi,
-                    (height-b-h) * self._figdpi / self.dpi,
-                    image)
-            self._raster_renderer = None
-            self._rasterizing = False
-
-            # restore the figure dpi.
-            self.figure.set_dpi(self._figdpi)
-
-        if self._bbox_inches_restore:  # when tight bbox is used
-            r = process_figure_for_rasterizing(self.figure,
-                                               self._bbox_inches_restore,
-                                               self._figdpi)
-            self._bbox_inches_restore = r

Some files were not shown because too many files changed in this diff