diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..528fa8e6e --- /dev/null +++ b/.gitattributes @@ -0,0 +1,2 @@ +ultraplot/*.pyi linguist-generated=true +ultraplot/**/*.pyi linguist-generated=true diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 1a2fcadb2..153bfb0d1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -22,6 +22,7 @@ jobs: - 'environment.yml' - '.github/workflows/**' - 'tools/ci/**' + - 'tools/generate_stubs.py' select-tests: runs-on: ubuntu-latest @@ -99,6 +100,7 @@ jobs: --always-full 'pyproject.toml' \ --always-full 'environment.yml' \ --always-full 'ultraplot/__init__.py' \ + --always-full 'tools/generate_stubs.py' \ --ignore 'docs/**' \ --ignore 'README.rst' echo "Selection output:" @@ -138,6 +140,53 @@ jobs: echo "Detected test matrix: $(echo "$OUTPUT" | jq -c '.test_matrix')" python tools/ci/version_support.py --format github-output >> $GITHUB_OUTPUT + stubs: + name: Static API stubs + runs-on: ubuntu-latest + needs: + - run-if-changes + if: always() && needs.run-if-changes.outputs.run == 'true' + steps: + - uses: actions/checkout@v7 + + - uses: actions/setup-python@v7 + with: + python-version: "3.13" + cache: pip + + - name: Install UltraPlot and typing tools + run: pip install -e ".[typing]" + + - name: Verify generated stubs + run: python tools/generate_stubs.py --check + + - name: Check Pylance-compatible consumption + run: basedpyright tools/ci/stub_consumer.py --level error + + - name: Check Pyrefly consumption and generated syntax + run: | + pyrefly check tools/ci/stub_consumer.py \ + --search-path . \ + --python-interpreter-path "$(command -v python)" \ + --progress-bar no + pyrefly check 'ultraplot/**/*.pyi' \ + --search-path . \ + --python-interpreter-path "$(command -v python)" \ + --ignore-missing-imports icecream \ + --ignore-missing-imports cartopy \ + --ignore-missing-imports cartopy.crs \ + --ignore-missing-imports cartopy.feature \ + --ignore-missing-imports cartopy.io \ + --ignore-missing-imports cartopy.mpl.feature_artist \ + --ignore-missing-imports cartopy.mpl.geoaxes \ + --ignore-missing-imports cartopy.mpl.gridliner \ + --ignore-missing-imports cartopy.mpl.path \ + --ignore-missing-imports cartopy.mpl.ticker \ + --ignore-missing-imports cftime \ + --ignore-missing-imports mpl_toolkits.basemap \ + --ignore-missing-imports matplotlib.fontconfig_pattern \ + --progress-bar no + coverage: name: Coverage runs-on: ubuntu-latest @@ -213,6 +262,7 @@ jobs: needs: - build - run-if-changes + - stubs if: always() runs-on: ubuntu-latest steps: @@ -220,7 +270,7 @@ jobs: if [[ '${{ needs.run-if-changes.outputs.run }}' == 'false' ]]; then echo "No changes detected, tests skipped." else - if [[ '${{ needs.build.result }}' == 'success' ]]; then + if [[ '${{ needs.build.result }}' == 'success' && '${{ needs.stubs.result }}' == 'success' ]]; then echo "All tests passed successfully!" else echo "Tests failed!" diff --git a/docs/conf.py b/docs/conf.py index cb17889ef..47515e8d7 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -13,6 +13,7 @@ # Import statements import datetime +import inspect import logging import os import re @@ -637,5 +638,20 @@ def _replace_snippet(match): pass +def process_signature( + app, what, name, obj, options, signature, return_annotation +): + """Use compact signatures marked by UltraPlot only in generated docs.""" + marked = getattr(obj, "__ultraplot_doc_signature__", None) + if marked is None and inspect.ismethod(obj): + marked = getattr(obj.__func__, "__ultraplot_doc_signature__", None) + if marked is None and inspect.isclass(obj): + marked = getattr(obj.__init__, "__ultraplot_doc_signature__", None) + if marked is not None: + return marked, return_annotation + return signature, return_annotation + + def setup(app): app.connect("autodoc-process-docstring", process_docstring) + app.connect("autodoc-process-signature", process_signature) diff --git a/docs/contributing.rst b/docs/contributing.rst index 6ccc4cc9c..e98b7d1a4 100644 --- a/docs/contributing.rst +++ b/docs/contributing.rst @@ -130,6 +130,37 @@ When adding a new submodule, make sure it is compatible with the lazy loader: By following these steps, your module will integrate cleanly with the lazy loading system without requiring manual registry updates. +Editor type information and docstrings +-------------------------------------- + +UltraPlot ships generated ``.pyi`` files so static analysis tools such as Pylance +and Pyrefly can see the public API and fully expanded docstrings without importing +the package. The runtime modules remain the source of truth and continue to use the +lazy loader. + +After changing a Python signature, annotation, public import, or docstring snippet, +install the pinned typing tools, regenerate the stubs from the repository root, and +commit the updated ``.pyi`` files: + +.. code-block:: bash + + pip install -e ".[typing]" + python tools/generate_stubs.py + +Installation does not generate or modify these files. Release artifacts include the +stubs that were generated and checked into the repository. The generator runs +Pyrefly against an isolated source-only package, merges its inferred annotations +into a complete syntax-derived representation of the package, and statically +expands registered docstring snippets. This preserves declarations that Pyrefly +cannot discover through decorators or lazy loading. + +To rerun inference and verify that every committed stub is up to date without +changing files, run: + +.. code-block:: bash + + python tools/generate_stubs.py --check + .. _contrib_pr: diff --git a/docs/projections.py b/docs/projections.py index 66dc30c37..d285e3dc1 100644 --- a/docs/projections.py +++ b/docs/projections.py @@ -273,13 +273,13 @@ # projections global extent by calling :meth:`~cartopy.mpl.geoaxes.GeoAxes.set_global`. # This is a deviation from cartopy, which determines map boundaries automatically # based on the coordinates of the plotted content. To revert to cartopy's -# default behavior, set :rcraw:`geo.extent` to ``'auto`` or pass ``extent='auto'`` +# default behavior, set :rcraw:`geo.extent` to ``'auto'`` or pass ``extent='auto'`` # to :func:`~ultraplot.axes.GeoAxes.format`. # * By default, UltraPlot gives circular boundaries to polar cartopy and basemap # projections like :class:`~cartopy.crs.NorthPolarStereo` (see `this example # `__ # from the cartopy website). To disable this feature, set :rcraw:`geo.round` to -# ``False`` or pass ``round=False` to :func:`~ultraplot.axes.GeoAxes.format`. Please note +# ``False`` or pass ``round=False`` to :func:`~ultraplot.axes.GeoAxes.format`. Please note # that older versions of cartopy cannot add gridlines to maps bounded by circles. # * To make things more consistent, the :class:`~ultraplot.constructor.Proj` constructor # function lets you supply native `PROJ `__ keyword names @@ -332,7 +332,7 @@ # (i.e., Plate Carrée) coordinates the *default* coordinate system for all plotting # commands by internally passing ``transform=ccrs.PlateCarree()`` to cartopy commands # and ``latlon=True`` to basemap commands. And again, when `basemap`_ is the backend, -# plotting is done "cartopy-style" by calling methods from the `ultraplot.axes.GeoAxes` +# plotting is done "cartopy-style" by calling methods from the :class:`~ultraplot.axes.GeoAxes` # instance rather than the :class:`~mpl_toolkits.basemap.Basemap` instance. # # To ensure that a 2D :class:`~ultraplot.axes.PlotAxes` command like diff --git a/docs/sphinxext/custom_roles.py b/docs/sphinxext/custom_roles.py index a4d8488e6..719ce6ac0 100644 --- a/docs/sphinxext/custom_roles.py +++ b/docs/sphinxext/custom_roles.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 """ -Custom :rc: and :rcraw: roles for rc settings. +Custom roles used by UltraPlot documentation. """ import os @@ -57,10 +57,22 @@ def rc_role(name, rawtext, text, lineno, inliner, options={}, content=[]): # no return node_list, [] +def mpltype_role(name, rawtext, text, lineno, inliner, options={}, content=[]): # noqa: U100 + """ + Render Matplotlib's ``:mpltype:`` annotations as inline literals. + + Matplotlib uses this role in inherited docstrings, but its documentation + extension is not loaded by this project. Registering it locally prevents + unresolved-role warnings and visibly broken API markup. + """ + return [nodes.literal(rawtext, text)], [] + + def setup(app): """ Set up the roles. """ app.add_role("rc", rc_role) app.add_role("rcraw", rc_raw_role) + app.add_role("mpltype", mpltype_role) return {"parallel_read_safe": True, "parallel_write_safe": True} diff --git a/pyproject.toml b/pyproject.toml index 91d897362..d58800c69 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,6 +49,9 @@ dynamic = ["version"] packages = {find = {exclude=["docs*", "baseline*", "logo*"]}} include-package-data = true +[tool.setuptools.package-data] +ultraplot = ["py.typed", "*.pyi", "**/*.pyi"] + [tool.setuptools_scm] write_to = "ultraplot/_version.py" write_to_template = "__version__ = '{version}'\n" @@ -71,6 +74,10 @@ filterwarnings = [ ] mpl-default-style = { axes.prop_cycle = "cycler('color', ['#4c72b0ff', '#55a868ff', '#c44e52ff', '#8172b2ff', '#ccb974ff', '#64b5cdff'])" } [project.optional-dependencies] +typing = [ + "basedpyright==1.31.4", + "pyrefly==1.2.0", +] docs = [ "jupyter", "jupytext", diff --git a/tools/ci/stub_consumer.py b/tools/ci/stub_consumer.py new file mode 100644 index 000000000..1209bd54d --- /dev/null +++ b/tools/ci/stub_consumer.py @@ -0,0 +1,13 @@ +"""Representative lazy public imports consumed by static type checkers.""" + +import ultraplot as uplt + +reveal_type(uplt.subplots) +reveal_type(uplt.Axes.format) + +figure, axes = uplt.subplots() +figure_check: uplt.Figure = figure +axes_check: uplt.SubplotGrid = axes +axis_check: uplt.Axes = axes[0] +axes[0].format(title="Static typing") +reveal_type(axes.plot) diff --git a/tools/generate_stubs.py b/tools/generate_stubs.py new file mode 100644 index 000000000..44b05f207 --- /dev/null +++ b/tools/generate_stubs.py @@ -0,0 +1,1137 @@ +"""Generate bundled type stubs with statically expanded docstrings.""" + +from __future__ import annotations + +import argparse +import ast +import builtins +import copy +import importlib +import inspect +import os +import re +import shutil +import subprocess +import sys +import tempfile +import warnings +from collections import defaultdict, deque +from collections.abc import Iterable +from pathlib import Path +from urllib.parse import quote_plus + +ROOT = Path(__file__).resolve().parents[1] +PACKAGE = ROOT / "ultraplot" +HEADER = "# @generated by tools/generate_stubs.py; do not edit\n# fmt: off\n" +VERSION_STUB = "__version__: str\n" +PYREFLY_VERSION = "1.2.0" +EXCLUDED_PARTS = {"tests", "results", "__pycache__"} +STATIC_DECORATORS = { + "abstractmethod", + "asynccontextmanager", + "cached_property", + "classmethod", + "contextmanager", + "dataclass", + "deprecated", + "final", + "getter", + "overload", + "override", + "property", + "setter", + "deleter", + "singledispatch", + "singledispatchmethod", + "staticmethod", +} +SNIPPET_PATTERN = re.compile(r"%\(([^)]+)\)s") +BUILTIN_NAMES = set(dir(builtins)) | {"None"} +TRY_NODES = (ast.Try,) + ((ast.TryStar,) if hasattr(ast, "TryStar") else ()) +RUNTIME_DOC_BANNERS = re.compile( + r"(?m)^=+\n(ultraplot documentation|Matplotlib documentation)\n=+\n?" +) +RST_LINK_PATTERN = re.compile(r"`([^`<>]+?)\s*<(https?://[^>]+)>`__?") +SPHINX_ROLE_PATTERN = re.compile( + r":(?:(?:py):)?(class|func|meth|attr|obj|mod|data|ref|doc|rc|rcraw|mpltype):" + r"`([^`]+)`" +) +SPHINX_TARGET_PATTERN = re.compile( + r"(? str | None: + """Return the dotted name represented by an expression.""" + if isinstance(node, ast.Call): + node = node.func + names = [] + while isinstance(node, ast.Attribute): + names.append(node.attr) + node = node.value + if isinstance(node, ast.Name): + names.append(node.id) + return ".".join(reversed(names)) + return None + + +def _is_overload(node: ast.FunctionDef | ast.AsyncFunctionDef) -> bool: + """Return whether a function is an overload declaration.""" + return any( + (_dotted_name(item) or "").split(".")[-1] == "overload" + for item in node.decorator_list + ) + + +def _has_decorator( + node: ast.FunctionDef | ast.AsyncFunctionDef, name: str +) -> bool: + """Return whether a function has a decorator with the given final name.""" + return any( + (_dotted_name(item) or "").split(".")[-1] == name + for item in node.decorator_list + ) + + +def _is_simple_target(node: ast.expr) -> bool: + """Return whether an assignment target is declarative stub syntax.""" + if isinstance(node, ast.Name): + return True + if isinstance(node, (ast.List, ast.Tuple)): + return all(_is_simple_target(item) for item in node.elts) + return False + + +def _target_names(node: ast.expr) -> list[str]: + """Return names contained in a simple assignment target.""" + if isinstance(node, ast.Name): + return [node.id] + if isinstance(node, (ast.List, ast.Tuple)): + return [name for item in node.elts for name in _target_names(item)] + return [] + + +def _is_unstable_expression(node: ast.expr) -> bool: + """Return whether ``ast.unparse`` changed for this expression by version.""" + unstable = ( + ast.DictComp, + ast.GeneratorExp, + ast.JoinedStr, + ast.Lambda, + ast.ListComp, + ast.SetComp, + ) + return any(isinstance(item, unstable) for item in ast.walk(node)) + + +def _is_type_checking(node: ast.expr) -> bool: + """Return whether *node* is a ``TYPE_CHECKING`` guard.""" + return (isinstance(node, ast.Name) and node.id == "TYPE_CHECKING") or ( + isinstance(node, ast.Attribute) and node.attr == "TYPE_CHECKING" + ) + + +def _is_docstring_statement(node: ast.stmt) -> bool: + """Return whether *node* is a module/class/function docstring statement.""" + return ( + isinstance(node, ast.Expr) + and isinstance(node.value, ast.Constant) + and isinstance(node.value.value, str) + ) + + +def _scope_statements(statements: list[ast.stmt]): + """Yield declarations from module/class scopes, including guarded branches.""" + for statement in statements: + yield statement + if isinstance(statement, ast.If): + yield from _scope_statements(statement.body) + yield from _scope_statements(statement.orelse) + elif isinstance(statement, TRY_NODES): + yield from _scope_statements(statement.body) + yield from _scope_statements(statement.orelse) + yield from _scope_statements(statement.finalbody) + for handler in statement.handlers: + yield from _scope_statements(handler.body) + + +def _declarations(statements: list[ast.stmt], prefix: tuple[str, ...] = ()): + """Yield qualified function declarations without descending into functions.""" + for statement in _scope_statements(statements): + if isinstance(statement, (ast.FunctionDef, ast.AsyncFunctionDef)): + yield ".".join((*prefix, statement.name)), statement + elif isinstance(statement, ast.ClassDef): + yield from _declarations(statement.body, (*prefix, statement.name)) + + +def _parameter_names(node: ast.FunctionDef | ast.AsyncFunctionDef) -> tuple[str, ...]: + """Return a signature key that distinguishes overloads and parameter kinds.""" + arguments = node.args + return ( + *(f"pos:{arg.arg}" for arg in (*arguments.posonlyargs, *arguments.args)), + *((f"var:{arguments.vararg.arg}",) if arguments.vararg else ()), + *(f"kw:{arg.arg}" for arg in arguments.kwonlyargs), + *((f"vkw:{arguments.kwarg.arg}",) if arguments.kwarg else ()), + ) + + +def _module_names(tree: ast.Module) -> set[str]: + """Return names that inferred annotations may safely reference in a stub.""" + names = set(BUILTIN_NAMES) + + def collect(statements: list[ast.stmt]): + for statement in _scope_statements(statements): + if isinstance(statement, ast.Import): + names.update( + alias.asname or alias.name.split(".")[0] + for alias in statement.names + ) + elif isinstance(statement, ast.ImportFrom): + names.update(alias.asname or alias.name for alias in statement.names) + elif isinstance( + statement, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef) + ): + names.add(statement.name) + if isinstance(statement, ast.ClassDef): + collect(statement.body) + elif isinstance(statement, ast.Assign): + for target in statement.targets: + names.update(_target_names(target)) + elif isinstance(statement, ast.AnnAssign): + names.update(_target_names(statement.target)) + + collect(tree.body) + names.add("Incomplete") + return names + + +class _AnnotationNameCollector(ast.NodeVisitor): + """Collect names, including names hidden inside forward-reference strings.""" + + def __init__(self): + self.names = set() + self._literal_depth = 0 + + def visit_Name(self, node: ast.Name) -> None: + if isinstance(node.ctx, ast.Load): + self.names.add(node.id) + + def visit_Constant(self, node: ast.Constant) -> None: + if not isinstance(node.value, str) or self._literal_depth: + return + try: + expression = ast.parse(node.value, mode="eval") + except SyntaxError: + return + self.names.update( + item.id + for item in ast.walk(expression) + if isinstance(item, ast.Name) and isinstance(item.ctx, ast.Load) + ) + + def visit_Subscript(self, node: ast.Subscript) -> None: + self.visit(node.value) + is_literal = (_dotted_name(node.value) or "").split(".")[-1] == "Literal" + self._literal_depth += is_literal + self.visit(node.slice) + self._literal_depth -= is_literal + + +def _safe_annotation(annotation: ast.expr | None, available: set[str]) -> ast.expr | None: + """Return a copied inferred annotation only when all root names resolve.""" + if annotation is None: + return None + if isinstance(annotation, (ast.Dict, ast.List, ast.Set, ast.Tuple)): + return None + collector = _AnnotationNameCollector() + collector.visit(annotation) + if collector.names <= available: + return copy.deepcopy(annotation) + return None + + +def _missing_annotation() -> ast.Name: + """Return the typing-spec placeholder used for an unknown annotation.""" + return ast.Name(id="Incomplete", ctx=ast.Load()) + + +def _merge_annotations( + tree: ast.Module, inferred: ast.Module | None +) -> tuple[int, int, int, int]: + """Fill missing source annotations using matching Pyrefly declarations. + + Explicit source annotations always win. If Pyrefly omitted a declaration or + inferred a name that is not available in the module, ``Incomplete`` is used + as the honest static placeholder recommended for generated stubs. + """ + candidates = defaultdict(deque) + if inferred is not None: + for qualname, node in _declarations(inferred.body): + candidates[(qualname, _parameter_names(node))].append(node) + + available = _module_names(tree) + inferred_count = fallback_count = unmatched_count = discarded_count = 0 + for qualname, node in _declarations(tree.body): + queue = candidates.get((qualname, _parameter_names(node))) + inferred_node = queue.popleft() if queue else None + if inferred_node is None: + unmatched_count += 1 + + source_args = ( + *node.args.posonlyargs, + *node.args.args, + *node.args.kwonlyargs, + ) + # Inferences copied from an overridden third-party method change with + # the installed dependency version. Keep only explicit source types for + # overrides so generation remains reproducible across supported envs. + use_inference = inferred_node is not None and not _has_decorator( + node, "override" + ) + inferred_args = () + if use_inference: + inferred_args = ( + *inferred_node.args.posonlyargs, + *inferred_node.args.args, + *inferred_node.args.kwonlyargs, + ) + inferred_by_name = {arg.arg: arg for arg in inferred_args} + for argument in source_args: + if argument.arg in {"self", "cls"}: + continue + if argument.annotation is not None: + annotation = _safe_annotation(argument.annotation, available) + if annotation is not None: + continue + argument.annotation = None + discarded_count += 1 + annotation = _safe_annotation( + inferred_by_name.get(argument.arg).annotation + if argument.arg in inferred_by_name + else None, + available, + ) + argument.annotation = annotation or _missing_annotation() + inferred_count += annotation is not None + fallback_count += annotation is None + + for source_arg, inferred_arg in ( + ( + node.args.vararg, + inferred_node.args.vararg if use_inference else None, + ), + (node.args.kwarg, inferred_node.args.kwarg if use_inference else None), + ): + if source_arg is None: + continue + if source_arg.annotation is not None: + annotation = _safe_annotation(source_arg.annotation, available) + if annotation is not None: + continue + source_arg.annotation = None + discarded_count += 1 + annotation = _safe_annotation( + inferred_arg.annotation if inferred_arg else None, available + ) + source_arg.annotation = annotation or _missing_annotation() + inferred_count += annotation is not None + fallback_count += annotation is None + + if node.returns is not None and _safe_annotation(node.returns, available) is None: + node.returns = None + discarded_count += 1 + if node.returns is None: + if node.name == "__init__": + node.returns = ast.Constant(None) + inferred_count += 1 + else: + annotation = _safe_annotation( + inferred_node.returns if use_inference else None, available + ) + node.returns = annotation or _missing_annotation() + inferred_count += annotation is not None + fallback_count += annotation is None + return inferred_count, fallback_count, unmatched_count, discarded_count + + +def _pyrefly_version(executable: str) -> str: + """Return the installed Pyrefly version or raise an actionable error.""" + result = subprocess.run( + [executable, "--version"], capture_output=True, text=True, check=True + ) + match = re.search(r"\b(\d+\.\d+\.\d+)\b", result.stdout + result.stderr) + if not match: + raise RuntimeError(f"Could not determine Pyrefly version from: {result.stdout!r}") + return match.group(1) + + +def _run_pyrefly(executable: str) -> tuple[dict[Path, ast.Module], list[Path]]: + """Run Pyrefly on a source-only package and parse its inferred stubs.""" + version = _pyrefly_version(executable) + if version != PYREFLY_VERSION: + raise RuntimeError( + f"Stub generation requires pyrefly=={PYREFLY_VERSION}; found {version}. " + f"Install with `python -m pip install pyrefly=={PYREFLY_VERSION}`." + ) + print(f"Running Pyrefly {version} type inference on a source-only package copy...") + with tempfile.TemporaryDirectory(prefix="ultraplot-stubgen-") as directory: + temporary = Path(directory) + source_root = temporary / "source" + source_package = source_root / PACKAGE.name + output_root = temporary / "inferred" + shutil.copytree( + PACKAGE, + source_package, + ignore=shutil.ignore_patterns( + "*.pyi", "tests", "results", "__pycache__", "*.pyc" + ), + ) + command = [ + executable, + "stubgen", + str(source_package), + "--output-dir", + str(output_root), + "--include-docstrings", + "--include-private", + "--threads", + "0", + "--search-path", + str(source_root), + "--python-interpreter-path", + sys.executable, + "--check-unannotated-defs", + "true", + "--infer-return-types", + "checked", + ] + result = subprocess.run( + command, cwd=ROOT, capture_output=True, text=True, check=False + ) + if result.returncode: + details = (result.stdout + "\n" + result.stderr).strip() + raise RuntimeError(f"Pyrefly stub generation failed:\n{details}") + + trees = {} + invalid = [] + for source_path in _source_files(): + relative = source_path.relative_to(PACKAGE).with_suffix(".pyi") + inferred_path = output_root / relative + if not inferred_path.exists(): + continue + try: + with warnings.catch_warnings(): + warnings.simplefilter("ignore", SyntaxWarning) + trees[source_path] = ast.parse( + inferred_path.read_text(), filename=str(inferred_path) + ) + except SyntaxError: + # Pyrefly 1.2.0 currently emits invalid ``((x: T) -> U)`` syntax + # for one callable assignment in rcsetup.py. The structural base + # and Incomplete fallbacks keep that module valid and complete. + invalid.append(relative) + return trees, invalid + + +def _module_name(source_path: Path) -> str: + """Return the dotted Python module name for a package file.""" + relative = source_path.relative_to(ROOT).with_suffix("") + parts = list(relative.parts) + if parts[-1] == "__init__": + parts.pop() + return ".".join(parts) + + +def _load_runtime_modules(source_files: Iterable[Path]) -> dict[Path, Any]: + """Evaluate package modules once and retain the resulting runtime API.""" + os.environ.setdefault("MPLCONFIGDIR", "/tmp/ultraplot-matplotlib") + if str(ROOT) not in sys.path: + sys.path.insert(0, str(ROOT)) + modules = {} + for source_path in source_files: + try: + modules[source_path] = importlib.import_module(_module_name(source_path)) + except Exception: + modules[source_path] = None + return modules + + +def _resolve_runtime_doc(module: Any, qualname: str) -> str | None: + """Retrieve the fully expanded runtime docstring for a given qualified name.""" + if module is None or not qualname: + return None + try: + obj = module + member_class = None + member_name = None + for part in qualname.split("."): + if isinstance(obj, type): + # A source declaration may override an optional dependency's + # member only in one environment. Never borrow an inherited + # runtime docstring: it makes generated stubs dependency-specific. + if part not in obj.__dict__: + return None + member_class = obj + member_name = part + candidate = obj.__dict__[part] + if isinstance(candidate, property): + if getattr(candidate.fget, "__module__", None) != module.__name__: + return None + doc = candidate.__doc__ or getattr(candidate.fget, "__doc__", None) + if doc: + return _clean_runtime_doc(inspect.cleandoc(doc)) + obj = getattr(obj, part) + # Conditional placeholders such as ``SomeOptionalClass = None`` and + # imported dependency objects are not the source declaration represented + # by this AST node. Fall back to its static docstring in those cases. + if getattr(obj, "__module__", None) != module.__name__: + return None + # Use inherited documentation only from required Matplotlib bases. + # ``inspect.getdoc`` also searches optional Cartopy bases, which made + # local and clean-CI output differ depending on whether Cartopy existed. + doc = getattr(obj, "__doc__", None) + if not doc and member_class is not None and member_name is not None: + for base in member_class.__mro__[1:]: + if member_name not in base.__dict__: + continue + if base.__module__.startswith("matplotlib."): + doc = inspect.getdoc(base.__dict__[member_name]) + break + if doc: + return _clean_runtime_doc(inspect.cleandoc(doc)) + except Exception: + pass + return None + + +def _clean_runtime_doc(doc: str) -> str: + """Remove website-oriented reStructuredText banners from editor hovers.""" + def replace(match: re.Match) -> str: + if match.group(1).startswith("ultraplot"): + return "" + return "Matplotlib documentation\n\n" + + doc = RUNTIME_DOC_BANNERS.sub(replace, doc) + return doc.strip() + + +def _split_sphinx_target(value: str) -> tuple[str, str]: + """Return the display label and canonical target from a Sphinx role body.""" + match = re.fullmatch(r"(.+?)\s*<([^>]+)>", value.strip()) + if match: + return match.group(1).strip(), match.group(2).strip().lstrip("~") + target = value.strip() + shortened = target.startswith("~") + target = target.lstrip("~") + return (target.rsplit(".", 1)[-1] if shortened else target), target + + +def _ultraplot_doc_url(target: str) -> str: + """Return the autosummary URL generated for an UltraPlot API target.""" + parts = target.split(".") + class_index = next( + (index for index, part in enumerate(parts) if part[:1].isupper()), None + ) + if class_index is not None and class_index < len(parts) - 1: + page = ".".join(parts[: class_index + 1]) + return f"https://ultraplot.readthedocs.io/en/stable/api/{page}.html#{target}" + return f"https://ultraplot.readthedocs.io/en/stable/api/{target}.html" + + +def _api_doc_url(target: str, role: str = "obj") -> str | None: + """Resolve common Sphinx API targets without loading remote inventories.""" + if target.startswith("ultraplot."): + return _ultraplot_doc_url(target) + templates = { + "matplotlib.": "https://matplotlib.org/stable/api/_as_gen/{target}.html", + "numpy.": "https://numpy.org/doc/stable/reference/generated/{target}.html", + "scipy.": "https://docs.scipy.org/doc/scipy/reference/generated/{target}.html", + "pandas.": "https://pandas.pydata.org/pandas-docs/stable/reference/api/{target}.html", + "xarray.": "https://docs.xarray.dev/en/stable/generated/{target}.html", + } + for prefix, template in templates.items(): + if target.startswith(prefix): + return template.format(target=target) + if role in {"rc", "rcraw"}: + return DOC_SEARCH_URLS["ultraplot"].format(query=quote_plus(target)) + if role in {"ref", "doc"}: + return DOC_SEARCH_URLS["ultraplot"].format(query=quote_plus(target)) + if role == "mpltype": + return DOC_SEARCH_URLS["matplotlib"].format(query=quote_plus(target)) + project = target.split(".", 1)[0] + if project in DOC_SEARCH_URLS: + return DOC_SEARCH_URLS[project].format(query=quote_plus(target)) + return None + + +def _markdown_api_link(label: str, target: str, role: str = "obj") -> str: + """Render a resolved target as a Markdown link or readable inline code.""" + url = _api_doc_url(target, role) + return f"[{label}]({url})" if url else f"`{label}`" + + +def _linkify_docstring(doc: str) -> str: + """Convert Sphinx links and API roles into LSP-friendly Markdown links.""" + doc = RST_LINK_PATTERN.sub(lambda match: f"[{match.group(1)}]({match.group(2)})", doc) + + def replace_role(match: re.Match) -> str: + role = match.group(1) + label, target = _split_sphinx_target(match.group(2)) + return _markdown_api_link(label, target, role) + + def replace_target(match: re.Match) -> str: + label, target = _split_sphinx_target(match.group(1)) + return _markdown_api_link(label, target) + + doc = SPHINX_ROLE_PATTERN.sub(replace_role, doc) + return SPHINX_TARGET_PATTERN.sub(replace_target, doc) + + +def _collapse_hover_text(text: str, limit: int) -> str: + """Return a single concise line suitable for an editor hover.""" + text = re.sub(r"\s+", " ", text).strip() + if not text: + return "" + sentence = re.search(r"(?<=[.!?])(?:\s+|$)", text) + if sentence and sentence.end() <= limit: + text = text[: sentence.start() + 1] + if len(text) > limit: + text = text[: limit + 1].rsplit(" ", 1)[0].rstrip(".,;:") + "…" + return text + + +def _doc_sections(lines: list[str]) -> list[tuple[str, int, int]]: + """Return NumPy-style docstring section names and content bounds.""" + starts = [] + for index in range(len(lines) - 1): + name = lines[index].strip() + underline = lines[index + 1].strip() + if ( + DOC_SECTION_PATTERN.fullmatch(name) + and len(underline) >= 3 + and set(underline) == {"-"} + ): + starts.append((name.lower(), index, index + 2)) + return [ + (name, content, starts[index + 1][1] if index + 1 < len(starts) else len(lines)) + for index, (name, _, content) in enumerate(starts) + ] + + +def _parameter_header(line: str) -> tuple[str, str] | None: + """Parse a NumPy-style parameter header into names and type text.""" + if not line or line[:1].isspace(): + return None + if ":" in line: + names, type_name = line.split(":", 1) + elif PARAMETER_NAME_PATTERN.fullmatch(line.strip()): + names, type_name = line, "" + else: + return None + parts = [part.strip() for part in names.split(",")] + if not parts or not all(PARAMETER_NAME_PATTERN.fullmatch(part) for part in parts): + return None + return ", ".join(parts), type_name.strip() + + +def _parameter_summaries(lines: list[str]) -> list[tuple[str, str, str]]: + """Extract parameter names, types, and first-sentence descriptions.""" + entries = [] + current = None + description = [] + + def finish(): + nonlocal current, description + if current is not None: + names, type_name = current + entries.append( + ( + names, + type_name, + _collapse_hover_text( + " ".join(description), HOVER_DOC_DESCRIPTION_CHARS + ), + ) + ) + current = None + description = [] + + for line in lines: + header = _parameter_header(line.rstrip()) + if header: + finish() + current = header + elif current is not None: + stripped = line.strip() + if stripped and not stripped.startswith(".. "): + if not current[1] and not line[:1].isspace(): + current = (current[0], stripped) + else: + description.append(stripped) + finish() + return entries + + +def _hover_doc_url(module: Any, qualname: str) -> str | None: + """Return the public API URL associated with a generated declaration.""" + module_name = getattr(module, "__name__", "") + if not module_name.startswith("ultraplot"): + return None + module_parts = module_name.split(".")[1:] + if any(part.startswith("_") for part in module_parts): + return None + if module_name.startswith("ultraplot.axes."): + module_name = "ultraplot.axes" + parts = [part for part in qualname.split(".") if part != "__init__"] + if not parts or any(part.startswith("_") for part in parts): + return None + return _ultraplot_doc_url(".".join((module_name, *parts))) + + +def _compact_hover_docstring(doc: str, module: Any, qualname: str) -> str: + """Reduce long runtime documentation to a scannable LSP hover summary.""" + if len(doc) <= HOVER_DOC_MAX_CHARS: + return doc + + lines = doc.splitlines() + sections = _doc_sections(lines) + first_section = sections[0][1] - 2 if sections else len(lines) + summary = _collapse_hover_text(" ".join(lines[:first_section]), 420) + entries = [] + seen = set() + for name, start, end in sections: + if name not in {"parameters", "other parameters", "keyword arguments"}: + continue + for entry in _parameter_summaries(lines[start:end]): + if entry[0] not in seen: + seen.add(entry[0]) + entries.append(entry) + + rendered = [summary] if summary else [] + if entries: + rendered.extend(("", "Parameters", "----------")) + visible = entries[:HOVER_DOC_MAX_PARAMETERS] + for names, _, description in visible: + rendered.append( + f"- `{names}`: {description or 'See the full API documentation.'}" + ) + hidden = len(entries) - len(visible) + if hidden: + rendered.append( + f"- _{hidden} additional parameter groups are documented online._" + ) + + url = _hover_doc_url(module, qualname) + if url: + rendered.extend(("", f"[Full API documentation]({url})")) + return "\n".join(rendered).strip() + + +class _StubTransformer(ast.NodeTransformer): + """Reduce implementation syntax to declarations suitable for ``.pyi`` files.""" + + def __init__(self, expand_docstring, module: Any = None): + self._expand_docstring = expand_docstring + self._module = module + self._scope: list[str] = [] + + def _decorators(self, nodes: list[ast.expr]) -> list[ast.expr]: + kept = [] + for node in nodes: + name = (_dotted_name(node) or "").split(".")[-1] + if name in STATIC_DECORATORS: + kept.append(node) + return kept + + def _doc_body( + self, node: ast.AST, qualname: str | None = None + ) -> list[ast.stmt]: + doc = None + if qualname: + doc = _resolve_runtime_doc(self._module, qualname) + if not doc: + ast_doc = ast.get_docstring(node, clean=True) + if ast_doc: + doc = self._expand_docstring(ast_doc) + elif "%(" in doc: + doc = self._expand_docstring(doc) + if doc: + doc = _compact_hover_docstring(doc, self._module, qualname or "") + doc = _linkify_docstring(doc) + + body = [] + if doc: + body.append(ast.Expr(value=ast.Constant(doc))) + body.append(ast.Expr(value=ast.Constant(Ellipsis))) + return body + + def _scope_body(self, statements: list[ast.stmt]) -> list[ast.stmt]: + overloaded = { + item.name + for item in statements + if isinstance(item, (ast.FunctionDef, ast.AsyncFunctionDef)) + and _is_overload(item) + } + body = [] + for statement in statements: + if ( + isinstance(statement, (ast.FunctionDef, ast.AsyncFunctionDef)) + and statement.name in overloaded + and not _is_overload(statement) + ): + continue + transformed = self.visit(statement) + if transformed is None: + continue + if isinstance(transformed, list): + body.extend(transformed) + else: + body.append(transformed) + return body + + def visit_Module(self, node: ast.Module) -> ast.Module: + node.body = self._scope_body(node.body) + insertion = int(bool(node.body) and _is_docstring_statement(node.body[0])) + node.body.insert( + insertion, + ast.ImportFrom( + module="_typeshed", + names=[ast.alias(name="Incomplete")], + level=0, + ), + ) + return node + + def visit_ClassDef(self, node: ast.ClassDef) -> ast.ClassDef: + node.decorator_list = self._decorators(node.decorator_list) + self._scope.append(node.name) + try: + node.body = self._scope_body(node.body) + finally: + self._scope.pop() + if node.body and _is_docstring_statement(node.body[0]): + qualname = ".".join((*self._scope, node.name)) + doc = _resolve_runtime_doc(self._module, qualname) + if not doc: + doc = ast.get_docstring(node, clean=True) + if doc: + doc = self._expand_docstring(doc) + doc = _compact_hover_docstring(doc, self._module, qualname) + doc = _linkify_docstring(doc) + node.body[0] = ast.Expr(value=ast.Constant(doc)) + if not node.body: + node.body = [ast.Expr(value=ast.Constant(Ellipsis))] + return node + + def visit_FunctionDef(self, node: ast.FunctionDef) -> ast.FunctionDef: + node.decorator_list = self._decorators(node.decorator_list) + qualname = ".".join((*self._scope, node.name)) + node.body = self._doc_body(node, qualname) + return node + + def visit_AsyncFunctionDef( + self, node: ast.AsyncFunctionDef + ) -> ast.AsyncFunctionDef: + node.decorator_list = self._decorators(node.decorator_list) + qualname = ".".join((*self._scope, node.name)) + node.body = self._doc_body(node, qualname) + return node + + def visit_Expr(self, node: ast.Expr) -> ast.Expr | None: + if isinstance(node.value, ast.Constant) and isinstance(node.value.value, str): + value = self._expand_docstring(node.value.value) + value = _linkify_docstring(value) + return ast.Expr(value=ast.Constant(value)) + return None + + def visit_Assign(self, node: ast.Assign) -> ast.Assign | None: + if all(_is_simple_target(target) for target in node.targets): + names = [name for target in node.targets for name in _target_names(target)] + if ( + names and all(name.endswith("_docstring") for name in names) + ) or _is_unstable_expression(node.value): + # Comprehension parentheses, lambda spacing, and f-string quote + # selection changed across supported Python versions. These + # implementation values are irrelevant to static declarations. + node.value = ast.Constant(Ellipsis) + return node + return None + + def visit_AnnAssign(self, node: ast.AnnAssign) -> ast.AnnAssign | None: + if _is_simple_target(node.target): + if node.value is not None and _is_unstable_expression(node.value): + node.value = ast.Constant(Ellipsis) + return node + return None + + def visit_AugAssign(self, node: ast.AugAssign) -> None: + return None + + def visit_If(self, node: ast.If) -> ast.If | list[ast.stmt] | None: + if _is_type_checking(node.test): + return self._scope_body(node.body) + node.body = self._scope_body(node.body) + node.orelse = self._scope_body(node.orelse) + if not node.body: + return node.orelse or None + return node + + def visit_Try(self, node: ast.Try) -> ast.Try | list[ast.stmt] | None: + node.body = self._scope_body(node.body) + node.orelse = self._scope_body(node.orelse) + node.finalbody = self._scope_body(node.finalbody) + for handler in node.handlers: + handler.body = self._scope_body(handler.body) + if not node.body: + return [item for handler in node.handlers for item in handler.body] or None + return node + + def visit_For(self, node: ast.For) -> None: + return None + + def visit_AsyncFor(self, node: ast.AsyncFor) -> None: + return None + + def visit_While(self, node: ast.While) -> None: + return None + + def visit_With(self, node: ast.With) -> None: + return None + + def visit_AsyncWith(self, node: ast.AsyncWith) -> None: + return None + + def visit_Match(self, node: ast.Match) -> None: + return None + + def visit_ImportFrom(self, node: ast.ImportFrom) -> ast.ImportFrom | None: + # Future annotations are unnecessary in stubs, and both Pylance and + # Pyrefly require future imports to precede generated module docstrings. + if node.module == "__future__": + return None + return node + + +def _source_files() -> Iterable[Path]: + """Yield Python implementation files included in the distributed package.""" + for path in sorted(PACKAGE.rglob("*.py")): + if not EXCLUDED_PARTS.intersection(path.parts): + yield path + + +def _snippet_expander(): + """Return a function that expands all registered UltraPlot snippets.""" + os.environ.setdefault("MPLCONFIGDIR", "/tmp/ultraplot-matplotlib") + sys.path.insert(0, str(ROOT)) + from ultraplot.internals.docstring import _snippet_manager + + def expand(doc: str) -> str: + def replace(match: re.Match) -> str: + key = match.group(1) + try: + return str(_snippet_manager[key]) + except KeyError: + # Some internal helper docstrings explain the placeholder syntax. + return match.group(0) + + previous = None + while previous != doc: + previous = doc + doc = SNIPPET_PATTERN.sub(replace, doc) + return doc + + return expand + + +def _add_static_forwarding_bases(source_path: Path, tree: ast.Module) -> None: + """Expose runtime ``__getattr__`` proxies to static analyzers. + + ``SubplotGrid`` forwards missing attributes to its axes, but language servers + cannot enumerate attributes implemented by ``__getattr__``. Its stub can + advertise the shared two-dimensional plotting API as a base, while the + runtime proxy continues to handle calls for each compatible axes. + """ + if source_path != PACKAGE / "gridspec.py": + return + for node in tree.body: + if isinstance(node, ast.ClassDef) and node.name == "SubplotGrid": + node.bases.append( + ast.Attribute( + value=ast.Name(id="paxes", ctx=ast.Load()), + attr="PlotAxes", + ctx=ast.Load(), + ) + ) + return + + +def _add_static_signatures(source_path: Path, tree: ast.Module) -> None: + """Add useful signatures for public wrappers that are dynamic at runtime.""" + if source_path != PACKAGE / "axes" / "plot.py": + return + + signature = ast.parse( + "def plot(" + "self, *args: Any, " + "scalex: bool = ..., scaley: bool = ..., data: Any = ..., " + "**kwargs: Any" + ") -> list[Any]: ..." + ).body[0] + for node in tree.body: + if not isinstance(node, ast.ClassDef) or node.name != "PlotAxes": + continue + for member in node.body: + if isinstance(member, ast.FunctionDef) and member.name == "plot": + member.args = signature.args + member.returns = signature.returns + return + + +def _render( + source_path: Path, + expand_docstring, + inferred: ast.Module | None, + runtime_module: Any, +) -> tuple[str, tuple[int, int, int, int]]: + """Render one implementation module as a deterministic type stub.""" + if source_path == PACKAGE / "_version.py": + # setuptools-scm rewrites this module while building each commit. Its + # public interface is stable even though the assigned value is not. + return HEADER + VERSION_STUB, (0, 0, 0, 0) + source = source_path.read_text() + tree = ast.parse(source, filename=str(source_path)) + annotation_counts = _merge_annotations(tree, inferred) + _add_static_forwarding_bases(source_path, tree) + _add_static_signatures(source_path, tree) + tree = _StubTransformer(expand_docstring, module=runtime_module).visit( + copy.deepcopy(tree) + ) + ast.fix_missing_locations(tree) + rendered = ast.unparse(tree) + rendered = "\n".join(line.rstrip() for line in rendered.splitlines()) + rendered = rendered.rstrip() + "\n" + return HEADER + rendered, annotation_counts + + +def _stub_path(source_path: Path) -> Path: + return source_path.with_suffix(".pyi") + + +def _is_generated_stub(path: Path) -> bool: + try: + return path.read_text().startswith(HEADER.splitlines()[0]) + except OSError: + return False + + +def main(argv: list[str] | None = None) -> int: + """Generate bundled stubs, or report stale output with ``--check``.""" + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--check", action="store_true") + parser.add_argument( + "--pyrefly", + help="Pyrefly executable (default: resolve `pyrefly` from PATH)", + ) + args = parser.parse_args(argv) + + executable = args.pyrefly or shutil.which("pyrefly") + if not executable: + parser.error( + f"pyrefly=={PYREFLY_VERSION} is required; install the `typing` extra " + "or pass --pyrefly PATH" + ) + try: + inferred_trees, invalid_inference = _run_pyrefly(executable) + except (OSError, subprocess.SubprocessError, RuntimeError) as error: + parser.error(str(error)) + + expand_docstring = _snippet_expander() + source_files = list(_source_files()) + runtime_modules = _load_runtime_modules(source_files) + expected = set() + changed = [] + inferred_count = fallback_count = unmatched_count = discarded_count = 0 + if args.check: + print(f"Checking {len(source_files)} source modules and their stubs...") + for source_path in source_files: + stub_path = _stub_path(source_path) + expected.add(stub_path) + rendered, counts = _render( + source_path, + expand_docstring, + inferred_trees.get(source_path), + runtime_modules.get(source_path), + ) + inferred_count += counts[0] + fallback_count += counts[1] + unmatched_count += counts[2] + discarded_count += counts[3] + current = stub_path.read_text() if stub_path.exists() else None + if current == rendered: + continue + changed.append(stub_path) + if not args.check: + stub_path.write_text(rendered) + + obsolete = [ + path + for path in PACKAGE.rglob("*.pyi") + if path not in expected and _is_generated_stub(path) + ] + if not args.check: + for path in obsolete: + path.unlink() + + for path in changed: + action = "Stale" if args.check else "Generated" + print(f"{action}: {path.relative_to(ROOT)}") + for path in obsolete: + action = "Obsolete" if args.check else "Removed" + print(f"{action}: {path.relative_to(ROOT)}") + print( + f"Annotation merge: {inferred_count} inferred, " + f"{fallback_count} marked Incomplete; " + f"{discarded_count} invalid source annotations replaced; " + f"{unmatched_count} source declarations absent from Pyrefly output." + ) + if invalid_inference: + print( + "Pyrefly output skipped after syntax validation: " + + ", ".join(str(path) for path in invalid_inference) + ) + if args.check: + if changed or obsolete: + count = len(changed) + len(obsolete) + print( + f"Check failed: {count} stale or obsolete stub(s). " + "Run `python tools/generate_stubs.py` to update them." + ) + else: + print(f"Checked {len(expected)} stubs: all up to date.") + else: + unchanged = len(expected) - len(changed) + print( + f"Stub generation complete: {len(changed)} updated, " + f"{unchanged} unchanged, {len(obsolete)} obsolete removed." + ) + return int(args.check and bool(changed or obsolete)) + + +if __name__ == "__main__": + raise SystemExit(main()) diff --git a/ultraplot/__init__.pyi b/ultraplot/__init__.pyi new file mode 100644 index 000000000..8cb79c01a --- /dev/null +++ b/ultraplot/__init__.pyi @@ -0,0 +1,177 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +A succinct matplotlib wrapper for making beautiful, publication-quality graphics. +""" +from _typeshed import Incomplete +import sys +from pathlib import Path +from typing import TYPE_CHECKING, Optional +from ._lazy import LazyLoader, install_module_proxy +import matplotlib.pyplot as pyplot +from .animation import ArtistAnimation as ArtistAnimation +from .animation import FuncAnimation as FuncAnimation +from .axes import Axes as Axes +from .axes import CartesianAxes as CartesianAxes +from .axes import ExternalAxesContainer as ExternalAxesContainer +from .axes import GeoAxes as GeoAxes +from .axes import PlotAxes as PlotAxes +from .axes import PolarAxes as PolarAxes +from .axes import TaylorAxes as TaylorAxes +from .axes import ThreeAxes as ThreeAxes +from .colors import ColormapDatabase as ColormapDatabase +from .colors import ColorDatabase as ColorDatabase +from .colors import ContinuousColormap as ContinuousColormap +from .colors import DiscreteColormap as DiscreteColormap +from .colors import DiscreteNorm as DiscreteNorm +from .colors import DivergingNorm as DivergingNorm +from .colors import PerceptualColormap as PerceptualColormap +from .colors import SegmentedNorm as SegmentedNorm +from .colors import _cmap_database as colormaps +from .config import config_inline_backend as config_inline_backend +from .config import Configurator as Configurator +from .config import rc as rc +from .config import rc_matplotlib as rc_matplotlib +from .config import rc_ultraplot as rc_ultraplot +from .config import register_cmaps as register_cmaps +from .config import register_colors as register_colors +from .config import register_cycles as register_cycles +from .config import register_fonts as register_fonts +from .config import use_style as use_style +from .constructor import Colormap as Colormap +from .constructor import Cycle as Cycle +from .constructor import Formatter as Formatter +from .constructor import FORMATTERS as FORMATTERS +from .constructor import Locator as Locator +from .constructor import LOCATORS as LOCATORS +from .constructor import Norm as Norm +from .constructor import NORMS as NORMS +from .constructor import Proj as Proj +from .constructor import PROJS as PROJS +from .constructor import Scale as Scale +from .constructor import SCALES as SCALES +from .demos import show_channels as show_channels +from .demos import show_cmaps as show_cmaps +from .demos import show_colorspaces as show_colorspaces +from .demos import show_colors as show_colors +from .demos import show_cycles as show_cycles +from .demos import show_fonts as show_fonts +from .figure import Figure as Figure +from .gridspec import GridSpec as GridSpec +from .gridspec import SubplotGrid as SubplotGrid +from .legend import GeometryEntry as GeometryEntry +from .legend import Legend as Legend +from .legend import LegendEntry as LegendEntry +from .proj import Aitoff as Aitoff +from .proj import Hammer as Hammer +from .proj import KavrayskiyVII as KavrayskiyVII +from .proj import NorthPolarAzimuthalEquidistant as NorthPolarAzimuthalEquidistant +from .proj import NorthPolarGnomonic as NorthPolarGnomonic +from .proj import NorthPolarLambertAzimuthalEqualArea as NorthPolarLambertAzimuthalEqualArea +from .proj import SouthPolarAzimuthalEquidistant as SouthPolarAzimuthalEquidistant +from .proj import SouthPolarGnomonic as SouthPolarGnomonic +from .proj import SouthPolarLambertAzimuthalEqualArea as SouthPolarLambertAzimuthalEqualArea +from .proj import WinkelTripel as WinkelTripel +from .scale import CutoffScale as CutoffScale +from .scale import ExpScale as ExpScale +from .scale import FuncScale as FuncScale +from .scale import InverseScale as InverseScale +from .scale import LinearScale as LinearScale +from .scale import LogitScale as LogitScale +from .scale import LogScale as LogScale +from .scale import MercatorLatitudeScale as MercatorLatitudeScale +from .scale import PowerScale as PowerScale +from .scale import SineLatitudeScale as SineLatitudeScale +from .scale import SymmetricalLogScale as SymmetricalLogScale +from .text import CurvedText as CurvedText +from .textalign import align_text as align_text +from .ultralayout import ColorbarLayoutSolver as ColorbarLayoutSolver +from .ultralayout import compute_ultra_positions as compute_ultra_positions +from .ultralayout import get_grid_positions_ultra as get_grid_positions_ultra +from .ultralayout import is_orthogonal_layout as is_orthogonal_layout +from .ultralayout import UltraLayoutSolver as UltraLayoutSolver +from .ticker import AutoCFDatetimeFormatter as AutoCFDatetimeFormatter +from .ticker import AutoCFDatetimeLocator as AutoCFDatetimeLocator +from .ticker import AutoFormatter as AutoFormatter +from .ticker import CFDatetimeFormatter as CFDatetimeFormatter +from .ticker import DegreeFormatter as DegreeFormatter +from .ticker import DegreeLocator as DegreeLocator +from .ticker import DiscreteLocator as DiscreteLocator +from .ticker import FracFormatter as FracFormatter +from .ticker import IndexFormatter as IndexFormatter +from .ticker import IndexLocator as IndexLocator +from .ticker import LatitudeFormatter as LatitudeFormatter +from .ticker import LatitudeLocator as LatitudeLocator +from .ticker import LongitudeFormatter as LongitudeFormatter +from .ticker import LongitudeLocator as LongitudeLocator +from .ticker import SciFormatter as SciFormatter +from .ticker import SigFigFormatter as SigFigFormatter +from .ticker import SimpleFormatter as SimpleFormatter +from .ui import close as close +from .ui import figure as figure +from .ui import ioff as ioff +from .ui import ion as ion +from .ui import isinteractive as isinteractive +from .ui import show as show +from .ui import subplot as subplot +from .ui import subplots as subplots +from .ui import switch_backend as switch_backend +from .utils import arange as arange +from .utils import check_for_update as check_for_update +from .utils import edges as edges +from .utils import edges2d as edges2d +from .utils import get_colors as get_colors +from .utils import scale_luminance as scale_luminance +from .utils import scale_saturation as scale_saturation +from .utils import set_alpha as set_alpha +from .utils import set_hue as set_hue +from .utils import set_luminance as set_luminance +from .utils import set_saturation as set_saturation +from .utils import shift_hue as shift_hue +from .utils import to_hex as to_hex +from .utils import to_rgb as to_rgb +from .utils import to_rgba as to_rgba +from .utils import to_xyz as to_xyz +from .utils import to_xyza as to_xyza +from .utils import units as units +name = 'ultraplot' +try: + from ._version import __version__ +except ImportError: + __version__ = 'unknown' +version = __version__ +_SETUP_DONE = False +_SETUP_RUNNING = False +_EAGER_DONE = False +_EXPOSED_MODULES = set() +_ATTR_MAP = None +_REGISTRY_ATTRS = None +_LAZY_LOADING_EXCEPTIONS = {'constructor': ('constructor', None), 'crs': ('proj', None), 'colormaps': ('colors', '_cmap_database'), 'check_for_update': ('utils', 'check_for_update'), 'NORMS': ('constructor', 'NORMS'), 'LOCATORS': ('constructor', 'LOCATORS'), 'FORMATTERS': ('constructor', 'FORMATTERS'), 'SCALES': ('constructor', 'SCALES'), 'PROJS': ('constructor', 'PROJS'), 'internals': ('internals', None), 'externals': ('externals', None), 'Proj': ('constructor', 'Proj'), 'tests': ('tests', None), 'rcsetup': ('internals', 'rcsetup'), 'warnings': ('internals', 'warnings'), 'figure': ('ui', 'figure'), 'Figure': ('figure', 'Figure'), 'Colormap': ('constructor', 'Colormap'), 'Cycle': ('constructor', 'Cycle'), 'Norm': ('constructor', 'Norm'), 'Locator': ('constructor', 'Locator'), 'Scale': ('constructor', 'Scale'), 'Formatter': ('constructor', 'Formatter')} + +def _setup() -> None: + ... + +def setup(eager: Optional[bool]=None) -> None: + """Initialize registries and optionally import the public API eagerly.""" + ... + +def _build_registry_map() -> None: + ... + +def _get_registry_attr(name: Incomplete) -> None: + ... +_LOADER: LazyLoader = ... + +def __getattr__(name: Incomplete) -> Incomplete: + ... + +def __dir__() -> list[str]: + ... + +def _patch_seaborn_move_legend() -> None: + """Let ``sns.move_legend(ax, ...)`` accept singleton `SubplotGrid` objects. + +Seaborn only accepts native Matplotlib axes, figures, and its own grids. The +wrapper unwraps a singleton grid to its underlying axes; callers can avoid +this compatibility patch by passing ``ax[0]`` directly.""" + ... diff --git a/ultraplot/_animation.pyi b/ultraplot/_animation.pyi new file mode 100644 index 000000000..22c4c6b33 --- /dev/null +++ b/ultraplot/_animation.pyi @@ -0,0 +1,311 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Helpers for responsive interactive and animated UltraPlot figures. +""" +from _typeshed import Incomplete +from collections.abc import Iterable +from contextlib import contextmanager +from weakref import WeakSet +import matplotlib.artist as martist +import matplotlib.axis as maxis +import matplotlib.collections as mcollections +import matplotlib.image as mimage +import matplotlib.lines as mlines +import matplotlib.text as mtext +import matplotlib.transforms as mtransforms +import numpy as np +from matplotlib.backend_bases import DrawEvent +from ._interaction import _NavigationInteractionManager +from ._layout import _is_internal_ticker +_POINTS_PER_INCH = 72.0 +_STROKE_HALF_WIDTH = 0.5 +_SQRT2 = np.sqrt(2.0) +_MITER_LIMIT = 4.0 +_BBOX_TOLERANCE = 1e-06 +_MISSING = object() +_OPAQUE_TICKER_TYPES = frozenset(('FuncFormatter', 'FuncScale', 'FuncScaleLog')) + +class _SelectiveDrawManager: + """Retain safe draw layers and bypass unchanged Matplotlib traversal. + +Multi-axes figures retain each complete axes as one layer. Single Cartesian +axes retain the stable draw-order prefix below their first clipped numeric +line, then redraw that line and every later artist as an exact z-order suffix. +Unknown stale artists, geometry changes, overlapping layers, unsupported +artist orders, and export draws fall back to a complete draw. The first display +is always untouched; a later complete draw primes the retained layers.""" + _data_artist_types = (mlines.Line2D, mcollections.Collection, mimage.AxesImage) + _region_pad = 2 + _min_axes_for_view_redraw = 3 + + def __init__(self, canvas: Incomplete, figure: Incomplete=None) -> None: + ... + + @staticmethod + def _bbox_signature(bbox: Incomplete) -> tuple[float, ...]: + ... + + def _axes_signature(self, ax: Incomplete) -> Incomplete: + ... + + @staticmethod + def _ticker_fingerprint(ticker: Incomplete) -> Incomplete: + """Return a value that changes when a locator or formatter is retuned.""" + ... + + @staticmethod + def _ticker_axes(ax: Incomplete) -> Incomplete: + """Return the named axis objects that own locators and formatters.""" + ... + + @classmethod + def _ticker_signature(cls, ax: Incomplete) -> Incomplete: + """Return the tuned state of every locator and formatter on an axes.""" + ... + + @classmethod + def _has_untrusted_ticker(cls, ax: Incomplete) -> bool: + """Return whether any ticker on *ax* can change without being noticed.""" + ... + + def _axes_view_signature(self, ax: Incomplete) -> Incomplete: + """Return paint-only limits, scales, and projection camera state.""" + ... + + def _current_canvas_signature(self) -> tuple[float, tuple[float, ...], float, float, float] | None: + """Return framebuffer properties that invalidate copied pixel regions.""" + ... + + def _view_signature(self, axes: Incomplete=None) -> Incomplete: + """Return the view state last presented by a complete canvas draw.""" + ... + + @staticmethod + def _camera_signature(ax: Incomplete) -> tuple[float, float, float, int, tuple[float, ...], tuple[float, ...], tuple[float, ...], float, tuple[float, ...]] | None: + """Return 3D camera and limits, or ``None`` for ordinary 2D axes.""" + ... + + def _visible_axes(self) -> Incomplete: + ... + + def _has_explicit_blit_manager(self) -> bool: + ... + + def _has_animated_artist(self, axes: Incomplete) -> bool: + ... + + def _figure_overlay_bboxes(self, renderer: Incomplete) -> Incomplete: + """Return display bboxes of figure artists that can paint over an axes, or +``None`` if any of them cannot be measured. + +Every axes queries the same set within one draw pass, so measure the +figure once and let each query reuse it.""" + ... + + def _has_overlapping_figure_artist(self, targets: Incomplete) -> bool: + """Return whether a figure artist overlaps retained artists or regions.""" + ... + + @staticmethod + def _bbox_contains(outer: Incomplete, inner: Incomplete, tolerance: Incomplete=_BBOX_TOLERANCE) -> Incomplete: + ... + + def _suffix_fits_region(self, suffix: Incomplete, region: Incomplete, renderer: Incomplete) -> bool: + """Return whether restoring *region* clears every suffix paint extent.""" + ... + + @staticmethod + def _has_numeric_line_data(line: Incomplete) -> bool: + """Return whether line conversion cannot mutate categorical/date axes.""" + ... + + def _resolve_line_suffix(self, ax: Incomplete) -> Incomplete: + """Return the exact draw-order suffix starting at the first data line.""" + ... + + @staticmethod + def _max_concurrent(intervals: Incomplete) -> int: + """Return the largest number of intervals open at any one coordinate.""" + ... + + @classmethod + def _regions_overlap(cls, regions: Incomplete) -> bool: + """Return whether any two regions share a positive-area intersection.""" + ... + _bounded_path_effects = frozenset(('Normal', 'Stroke', 'withStroke')) + + @classmethod + def _path_effect_overhang(cls, artist: Incomplete, dpi: Incomplete) -> float | None: + """Return pixels *artist*'s path effects add, or ``None`` if unbounded.""" + ... + + @staticmethod + def _has_miter_join(artist: Incomplete) -> bool: + """Return whether *artist* joins segments with an unbounded miter.""" + ... + + @classmethod + def _stroke_overhang(cls, artist: Incomplete, dpi: Incomplete) -> Incomplete: + """Return pixels *artist* can paint beyond its measured extent.""" + ... + + def _expand_for_overhang(self, ax: Incomplete, renderer: Incomplete, region: Incomplete) -> Incomplete: + """Grow an already padded *region* to cover strokes painting past their +measured extents. Artist extents carry the same safety pad, so the result +clears every painted pixel by ``_region_pad`` on all sides.""" + ... + + def _region_signature(self, ax: Incomplete) -> Incomplete: + """Return a cheap key for a resolved region, or ``None`` if unusable.""" + ... + + def _resolve_region(self, ax: Incomplete, renderer: Incomplete, cached_regions: Incomplete) -> Incomplete: + ... + + @staticmethod + def _mark_axes_clean(axes: Incomplete) -> None: + """Clear placeholder staleness left behind by ``Axes.draw()``.""" + ... + + def invalidate(self) -> None: + """Discard all retained axes layers.""" + ... + + def _on_resize(self, event: Incomplete) -> None: + ... + + def _on_draw(self, event: Incomplete) -> None: + ... + + @contextmanager + def full_draw_context(self) -> Incomplete: + """Temporarily split a full draw into static and axes layers.""" + ... + + def _dirty_axes(self) -> Incomplete: + ... + + def _damage_closure(self, dirty: Incomplete, damage: Incomplete) -> Incomplete: + """Expand damage to intersecting axes and preserve figure-level order.""" + ... + + def _view_damage(self, dirty: Incomplete, renderer: Incomplete) -> Incomplete: + """Resolve exact damage after view changes and axes needing repaint.""" + ... + + def draw_if_possible(self) -> bool: + """Use retained axes layers for paint-only data changes.""" + ... + + @contextmanager + def save_context(self) -> Incomplete: + """Suspend retained drawing while producing external output.""" + ... + + def close(self) -> None: + ... + +class _BlitManager: + """Manage efficient updates of a small set of changing artists. + +The manager caches the static canvas background, restores it for each +update, redraws only the managed artists, and blits the affected region. +Backends without blitting support safely fall back to ``draw_idle()``. + +Parameters +---------- +canvas : [FigureCanvasBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.FigureCanvasBase.html) + Canvas containing the artists. +artists : iterable of [Artist](https://matplotlib.org/stable/api/_as_gen/matplotlib.artist.Artist.html), optional + Artists that will change between updates. +bbox : [Bbox](https://matplotlib.org/stable/api/_as_gen/matplotlib.transforms.Bbox.html) or object with a ``bbox`` attribute, optional + Region to cache and blit. By default, the union of the managed artists' + axes bounding boxes is used. Figure-level artists fall back to the full + figure bounding box. + +Notes +----- +Managed artists are drawn above the cached static background, matching +Matplotlib's standard blitting behavior.""" + + def __init__(self, canvas: Incomplete, artists: Iterable[martist.Artist]=(), bbox: Incomplete=None) -> None: + ... + + @property + def artists(self) -> Incomplete: + """Managed artists as an immutable tuple.""" + ... + + @property + def supports_blit(self) -> bool: + """Whether the associated canvas supports blitting.""" + ... + + def _resolve_bbox(self) -> Incomplete: + ... + + def _draw_artists(self) -> None: + ... + + def _on_draw(self, event: Incomplete) -> None: + ... + + def _on_resize(self, event: Incomplete) -> None: + ... + + def add_artist(self, artist: martist.Artist) -> Incomplete: + """Add an artist to the managed update set. + +Returns +------- +_BlitManager + This manager, to permit chained calls.""" + ... + + def remove_artist(self, artist: martist.Artist) -> Incomplete: + """Stop managing an artist and restore its original animated state. + +Returns +------- +_BlitManager + This manager, to permit chained calls.""" + ... + + def invalidate(self) -> None: + """Discard the cached background before the next update.""" + ... + + @contextmanager + def _save_context(self) -> Incomplete: + """Temporarily restore original artist states for a complete export.""" + ... + + def update(self, *, flush: Incomplete=False) -> bool: + """Redraw the managed artists. + +Parameters +---------- +flush : bool, default: False + Whether to immediately process pending GUI events after blitting. + +Returns +------- +bool + ``True`` when the blitting fast path was used, otherwise ``False``.""" + ... + + def close(self, *, redraw: Incomplete=True) -> None: + """Disconnect callbacks and restore the artists' animated states. + +Parameters +---------- +redraw : bool, default: True + Whether to schedule a normal full redraw after restoring the artists.""" + ... + + def __enter__(self) -> Incomplete: + ... + + def __exit__(self, exc_type: Incomplete, exc: Incomplete, traceback: Incomplete) -> None: + ... diff --git a/ultraplot/_interaction.pyi b/ultraplot/_interaction.pyi new file mode 100644 index 000000000..dfccd1ed2 --- /dev/null +++ b/ultraplot/_interaction.pyi @@ -0,0 +1,212 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +"""Private helpers for responsive interactive figure navigation.""" +from _typeshed import Incomplete +from contextlib import contextmanager +from dataclasses import dataclass, field +import time +import matplotlib.collections as mcollections +import numpy as np +from matplotlib.backend_bases import TimerBase +from matplotlib.ticker import MaxNLocator, NullLocator +_MISSING = object() +_MIN_PREVIEW_SURFACE_CELLS = 625 +_PREVIEW_SURFACE_SAMPLES = 10 +_PREVIEW_TICK_COUNT = 3 +_TARGET_FRAME_RATE = 60 +_MS_PER_SECOND = 1000 + +def _preview_enabled() -> Incomplete: + """Return the current runtime setting for approximate navigation frames.""" + ... + +def _state_equal(left: Incomplete, right: Incomplete) -> bool: + """Return whether an artist property still matches our preview value.""" + ... + +@dataclass +class _LocatorPreviewState: + """Exact and temporary locators for one axis.""" + axis: object + original_major: object + original_minor: object + preview_major: object + preview_minor: object + + def restore(self) -> None: + ... + +@dataclass +class _LinePreviewState: + """Exact and sampled data for one line artist.""" + artist: object + original: tuple + preview: tuple + dimensions: str + + def restore(self) -> None: + ... + +@dataclass +class _ScatterPreviewState: + """Exact and sampled private collection fields for one scatter artist.""" + artist: object + original: dict + preview: dict + + def restore(self) -> None: + ... + +@dataclass +class _SurfacePreviewState: + """Temporary surface proxy attachment and draw-suppression state.""" + artist: object + proxy: object + ax: object + proxy_attached: bool + proxy_visible: bool + hidden_marker: object + + def restore(self) -> None: + ... + +@dataclass +class _AxesPreviewState: + """All temporary navigation state owned for one axes.""" + ax: object + grid_marker: object = _MISSING + locators: list = field(default_factory=list) + lines: list = field(default_factory=list) + scatters: list = field(default_factory=list) + surfaces: list = field(default_factory=list) + restored: bool = False + + def restore(self) -> None: + ... + +@dataclass +class _SurfaceProxyRecipe: + """Lazy recipe for a coarse surface used only during navigation.""" + arrays: tuple + args: tuple + kwargs: dict + geometry_signature: tuple + facecolor_signature: tuple + proxy: object = None + +def _surface_geometry_signature(surface: Incomplete) -> Incomplete: + ... + +def _surface_facecolor_signature(surface: Incomplete) -> Incomplete: + ... + +def _register_surface_preview(surface: Incomplete, X: Incomplete, Y: Incomplete, Z: Incomplete, args: Incomplete, kwargs: Incomplete) -> None: + """Attach a lazy coarse-surface recipe without constructing another artist.""" + ... + +def _sync_surface_proxy(surface: Incomplete, proxy: Incomplete) -> None: + """Copy safe presentation properties from an exact surface to its proxy.""" + ... + +def _prepare_surface_preview(surface: Incomplete) -> Incomplete: + """Synchronize an attached proxy and return whether to suppress the exact one.""" + ... + +def _resolve_surface_proxy(surface: Incomplete) -> Incomplete: + """Create or return a valid lazy surface proxy for an exact collection.""" + ... + +class _FramePacer: + """Coalesce GUI draws and submit the newest view near a 60 Hz cadence.""" + _interval = 1 / _TARGET_FRAME_RATE + + def __init__(self, canvas: Incomplete, is_active: Incomplete) -> None: + ... + + def cancel(self) -> None: + ... + + def _submit(self) -> Incomplete: + ... + + def _schedule(self) -> bool: + ... + + def request(self, draw: Incomplete) -> bool: + ... + + def acknowledge(self) -> None: + ... + +class _NavigationInteractionManager: + """Temporarily simplify dense scenes during interactive navigation.""" + _line_limit = 2000 + _scatter_limit = 2000 + + def __init__(self, canvas: Incomplete, figure: Incomplete, selective: Incomplete) -> None: + ... + + def _is_active(self) -> Incomplete: + ... + + @staticmethod + def _is_three_axes(ax: Incomplete) -> Incomplete: + ... + + @staticmethod + def _subset_indices(arrays: Incomplete, limit: Incomplete) -> Incomplete: + ... + + @staticmethod + def _shared_view_axes(ax: Incomplete) -> Incomplete: + ... + + @staticmethod + def _shared_two_axes(ax: Incomplete) -> Incomplete: + ... + + @staticmethod + def _simplify_locator(axis: Incomplete, state: Incomplete) -> None: + ... + + def _simplify_line(self, line: Incomplete, dimensions: Incomplete, state: Incomplete) -> None: + ... + + def _simplify_scatter(self, artist: Incomplete, arrays: Incomplete, indices: Incomplete, names: Incomplete, state: Incomplete) -> None: + ... + + def _simplify_three_axes(self, ax: Incomplete) -> _AxesPreviewState: + ... + + def _simplify_two_axes(self, ax: Incomplete) -> _AxesPreviewState: + ... + + def activate(self, ax: Incomplete) -> bool: + """Activate preview quality for the navigated axes and shared siblings.""" + ... + + def deactivate(self, *, redraw: Incomplete=True) -> bool: + """Restore exact artists and formatting after interactive navigation.""" + ... + + def request_draw(self, draw: Incomplete) -> bool: + ... + + @contextmanager + def full_quality_context(self) -> Incomplete: + ... + + def _on_press(self, event: Incomplete) -> None: + ... + + def _on_release(self, event: Incomplete) -> None: + ... + + def _on_draw(self, event: Incomplete) -> None: + ... + + def _on_close(self, event: Incomplete) -> None: + ... + + def close(self) -> None: + ... diff --git a/ultraplot/_layout.pyi b/ultraplot/_layout.pyi new file mode 100644 index 000000000..e3f40c325 --- /dev/null +++ b/ultraplot/_layout.pyi @@ -0,0 +1,200 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Private helpers for reducing repeated layout work. + +There are two cache lifetimes: + +- Tick computations are reused only within one layout-and-render transaction. +- Relative axes outsets persist across transactions until their dependencies + change. + +``_LayoutTransaction`` owns both lifecycles. Temporary matplotlib method +overrides are restored when the transaction exits, including after exceptions. +""" +from _typeshed import Incomplete +from collections import OrderedDict +from contextlib import ExitStack +from dataclasses import dataclass +import matplotlib.transforms as mtransforms +import numpy as np +_MISSING = object() + +def _is_internal_ticker(obj: Incomplete) -> bool: + """Return whether a locator or formatter is safe for draw-local reuse.""" + ... + +def _interval_key(values: Incomplete) -> Incomplete: + """Convert a numerical interval to an immutable exact cache key.""" + ... + +@dataclass(frozen=True) +class _AxisTickState: + """State that can affect ``Axis._update_ticks`` within one canvas draw.""" + view_interval: tuple + data_interval: tuple + axes_size: tuple + dpi: float + scale: str + major_locator: int + major_formatter: int + minor_locator: int + minor_formatter: int + converter: int + units: int + +@dataclass +class _AxisTickResult: + """Cached ticks and formatter locations for one axis state.""" + ticks: list + major_locs: np.ndarray | tuple + minor_locs: np.ndarray | tuple + +class _AxisTickCache: + """Cache repeated tick updates during one layout-and-render transaction. + +Tight bounding-box calculation and the final axes draw repeatedly call +``Axis._update_ticks`` with identical state. The method runs locators, +formatters, tick positioning, and visibility filtering each time. This +manager replaces the method on individual axes for the duration of a +canvas draw and restores the original instance state afterwards. + +Custom third-party locators and formatters conservatively bypass the +cache because they may rely on repeated side effects.""" + _MAX_STATES_PER_AXIS = 4 + + def __init__(self, figure: Incomplete) -> None: + ... + + def __enter__(self) -> Incomplete: + ... + + def __exit__(self, *args: Incomplete) -> None: + ... + + def refresh(self) -> None: + """Patch axes added while queued guides and panels are materialized.""" + ... + + def _patch(self, axis: Incomplete) -> None: + ... + + @staticmethod + def _is_cacheable(axis: Incomplete) -> bool: + ... + + def _get_state(self, axis: Incomplete) -> _AxisTickState: + ... + + @staticmethod + def _copy_formatter_locs(formatter: Incomplete) -> Incomplete: + ... + + @staticmethod + def _restore_formatter_locs(axis: Incomplete, result: Incomplete) -> None: + ... + +@dataclass(frozen=True) +class _AxesExtentState: + """Geometry that can alter outsets relative to an axes rectangle.""" + bbox_size: tuple + bbox_position: tuple + dpi: float + axis_states: tuple + decorations: tuple + subset_titles: tuple + +@dataclass +class _AxesExtentRecord: + """One relative tight-bbox measurement.""" + version: int + state: _AxesExtentState + outsets: tuple + +class _LayoutExtentStore: + """Persist relative axes outsets and dependency versions between layouts. + +Absolute axes positions are solver outputs. Tick labels, axis labels, and +titles are better represented as four overhangs around those positions. +Standard Cartesian axes can therefore move without repeating renderer text +measurements. Position-sensitive axes and extra artists automatically add +the absolute origin to their state key.""" + + def __init__(self, figure: Incomplete) -> None: + ... + + def __enter__(self) -> Incomplete: + ... + + def refresh(self) -> Incomplete: + """Synchronize axes added by queued guide and panel creation.""" + ... + + def __exit__(self, *args: Incomplete) -> None: + ... + + def get_tightbbox(self, axes: Incomplete, renderer: Incomplete, *, include_subset_titles: Incomplete=True, use_cache: Incomplete=True) -> Incomplete: + """Return an exact or reconstructed tight bbox in display units.""" + ... + + def _get_state(self, axes: Incomplete, include_subset_titles: Incomplete=True) -> _AxesExtentState: + ... + + def _rebase_records(self) -> None: + """Rebase reusable outsets onto final post-render axes dimensions. + +UltraLayout may make a small solver adjustment after measuring an axes. +The final render updates locator/formatter locations for that geometry. +If those locations and every non-size dependency are unchanged, the +relative outsets remain valid for the next layout transaction.""" + ... + + def _get_retained_bboxes(self, axes: Incomplete) -> Incomplete: + """Return exact cached display bboxes for retained axes drawing.""" + ... + + @staticmethod + def _get_decoration_state(axes: Incomplete) -> Incomplete: + ... + + def _get_subset_title_state(self, axes: Incomplete, include_subset_titles: Incomplete) -> Incomplete: + ... + + @staticmethod + def _is_position_sensitive(axes: Incomplete) -> bool: + ... + + @staticmethod + def _is_cacheable_axes(axes: Incomplete) -> bool: + ... + + @staticmethod + def _get_outsets(axes_bbox: Incomplete, tight_bbox: Incomplete) -> Incomplete: + ... + + @staticmethod + def _bbox_from_outsets(axes_bbox: Incomplete, outsets: Incomplete) -> Incomplete: + ... + + @staticmethod + def _measure_tightbbox(axes: Incomplete, renderer: Incomplete, include_subset_titles: Incomplete) -> Incomplete: + ... + +class _LayoutTransaction: + """Own temporary and persistent caches for one dirty canvas draw. + +Figure code only needs to know whether a transaction is active. Cache setup, +dynamic-axes refresh, and exception-safe cleanup stay private to this object.""" + + def __init__(self, figure: Incomplete, *, cache_ticks: Incomplete=True, cache_extents: Incomplete=True) -> None: + ... + + def __enter__(self) -> Incomplete: + ... + + def __exit__(self, *args: Incomplete) -> Incomplete: + ... + + def refresh(self) -> None: + """Synchronize caches after queued guides create axes or panels.""" + ... diff --git a/ultraplot/_lazy.pyi b/ultraplot/_lazy.pyi new file mode 100644 index 000000000..2e70a32c7 --- /dev/null +++ b/ultraplot/_lazy.pyi @@ -0,0 +1,61 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Helpers for lazy attribute loading in [ultraplot](https://ultraplot.readthedocs.io/en/stable/search.html?q=ultraplot). +""" +from _typeshed import Incomplete +import ast +import importlib.util +import types +from importlib import import_module +from pathlib import Path +from typing import Any, Callable, Dict, Mapping, MutableMapping, Optional + +class LazyLoader: + """Encapsulates lazy-loading mechanics for the ultraplot top-level module.""" + + def __init__(self, *, package: str, package_path: Path, exceptions: Mapping[str, tuple[str, Optional[str]]], setup_callback: Callable[[], None], registry_attr_callback: Callable[[str], Optional[type]], registry_build_callback: Callable[[], None], registry_names_callback: Callable[[], Optional[Mapping[str, type]]], attr_map_key: str='_ATTR_MAP', eager_key: str='_EAGER_DONE') -> None: + ... + + def _import_module(self, module_name: str) -> types.ModuleType: + ... + + def _get_attr_map(self, module_globals: Mapping[str, Any]) -> Optional[Dict[str, tuple[str, Optional[str]]]]: + ... + + def _set_attr_map(self, module_globals: MutableMapping[str, Any], value: Dict[str, tuple[str, Optional[str]]]) -> None: + ... + + def _get_eager_done(self, module_globals: Mapping[str, Any]) -> bool: + ... + + def _set_eager_done(self, module_globals: MutableMapping[str, Any], value: bool) -> None: + ... + + @staticmethod + def _parse_all(path: Path) -> Optional[list[str]]: + ... + + def _discover_modules(self, module_globals: MutableMapping[str, Any]) -> None: + ... + + def resolve_extra(self, name: str, module_globals: MutableMapping[str, Any]) -> Any: + ... + + def load_all(self, module_globals: MutableMapping[str, Any]) -> list[str]: + ... + + def get_attr(self, name: str, module_globals: MutableMapping[str, Any]) -> Any: + ... + + def iter_dir_names(self, module_globals: MutableMapping[str, Any]) -> list[str]: + ... + +class _UltraPlotModule(types.ModuleType): + + def __setattr__(self, name: str, value: Any) -> None: + ... + +def install_module_proxy(module: Optional[types.ModuleType]) -> None: + """Prevent lazy-loading names from being clobbered by submodule imports.""" + ... diff --git a/ultraplot/_subplots.pyi b/ultraplot/_subplots.pyi new file mode 100644 index 000000000..18711a6ef --- /dev/null +++ b/ultraplot/_subplots.pyi @@ -0,0 +1,69 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Subplot creation and management for ultraplot figures. +""" +from _typeshed import Incomplete +from numbers import Integral +from typing import TYPE_CHECKING +import matplotlib.axes as maxes +import matplotlib.gridspec as mgridspec +import matplotlib.projections as mproj +import numpy as np +from . import axes as paxes +from . import constructor +from . import gridspec as pgridspec +from .internals import _not_none, _pop_params, warnings +from .figure import Figure + +class SubplotManager: + """Manages subplot creation, gridspec ownership, and projection parsing +for a Figure instance. + +Parameters +---------- +figure : [Figure](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html) + The parent figure.""" + + def __init__(self, figure: 'Figure') -> None: + ... + + def reset(self) -> None: + """Forget every subplot and release the gridspec. + +Called by [clear](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.clear), which destroys the axes this +manager tracks. Without this the figure keeps handing out axes that are no +longer attached to it.""" + ... + + @property + def gridspec(self) -> Incomplete: + """The single GridSpec used for all subplots in the figure.""" + ... + + @gridspec.setter + def gridspec(self, gs: Incomplete) -> None: + """The single GridSpec used for all subplots in the figure.""" + ... + + @staticmethod + def parse_backend(backend: Incomplete=None, basemap: Incomplete=None) -> Incomplete: + """Handle deprecation of basemap and cartopy package.""" + ... + + def parse_proj(self, proj: Incomplete=None, projection: Incomplete=None, proj_kw: Incomplete=None, projection_kw: Incomplete=None, backend: Incomplete=None, basemap: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Translate user-input projection into a registered matplotlib axes class.""" + ... + + def add_subplot(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """The driver function for adding single subplots.""" + ... + + def add_subplots(self, array: Incomplete=None, nrows: Incomplete=1, ncols: Incomplete=1, order: Incomplete='C', proj: Incomplete=None, projection: Incomplete=None, proj_kw: Incomplete=None, projection_kw: Incomplete=None, backend: Incomplete=None, basemap: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """The driver function for adding multiple subplots.""" + ... + + @property + def subplotgrid(self) -> Incomplete: + """A SubplotGrid of numbered subplots sorted by number.""" + ... diff --git a/ultraplot/_version.pyi b/ultraplot/_version.pyi new file mode 100644 index 000000000..362a9157c --- /dev/null +++ b/ultraplot/_version.pyi @@ -0,0 +1,3 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +__version__: str diff --git a/ultraplot/animation.pyi b/ultraplot/animation.pyi new file mode 100644 index 000000000..60312316c --- /dev/null +++ b/ultraplot/animation.pyi @@ -0,0 +1,263 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Fast drop-in replacements for the [matplotlib.animation](https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.html) classes. + +The classes here subclass their Matplotlib counterparts, so the constructor +signatures, the attributes, and the notebook representations are unchanged. +What differs is how frames are rendered: + +* [save](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.animation.FuncAnimation.html#ultraplot.animation.FuncAnimation.save) bypasses the per-frame + [savefig](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.savefig.html) call used by Matplotlib's writers and + instead renders straight into the Agg buffer, piping raw ``RGBA`` bytes to + the encoder. No PNG round-trip, no ``print_figure`` machinery. +* The expensive UltraPlot tight-layout pass runs once, for the first frame, + rather than on every frame. +* Blitting is used while saving, not just interactively, so only the artists + the update function returns are redrawn per frame. + +Everything falls back to Matplotlib's own implementation when the fast path +cannot be used (custom writer instances, ``bbox_inches``, vector output, and +so on), so the output is never silently wrong. +""" +from _typeshed import Incomplete +import itertools +import os +import subprocess +from contextlib import ExitStack, contextmanager, suppress +from tempfile import TemporaryFile +from pathlib import Path +import matplotlib as mpl +import matplotlib.animation as manimation +import numpy as np +from matplotlib import cbook +__all__ = ['FuncAnimation', 'ArtistAnimation'] +_FFMPEG_SUFFIXES = frozenset(('.mp4', '.m4v', '.mov', '.mkv', '.webm', '.avi', '.ogv', '.ogg') + ('.gif', '.webp', '.apng', '.avif')) +_PILLOW_SUFFIXES = frozenset(('.gif', '.webp', '.apng')) +_SUFFIX_CODECS = frozenset(('.gif', '.webp', '.apng', '.avif')) +_FAST_WRITERS = frozenset(('ffmpeg', 'pillow')) + +def _suffix(filename: Incomplete) -> Incomplete: + """Return the lowercase suffix of a path-like filename.""" + ... + +class _RawWriter: + """Base class for writers that consume raw ``RGBA`` frames. + +Subclasses implement `write`, `_close`, and `_discard`. The output file is +deleted unless `finish` completed, so an animation that fails halfway +through never leaves a truncated movie that looks like a whole one.""" + + def __init__(self, filename: Incomplete, fps: Incomplete) -> None: + ... + + def setup(self, width: Incomplete, height: Incomplete) -> Incomplete: + ... + + def write(self, buffer: Incomplete) -> Incomplete: + ... + + def _close(self) -> Incomplete: + ... + + def _discard(self) -> Incomplete: + ... + + def finish(self) -> Incomplete: + """Complete the file. Anything short of this counts as a failed save.""" + ... + + def cleanup(self) -> Incomplete: + """Release resources, and remove the output of an unfinished save.""" + ... + +class _RawFFMpegWriter(_RawWriter): + """Pipe raw ``RGBA`` frames into ``ffmpeg`` with no intermediate encoding.""" + + def __init__(self, filename: Incomplete, fps: Incomplete, *, codec: Incomplete=None, bitrate: Incomplete=None, extra_args: Incomplete=None, metadata: Incomplete=None) -> None: + ... + + @staticmethod + def available() -> Incomplete: + """Return whether the configured ``ffmpeg`` binary can be executed.""" + ... + + def _command(self) -> Incomplete: + ... + + def setup(self, width: Incomplete, height: Incomplete) -> Incomplete: + ... + + def _stderr_text(self) -> Incomplete: + ... + + def write(self, buffer: Incomplete) -> Incomplete: + ... + + def _close(self) -> Incomplete: + ... + + def _discard(self) -> Incomplete: + ... + +class _RawPillowWriter(_RawWriter): + """Collect raw ``RGBA`` frames and write an animated image with Pillow.""" + + def __init__(self, filename: Incomplete, fps: Incomplete) -> None: + ... + + def write(self, buffer: Incomplete) -> Incomplete: + ... + + def _close(self) -> Incomplete: + ... + + def _discard(self) -> Incomplete: + ... + +class _FastSaveMixin: + """The fast `save` path, shared by the animation classes. + +Subclasses supply the three frame hooks below; everything else here is the +machinery that renders those frames into a movie file.""" + + def _fast_frame_seq(self) -> Incomplete: + ... + + def _fast_frame_artists(self, frame: Incomplete) -> Incomplete: + ... + + def _fast_init_artists(self, frame: Incomplete) -> Incomplete: + ... + + @contextmanager + def _frozen_layout(self) -> Incomplete: + """Run the UltraPlot layout solver once instead of once per frame. + +UltraPlot recomputes tight layout whenever the figure is marked dirty. +During an animation the geometry must stay fixed anyway, or frames +would jitter, so the solver is switched off after the first draw. Yields +a function that marks the current layout as final.""" + ... + + @contextmanager + def _animated_artists(self, artists: Incomplete=()) -> Incomplete: + """Temporarily mark artists as animated so full draws skip them. + +Yields a function that marks further artists, for update functions that +return a different set of artists as the animation goes on.""" + ... + + @contextmanager + def _suspended_event_source(self) -> Incomplete: + """Keep the interactive timer from starting on the frames drawn here. + +[matplotlib.animation.Animation](https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.Animation.html) starts itself from the figure's first +``draw_event``. The draws below are for the movie file, not the screen.""" + ... + + @contextmanager + def _suspended_figure_blitting(self) -> Incomplete: + """Stand down the figure's own retained-draw machinery while saving. + +[savefig](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.savefig) does the same before printing. A live +[_BlitManager](https://ultraplot.readthedocs.io/en/stable/api/ultraplot._animation._BlitManager.html) keeps its artists flagged animated +and repaints them from a ``draw_event`` handler, which would fight the +frames drawn here.""" + ... + + @contextmanager + def _agg_canvas(self) -> Incomplete: + """Ensure the figure has a canvas that can blit and expose an RGBA buffer.""" + ... + + def _resolve_writer(self, filename: Incomplete, writer: Incomplete, savefig_kwargs: Incomplete, extra_anim: Incomplete) -> Incomplete: + """Return the name of the fast writer to use, or ``None`` for none. + +The fast path must pick the same writer Matplotlib would, or the same +call would produce a differently encoded file than before.""" + ... + + def _make_raw_writer(self, filename: Incomplete, writer: Incomplete, fps: Incomplete, codec: Incomplete, bitrate: Incomplete, extra_args: Incomplete, metadata: Incomplete) -> Incomplete: + """Return the raw-frame writer for the resolved writer name.""" + ... + + def _fast_save(self, filename: Incomplete, writer: Incomplete, fps: Incomplete, dpi: Incomplete, codec: Incomplete, bitrate: Incomplete, extra_args: Incomplete, metadata: Incomplete, progress_callback: Incomplete, blit: Incomplete) -> Incomplete: + """Render every frame straight into the Agg buffer and pipe it out.""" + ... + + def save(self, filename: Incomplete, writer: Incomplete=None, fps: Incomplete=None, dpi: Incomplete=None, codec: Incomplete=None, bitrate: Incomplete=None, extra_args: Incomplete=None, metadata: Incomplete=None, extra_anim: Incomplete=None, savefig_kwargs: Incomplete=None, *, progress_callback: Incomplete=None, fast: Incomplete=None, blit: Incomplete=None) -> Incomplete: + """Save the animation to a movie file. + +Parameters +---------- +- `filename`: The output file, e.g. +- `writer`: Same meaning as in [matplotlib.animation.Animation.save](https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.Animation.save.html). +- `fps`: Frames per second. +- `dpi`: Resolution of the saved frames. +- `codec, bitrate, extra_args, metadata`: Passed to the encoder, as in Matplotlib. +- `extra_anim`: Additional animations to composite. +- `savefig_kwargs`: Extra [savefig](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.savefig.html) arguments. +- `progress_callback`: Called as ``progress_callback(current_frame, total_frames)``. +- `fast`: Whether to use the fast renderer. +- `blit`: Whether to blit while saving.""" + ... + +class FuncAnimation(_FastSaveMixin, manimation.FuncAnimation): + """A faster drop-in replacement for [matplotlib.animation.FuncAnimation](https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.FuncAnimation.html). + +Parameters +---------- +- `fig`: The figure to animate. +- `func`: The update function, called as ``func(frame, *fargs)``. +- `frames`: Source of frame data, as in Matplotlib. +- `init_func`: Function drawing the clear frame. +- `fargs`: Extra positional arguments for `func` and `init_func`. +- `save_count`: Number of frames to cache from a generator. +- `blit`: Whether to redraw only the artists returned by `func`. +- `cache_frame_data`: Whether to cache frame data, as in Matplotlib. +- `**kwargs`: Passed to [matplotlib.animation.TimedAnimation](https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.TimedAnimation.html), e.g. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.animation.FuncAnimation.html)""" + + def __init__(self, fig: Incomplete, func: Incomplete, frames: Incomplete=None, init_func: Incomplete=None, fargs: Incomplete=None, save_count: Incomplete=None, *, blit: Incomplete=True, **kwargs: Incomplete) -> None: + """Initialize self. See help(type(self)) for accurate signature.""" + ... + + def _fast_frame_seq(self) -> Incomplete: + ... + + def _fast_init_artists(self, frame: Incomplete) -> Incomplete: + ... + + def _fast_frame_artists(self, frame: Incomplete) -> Incomplete: + ... + +class ArtistAnimation(_FastSaveMixin, manimation.ArtistAnimation): + """A faster drop-in replacement for [matplotlib.animation.ArtistAnimation](https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.ArtistAnimation.html). + +Frames are lists of artists that are made visible in turn. Saving uses the +same direct-to-buffer renderer as `FuncAnimation`. + +Parameters +---------- +fig : [Figure](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html) + The figure to animate. +artists : list of list of [Artist](https://matplotlib.org/stable/api/_as_gen/matplotlib.artist.Artist.html) + Each entry is the collection of artists making up one frame. +**kwargs + Passed to [matplotlib.animation.TimedAnimation](https://matplotlib.org/stable/api/_as_gen/matplotlib.animation.TimedAnimation.html). + +See also +-------- +matplotlib.animation.ArtistAnimation +ultraplot.animation.FuncAnimation""" + + def _fast_frame_seq(self) -> Incomplete: + ... + + def _fast_init_artists(self, frame: Incomplete) -> Incomplete: + ... + + def _fast_frame_artists(self, frame: Incomplete) -> Incomplete: + ... diff --git a/ultraplot/axes/__init__.pyi b/ultraplot/axes/__init__.pyi new file mode 100644 index 000000000..1a7c30814 --- /dev/null +++ b/ultraplot/axes/__init__.pyi @@ -0,0 +1,20 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The various axes classes used throughout ultraplot. +""" +from _typeshed import Incomplete +import matplotlib.projections as mproj +from ..internals import context +from .base import Axes +from .cartesian import CartesianAxes +from .container import ExternalAxesContainer +from .geo import GeoAxes, _BasemapAxes, _CartopyAxes +from .plot import PlotAxes +from .polar import PolarAxes +from .shared import _SharedAxes +from .taylor import TaylorAxes +from .three import ThreeAxes +__all__ = ['Axes', 'PlotAxes', 'CartesianAxes', 'PolarAxes', 'TaylorAxes', 'GeoAxes', 'ThreeAxes', 'ExternalAxesContainer'] +_cls_dict = {} +_cls_table = ... diff --git a/ultraplot/axes/_formatting.pyi b/ultraplot/axes/_formatting.pyi new file mode 100644 index 000000000..a2d65bf1c --- /dev/null +++ b/ultraplot/axes/_formatting.pyi @@ -0,0 +1,39 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Shared metadata for axis formatting keyword routing and persistence. +""" +from _typeshed import Incomplete +import inspect +_AXIS_STYLE_FIELD_TEMPLATES = {'color': ('{axis}color', 'color', '{axis}ec', 'ec', '{axis}edgecolor', 'edgecolor', 'axesec', 'axesedgecolor'), 'linewidth': ('{axis}linewidth', 'linewidth', '{axis}lw', 'lw', 'axeslw', 'axeslinewidth'), 'rotation': ('{axis}rotation', 'rotation'), 'spineloc': ('{axis}spineloc', '{axis}loc'), 'tickloc': ('{axis}tickloc',), 'ticklabelloc': ('{axis}ticklabelloc',), 'labelloc': ('{axis}labelloc',), 'offsetloc': ('{axis}offsetloc',), 'grid': ('{axis}grid',), 'gridminor': ('{axis}gridminor',), 'gridcolor': ('{axis}gridcolor', 'gridcolor'), 'tickdir': ('{axis}tickdir', 'tickdir'), 'tickcolor': ('{axis}tickcolor', 'tickcolor'), 'ticklen': ('{axis}ticklen', 'ticklen'), 'ticklenratio': ('{axis}ticklenratio', 'ticklenratio'), 'tickwidth': ('{axis}tickwidth', 'tickwidth'), 'tickwidthratio': ('{axis}tickwidthratio', 'tickwidthratio'), 'ticklabeldir': ('{axis}ticklabeldir', 'ticklabeldir'), 'ticklabelpad': ('{axis}ticklabelpad',), 'ticklabelcolor': ('{axis}ticklabelcolor', 'ticklabelcolor'), 'ticklabelsize': ('{axis}ticklabelsize', 'ticklabelsize'), 'ticklabelweight': ('{axis}ticklabelweight', 'ticklabelweight'), 'labelpad': ('{axis}labelpad',), 'labelcolor': ('{axis}labelcolor', 'labelcolor'), 'labelsize': ('{axis}labelsize', 'labelsize'), 'labelweight': ('{axis}labelweight', 'labelweight')} +_PAINT_ONLY_AXIS_STYLE_FIELDS = {'color', 'linewidth', 'grid', 'gridminor', 'gridcolor', 'tickcolor', 'tickwidth', 'tickwidthratio', 'ticklabelcolor', 'labelcolor'} + +def _dedupe(items: Incomplete) -> Incomplete: + ... +GENERIC_AXIS_FORMAT_KEYS = ... +PAINT_ONLY_AXIS_FORMAT_KEYS = ... +CARTESIAN_PARENT_FILTER_KEYS = GENERIC_AXIS_FORMAT_KEYS + ('label_kw', 'scale_kw', 'locator_kw', 'formatter_kw', 'minorlocator_kw') + +def axis_format_requires_layout(keys: Incomplete) -> bool: + """Return whether explicit Cartesian formatting keys can affect layout. + +Unknown keys are treated as layout-affecting so new formatting options +remain correct until they are deliberately classified.""" + ... + +def get_axis_style_fields(axis: Incomplete) -> dict[str, tuple[str, ...]]: + """Return the parameter names used to store explicit style overrides.""" + ... + +def _signature_param_names(*funcs: Incomplete) -> Incomplete: + ... + +def pop_axis_format_kwargs(kwargs: Incomplete, *funcs: Incomplete) -> Incomplete: + """Pop axis-format kwargs so they survive rc parsing. + +Returns +------- +tuple(dict, dict) + The signature-defined keyword arguments and the generic alias keyword + arguments that are not represented in the stored signatures.""" + ... diff --git a/ultraplot/axes/base.py b/ultraplot/axes/base.py index c08c93d41..39e64c1a6 100644 --- a/ultraplot/axes/base.py +++ b/ultraplot/axes/base.py @@ -87,24 +87,24 @@ # Projection docstring _proj_docstring = """ proj, projection : -str, `cartopy.crs.Projection`, or `~mpl_toolkits.basemap.Basemap`, optional +str, :class:`cartopy.crs.Projection`, or :class:`~mpl_toolkits.basemap.Basemap`, optional The map projection specification(s). If ``'cart'`` or ``'cartesian'`` - (the default), a `~ultraplot.axes.CartesianAxes` is created. If ``'polar'``, + (the default), a :class:`~ultraplot.axes.CartesianAxes` is created. If ``'polar'``, a :class:`~ultraplot.axes.PolarAxes` is created. Otherwise, the argument is - interpreted by `~ultraplot.constructor.Proj`, and the result is used - to make a `~ultraplot.axes.GeoAxes` (in this case the argument can be - a `cartopy.crs.Projection` instance, a `~mpl_toolkits.basemap.Basemap` + interpreted by :class:`~ultraplot.constructor.Proj`, and the result is used + to make a :class:`~ultraplot.axes.GeoAxes` (in this case the argument can be + a :class:`cartopy.crs.Projection` instance, a :class:`~mpl_toolkits.basemap.Basemap` instance, or a projection name listed in :ref:`this table `). """ _proj_kw_docstring = """ proj_kw, projection_kw : dict-like, optional - Keyword arguments passed to `~mpl_toolkits.basemap.Basemap` or - cartopy `~cartopy.crs.Projection` classes on instantiation. + Keyword arguments passed to :class:`~mpl_toolkits.basemap.Basemap` or + :class:`~cartopy.crs.Projection` classes on instantiation. """ _backend_docstring = """ backend : {'cartopy', 'basemap'}, default: :rc:`geo.backend` - Whether to use `~mpl_toolkits.basemap.Basemap` or - `~cartopy.crs.Projection` for map projections. + Whether to use :class:`~mpl_toolkits.basemap.Basemap` or + :class:`~cartopy.crs.Projection` for map projections. .. deprecated:: 3.0.0 The ``'basemap'`` backend is deprecated and may be removed in a @@ -615,7 +615,7 @@ group of artists, the tuple group is expanded into unique legend entries -- otherwise, the tuple group elements are drawn on top of eachother). For details on matplotlib legend handlers and tuple groups, see the matplotlib `legend guide --`__. +`__. """ _legend_kwargs_docstring = """ frame, frameon : bool, optional diff --git a/ultraplot/axes/base.pyi b/ultraplot/axes/base.pyi new file mode 100644 index 000000000..28425d220 --- /dev/null +++ b/ultraplot/axes/base.pyi @@ -0,0 +1,1056 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The first-level axes subclass used for all ultraplot figures. +Implements basic shared functionality. +""" +from _typeshed import Incomplete +import contextlib +import copy +import inspect +import re +import sys +import types +from collections.abc import Iterable as IterableType +from numbers import Integral, Number +from typing import Any, Iterable, MutableMapping, Optional, Tuple, Union +try: + from typing import override +except ImportError: + from typing_extensions import override +import matplotlib.axes as maxes +import matplotlib.axis as maxis +import matplotlib.cm as mcm +import matplotlib.colors as mcolors +import matplotlib.container as mcontainer +import matplotlib.contour as mcontour +import matplotlib.offsetbox as moffsetbox +import matplotlib.patches as mpatches +import matplotlib.projections as mproj +import matplotlib.text as mtext +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +import numpy as np +from matplotlib import cbook +from packaging import version +from .. import colors as pcolors +from .. import constructor +from .. import legend as plegend +from .. import ticker as pticker +from ..colorbar import UltraColorbar, _anchor_inset_colorbar_bounds, _apply_inset_colorbar_layout, _determine_label_rotation, _get_axis_for, _get_colorbar_long_axis, _legacy_inset_colorbar_bounds, _reflow_inset_colorbar_frame, _register_inset_colorbar_reflow, _solve_inset_colorbar_bounds +from ..config import rc +from ..internals import _kwargs_to_args, _not_none, _pop_kwargs, _pop_params, _pop_props, _pop_rc, _translate_loc, _version_mpl, docstring, guides, ic, labels, rcsetup, warnings +from ..ultralayout import KIWI_AVAILABLE, ColorbarLayoutSolver +from ..utils import _fontsize_to_pt, edges, units +try: + from cartopy.crs import CRS, PlateCarree +except Exception: + CRS = PlateCarree = object +__all__ = ['Axes'] +ABC_STRING = 'abcdefghijklmnopqrstuvwxyz' +_proj_docstring = ... +_proj_kw_docstring = ... +_backend_docstring = ... +_space_docstring = ... +_transform_docstring = ... +_inset_docstring = ... +_indicate_inset_docstring = ... +_panel_loc_docstring = ... +_panel_docstring = ... +_axes_format_docstring = ... +_figure_format_docstring = ... +_rc_init_docstring = ... +_rc_format_docstring = ... +_colorbar_args_docstring = ... +_colorbar_kwargs_docstring = ... +_edgefix_docstring = ... +_legend_args_docstring = ... +_legend_kwargs_docstring = ... + +def _align_bbox(align: Incomplete, length: Incomplete) -> Incomplete: + """Return a simple alignment bounding box for intersection calculations.""" + ... + +def _get_side_colorbar_ticklocation(side: Incomplete, orientation: Incomplete, tickloc: Incomplete, ticklocation: Incomplete, *, orientation_explicit: Incomplete=False) -> Incomplete: + """Return the outward-facing tick location for a side colorbar.""" + ... + +def _convert_side_colorbar_units(axes: Incomplete, orientation: Incomplete, length: Incomplete, width: Incomplete, pad: Incomplete) -> Incomplete: + """Convert side colorbar dimensions to axes-relative units.""" + ... + +def _get_side_colorbar_bounds(side: Incomplete, align: Incomplete, length: Incomplete, width: Incomplete, xpad: Incomplete, ypad: Incomplete) -> Incomplete: + """Return axes-relative bounds for a side colorbar.""" + ... + +def _get_filled_colorbar_bounds(side: Incomplete, align: Incomplete, length: Incomplete) -> Incomplete: + """Return panel-relative bounds for a side colorbar.""" + ... + +def _get_colorbar_aligned_position(side: Incomplete, align: Incomplete, length: Incomplete) -> Incomplete: + """Validate colorbar alignment and return its long-axis start position.""" + ... + +class _TransformedBoundsLocator: + """Axes locator for `~Axes.inset_axes` and other axes.""" + + def __init__(self, bounds: Incomplete, transform: Incomplete) -> None: + ... + + def __call__(self, ax: Incomplete, renderer: Incomplete) -> Incomplete: + ... + +class _AspectAwareTransformedBoundsLocator(_TransformedBoundsLocator): + """Preserve an inset's lower-left anchor after box-aspect adjustment.""" + + def __call__(self, ax: Incomplete, renderer: Incomplete) -> Incomplete: + ... + +class _SideColorbarLocator: + """Position a side colorbar beyond its parent axes decorations.""" + + def __init__(self, parent: Incomplete, side: Incomplete, bounds: Incomplete, pad: Incomplete, previous: Incomplete=()) -> None: + ... + + def __call__(self, ax: Incomplete, renderer: Incomplete) -> Incomplete: + ... + +class _ExternalModeMixin: + """Mixin providing explicit external-mode control and a context manager.""" + + def set_external(self, value: Incomplete=True) -> Incomplete: + """Set explicit external-mode override for this axes. + +value: + - True: force external behavior (defer on-the-fly guides, etc.) + - False: force UltraPlot behavior""" + ... + + class _ExternalContext: + + def __init__(self, ax: Incomplete, value: Incomplete=True) -> None: + ... + + def __enter__(self) -> Incomplete: + ... + + def __exit__(self, exc_type: Incomplete, exc: Incomplete, tb: Incomplete) -> Incomplete: + ... + + def external(self, value: Incomplete=True) -> Incomplete: + """Context manager toggling external mode during the block.""" + ... + + def _in_external_context(self) -> Incomplete: + """Return True if UltraPlot helper behaviors should be suppressed.""" + ... + +class Axes(_ExternalModeMixin, maxes.Axes): + """The lowest-level [Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html) subclass used by ultraplot. +Implements basic universal features.""" + _name = None + _name_aliases = () + _make_inset_locator = _TransformedBoundsLocator + + def __repr__(self) -> str: + """Return repr(self).""" + ... + + def __str__(self) -> str: + """Return str(self).""" + ... + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `*args`: Passed to [matplotlib.axes.Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html). +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- `abcloc, titleloc`: Strings indicating the location for the a-b-c label and main title. +- `abcborder, titleborder`: Whether to draw a white border around titles and a-b-c labels positioned inside the axes. +- `abcbbox, titlebbox`: Whether to draw a white bbox around titles and a-b-c labels positioned inside the axes. +- `abcpad`: Horizontal offset to shift the a-b-c label position. +- `abc_kw, title_kw`: Additional settings used to update the a-b-c label and title with ``text.update()``. +- `titlepad`: The padding for the inner and outer titles and a-b-c labels. +- `titleabove`: Whether to try to put outer titles and a-b-c labels above panels, colorbars, or legends that are above the axes. +- `abctitlepad`: The horizontal padding between a-b-c labels and titles in the same location. +- `ltitle, ctitle, rtitle, ultitle, uctitle, urtitle, lltitle, lctitle, lrtitle`: Shorthands for the below keywords. +- `lowerlefttitle, lowercentertitle, lowerrighttitle`: Additional titles in specific positions (see `title` for details). +- `a, alpha, fc, facecolor, ec, edgecolor, lw, linewidth, ls, linestyle`: [axes.alpha](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.alpha) (default: 1.0), [axes.facecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.facecolor) (default: white), [axes.edgecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.edgecolor) (default: black), [axes.linewidth](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.linewidth) (default: 0.6), - Additional settings applied to… +- `rc_mode`: The context mode passed to [context](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.context). +- `rc_kw`: An alternative to passing extra keyword arguments. +- `**kwargs`: Remaining keyword arguments are passed to [matplotlib.axes.Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html).\\n Keyword arguments that match the name of an [rc](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.rc.html) setting are passed to… + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html)""" + ... + + def _add_inset_axes(self, bounds: Incomplete, transform: Incomplete=None, *, proj: Incomplete=None, projection: Incomplete=None, zoom: Incomplete=None, zoom_kw: Incomplete=None, zorder: Incomplete=None, **kwargs: Incomplete) -> Axes: + """Add an inset axes using arbitrary projection.""" + ... + + def _add_queued_guides(self) -> None: + """Draw the queued-up legends and colorbars. Wrapper funcs and legend func let +user add handles to location lists with successive calls.""" + ... + + def _add_guide_frame(self, xmin: Incomplete, ymin: Incomplete, width: Incomplete, height: Incomplete, *, fontsize: Incomplete, fancybox: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add a colorbar or multilegend frame.""" + ... + + def _add_guide_panel(self, loc: str='fill', align: str='center', length: Union[float, str]=0, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, **kwargs: Incomplete) -> 'Axes': + """Add a panel to be filled by an "outer" colorbar or legend.""" + ... + + def _add_colorbar(self, mappable: Incomplete, values: Incomplete=None, *, loc: Optional[str]=None, align: Optional[str]=None, space: Optional[Union[float, str]]=None, pad: Optional[Union[float, str]]=None, width: Optional[Union[float, str]]=None, length: Optional[Union[float, str]]=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, shrink: Optional[Union[float, str]]=None, label: Incomplete=None, title: Incomplete=None, reverse: Incomplete=False, rotation: Incomplete=None, grid: Incomplete=None, edges: Incomplete=None, drawedges: Incomplete=None, extend: Incomplete=None, extendsize: Incomplete=None, extendfrac: Incomplete=None, ticks: Incomplete=None, locator: Incomplete=None, locator_kw: Incomplete=None, format: Incomplete=None, formatter: Incomplete=None, ticklabels: Incomplete=None, formatter_kw: Incomplete=None, minorticks: Incomplete=None, minorlocator: Incomplete=None, minorlocator_kw: Incomplete=None, tickminor: Incomplete=None, ticklen: Incomplete=None, ticklenratio: Incomplete=None, tickdir: Incomplete=None, tickdirection: Incomplete=None, tickwidth: Incomplete=None, tickwidthratio: Incomplete=None, ticklabelsize: Incomplete=None, ticklabelweight: Incomplete=None, ticklabelcolor: Incomplete=None, labelloc: Incomplete=None, labellocation: Incomplete=None, labelsize: Incomplete=None, labelweight: Incomplete=None, labelcolor: Incomplete=None, c: Incomplete=None, color: Incomplete=None, lw: Incomplete=None, linewidth: Incomplete=None, edgefix: Incomplete=None, rasterized: Incomplete=None, frame: Optional[bool]=None, frameon: Optional[bool]=None, outline: Union[bool, None]=None, labelrotation: Union[str, float]=None, center_levels: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + ... + + def _add_legend(self, handles: Incomplete=None, labels: Incomplete=None, *, loc: Incomplete=None, align: Incomplete=None, width: Incomplete=None, pad: Incomplete=None, space: Incomplete=None, frame: Incomplete=None, frameon: Incomplete=None, ncol: Incomplete=None, ncols: Incomplete=None, alphabetize: Incomplete=False, center: Incomplete=None, order: Incomplete=None, label: Incomplete=None, title: Incomplete=None, fontsize: Incomplete=None, fontweight: Incomplete=None, fontcolor: Incomplete=None, titlefontsize: Incomplete=None, titlefontweight: Incomplete=None, titlefontcolor: Incomplete=None, handle_kw: Incomplete=None, handler_map: Incomplete=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, **kwargs: Incomplete) -> Incomplete: + ... + + def _apply_title_above(self) -> None: + """Change assignment of outer titles between main subplot and upper panels. +This is called when a panel is created or `_update_title` is called.""" + ... + + def _apply_auto_share(self) -> None: + """Automatically configure axis sharing based on the horizontal and +vertical extent of subplots in the figure gridspec.""" + ... + + def _artist_fully_clipped(self, artist: Incomplete) -> Incomplete: + """Return a boolean flag, ``True`` if the artist is clipped to the axes +and can thus be skipped in layout calculations.""" + ... + + def _format_inset(self, bounds: tuple[float, float, float, float], parent: 'Axes', **kwargs: Incomplete) -> Incomplete: + ... + + def __format_inset(self, bounds: tuple[float, float, float, float], parent: 'Axes', **kwargs: Incomplete) -> Incomplete: + ... + + def __format_inset_legacy(self, bounds: tuple[float, float, float, float], parent: 'Axes', **kwargs: Incomplete) -> tuple[mpatches.Rectangle, list[mpatches.ConnectionPatch]]: + ... + + def _get_legend_handles(self, handler_map: Incomplete=None) -> Incomplete: + """Internal implementation of matplotlib's ``get_legend_handles_labels``.""" + ... + + def _get_share_axes(self, sx: Incomplete, panels: Incomplete=False) -> Incomplete: + """Return the axes whose horizontal or vertical extent in the main gridspec +matches the horizontal or vertical extent of this axes.""" + ... + + def _get_span_axes(self, side: Incomplete, panels: Incomplete=False) -> Incomplete: + """Return the axes whose left, right, top, or bottom sides abutt against +the same row or column as this axes. Deflect to shared panels.""" + ... + + def _get_size_inches(self) -> Incomplete: + """Return the width and height of the axes in inches.""" + ... + + def _get_topmost_axes(self) -> Incomplete: + """Return the topmost axes including panels and parents.""" + ... + + def _get_transform(self, transform: Incomplete, default: Incomplete='data') -> Incomplete: + """Translates user input transform. Also used in an axes method.""" + ... + + def _parse_anchor(self, coordinates: Incomplete, transform: Incomplete=None, default: Incomplete='data') -> Incomplete: + """Parse coordinates and their transform. + +Coordinates can be passed with the transform separately or packaged as +a ``(coordinates, transform)`` tuple. The latter is useful for APIs +that accept a single anchor argument, such as ``inset_axes``.""" + ... + + def _register_guide(self, guide: Incomplete, obj: Incomplete, key: Incomplete, **kwargs: Incomplete) -> None: + """Queue up or replace objects for legends and list-of-artist style colorbars.""" + ... + + def _update_guide(self, objs: Incomplete, legend: Incomplete=None, legend_kw: Incomplete=None, queue_legend: Incomplete=True, colorbar: Incomplete=None, colorbar_kw: Incomplete=None, queue_colorbar: Incomplete=True) -> None: + """Update queues for on-the-fly legends and colorbars or track keyword arguments.""" + ... + + @staticmethod + def _parse_frame(guide: Incomplete, fancybox: Incomplete=None, shadow: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Parse frame arguments.""" + ... + + @staticmethod + def _parse_colorbar_arg(mappable: Incomplete, values: Incomplete=None, norm: Incomplete=None, norm_kw: Incomplete=None, vmin: Incomplete=None, vmax: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Generate a mappable from flexible non-mappable input. Useful in bridging +the gap between legends and colorbars (e.g., creating colorbars from line +objects whose data values span a natural colormap range).""" + ... + + def _parse_colorbar_filled(self, length: Incomplete=None, align: Incomplete=None, tickloc: Incomplete=None, ticklocation: Incomplete=None, orientation: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return the axes and adjusted keyword args for a panel-filling colorbar.""" + ... + + def _parse_colorbar_inset(self, loc: Incomplete=None, bbox_to_anchor: Incomplete=None, width: Incomplete=None, length: Incomplete=None, shrink: Incomplete=None, frame: Incomplete=None, frameon: Incomplete=None, label: Incomplete=None, labelsize: Incomplete=None, pad: Incomplete=None, tickloc: Incomplete=None, ticklocation: Incomplete=None, orientation: Incomplete=None, labelloc: Incomplete=None, labelrotation: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return the axes and adjusted keyword args for an inset colorbar.""" + ... + + def _add_colorbar_child_axes(self, bounds: Incomplete, locator: Incomplete=None, track_parent: Incomplete=True) -> Axes: + """Add and return a colorbar axes positioned relative to this axes.""" + ... + + def _parse_colorbar_inset_side(self, loc: Incomplete=None, align: Incomplete=None, width: Incomplete=None, length: Incomplete=None, shrink: Incomplete=None, space: Incomplete=None, pad: Incomplete=None, tickloc: Incomplete=None, ticklocation: Incomplete=None, orientation: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return the axes and adjusted keyword args for a side colorbar on an inset axes.""" + ... + + def _parse_legend_aligned(self, pairs: Incomplete, ncol: Incomplete=None, order: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Draw an individual legend with aligned columns. Includes support +for switching legend-entries between column-major and row-major.""" + ... + + def _parse_legend_centered(self, pairs: Incomplete, *, fontsize: Incomplete, loc: Incomplete=None, title: Incomplete=None, frameon: Incomplete=None, kw_frame: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Draw "legend" with centered rows by creating separate legends for +each row. The label spacing/border spacing will be exactly replicated.""" + ... + + @staticmethod + def _parse_legend_group(handles: Incomplete, labels: Incomplete=None, handler_map: Incomplete=None) -> Incomplete: + """Parse possibly tuple-grouped input handles.""" + ... + + def _parse_legend_handles(self, handles: Incomplete, labels: Incomplete, ncol: Incomplete=None, order: Incomplete=None, center: Incomplete=None, alphabetize: Incomplete=None, handler_map: Incomplete=None) -> Incomplete: + """Parse input handles and labels.""" + ... + + def _range_subplotspec(self, s: Incomplete) -> Incomplete: + """Return the column or row range for the subplotspec.""" + ... + + def _range_tightbbox(self, s: Incomplete) -> Incomplete: + """Return the tight bounding box span from the cached bounding box.""" + ... + + def _unshare(self, *, which: str) -> None: + """Remove this Axes from the shared Grouper for the given axis ('x', 'y', 'z', or 'view'). +Note this isolates the axis and does not preserve the transitivity of sharing.""" + ... + + def _sharex_setup(self, sharex: Incomplete, **kwargs: Incomplete) -> None: + """Configure x-axis sharing for panels. See also `~CartesianAxes._sharex_setup`.""" + ... + + def _sharey_setup(self, sharey: Incomplete, **kwargs: Incomplete) -> None: + """Configure y-axis sharing for panels. See also `~CartesianAxes._sharey_setup`.""" + ... + + def _share_short_axis(self, share: Incomplete, side: Incomplete, **kwargs: Incomplete) -> None: + """Share the "short" axes of panels in this subplot with other panels.""" + ... + + def _share_long_axis(self, share: Incomplete, side: Incomplete, **kwargs: Incomplete) -> None: + """Share the "long" axes of panels in this subplot with other panels.""" + ... + + def _reposition_subplot(self) -> None: + """Reposition the subplot axes.""" + ... + + def _update_abc(self, **kwargs: Incomplete) -> None: + """Update the a-b-c label.""" + ... + + def _update_outer_abc_loc(self, loc: Incomplete) -> None: + """For the outer labels, we need to align them vertically and create the +offset based on the tick length and the tick label. This function loops +through all axes in the figure to find maximum tick length and label size +and transforms the position accordingly.""" + ... + + def _update_title(self, loc: Incomplete, title: Incomplete=None, **kwargs: Incomplete) -> None: + """Update the title at the specified location.""" + ... + + def _update_title_position(self, renderer: Incomplete) -> None: + """Update the position of inset titles and outer titles. This is called +by matplotlib at drawtime.""" + ... + + def _update_super_title(self, suptitle: Incomplete=None, **kwargs: Incomplete) -> None: + """Update the figure super title.""" + ... + + def _update_super_labels(self, side: Incomplete, labels: Incomplete=None, **kwargs: Incomplete) -> None: + """Update the figure super labels.""" + ... + + @staticmethod + def get_center_of_axes(axes: Incomplete=None) -> Incomplete: + ... + + def _update_share_labels(self, axes: Incomplete=None, target: Incomplete='x') -> None: + """Update shared axis labels for a group of axes. + +Parameters +---------- +axes : list of int or list of Axes, optional + The axes indices or Axes objects to share labels between +target : {'x', 'y'}, optional + Which axis labels to share ('x' for x-axis, 'y' for y-axis)""" + ... + + def format(self, *, title: Incomplete=None, title_kw: Incomplete=None, abc_kw: Incomplete=None, ltitle: Incomplete=None, lefttitle: Incomplete=None, ctitle: Incomplete=None, centertitle: Incomplete=None, rtitle: Incomplete=None, righttitle: Incomplete=None, ultitle: Incomplete=None, upperlefttitle: Incomplete=None, uctitle: Incomplete=None, uppercentertitle: Incomplete=None, urtitle: Incomplete=None, upperrighttitle: Incomplete=None, lltitle: Incomplete=None, lowerlefttitle: Incomplete=None, lctitle: Incomplete=None, lowercentertitle: Incomplete=None, lrtitle: Incomplete=None, lowerrighttitle: Incomplete=None, share_xlabels: Incomplete=None, share_ylabels: Incomplete=None, **kwargs: Incomplete) -> None: + """Modify the a-b-c label, axes title(s), and background patch, and call [ultraplot.figure.Figure.format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.format) on the axes figure. + +Parameters +---------- +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- `abcloc, titleloc`: Strings indicating the location for the a-b-c label and main title. +- `abcborder, titleborder`: Whether to draw a white border around titles and a-b-c labels positioned inside the axes. +- `abcbbox, titlebbox`: Whether to draw a white bbox around titles and a-b-c labels positioned inside the axes. +- `abcpad`: Horizontal offset to shift the a-b-c label position. +- `abc_kw, title_kw`: Additional settings used to update the a-b-c label and title with ``text.update()``. +- `titlepad`: The padding for the inner and outer titles and a-b-c labels. +- `titleabove`: Whether to try to put outer titles and a-b-c labels above panels, colorbars, or legends that are above the axes. +- `abctitlepad`: The horizontal padding between a-b-c labels and titles in the same location. +- `ltitle, ctitle, rtitle, ultitle, uctitle, urtitle, lltitle, lctitle, lrtitle`: Shorthands for the below keywords. +- `lowerlefttitle, lowercentertitle, lowerrighttitle`: Additional titles in specific positions (see `title` for details). +- `a, alpha, fc, facecolor, ec, edgecolor, lw, linewidth, ls, linestyle`: [axes.alpha](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.alpha) (default: 1.0), [axes.facecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.facecolor) (default: white), [axes.edgecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.edgecolor) (default: black), [axes.linewidth](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.linewidth) (default: 0.6), - Additional settings applied to… +- `leftlabels, toplabels, rightlabels, bottomlabels`: Labels for the subplots lying along the left, top, right, and bottom edges of the figure. +- `leftlabelpad, toplabelpad, rightlabelpad, bottomlabelpad`: : [leftlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.pad), [toplabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.pad), [rightlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.pad), [bottomlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.pad) The padding between the labels and the axes content. +- `leftlabelsharedpad, toplabelsharedpad, rightlabelsharedpad, bottomlabelsharedpad`: : [leftlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.sharedpad), [toplabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.sharedpad), [rightlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.sharedpad), [bottomlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.sharedpad) The padding between side labels and a shared spanning axis label on… +- `leftlabels_kw, toplabels_kw, rightlabels_kw, bottomlabels_kw`: Additional settings used to update the labels with ``text.update()``. +- `figtitle`: Alias for `suptitle`. +- `suptitle`: The figure "super" title, centered between the left edge of the leftmost subplot and the right edge of the rightmost subplot. +- `suptitlepad`: The padding between the super title and the axes content. +- `suptitle_kw`: Additional settings used to update the super title with ``text.update()``. +- `includepanels`: Whether to include panels when aligning figure "super titles" along the top of the subplot grid and when aligning the `spanx` *x* axis labels and `spany` *y* axis labels along the… +- `rc_mode`: The context mode passed to [context](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.context). +- `rc_kw`: An alternative to passing extra keyword arguments. +- `**kwargs`: Keyword arguments that match the name of an [rc](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.rc.html) setting are passed to [ultraplot.config.Configurator.context](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.context) and used to update the axes. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.format)""" + ... + + def draw(self, renderer: Incomplete=None, *args: Incomplete, **kwargs: Incomplete) -> None: + """Draw the Artist (and its children) using the given renderer. + +This has no effect if the artist is not visible (`.Artist.get_visible` +returns False). + +Parameters +---------- +renderer : [RendererBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.RendererBase.html) subclass. + +Notes +----- +This method is overridden in the Artist subclasses.""" + ... + + def get_tightbbox(self, renderer: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """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` subclass + 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 : bool, 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. + +for_layout_only : default: False + The bounding box will *not* include the x-extent of the title and + the xlabel, or the y-extent of the ylabel. + +Returns +------- +`.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""" + ... + + def get_default_bbox_extra_artists(self) -> Incomplete: + """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)``.""" + ... + + def set_prop_cycle(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Set the property cycle of the Axes. + +Parameters +---------- +- `cycler`: Set the given Cycler. +- `label`: The property key. +- `values`: Finite-length iterable of the property values. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.set_prop_cycle)""" + ... + + def _is_panel_group_member(self, other: 'Axes') -> bool: + """Determine if the current axes and another axes belong to the same panel group. + +Two axes belong to the same panel group if any of the following is true: +1. One axis is the parent of the other +2. Both axes are panels sharing the same parent + +Parameters +---------- +other : Axes + The other axes to compare with + +Returns +------- +bool + True if both axes belong to the same panel group, False otherwise""" + ... + + def _label_key(self, side: str) -> str: + """Map requested side name to the correct tick_params key across mpl versions. + +This accounts for the API change around Matplotlib 3.10 where labeltop/labelbottom +became first-class tick parameter keys. For older versions, these map to +labelright/labelleft respectively.""" + ... + + def _is_ticklabel_on(self, side: str) -> bool: + """Check if tick labels are on for the specified sides.""" + ... + + def inset(self, *args: Incomplete, **kwargs: Incomplete) -> Axes: + """Add an inset axes. + +Parameters +---------- +- `bounds`: The (left, bottom, width, height) coordinates for the axes. +- `transform`: The transform used to interpret the bounds. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `zorder`: The [zorder](https://matplotlib.org/stable/gallery/misc/zorder_demo.html) of the axes. +- `zoom`: Whether to draw lines indicating the inset zoom using `~Axes.indicate_inset_zoom`. +- `zoom_kw`: Passed to `~Axes.indicate_inset_zoom`. +- `**kwargs`: Passed to [ultraplot.axes.Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.inset)""" + ... + + def inset_axes(self, *args: Incomplete, **kwargs: Incomplete) -> Axes: + """Add an inset axes. + +Parameters +---------- +- `bounds`: The (left, bottom, width, height) coordinates for the axes. +- `transform`: The transform used to interpret the bounds. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `zorder`: The [zorder](https://matplotlib.org/stable/gallery/misc/zorder_demo.html) of the axes. +- `zoom`: Whether to draw lines indicating the inset zoom using `~Axes.indicate_inset_zoom`. +- `zoom_kw`: Passed to `~Axes.indicate_inset_zoom`. +- `**kwargs`: Passed to [ultraplot.axes.Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.inset_axes)""" + ... + + @override + def indicate_inset_zoom(self, **kwargs: Incomplete) -> Incomplete: + """Add indicators denoting the zoom range of the inset axes. +This will replace previously drawn zoom indicators. + +Parameters +----------- +linewidth : unit-spec, default: [patch.linewidth](https://ultraplot.readthedocs.io/en/stable/search.html?q=patch.linewidth) + The edge width of the patch(es). Aliases: ``lw``, ``linewidths``. + If float, units are points. If string, interpreted by [units](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.utils.units.html). +linestyle : str, default: '-' + The edge style of the patch(es). Aliases: ``ls``, ``linestyles``. +edgecolor : color-spec, default: 'none' + The edge color of the patch(es). Aliases: ``ec``, ``edgecolors``. +facecolor : color-spec, optional + The face color of the patch(es). The property `cycle` is used by default. Aliases: ``fc``, ``facecolors``, ``fillcolor``, ``fillcolors``. +alpha : float, optional + The opacity of the patch(es). Inferred from `facecolor` and `edgecolor` by default. Aliases: ``a``, ``alphas``. +zorder : float, default: 3.5 + The [zorder](https://matplotlib.org/stable/gallery/misc/zorder_demo.html) of + the indicators. Should be greater than the zorder of elements in the parent axes. + +Other parameters +----------------- +**kwargs + Passed to [Patch](https://matplotlib.org/stable/api/_as_gen/matplotlib.patches.Patch.html). + +Note +----- +This command must be called from the inset axes rather than the parent axes. +It is called automatically when ``zoom=True`` is passed to `~Axes.inset_axes` +and whenever the axes are drawn (so the line positions always track the axis +limits even if they are later changed). + +See also +--------- +matplotlib.axes.Axes.indicate_inset +matplotlib.axes.Axes.indicate_inset_zoom""" + ... + + def panel(self, side: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add a panel axes. + +Parameters +---------- +- `side`: The panel location. +- `width`: The panel width. +- `space`: The fixed space between the panel and the subplot edge. +- `pad`: The [tight layout padding](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) between the panel and the subplot. +- `span`: Integer(s) indicating the span of the panel across rows and columns of subplots. +- `share`: Whether to enable axis sharing between the *x* and *y* axes of the main subplot and the panel long axes for each panel in the "stack". +- `**kwargs`: Passed to [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.panel)""" + ... + + def panel_axes(self, side: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add a panel axes. + +Parameters +---------- +- `side`: The panel location. +- `width`: The panel width. +- `space`: The fixed space between the panel and the subplot edge. +- `pad`: The [tight layout padding](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) between the panel and the subplot. +- `span`: Integer(s) indicating the span of the panel across rows and columns of subplots. +- `share`: Whether to enable axis sharing between the *x* and *y* axes of the main subplot and the panel long axes for each panel in the "stack". +- `**kwargs`: Passed to [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.panel_axes)""" + ... + + def colorbar(self, mappable: Incomplete, values: Incomplete=None, loc: Incomplete=None, location: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add an inset colorbar or an outer colorbar along the edge of the axes. + +Parameters +---------- +- `space`: For outer colorbars only. +- `pad`: For outer colorbars, this is the [tight layout padding](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) between the colorbar and the subplot (default is [subplots.panelpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=subplots.panelpad)). +- `align`: For outer colorbars only. +- `norm`: Ignored if `mappable` is a [ScalarMappable](https://matplotlib.org/stable/api/_as_gen/matplotlib.cm.ScalarMappable.html). +- `norm_kw`: Ignored if `mappable` is a [ScalarMappable](https://matplotlib.org/stable/api/_as_gen/matplotlib.cm.ScalarMappable.html). +- `vmin, vmax`: Ignored if `mappable` is a [ScalarMappable](https://matplotlib.org/stable/api/_as_gen/matplotlib.cm.ScalarMappable.html). +- `label, title`: The colorbar label. +- `reverse`: Whether to reverse the direction of the colorbar. +- `rotation`: The tick label rotation. +- `grid, edges, drawedges`: Whether to draw "grid" dividers between each distinct color. +- `extend`: Direction for drawing colorbar "extensions" (i.e. +- `extendfrac`: The length of the colorbar "extensions" relative to the length of the colorbar. +- `extendsize`: The length of the colorbar "extensions" in physical units. +- `extendrect`: Whether to draw colorbar "extensions" as rectangles. +- `locator, ticks`: Used to determine the colorbar tick positions. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `minorlocator_kw`: As with `locator_kw`, but for the minor ticks. +- `format, formatter, ticklabels`: The tick label format. +- `formatter_kw`: Keyword arguments passed to [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `frame, frameon`: For inset colorbars, indicates whether to draw a background "frame", just like [legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html). +- `tickminor`: Whether to add minor ticks using [minorticks_on](https://matplotlib.org/stable/api/_as_gen/matplotlib.colorbar.ColorbarBase.minorticks_on.html). +- `tickloc, ticklocation`: Where to draw tick marks on the colorbar. +- `tickdir, tickdirection`: Direction of major and minor colorbar ticks. +- `ticklen`: Major tick lengths for the colorbar ticks. +- `ticklenratio`: Relative scaling of `ticklen` used to determine minor tick lengths. +- `tickwidth`: Major tick widths for the colorbar ticks. +- `tickwidthratio`: Relative scaling of `tickwidth` used to determine minor tick widths. +- `ticklabelcolor, ticklabelsize, ticklabelweight`: The font color, size, and weight for colorbar tick labels +- `labelloc, labellocation`: The colorbar label location. +- `labelcolor, labelsize, labelweight`: The font color, size, and weight for the colorbar label. +- `a, alpha, framealpha, fc, facecolor, framecolor, ec, edgecolor, ew, edgewidth`: For inset colorbars only. +- `lw, linewidth, c, color`: Controls the line width and edge color for both the colorbar outline and the level dividers. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `rasterize`: Whether to rasterize the colorbar solids. +- `outline`: Controls the visibility of the outer colorbar outline. +- `labelrotation`: Controls the rotation of the colorbar label. +- _1 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar)""" + ... + + def legend(self, handles: Incomplete=None, labels: Incomplete=None, loc: Incomplete=None, location: Incomplete=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, **kwargs: Incomplete) -> Incomplete: + """Add an inset legend or outer legend along the edge of the axes. + +Parameters +---------- +- `handles`: List of matplotlib artists, or a list of lists of artist instances (see the `center` keyword). +- `labels`: A matching list of string labels or ``None`` placeholders, or a matching list of lists (see the `center` keyword). +- `loc, location`: The legend location. +- `width`: For outer legends only. +- `queue`: If ``True`` and `loc` is the same as an existing legend, the input arguments are added to a queue and this function returns ``None``. +- `space`: For outer legends only. +- `pad`: For outer legends, this is the [tight layout padding](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) between the legend and the subplot (default is [subplots.panelpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=subplots.panelpad)). +- `align`: For outer legends only. +- `frame, frameon`: Toggles the legend frame. +- `ncol, ncols`: The number of columns. +- `order`: Whether legend handles are drawn in row-major (``'C'``) or column-major (``'F'``) order. +- `center`: Whether to center each legend row individually. +- `alphabetize`: Whether to alphabetize the legend entries according to the legend labels. +- `title, label`: The legend title. +- `fontsize, fontweight, fontcolor`: The font size, weight, and color for the legend text. +- `titlefontsize, titlefontweight, titlefontcolor`: The font size, weight, and color for the legend title. +- `borderpad, borderaxespad, handlelength, handleheight, handletextpad, labelspacing, columnspacing`: Various matplotlib [legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html) spacing arguments. +- `a, alpha, framealpha, fc, facecolor, framecolor, ec, edgecolor, ew, edgewidth`: See the full API documentation. +- `c, color, lw, linewidth, m, marker, ls, linestyle, dashes, ms, markersize`: Properties used to override the legend handles. +- `handle_kw`: Additional properties used to override legend handles, e.g. +- `handler_map`: A dictionary mapping instances or types to a legend handler. +- `**kwargs`: Passed to [legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html). +- `loc`: The location of the legend. +- `bbox_to_anchor`: Box that is used to position the legend in conjunction with *loc*. +- `ncols`: The number of columns that the legend has. +- `prop`: The font properties of the legend. +- `fontsize`: The font size of the legend. +- `labelcolor`: The color of the text in the legend. +- `numpoints`: The number of marker points in the legend when creating a legend entry for a `.Line2D` (line). +- `scatterpoints`: The number of marker points in the legend when creating a legend entry for a `.PathCollection` (scatter plot). +- `scatteryoffsets`: The vertical offset (relative to the font size) for the markers created for a scatter plot legend entry. +- `markerscale`: The relative size of legend markers compared to the originally drawn ones. +- `markerfirst`: If *True*, legend marker is placed to the left of the legend label. +- `reverse`: If *True*, the legend labels are displayed in reverse order from the input. +- `frameon`: Whether the legend should be drawn on a patch (frame). +- `fancybox`: Whether round edges should be enabled around the `.FancyBboxPatch` which makes up the legend's background. +- _18 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend)""" + ... + + def add_legend(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Back-compatibility alias for older Matplotlib/Seaborn integrations that call +``add_legend``. + +Newer code should call `legend`, but some callers still rely on this +Matplotlib-internal entry point.""" + ... + + def catlegend(self, categories: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Build a categorical legend — one handle per unique category — and optionally draw it. + +Parameters +---------- +- `categories`: Category labels in display order. +- `line`: Whether to render connector lines through the markers. +- `handle_kw`: Style overrides applied to each generated handle. +- `add`: When ``True`` (default), draw the legend on the axes and return the legend artist. +- `**kwargs`: Style keywords applied per entry (see above), plus any [Legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.legend.Legend.html) keyword. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.catlegend)""" + ... + + def entrylegend(self, entries: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Build generic semantic legend entries from explicit ``{label: style}`` entries and optionally draw the legend. + +Parameters +---------- +- `entries`: Entry specifications. +- `line`: Whether each entry shows a connector line. +- `handle_kw`: Style overrides applied to each generated handle. +- `add`: When ``True`` (default), draw the legend on the axes and return the legend artist. +- `**kwargs`: Style keywords applied per entry (see above), plus any [Legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.legend.Legend.html) keyword. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.entrylegend)""" + ... + + def sizelegend(self, levels: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Build a size legend — one handle per level, scaled by marker size — and optionally draw it. + +Parameters +---------- +- `levels`: Numeric values to render as size-scaled markers. +- `labels`: Custom labels. +- `area`: Treat ``levels`` as marker areas (``True``, default) or diameters (``False``). +- `values`: Full scatter-size data used to infer the scaling range for ``levels``. +- `vmin, vmax`: Explicit data range for scatter-style size scaling. +- `smin, smax`: Minimum and maximum scaled marker sizes, with the same meaning as in [scatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.scatter). +- `area_size, absolute_size`: Scatter-style size scaling switches. +- `scale`: Multiplier applied after area/diameter conversion. +- `minsize`: Lower bound on rendered marker size. +- `fmt`: Format used to label levels. +- `handle_kw`: Style overrides applied to each generated handle. +- `add`: When ``True`` (default), draw the legend on the axes and return the legend artist. +- `**kwargs`: Style keywords applied per entry (see above), plus any [Legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.legend.Legend.html) keyword. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.sizelegend)""" + ... + + def numlegend(self, levels: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Build a numeric legend — one patch handle per level, colored from a colormap — and optionally draw it. + +Parameters +---------- +- `levels`: Numeric levels to render. +- `vmin, vmax`: Limits for sampling ``cmap`` when ``norm`` is not provided. +- `n`: Number of levels to sample when ``levels`` is omitted. +- `cmap`: Colormap used to color the patches. +- `norm`: Normalization applied to ``levels`` before colormap lookup. +- `fmt`: Format used to label levels. +- `handle_kw`: Style overrides applied to each generated handle. +- `add`: When ``True`` (default), draw the legend on the axes and return the legend artist. +- `**kwargs`: Style keywords applied per entry (see above), plus any [Legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.legend.Legend.html) keyword. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.numlegend)""" + ... + + def geolegend(self, entries: Incomplete, labels: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Build a geometry legend — one patch handle per geometry entry — and optionally draw it. + +Parameters +---------- +- `entries`: Either a sequence of ``(label, geometry)`` pairs or a mapping from label to geometry specification (string keyword, shapely geometry, ``cartopy`` feature, or a country name when… +- `labels`: Labels overriding those derived from ``entries``. +- `country_reso`: Natural Earth resolution for country geometries (e.g. +- `country_territories`: Whether country lookups include overseas territories. +- `country_proj`: Projection used to render country geometries; ignored for non- country entries. +- `handlesize`: Multiplier applied to legend ``handlelength`` / ``handleheight`` to enlarge geometry handles. +- `handle_kw`: Style overrides applied to each generated handle. +- `add`: When ``True`` (default), draw the legend on the axes and return the legend artist. +- `**kwargs`: Style keywords applied per entry (see above), plus any [Legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.legend.Legend.html) keyword. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.geolegend)""" + ... + + @classmethod + def _coerce_curve_xy(cls, x: Incomplete, y: Incomplete) -> Incomplete: + """Return validated 1D numeric curve coordinates or ``None``.""" + ... + + @classmethod + def _coerce_curve_xy_from_xy_arg(cls, xy: Incomplete) -> Incomplete: + """Parse annotate-style ``xy`` into validated curve arrays or ``None``.""" + ... + + @staticmethod + def _curve_center(x: Incomplete, y: Incomplete, transform: Incomplete) -> tuple[float, float]: + """Return the arc-length midpoint of a curve in the curve coordinate system.""" + ... + + def text(self, *args: Incomplete, avoid_overlap: Incomplete=None, border: Incomplete=False, bbox: Incomplete=False, bordercolor: Incomplete='w', borderwidth: Incomplete=2, borderinvert: Incomplete=False, borderstyle: Incomplete=None, bboxcolor: Incomplete='w', bboxstyle: Incomplete='round', bboxalpha: Incomplete=0.5, bboxpad: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add text to the axes. + +Parameters +---------- +- `s, text`: The string for the text. +- `transform`: The transform used to interpret the bounds. +- `avoid_overlap`: Whether to automatically nudge this text at draw time so it does not overlap other auto-aligned text or the plotted data. +- `border`: Whether to draw border around text. +- `borderwidth`: The width of the text border. +- `bordercolor`: The color of the text border. +- `borderinvert`: If ``True``, the text and border colors are swapped. +- `borderstyle`: The [line join style](https://matplotlib.org/stable/gallery/lines_bars_and_markers/joinstyle.html) used for the border. +- `bbox`: Whether to draw a bounding box around text. +- `bboxcolor`: The color of the text bounding box. +- `bboxstyle`: The style of the bounding box. +- `bboxalpha`: The alpha for the bounding box. +- `bboxpad`: The padding for the bounding box. +- `fontfamily`: The font typeface name (e.g., ``'Fira Math'``) or font family name (e.g., ``'serif'``). +- `fontsize`: The font size. +- `**kwargs`: Passed to [matplotlib.axes.Axes.text](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.text.html). +- `x, y`: The position to place the text. +- `s`: The text. +- `fontdict`: The use of *fontdict* is discouraged. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.text)""" + ... + + def _register_align_text(self, obj: Incomplete, avoid_overlap: Incomplete=None) -> Incomplete: + """Queue a text object for draw-time overlap avoidance, or release it.""" + ... + + def auto_align_text(self, *objs: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Automatically reposition text so that it does not overlap. + +Parameters +---------- +- `*objs`: The text or annotation objects to align. +- `pad`: Padding in points kept around each label. +- `avoid_points`: Whether labels also repel the data points of lines and scatter plots. +- `avoid`: Extra artists whose bounding boxes the labels must stay clear of. +- `only_move`: Restrict movement to one axis. +- `max_iter`: Maximum number of relaxation iterations. +- `spring`: Strength of the pull back towards the original position. +- `step`: Damping applied to each iteration's displacement. +- `clip`: Whether to keep labels inside the axes. +- `arrows`: Whether to draw a connector from each displaced label back to the point it labels. +- `min_arrow_dist`: Only draw connectors for labels displaced further than this, in points. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.auto_align_text)""" + ... + + def _apply_align_text(self, renderer: Incomplete) -> None: + """Run the overlap solver for this axes (called on every draw).""" + ... + + def annotate(self, text: str, xy: Union[Tuple[float, float], Tuple[Iterable[float], Iterable[float]], Iterable[float], np.ndarray], xytext: Optional[Union[Tuple[float, float], Iterable[float], np.ndarray]]=None, xycoords: Union[str, mtransforms.Transform]='data', textcoords: Optional[Union[str, mtransforms.Transform]]=None, arrowprops: Optional[dict[str, Any]]=None, annotation_clip: Optional[bool]=None, avoid_overlap: Optional[bool]=None, **kwargs: Any) -> Incomplete: + """Add an annotation. + +Parameters +---------- +- `avoid_overlap`: Whether to automatically nudge this annotation at draw time so it does not overlap other auto-aligned text or the plotted data. +- `text`: The text of the annotation. +- `xy`: The point *(x, y)* to annotate. +- `xytext`: The position *(x, y)* to place the text at. +- `xycoords`: The coordinate system that *xy* is given in. +- `textcoords`: The coordinate system that *xytext* is given in. +- `arrowprops`: The properties used to draw a `.FancyArrowPatch` arrow between the positions *xy* and *xytext*. +- `annotation_clip`: Whether to clip (i.e. +- `**kwargs`: Additional kwargs are passed to `.Text`. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.annotate)""" + ... + + def curvedtext(self, x: Incomplete, y: Incomplete, text: Incomplete, *, upright: Incomplete=None, ellipsis: Incomplete=None, avoid_overlap: Incomplete=None, overlap_tol: Incomplete=None, curvature_pad: Incomplete=None, min_advance: Incomplete=None, border: Incomplete=False, bbox: Incomplete=False, bordercolor: Incomplete='w', borderwidth: Incomplete=2, borderinvert: Incomplete=False, borderstyle: Incomplete='miter', bboxcolor: Incomplete='w', bboxstyle: Incomplete='round', bboxalpha: Incomplete=0.5, bboxpad: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add curved text that follows a curve. + +Parameters +---------- +- `x, y`: Curve coordinates. +- `text`: The string for the text. +- `transform`: The transform used to interpret the bounds. +- `border`: Whether to draw border around text. +- `borderwidth`: The width of the text border. +- `bordercolor`: The color of the text border. +- `borderinvert`: If ``True``, the text and border colors are swapped. +- `upright`: Whether to flip the curve direction to keep text upright. +- `ellipsis`: Whether to show an ellipsis when the text exceeds curve length. +- `avoid_overlap`: Whether to hide glyphs that overlap after rotation. +- `overlap_tol`: Fractional overlap area (0–1) required before hiding a glyph. +- `curvature_pad`: Extra spacing in pixels per radian of local curvature. +- `min_advance`: Minimum additional spacing (pixels) enforced between glyph centers. +- `borderstyle`: The [line join style](https://matplotlib.org/stable/gallery/lines_bars_and_markers/joinstyle.html) used for the border. +- `bbox`: Whether to draw a bounding box around text. +- `bboxcolor`: The color of the text bounding box. +- `bboxstyle`: The style of the bounding box. +- `bboxalpha`: The alpha for the bounding box. +- `bboxpad`: The padding for the bounding box. +- `fontfamily`: The font typeface name (e.g., ``'Fira Math'``) or font family name (e.g., ``'serif'``). +- `fontsize`: The font size. +- `**kwargs`: Passed to [matplotlib.text.Text](https://matplotlib.org/stable/api/_as_gen/matplotlib.text.Text.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.curvedtext)""" + ... + + def _toggle_spines(self, spines: Union[bool, Iterable, str]) -> None: + """Turns spines on or off depending on input. Spines can be a list such as ['left', 'right'] etc""" + ... + + def _iter_axes(self, hidden: Incomplete=False, children: Incomplete=False, panels: Incomplete=True) -> Incomplete: + """Return a list of visible axes, panel axes, and child axes of both. + +Parameters +---------- +hidden : bool, optional + Whether to include "hidden" panels. +children : bool, optional + Whether to include children. Note this now includes "twin" axes. +panels : bool or str or sequence of str, optional + Whether to include panels or the panels to include.""" + ... + + @property + def number(self) -> Incomplete: + """The axes number. This controls the order of a-b-c labels and the +order of appearance in the [SubplotGrid](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html) returned +by [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots).""" + ... + + @number.setter + def number(self, num: Incomplete) -> None: + """The axes number. This controls the order of a-b-c labels and the +order of appearance in the [SubplotGrid](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html) returned +by [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots).""" + ... + + @property + def use_sticky_edges(self) -> Incomplete: + """Whether plotting commands like `plot`, `plotx`, `vlines`, `hlines`, +`fill_between`, and `fill_betweenx` add "sticky" edges to their artists, +i.e. whether the default axis limits are the artist bounds with no padding. +Initialized from [axes.sticky_edges](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.sticky_edges).""" + ... + + @use_sticky_edges.setter + def use_sticky_edges(self, value: Incomplete) -> None: + """Whether plotting commands like `plot`, `plotx`, `vlines`, `hlines`, +`fill_between`, and `fill_betweenx` add "sticky" edges to their artists, +i.e. whether the default axis limits are the artist bounds with no padding. +Initialized from [axes.sticky_edges](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.sticky_edges).""" + ... + +def _get_pos_from_locator(loc: str, x_pad: float, y_pad: float) -> tuple[float, float]: + """Helper function to map string locators to x and y coordinates.""" + ... + +def _get_axis_for(labelloc: str, loc: str, *, ax: Axes, orientation: str) -> Axes: + """Helper function to determine the axis for a label. +Particularly used for colorbars but can be used for other purposes""" + ... + +def _determine_label_rotation(labelrotation: str | Number, labelloc: str, orientation: str, kw_label: MutableMapping) -> Incomplete: + """Note we update kw_label in place.""" + ... + +def _resolve_label_rotation(labelrotation: str | Number, *, labelloc: str, orientation: str) -> float: + ... + +def _measure_label_points(label: str, rotation: float, fontsize: float, figure: Incomplete) -> Optional[Tuple[float, float]]: + ... + +def _measure_text_artist_points(text: mtext.Text, figure: Incomplete) -> Optional[Tuple[float, float]]: + ... + +def _measure_ticklabel_extent_points(axis: Incomplete, figure: Incomplete) -> Optional[Tuple[float, float]]: + ... + +def _measure_text_overhang_axes(text: mtext.Text, axes: Incomplete) -> Optional[Tuple[float, float, float, float]]: + ... + +def _measure_ticklabel_overhang_axes(axis: Incomplete, axes: Incomplete) -> Optional[Tuple[float, float, float, float]]: + ... + +def _get_colorbar_long_axis(colorbar: Incomplete) -> Incomplete: + ... + +def _register_inset_colorbar_reflow(fig: Incomplete) -> Incomplete: + ... + +def _solve_inset_colorbar_bounds(*, axes: 'Axes', loc: str, orientation: str, length: float, width: float, xpad: float, ypad: float, ticklocation: str, labelloc: Optional[str], label: Incomplete, labelrotation: Union[str, float, None], tick_fontsize: float, label_fontsize: float) -> Tuple[list[float], list[float]]: + ... + +def _legacy_inset_colorbar_bounds(*, axes: 'Axes', loc: str, orientation: str, length: float, width: float, xpad: float, ypad: float, ticklocation: str, labelloc: Optional[str], label: Incomplete, labelrotation: Union[str, float, None], tick_fontsize: float, label_fontsize: float) -> Tuple[list[float], list[float]]: + ... + +def _apply_inset_colorbar_layout(axes: 'Axes', *, bounds_inset: list[float], bounds_frame: list[float], frame: Optional[mpatches.FancyBboxPatch]) -> Incomplete: + ... + +def _has_finite_bbox(bbox: Incomplete) -> bool: + ... + +def _collect_inset_colorbar_bboxes(colorbar: Incomplete, *, labelloc_layout: str, loc: str, orientation: str, renderer: Incomplete) -> Incomplete: + ... + +def _inset_colorbar_frame_needs_reflow(colorbar: Incomplete, *, labelloc: str, renderer: Incomplete) -> bool: + ... + +def _reflow_inset_colorbar_frame(colorbar: Incomplete, *, labelloc: str, ticklen: float, renderer: Incomplete=None) -> Incomplete: + ... diff --git a/ultraplot/axes/cartesian.py b/ultraplot/axes/cartesian.py index 064c1eed8..9957e1b2c 100644 --- a/ultraplot/axes/cartesian.py +++ b/ultraplot/axes/cartesian.py @@ -7,7 +7,7 @@ import functools import inspect from dataclasses import dataclass, field -from typing import Any, Dict, Optional, Tuple, Union +from typing import Any, Callable, Dict, Optional, Tuple, TypeVar, Union, cast import matplotlib.axis as maxis import matplotlib.dates as mdates @@ -40,6 +40,8 @@ __all__ = ["CartesianAxes"] +_F = TypeVar("_F", bound=Callable[..., Any]) + # Tuple of date converters DATE_CONVERTERS = (mdates.DateConverter,) @@ -1860,7 +1862,7 @@ def get_tightbbox(self, renderer, *args, **kwargs): return super().get_tightbbox(renderer, *args, **kwargs) -def _capture_explicit_format_keys(func): +def _capture_explicit_format_keys(func: _F) -> _F: """ Preserve raw keyword names before Python binds them to the format signature. """ @@ -1870,7 +1872,7 @@ def wrapper(self, *args, **kwargs): kwargs.setdefault("_explicit_format_keys", set(kwargs)) return func(self, *args, **kwargs) - return wrapper + return cast(_F, wrapper) # tmp diff --git a/ultraplot/axes/cartesian.pyi b/ultraplot/axes/cartesian.pyi new file mode 100644 index 000000000..d9462c9e6 --- /dev/null +++ b/ultraplot/axes/cartesian.pyi @@ -0,0 +1,579 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The standard Cartesian axes used for most ultraplot figures. +""" +from _typeshed import Incomplete +import copy +import functools +import inspect +from dataclasses import dataclass, field +from typing import Any, Callable, Dict, Optional, Tuple, TypeVar, Union, cast +import matplotlib.axis as maxis +import matplotlib.dates as mdates +import matplotlib.ticker as mticker +import numpy as np +from packaging import version +from .. import constructor +from .. import scale as pscale +from .. import ticker as pticker +from ..config import rc +from ..internals import _not_none, _pop_params, _pop_rc, _version_mpl, docstring, ic, labels, warnings +from ..utils import units +from ._formatting import CARTESIAN_PARENT_FILTER_KEYS, axis_format_requires_layout, get_axis_style_fields, pop_axis_format_kwargs +from . import plot, shared +__all__ = ['CartesianAxes'] +_F = TypeVar('_F', bound=Callable[..., Any]) +DATE_CONVERTERS = (mdates.DateConverter,) +OPPOSITE_SIDE = {'left': 'right', 'right': 'left', 'bottom': 'top', 'top': 'bottom'} +_format_docstring = ... +_shared_x_keys = {'x': 'x', 'x1': 'bottom', 'x2': 'top', 'y': 'y', 'y1': 'left', 'y2': 'right'} +_shared_y_keys = {'x': 'y', 'x1': 'left', 'x2': 'right', 'y': 'x', 'y1': 'bottom', 'y2': 'top'} +_shared_docstring = ... +_alt_descrip = '\nAdd an axis locked to the same location with a\ndistinct {x} axis.\nThis is an alias and arguably more intuitive name for\n`~ultraplot.axes.CartesianAxes.twin{y}`, which generates\ntwo {x} axes with a shared ("twin") {y} axes.\n' +_alt_docstring = ... +_twin_descrip = '\nAdd an axis locked to the same location with a\ndistinct {x} axis.\nThis builds upon `matplotlib.axes.Axes.twin{y}`.\n' +_twin_docstring = ... +_dual_descrip = '\nAdd an axes locked to the same location whose {x} axis denotes\nequivalent coordinates in alternate units.\nThis is an alternative to `matplotlib.axes.Axes.secondary_{x}axis` with\nadditional convenience features.\n' +_dual_extra = '\nfuncscale : callable, 2-tuple of callables, or scale-spec\n The scale used to transform units from the parent axis to the secondary\n axis. This can be a `~ultraplot.scale.FuncScale` itself or a function,\n (function, function) tuple, or an axis scale specification interpreted\n by the `~ultraplot.constructor.Scale` constructor function, any of which\n will be used to build a `~ultraplot.scale.FuncScale` and applied\n to the dual axis (see `~ultraplot.scale.FuncScale` for details).\n' +_dual_docstring = ... + +@dataclass +class _AxisFormatConfig: + """A dataclass to hold formatting options for a single axis.""" + min_: Optional[float] = None + max_: Optional[float] = None + lim: Optional[Tuple[Optional[float], Optional[float]]] = None + reverse: Optional[bool] = None + margin: Optional[float] = None + bounds: Optional[Tuple[float, float]] = None + tickrange: Optional[Tuple[float, float]] = None + wraprange: Optional[Tuple[float, float]] = None + scale: Any = None + scale_kw: Dict[str, Any] = field(default_factory=dict) + spineloc: Any = None + tickloc: Any = None + ticklabelloc: Any = None + labelloc: Any = None + offsetloc: Any = None + grid: Optional[bool] = None + gridminor: Optional[bool] = None + gridcolor: Any = None + locator: Any = None + locator_kw: Dict[str, Any] = field(default_factory=dict) + minorlocator: Any = None + minorlocator_kw: Dict[str, Any] = field(default_factory=dict) + formatter: Any = None + formatter_kw: Dict[str, Any] = field(default_factory=dict) + label: Optional[str] = None + label_kw: Dict[str, Any] = field(default_factory=dict) + labelpad: Any = None + labelcolor: Any = None + labelsize: Any = None + labelweight: Optional[str] = None + color: Any = None + linewidth: Any = None + rotation: Optional[Union[float, str]] = None + tickminor: Optional[bool] = None + tickdir: Optional[str] = None + tickcolor: Any = None + ticklen: Any = None + ticklenratio: Optional[float] = None + tickwidth: Any = None + tickwidthratio: Optional[float] = None + ticklabeldir: Optional[str] = None + ticklabelpad: Any = None + ticklabelcolor: Any = None + ticklabelsize: Any = None + ticklabelweight: Optional[str] = None + +class CartesianAxes(shared._SharedAxes, plot.PlotAxes): + """Axes subclass for plotting in ordinary Cartesian coordinates. Adds the +`~CartesianAxes.format` method and overrides several existing methods. + +Important +--------- +This is the default axes subclass. It can be specified explicitly by passing +``proj='cart'``, ``proj='cartesian'``, ``proj='rect'``, or ``proj='rectilinear'`` +to axes-creation commands like [add_axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_axes), +[add_subplot](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_subplot), and [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots).""" + _name = 'cartesian' + _name_aliases = ('cart', 'rect', 'rectilinar') + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `*args`: Passed to [matplotlib.axes.Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html). +- `aspect`: The data aspect ratio. +- `xlabel, ylabel`: The x and y axis labels. +- `xlabel_kw, ylabel_kw`: Additional axis label settings applied with [set_xlabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlabel.html) and [set_ylabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_ylabel.html). +- `xlim, ylim`: The x and y axis data limits. +- `xmin, ymin`: The x and y minimum data limits. +- `xmax, ymax`: The x and y maximum data limits. +- `xreverse, yreverse`: Whether to "reverse" the x and y axis direction. +- `xscale, yscale`: The x and y axis scales. +- `xscale_kw, yscale_kw`: The x and y axis scale settings. +- `xmargin, ymargin, margin`: The default margin between plotted content and the x and y axis spines in axes-relative coordinates. +- `xbounds, ybounds`: The x and y axis data bounds within which to draw the spines. +- `xtickrange, ytickrange`: The x and y axis data ranges within which major tick marks are labelled. +- `xwraprange, ywraprange`: The x and y axis data ranges with which major tick mark values are wrapped. +- `xloc, yloc`: Shorthands for `xspineloc`, `yspineloc`. +- `xspineloc, yspineloc`: The x and y spine locations. +- `xtickloc, ytickloc`: Which x and y axis spines should have major and minor tick marks. +- `xticklabelloc, yticklabelloc`: Which x and y axis spines should have major tick labels. +- `xlabelloc, ylabelloc`: Which x and y axis spines should have axis labels. +- `xoffsetloc, yoffsetloc`: Which x and y axis spines should have the axis offset indicator. +- `xtickdir, ytickdir, tickdir`: Direction that major and minor tick marks point for the x and y axis. +- `xticklabeldir, yticklabeldir`: Whether to place x and y axis tick label text inside or outside the axes. +- `xrotation, yrotation`: The rotation for x and y axis tick labels. +- `xgrid, ygrid, grid`: Whether to draw major gridlines on the x and y axis. +- `xgridminor, ygridminor, gridminor`: Whether to draw minor gridlines for the x and y axis. +- `xtickminor, ytickminor, tickminor`: Whether to draw minor ticks on the x and y axes. +- `xticks, yticks`: Aliases for `xlocator`, `ylocator`. +- `xlocator, ylocator`: Used to determine the x and y axis tick mark positions. +- `xlocator_kw, ylocator_kw`: Keyword arguments passed to the [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `xminorticks, yminorticks`: Aliases for `xminorlocator`, `yminorlocator`. +- `xminorlocator, yminorlocator`: As for `xlocator`, `ylocator`, but for the minor ticks. +- `xticklabels, yticklabels`: Aliases for `xformatter`, `yformatter`. +- `xformatter, yformatter`: Used to determine the x and y axis tick label string format. +- `xformatter_kw, yformatter_kw`: Keyword arguments passed to the [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `xcolor, ycolor, color`: Color for the x and y axis spines, ticks, tick labels, and axis labels. +- `xgridcolor, ygridcolor, gridcolor`: Color for the x and y axis major and minor gridlines. +- _30 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html)""" + ... + + def _get_axis_style_state(self, axis: Incomplete) -> Incomplete: + """Return the cached explicit style overrides for this axis.""" + ... + + def _merge_axis_style_state(self, axis: Incomplete, params: Incomplete) -> Incomplete: + """Merge the current explicit style overrides with the cached overrides.""" + ... + + def _set_axis_style_state(self, axis: Incomplete, params: Incomplete) -> None: + """Cache the explicit style overrides for this axis.""" + ... + + def _apply_axis_sharing(self) -> None: + """Enforce the "shared" axis labels and axis tick labels. If this is not +called at drawtime, "shared" labels can be inadvertantly turned off.""" + ... + + def _apply_axis_sharing_for_axis(self, axis_name: str, border_axes: dict[str, plot.PlotAxes]) -> None: + """Apply axis sharing for a specific axis (x or y). + +Parameters +---------- +axis_name : str + Either 'x' or 'y' +border_axes : dict + Dictionary from _get_border_axes() containing border information""" + ... + + def _determine_tick_label_visibility(self, axis: maxis.Axis, shared_axis: maxis.Axis, axis_name: str, label_params: list[str], border_sides: list[str], border_axes: dict[str, list[plot.PlotAxes]]) -> dict[str, bool]: + """Determine which tick labels should be visible based on sharing rules and borders. + +Parameters +---------- +axis : matplotlib axis + The current axis object +shared_axis : Axes + The axes this one shares with +axis_name : str + Either 'x' or 'y' +label_params : list + List of label parameter names (e.g., ['labeltop', 'labelbottom']) +border_sides : list + List of border side names (e.g., ['top', 'bottom']) +border_axes : dict + Dictionary from _get_border_axes() + +Returns +------- +dict + Dictionary of label visibility parameters""" + ... + + def _add_alt(self, sx: Incomplete, **kwargs: Incomplete) -> CartesianAxes: + """Add an alternate axes.""" + ... + + def _dual_scale(self, s: Incomplete, funcscale: Incomplete=None) -> None: + """Lock the child "dual" axis limits to the parent.""" + ... + + def _fix_ticks(self, s: Incomplete, fixticks: Incomplete=False) -> None: + """Ensure there are no out-of-bounds ticks. Mostly a brute-force version of +[set_smart_bounds](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.Axis.set_smart_bounds.html) (which I couldn't get to work).""" + ... + + def _get_spine_side(self, s: Incomplete, loc: Incomplete) -> Incomplete: + """Get the spine side implied by the input location or position. This +propagates to tick mark, tick label, and axis label positions.""" + ... + + def _sharex_limits(self, sharex: Incomplete) -> None: + """Safely share limits and tickers without resetting things.""" + ... + + def _sharey_limits(self, sharey: Incomplete) -> None: + """Safely share limits and tickers without resetting things.""" + ... + + def _sharex_setup(self, sharex: Incomplete, *, labels: Incomplete=True, limits: Incomplete=True) -> None: + """Configure shared axes accounting. Input is the 'parent' axes from which this +one will draw its properties. Use keyword args to override settings.""" + ... + + def _sharey_setup(self, sharey: Incomplete, *, labels: Incomplete=True, limits: Incomplete=True) -> None: + """Configure shared axes accounting for panels. The input is the +'parent' axes, from which this one will draw its properties.""" + ... + + def _apply_log_formatter_on_scale(self, s: Incomplete) -> None: + """Enforce log formatter when log scale is set and rc is enabled.""" + ... + + def set_xscale(self, value: Incomplete, **kwargs: Incomplete) -> None: + """Set the xaxis' scale. + +Parameters +---------- +value : str or `.ScaleBase` + The axis scale type to apply. Valid string values are the names of scale + classes ("linear", "log", "function",...). These may be the names of any + of the [built-in scales](https://ultraplot.readthedocs.io/en/stable/search.html?q=builtin_scales) or of any custom scales + registered using [matplotlib.scale.register_scale](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.register_scale.html). + +**kwargs + If *value* is a string, keywords are passed to the instantiation method of + the respective class.""" + ... + + def set_yscale(self, value: Incomplete, **kwargs: Incomplete) -> None: + """Set the yaxis' scale. + +Parameters +---------- +value : str or `.ScaleBase` + The axis scale type to apply. Valid string values are the names of scale + classes ("linear", "log", "function",...). These may be the names of any + of the [built-in scales](https://ultraplot.readthedocs.io/en/stable/search.html?q=builtin_scales) or of any custom scales + registered using [matplotlib.scale.register_scale](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.register_scale.html). + +**kwargs + If *value* is a string, keywords are passed to the instantiation method of + the respective class.""" + ... + + def _update_formatter(self, s: Incomplete, formatter: Incomplete=None, *, formatter_kw: Incomplete=None, tickrange: Incomplete=None, wraprange: Incomplete=None) -> None: + """Update the axis formatter. Passes `formatter` through `Formatter` with kwargs.""" + ... + + def _update_labels(self, s: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> None: + """Apply axis labels to the relevant shared axis. If spanning labels are toggled +this keeps the labels synced for all subplots in the same row or column. Label +positions will be adjusted at draw-time with figure._align_axislabels.""" + ... + + def _update_locators(self, s: Incomplete, locator: Incomplete=None, minorlocator: Incomplete=None, *, tickminor: Incomplete=None, locator_kw: Incomplete=None, minorlocator_kw: Incomplete=None) -> None: + """Update the locators. Requires `Locator` instances.""" + ... + + def _update_limits(self, s: Incomplete, *, min_: Incomplete=None, max_: Incomplete=None, lim: Incomplete=None, reverse: Incomplete=None) -> None: + """Update the axis limits.""" + ... + + def _update_rotation(self, s: Incomplete, *, rotation: Incomplete=None) -> None: + """Rotate the tick labels. Rotate 90 degrees by default for datetime *x* axes.""" + ... + + def _update_spines(self, s: Incomplete, *, loc: Incomplete=None, bounds: Incomplete=None) -> None: + """Update the spine settings.""" + ... + + def _update_locs(self, s: Incomplete, *, tickloc: Incomplete=None, ticklabelloc: Incomplete=None, labelloc: Incomplete=None, offsetloc: Incomplete=None) -> None: + """Update the tick, tick label, and axis label locations.""" + ... + + def _format_axis(self, s: str, config: _AxisFormatConfig, fixticks: bool) -> None: + """Helper for `format` that applies settings to a single axis.""" + ... + + def _resolve_axis_format(self, axis: Incomplete, params: Incomplete, rc_kw: Incomplete) -> _AxisFormatConfig: + """Resolve formatting parameters for a single axis (x or y).""" + ... + + def format(self, *, aspect: Incomplete=None, xloc: Incomplete=None, yloc: Incomplete=None, xspineloc: Incomplete=None, yspineloc: Incomplete=None, xoffsetloc: Incomplete=None, yoffsetloc: Incomplete=None, xwraprange: Incomplete=None, ywraprange: Incomplete=None, xreverse: Incomplete=None, yreverse: Incomplete=None, xlim: Incomplete=None, ylim: Incomplete=None, xmin: Incomplete=None, ymin: Incomplete=None, xmax: Incomplete=None, ymax: Incomplete=None, xscale: Incomplete=None, yscale: Incomplete=None, xbounds: Incomplete=None, ybounds: Incomplete=None, xmargin: Incomplete=None, ymargin: Incomplete=None, xrotation: Incomplete=None, yrotation: Incomplete=None, xformatter: Incomplete=None, yformatter: Incomplete=None, xticklabels: Incomplete=None, yticklabels: Incomplete=None, xticks: Incomplete=None, yticks: Incomplete=None, xlocator: Incomplete=None, ylocator: Incomplete=None, xminorticks: Incomplete=None, yminorticks: Incomplete=None, xminorlocator: Incomplete=None, yminorlocator: Incomplete=None, xcolor: Incomplete=None, ycolor: Incomplete=None, xlinewidth: Incomplete=None, ylinewidth: Incomplete=None, xtickloc: Incomplete=None, ytickloc: Incomplete=None, fixticks: Incomplete=False, xtickdir: Incomplete=None, ytickdir: Incomplete=None, xtickminor: Incomplete=None, ytickminor: Incomplete=None, xtickrange: Incomplete=None, ytickrange: Incomplete=None, xtickcolor: Incomplete=None, ytickcolor: Incomplete=None, xticklen: Incomplete=None, yticklen: Incomplete=None, xticklenratio: Incomplete=None, yticklenratio: Incomplete=None, xtickwidth: Incomplete=None, ytickwidth: Incomplete=None, xtickwidthratio: Incomplete=None, ytickwidthratio: Incomplete=None, xticklabelloc: Incomplete=None, yticklabelloc: Incomplete=None, xticklabeldir: Incomplete=None, yticklabeldir: Incomplete=None, xticklabelpad: Incomplete=None, yticklabelpad: Incomplete=None, xticklabelcolor: Incomplete=None, yticklabelcolor: Incomplete=None, xticklabelsize: Incomplete=None, yticklabelsize: Incomplete=None, xticklabelweight: Incomplete=None, yticklabelweight: Incomplete=None, xlabel: Incomplete=None, ylabel: Incomplete=None, xlabelloc: Incomplete=None, ylabelloc: Incomplete=None, xlabelpad: Incomplete=None, ylabelpad: Incomplete=None, xlabelcolor: Incomplete=None, ylabelcolor: Incomplete=None, xlabelsize: Incomplete=None, ylabelsize: Incomplete=None, xlabelweight: Incomplete=None, ylabelweight: Incomplete=None, xgrid: Incomplete=None, ygrid: Incomplete=None, xgridminor: Incomplete=None, ygridminor: Incomplete=None, xgridcolor: Incomplete=None, ygridcolor: Incomplete=None, xlabel_kw: Incomplete=None, ylabel_kw: Incomplete=None, xscale_kw: Incomplete=None, yscale_kw: Incomplete=None, xlocator_kw: Incomplete=None, ylocator_kw: Incomplete=None, xformatter_kw: Incomplete=None, yformatter_kw: Incomplete=None, xminorlocator_kw: Incomplete=None, yminorlocator_kw: Incomplete=None, **kwargs: Incomplete) -> None: + """Modify axes limits, axis scales, axis labels, spine locations, tick locations, tick labels, and more. + +Parameters +---------- +- `aspect`: The data aspect ratio. +- `xlabel, ylabel`: The x and y axis labels. +- `xlabel_kw, ylabel_kw`: Additional axis label settings applied with [set_xlabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlabel.html) and [set_ylabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_ylabel.html). +- `xlim, ylim`: The x and y axis data limits. +- `xmin, ymin`: The x and y minimum data limits. +- `xmax, ymax`: The x and y maximum data limits. +- `xreverse, yreverse`: Whether to "reverse" the x and y axis direction. +- `xscale, yscale`: The x and y axis scales. +- `xscale_kw, yscale_kw`: The x and y axis scale settings. +- `xmargin, ymargin, margin`: The default margin between plotted content and the x and y axis spines in axes-relative coordinates. +- `xbounds, ybounds`: The x and y axis data bounds within which to draw the spines. +- `xtickrange, ytickrange`: The x and y axis data ranges within which major tick marks are labelled. +- `xwraprange, ywraprange`: The x and y axis data ranges with which major tick mark values are wrapped. +- `xloc, yloc`: Shorthands for `xspineloc`, `yspineloc`. +- `xspineloc, yspineloc`: The x and y spine locations. +- `xtickloc, ytickloc`: Which x and y axis spines should have major and minor tick marks. +- `xticklabelloc, yticklabelloc`: Which x and y axis spines should have major tick labels. +- `xlabelloc, ylabelloc`: Which x and y axis spines should have axis labels. +- `xoffsetloc, yoffsetloc`: Which x and y axis spines should have the axis offset indicator. +- `xtickdir, ytickdir, tickdir`: Direction that major and minor tick marks point for the x and y axis. +- `xticklabeldir, yticklabeldir`: Whether to place x and y axis tick label text inside or outside the axes. +- `xrotation, yrotation`: The rotation for x and y axis tick labels. +- `xgrid, ygrid, grid`: Whether to draw major gridlines on the x and y axis. +- `xgridminor, ygridminor, gridminor`: Whether to draw minor gridlines for the x and y axis. +- `xtickminor, ytickminor, tickminor`: Whether to draw minor ticks on the x and y axes. +- `xticks, yticks`: Aliases for `xlocator`, `ylocator`. +- `xlocator, ylocator`: Used to determine the x and y axis tick mark positions. +- `xlocator_kw, ylocator_kw`: Keyword arguments passed to the [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `xminorticks, yminorticks`: Aliases for `xminorlocator`, `yminorlocator`. +- `xminorlocator, yminorlocator`: As for `xlocator`, `ylocator`, but for the minor ticks. +- `xticklabels, yticklabels`: Aliases for `xformatter`, `yformatter`. +- `xformatter, yformatter`: Used to determine the x and y axis tick label string format. +- `xformatter_kw, yformatter_kw`: Keyword arguments passed to the [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `xcolor, ycolor, color`: Color for the x and y axis spines, ticks, tick labels, and axis labels. +- `xgridcolor, ygridcolor, gridcolor`: Color for the x and y axis major and minor gridlines. +- `xlinewidth, ylinewidth, linewidth`: Line width for the x and y axis spines and major ticks. +- _38 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format)""" + ... + + def altx(self, **kwargs: Incomplete) -> CartesianAxes: + """Add an axis locked to the same location with a +distinct x axis. +This is an alias and arguably more intuitive name for +[twiny](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.twiny), which generates +two x axes with a shared ("twin") y axes. + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the x from keywords beginning with ``x`` -- for example + ``ax.altx(lim=(0, 10))`` is equivalent to ``ax.altx(xlim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.altx(loc='bottom')`` changes the default side from top to bottom. + +Returns +------- +ultraplot.axes.CartesianAxes + The resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old x axis on the bottom and the new x + axis on the top. +* Makes the old top spine invisible and the new bottom, left, + and right spines invisible. +* Adjusts the x axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new y axis limits and scales, and makes the + new y axis labels invisible.""" + ... + + def alty(self, **kwargs: Incomplete) -> CartesianAxes: + """Add an axis locked to the same location with a +distinct y axis. +This is an alias and arguably more intuitive name for +[twinx](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.twinx), which generates +two y axes with a shared ("twin") x axes. + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the y from keywords beginning with ``y`` -- for example + ``ax.alty(lim=(0, 10))`` is equivalent to ``ax.alty(ylim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.alty(loc='left')`` changes the default side from right to left. + +Returns +------- +ultraplot.axes.CartesianAxes + The resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old y axis on the left and the new y + axis on the right. +* Makes the old right spine invisible and the new left, bottom, + and top spines invisible. +* Adjusts the y axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new x axis limits and scales, and makes the + new x axis labels invisible.""" + ... + + def dualx(self, funcscale: Incomplete, **kwargs: Incomplete) -> CartesianAxes: + """Add an axes locked to the same location whose x axis denotes equivalent coordinates in alternate units. + +Parameters +---------- +- `funcscale`: The scale used to transform units from the parent axis to the secondary axis. +- `**kwargs`: Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.dualx)""" + ... + + def dualy(self, funcscale: Incomplete, **kwargs: Incomplete) -> CartesianAxes: + """Add an axes locked to the same location whose y axis denotes equivalent coordinates in alternate units. + +Parameters +---------- +- `funcscale`: The scale used to transform units from the parent axis to the secondary axis. +- `**kwargs`: Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.dualy)""" + ... + + def twinx(self, **kwargs: Incomplete) -> CartesianAxes: + """Add an axis locked to the same location with a +distinct y axis. +This builds upon [matplotlib.axes.Axes.twinx](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.twinx.html). + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the y from keywords beginning with ``y`` -- for example + ``ax.alty(lim=(0, 10))`` is equivalent to ``ax.alty(ylim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.alty(loc='left')`` changes the default side from right to left. + +Returns +------- +ultraplot.axes.CartesianAxes + The resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old y axis on the left and the new y + axis on the right. +* Makes the old right spine invisible and the new left, bottom, + and top spines invisible. +* Adjusts the y axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new x axis limits and scales, and makes the + new x axis labels invisible.""" + ... + + def twiny(self, **kwargs: Incomplete) -> CartesianAxes: + """Add an axis locked to the same location with a +distinct x axis. +This builds upon [matplotlib.axes.Axes.twiny](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.twiny.html). + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the x from keywords beginning with ``x`` -- for example + ``ax.altx(lim=(0, 10))`` is equivalent to ``ax.altx(xlim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.altx(loc='bottom')`` changes the default side from top to bottom. + +Returns +------- +ultraplot.axes.CartesianAxes + The resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old x axis on the bottom and the new x + axis on the top. +* Makes the old top spine invisible and the new bottom, left, + and right spines invisible. +* Adjusts the x axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new y axis limits and scales, and makes the + new y axis labels invisible.""" + ... + + def draw(self, renderer: Incomplete=None, *args: Incomplete, **kwargs: Incomplete) -> None: + """Draw the Artist (and its children) using the given renderer. + +This has no effect if the artist is not visible (`.Artist.get_visible` +returns False). + +Parameters +---------- +renderer : [RendererBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.RendererBase.html) subclass. + +Notes +----- +This method is overridden in the Artist subclasses.""" + ... + + def get_tightbbox(self, renderer: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """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` subclass + 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 : bool, 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. + +for_layout_only : default: False + The bounding box will *not* include the x-extent of the title and + the xlabel, or the y-extent of the ylabel. + +Returns +------- +`.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""" + ... + +def _capture_explicit_format_keys(func: _F) -> _F: + """Preserve raw keyword names before Python binds them to the format signature.""" + ... diff --git a/ultraplot/axes/container.pyi b/ultraplot/axes/container.pyi new file mode 100644 index 000000000..6ad4fdb4c --- /dev/null +++ b/ultraplot/axes/container.pyi @@ -0,0 +1,215 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Container class for external axes (e.g., mpltern, cartopy custom axes). + +This module provides the ExternalAxesContainer class which acts as a wrapper +around external axes classes, allowing them to be used within ultraplot's +figure system while maintaining their native functionality. +""" +from _typeshed import Incomplete +import matplotlib.axes as maxes +import matplotlib.transforms as mtransforms +from matplotlib import cbook, container +from ..config import rc +from ..internals import _pop_rc, warnings +from .cartesian import CartesianAxes +__all__ = ['ExternalAxesContainer'] +_ABOVE_AXES_TITLE_LOCS = {'left', 'center', 'right'} + +class ExternalAxesContainer(CartesianAxes): + """Container axes that wraps an external axes instance. + +Parameters +---------- +- `*args`: Positional arguments passed to Axes.__init__ +- `external_axes_class`: The external axes class to instantiate (e.g., mpltern.TernaryAxes) +- `external_axes_kwargs`: Keyword arguments to pass to the external axes constructor +- `external_shrink_factor`: The factor by which to shrink the external axes within the container to leave room for labels. +- `external_padding`: Padding in points to add around the external axes tight bbox. +- `**kwargs`: Keyword arguments passed to Axes.__init__ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.ExternalAxesContainer.html)""" + _EXTERNAL_DELEGATE_BLOCKLIST = {'format', 'colorbar', 'legend', 'set_title'} + + def __init__(self, *args: Incomplete, external_axes_class: Incomplete=None, external_axes_kwargs: Incomplete=None, **kwargs: Incomplete) -> None: + """Initialize the container and create the external axes child.""" + ... + + def _create_external_axes(self) -> None: + """Create the external axes instance as a child of this container.""" + ... + + def _shrink_external_for_labels(self, base_pos: Incomplete=None) -> None: + """Shrink the external axes to leave room for labels that extend beyond the plot area. + +This is particularly important for ternary plots where axis labels can extend +significantly beyond the triangular plot region.""" + ... + + def _ensure_external_fits_within_container(self, renderer: Incomplete) -> None: + """Iteratively shrink external axes until it fits completely within container bounds. + +This ensures that external axes labels don't extend beyond the container's +allocated space and overlap with adjacent subplots.""" + ... + + def _sync_position_to_external(self) -> None: + """Synchronize the container position to the external axes.""" + ... + + def set_position(self, pos: Incomplete, which: Incomplete='both') -> None: + """Override to sync position changes to external axes.""" + ... + + def _reposition_subplot(self) -> None: + ... + + def _update_title_position(self, renderer: Incomplete) -> None: + """Update the title position based on the bounding box enclosing +all the ticklabels and x-axis spine and xlabel...""" + ... + + def _title_reserves_external_space(self, loc: Incomplete) -> bool: + """Return whether a title-like artist needs room above an external axes.""" + ... + + def _iter_axes(self, hidden: Incomplete=True, children: Incomplete=True, panels: Incomplete=True) -> Incomplete: + """Override to only yield the container itself, not the external axes. + +The external axes is a rendering child, not a logical ultraplot child, +so we don't want ultraplot's iteration to find it and call ultraplot +methods on it.""" + ... + + def plot(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate plot to external axes.""" + ... + + def scatter(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate scatter to external axes.""" + ... + + def fill(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate fill to external axes.""" + ... + + def contour(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate contour to external axes.""" + ... + + def contourf(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate contourf to external axes.""" + ... + + def pcolormesh(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate pcolormesh to external axes.""" + ... + + def tripcolor(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate tripcolor to external axes.""" + ... + + def tricontour(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate tricontour to external axes.""" + ... + + def tricontourf(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate tricontourf to external axes.""" + ... + + def triplot(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate triplot to external axes.""" + ... + + def imshow(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate imshow to external axes.""" + ... + + def hexbin(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate hexbin to external axes.""" + ... + + def get_external_axes(self) -> Incomplete: + """Get the wrapped external axes instance. + +Returns +------- +axes + The external axes instance, or None if not created""" + ... + + def has_external_child(self) -> Incomplete: + """Check if this container has an external axes child. + +Returns +------- +bool + True if an external axes instance exists, False otherwise""" + ... + + def get_external_child(self) -> Incomplete: + """Get the external axes child (alias for get_external_axes). + +Returns +------- +axes + The external axes instance, or None if not created""" + ... + + def clear(self) -> None: + """Clear the container and mark external axes as stale.""" + ... + + def format(self, **kwargs: Incomplete) -> None: + """Format the container and delegate to external axes where appropriate. + +This method handles ultraplot-specific formatting on the container +and attempts to delegate common parameters to the external axes. + +Parameters +---------- +**kwargs + Formatting parameters. Common matplotlib parameters (title, xlabel, + ylabel, xlim, ylim) are delegated to the external axes if supported.""" + ... + + def draw(self, renderer: Incomplete) -> None: + """Override draw to render container (with abc/titles) and external axes.""" + ... + + def stale_callback(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Mark external axes as stale when container is marked stale.""" + ... + + def get_tightbbox(self, renderer: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Override to return the container bbox for consistent layout positioning. + +By returning the container's bbox, we ensure the layout engine positions +the container properly within the subplot grid, and we rely on our +iterative shrinking to ensure the external axes fits within the container.""" + ... + + def __getattr__(self, name: Incomplete) -> Incomplete: + """Delegate missing attributes to the external axes unless blocked.""" + ... + + def __dir__(self) -> list[str]: + """Include external axes attributes in dir() output.""" + ... + +def create_external_axes_container(external_axes_class: Incomplete, projection_name: Incomplete=None) -> Incomplete: + """Factory function to create a container class for a specific external axes type. + +Parameters +---------- +external_axes_class : type + The external axes class to wrap +projection_name : str, optional + The projection name to register with matplotlib + +Returns +------- +type + A subclass of ExternalAxesContainer configured for the external axes class""" + ... diff --git a/ultraplot/axes/geo.pyi b/ultraplot/axes/geo.pyi new file mode 100644 index 000000000..fcc2021f7 --- /dev/null +++ b/ultraplot/axes/geo.pyi @@ -0,0 +1,1138 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Axes filled with cartographic projections. +""" +from _typeshed import Incomplete +import copy +import inspect +from dataclasses import dataclass +from functools import partial +from numbers import Real +from types import SimpleNamespace +try: + from typing import override +except ImportError: + from typing_extensions import override +from collections.abc import Iterator, Mapping, MutableMapping, Sequence +from typing import Any, Optional, Protocol +import matplotlib.axis as maxis +import matplotlib.axes as maxes +import matplotlib.collections as mcollections +import matplotlib.patches as mpatches +import matplotlib.path as mpath +import matplotlib.text as mtext +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +import numpy as np +from .. import constructor +from .. import proj as pproj +from .. import ticker as pticker +from ..config import rc +from ..internals import _not_none, _pop_params, _pop_props, _pop_rc, _version_cartopy, docstring, ic, labels, warnings +from ..utils import units +from . import plot, shared +try: + import cartopy.crs as ccrs + import cartopy.feature as cfeature + import cartopy.mpl.gridliner as cgridliner + from cartopy.crs import Projection + from cartopy.mpl.geoaxes import GeoAxes as _GeoAxes +except ModuleNotFoundError: + ccrs = cfeature = cgridliner = None + _GeoAxes = Projection = object +try: + from mpl_toolkits.basemap import Basemap +except ModuleNotFoundError: + Basemap = object +__all__ = ['GeoAxes'] +GridlineDict = MutableMapping[float, tuple[list[Any], list[mtext.Text]]] +_GRIDLINER_PAD_SCALE = 2.0 +_MINOR_TICK_SCALE = 0.6 +_BASEMAP_LABEL_SIZE_SCALE = 0.5 +_BASEMAP_LABEL_Y_SCALE = 0.65 +_BASEMAP_LABEL_X_SCALE = 0.25 +_CARTOPY_LABEL_SIDES = ('labelleft', 'labelright', 'labelbottom', 'labeltop', 'geo') +_BASEMAP_LABEL_SIDES = ('labelleft', 'labelright', 'labelbottom', 'labeltop', 'geo') +_HAWKEYE_ANCHORS = {'ul': (0, 1), 'upper left': (0, 1), 'ur': (1, 1), 'upper right': (1, 1), 'll': (0, 0), 'lower left': (0, 0), 'lr': (1, 0), 'lower right': (1, 0), 'c': (0.5, 0.5), 'center': (0.5, 0.5), 'uc': (0.5, 1), 'upper center': (0.5, 1), 'lc': (0.5, 0), 'lower center': (0.5, 0), 'cl': (0, 0.5), 'center left': (0, 0.5), 'cr': (1, 0.5), 'center right': (1, 0.5)} + +class _AnchoredInsetLocator: + """Locate an inset by anchoring one of its points to a parent coordinate.""" + + def __init__(self, parent: Incomplete, xy: Incomplete, size: Incomplete, transform: Incomplete, anchor: Incomplete, square: Incomplete=False) -> None: + ... + + def __call__(self, ax: Incomplete, renderer: Incomplete) -> Incomplete: + ... +_HAWKEYE_TRANSFORM_NAMES = frozenset({'axes', 'data', 'figure', 'subfigure', 'map'}) + +def _parse_hawkeye_anchor(anchor: Incomplete, axes_relative: Incomplete=True) -> Incomplete: + """Translate a named hawkeye anchor to normalized axes coordinates. + +String anchors are always axes-relative. When ``axes_relative`` is False the +caller supplied a non-default ``anchor_transform``, so a coordinate 2-tuple +is required and string aliases are rejected.""" + ... + +def _parse_hawkeye_size(size: Incomplete) -> Incomplete: + """Normalize scalar hawkeye sizes to square inset dimensions.""" + ... + +def _hawkeye_crs_from_name(name: Incomplete) -> Incomplete: + """Resolve a projection name to a cartopy CRS for hawkeye coordinates.""" + ... + +def _hawkeye_crs(transform: Incomplete, param: Incomplete) -> Incomplete: + """Resolve a hawkeye geographic transform to a cartopy CRS. + +Accepts ``'map'`` (an alias for `~cartopy.crs.PlateCarree`), a cartopy CRS +instance, or a registered projection name (e.g. ``'cyl'``, ``'moll'``).""" + ... + +def _parse_hawkeye_extent_transform(transform: Incomplete) -> Incomplete: + """Translate hawkeye extent transforms to cartopy coordinate systems.""" + ... + +def _parse_hawkeye_anchor_transform(transform: Incomplete) -> Incomplete: + """Resolve the coordinate system for a hawkeye anchor point. + +``'axes'`` (the default) leaves the anchor as an inset axes fraction and is +signalled by returning ``None``. Any other value is resolved to a cartopy CRS +so the anchor can be interpreted as a geographic or projected point.""" + ... + +def _hawkeye_anchor_fraction(inset: Incomplete, anchor: Incomplete, anchor_transform: Incomplete) -> Incomplete: + """Convert a hawkeye anchor point to an inset axes fraction. + +With ``anchor_transform`` None the anchor is already an axes fraction and is +returned unchanged. Otherwise the anchor is a point in ``anchor_transform`` +coordinates; it is projected into the inset projection and normalized against +the inset view limits, which are fixed by the time this runs.""" + ... + +def _parse_hawkeye_connector(connector: Incomplete) -> Incomplete: + """Normalize connector shorthand to a named presentation mode.""" + ... + +def _parse_hawkeye_shape(value: Incomplete, name: Incomplete) -> Incomplete: + """Validate a hawkeye inset or target shape.""" + ... + +def _square_hawkeye_view(inset: Incomplete) -> Incomplete: + """Expand the shorter projected dimension to make a square map viewport.""" + ... + +def _infer_hawkeye_relation(parent_extent: Incomplete, inset_extent: Incomplete) -> Incomplete: + """Infer whether an inset is a geographic detail or overview.""" + ... + +def _segments_intersect(start1: Incomplete, end1: Incomplete, start2: Incomplete, end2: Incomplete) -> Incomplete: + """Return whether two display-coordinate line segments intersect.""" + ... + +def _select_hawkeye_connector_pairs(extent_display: Incomplete, frame_display: Incomplete) -> Incomplete: + """Select the shortest pair of non-crossing overview connectors.""" + ... + +def _add_hawkeye_overview_connectors(parent: Incomplete, inset: Incomplete, extent: Incomplete, transform: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Connect the parent frame to its geographic extent on an overview inset.""" + ... + +def _add_hawkeye_leader(inset: Incomplete, target_axes: Incomplete, target_xy: Incomplete, transform: Incomplete, target_patch: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Draw a leader from an inset edge to a geographic target point.""" + ... + +def _add_hawkeye_zoom_indicator(parent: 'GeoAxes', inset: 'GeoAxes', **kwargs: Any) -> Incomplete: + """Draw an ``indicate_inset_zoom`` marker with a version-stable return. + +matplotlib >= 3.10 returns an ``InsetIndicator`` artist exposing +``.rectangle`` and ``.connectors``. Earlier versions return a plain +``(rectangle, connectors)`` tuple, so wrap it to expose the same accessors.""" + ... + +def _select_enveloping_connectors(indicator: Incomplete, inset: 'GeoAxes', renderer: Incomplete=None) -> None: + """Show the two zoom connectors that wrap around the inset (outer tangents). + +The visible pair is chosen from the sign of the inset-to-indicator centre +offset: a diagonally opposite pair envelops the inset, whereas a same-side +pair would run parallel and cross the frustum.""" + ... + +def _envelop_hawkeye_zoom_connectors(indicator: Incomplete, inset: 'GeoAxes') -> None: + """Reassert the enveloping connector pair on every draw. + +matplotlib fixes connector visibility once, from a bounding-box rule that can +pick a parallel pair for a diagonally placed inset. The inset position is only +final at draw time, so recompute the enveloping pair from a draw hook: on +matplotlib >= 3.10 the ``InsetIndicator`` resolves its connectors in its own +``draw``, while the legacy wrapper draws its rectangle before the connectors.""" + ... + +@dataclass +class _HawkeyeSpec: + """Validated inputs for `GeoAxes.hawkeye`. + +``extent_transform`` and ``relation`` are only fully resolved when ``extent`` +is not ``None`` (they require a geographic extent to normalize and infer); +otherwise they retain their raw defaults and are never consumed. ``aspect`` is +intentionally not stored here because ``'projection'`` can only be resolved +from the live inset axes (see `GeoAxes._build_hawkeye_inset`). When +``anchor_transform`` is not ``None`` the ``anchor`` is a geographic/projected +point rather than an axes fraction; it is converted to a fraction against the +live inset view limits in `GeoAxes._build_hawkeye_inset`.""" + xy: tuple[float, float] + size: tuple[float, float] + anchor: tuple[float, float] + anchor_transform: Any + transform: Any + extent: Optional[tuple[float, float, float, float]] + extent_transform: Any + relation: str + connector: Optional[str] + shape: str + target: str + +def _apply_hawkeye_circle_boundary(inset: 'GeoAxes', aspect: str | float) -> None: + """Clip a hawkeye inset to a circular map boundary matching its view.""" + ... + +def _make_hawkeye_indicator_patch(extent: Sequence[float], transform: Any, target: str, **kwargs: Any) -> mpatches.Patch: + """Build the outline patch (box or circle) marking a hawkeye extent.""" + ... +_format_docstring = ... +_hawkeye_docstring = ... +_choropleth_docstring = ... + +class _GeoLabel(object): + """Optionally omit overlapping check if an rc setting is disabled.""" + + def check_overlapping(self, *args: Any, **kwargs: Any) -> bool: + ... +if cgridliner is not None and hasattr(cgridliner, 'Label'): + + class _CartopyLabel(_GeoLabel, cgridliner.Label): + """Label class with configurable overlap checks.""" + + class _CartopyGridliner(cgridliner.Gridliner): + """Gridliner subclass to localize cartopy quirks in one place.""" + LabelClass = _CartopyLabel + + def _generate_labels(self) -> Iterator[_CartopyLabel]: + """Yield label objects, reusing cached instances when possible.""" + ... + + def _axes_domain(self, *args: Any, **kwargs: Any) -> tuple[Any, Any]: + ... + + def _draw_gridliner(self, *args: Any, **kwargs: Any) -> Any: + ... +else: + _CartopyGridliner = None + +class _GeoAxis(object): + """Dummy axis used by longitude and latitude locators and for storing view limits on +longitude and latitude coordinates. Modeled after how [matplotlib.ticker._DummyAxis](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker._DummyAxis.html) +and [matplotlib.ticker.TickHelper](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.TickHelper.html) are used to control tick locations and labels.""" + + def __init__(self, axes: 'GeoAxes') -> None: + ... + + def _get_extent(self) -> tuple[float, float, float, float]: + ... + + @staticmethod + def _pad_ticks(ticks: np.ndarray, vmin: float, vmax: float) -> np.ndarray: + ... + + def get_scale(self) -> str: + ... + + def get_tick_space(self) -> int: + ... + + def get_major_formatter(self) -> mticker.Formatter | None: + ... + + def get_major_locator(self) -> mticker.Locator | None: + ... + + def get_minor_locator(self) -> mticker.Locator | None: + ... + + def get_majorticklocs(self) -> np.ndarray: + ... + + def get_minorticklocs(self) -> np.ndarray: + ... + + def set_major_formatter(self, formatter: mticker.Formatter, default: bool=False) -> None: + ... + + def set_major_locator(self, locator: mticker.Locator, default: bool=False) -> None: + ... + + def set_minor_locator(self, locator: mticker.Locator, default: bool=False) -> None: + ... + + def set_view_interval(self, vmin: float, vmax: float) -> None: + ... + + def _copy_locator_properties(self, other: '_GeoAxis') -> None: + """This function copies the locator properties. It is +used when the @self is sharing with @other.""" + ... + +class _GridlinerAdapter(Protocol): + """Lightweight facade used to normalize cartopy and basemap gridliner behavior. +These adapters let GeoAxes apply gridline label toggles and styles without +backend-specific branching.""" + + def labels_for_sides(self, *, bottom: bool | str | None=None, top: bool | str | None=None, left: bool | str | None=None, right: bool | str | None=None) -> dict[str, list[mtext.Text]]: + ... + + def toggle_labels(self, *, labelleft: bool | str | None=None, labelright: bool | str | None=None, labelbottom: bool | str | None=None, labeltop: bool | str | None=None, geo: bool | str | None=None) -> None: + ... + + def apply_style(self, *, axis: str='both', pad: float | None=None, labelsize: float | str | None=None, labelcolor: Any=None, labelrotation: float | None=None, linecolor: Any=None, linewidth: float | None=None) -> None: + ... + + def tick_positions(self, axis: str, *, lonaxis: '_GeoAxis', lataxis: '_GeoAxis') -> np.ndarray: + ... + + def is_label_on(self, side: str) -> bool: + ... + +class _CartopyGridlinerProtocol(Protocol): + """Structural protocol for the subset of cartopy Gridliner attributes we use. +This keeps type hints tight without importing cartopy at runtime.""" + collection_kwargs: dict[str, Any] + xlabel_style: dict[str, Any] + ylabel_style: dict[str, Any] + xlocator: mticker.Locator + ylocator: mticker.Locator + xpadding: float | None + ypadding: float | None + xlines: bool + ylines: bool + x_inline: bool | None + y_inline: bool | None + rotate_labels: bool | None + inline_labels: bool | str | None + geo_labels: bool | str | None + left_label_artists: list[mtext.Text] + right_label_artists: list[mtext.Text] + bottom_label_artists: list[mtext.Text] + top_label_artists: list[mtext.Text] + xline_artists: list[Any] + + def _axes_domain(self, *args: Any, **kwargs: Any) -> tuple[Any, Any]: + ... + + def _draw_gridliner(self, *args: Any, **kwargs: Any) -> Any: + ... + +class _CartopyGridlinerAdapter(_GridlinerAdapter): + """Adapter for cartopy's Gridliner, translating common label/style operations +into the Gridliner API while hiding cartopy version differences.""" + + def __init__(self, gridliner: Optional[_CartopyGridlinerProtocol]) -> None: + ... + + @staticmethod + def _side_labels() -> tuple[str, str, str, str]: + ... + + def labels_for_sides(self, *, bottom: bool | str | None=None, top: bool | str | None=None, left: bool | str | None=None, right: bool | str | None=None) -> dict[str, list[mtext.Text]]: + ... + + def toggle_labels(self, *, labelleft: bool | str | None=None, labelright: bool | str | None=None, labelbottom: bool | str | None=None, labeltop: bool | str | None=None, geo: bool | str | None=None) -> None: + ... + + def apply_style(self, *, axis: str='both', pad: float | None=None, labelsize: float | str | None=None, labelcolor: Any=None, labelrotation: float | None=None, linecolor: Any=None, linewidth: float | None=None) -> None: + ... + + def tick_positions(self, axis: str, *, lonaxis: _GeoAxis, lataxis: _GeoAxis) -> np.ndarray: + ... + + def is_label_on(self, side: str) -> bool: + ... + +class _BasemapGridlinerAdapter(_GridlinerAdapter): + """Adapter for basemap meridian/parallel dictionaries, emulating the subset +of cartopy Gridliner behavior needed by GeoAxes (labels, toggles, styling).""" + + def __init__(self, lonlines: GridlineDict | None, latlines: GridlineDict | None) -> None: + ... + + def labels_for_sides(self, *, bottom: bool | str | None=None, top: bool | str | None=None, left: bool | str | None=None, right: bool | str | None=None) -> dict[str, list[mtext.Text]]: + ... + + def toggle_labels(self, *, labelleft: bool | str | None=None, labelright: bool | str | None=None, labelbottom: bool | str | None=None, labeltop: bool | str | None=None, geo: bool | str | None=None) -> None: + ... + + def apply_style(self, *, axis: str='both', pad: float | None=None, labelsize: float | str | None=None, labelcolor: Any=None, labelrotation: float | None=None, linecolor: Any=None, linewidth: float | None=None) -> None: + ... + + def tick_positions(self, axis: str, *, lonaxis: _GeoAxis, lataxis: _GeoAxis) -> np.ndarray: + ... + + def is_label_on(self, side: str) -> bool: + ... + +class _LonAxis(_GeoAxis): + """Axis with default longitude locator.""" + axis_name = 'lon' + + def __init__(self, axes: 'GeoAxes') -> None: + ... + + def _get_ticklocs(self, locator: mticker.Locator) -> np.ndarray: + ... + + def get_view_interval(self) -> tuple[float, float]: + ... + +class _LatAxis(_GeoAxis): + """Axis with default latitude locator.""" + axis_name = 'lat' + + def __init__(self, axes: 'GeoAxes', latmax: float=90) -> None: + ... + + def _get_ticklocs(self, locator: mticker.Locator) -> np.ndarray: + ... + + def get_latmax(self) -> float: + ... + + def get_view_interval(self) -> tuple[float, float]: + ... + + def set_latmax(self, latmax: float) -> None: + ... + +def _gridliner_sides_from_arrays(lonarray: Sequence[bool | None] | None, latarray: Sequence[bool | None] | None, *, order: Sequence[str], allow_xy: bool, include_false: bool) -> dict[str, bool | str]: + """Map lon/lat label arrays to gridliner toggle flags. + +Parameters +---------- +allow_xy + Use "x"/"y" to preserve axis-specific toggles when only one of lon/lat + is enabled for a given side (cartopy behavior). +include_false + Include explicit False entries to actively hide existing labels instead + of leaving previous state untouched (backend-dependent behavior).""" + ... + +class GeoAxes(shared._SharedAxes, plot.PlotAxes): + """Axes subclass for plotting in geographic projections. Uses either cartopy +or basemap as a "backend". + +Note +---- +This subclass uses longitude and latitude as the default coordinate system for all +plotting commands by internally passing ``transform=cartopy.crs.PlateCarree()`` to +cartopy commands and ``latlon=True`` to basemap commands. Also, when using basemap +as the "backend", plotting is still done "cartopy-style" by calling methods from +the axes instance rather than the `~mpl_toolkits.basemap.Basemap` instance. + +Important +--------- +This axes subclass can be used by passing ``proj='proj_name'`` +to axes-creation commands like [add_axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_axes), +[add_subplot](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_subplot), and [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots), +where ``proj_name`` is a registered [PROJ projection name](https://ultraplot.readthedocs.io/en/stable/search.html?q=proj_table). +You can also pass a `~cartopy.crs.Projection` or `~mpl_toolkits.basemap.Basemap` +instance instead of a projection name. Alternatively, you can pass any of the +matplotlib-recognized axes subclass names ``proj='cartopy'``, ``proj='geo'``, or +``proj='geographic'`` with a `~cartopy.crs.Projection` `map_projection` keyword +argument, or pass ``proj='basemap'`` with a `~mpl_toolkits.basemap.Basemap` +`map_projection` keyword argument.""" + + def __init__(self, *args: Any, **kwargs: Any) -> None: + """Parameters +---------- +- `*args`: Passed to [matplotlib.axes.Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html). +- `map_projection`: The cartopy or basemap projection instance. +- `aspect`: The map aspect ratio. +- `abcanchor`: The coordinate box used for the a-b-c label. +- `round`: *For polar cartopy axes only*. +- `extent`: *For cartopy axes only*. +- `lonlim, latlim`: *For cartopy axes only.* The approximate longitude and latitude boundaries of the map, applied with `~cartopy.mpl.geoaxes.GeoAxes.set_extent`. +- `boundinglat`: *For cartopy axes only.* The edge latitude for the circle bounding North Pole and South Pole-centered projections. +- `longrid, latgrid, grid`: Whether to draw longitude and latitude gridlines. +- `longridminor, latgridminor, gridminor`: Whether to draw "minor" longitude and latitude lines. +- `lonticklen, latticklen, ticklen`: Major tick lengths for the longitudinal (x) and latitude (y) axis. +- `latmax`: The maximum absolute latitude for gridlines. +- `nsteps`: *For cartopy axes only.* The number of interpolation steps used to draw gridlines. +- `lonlocator, latlocator`: Used to determine the longitude and latitude gridline locations. +- `lonlocator_kw, latlocator_kw`: Keyword arguments passed to the [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `lonminorlocator, latminorlocator`: As with `lonlocator` and `latlocator` but for the "minor" gridlines. +- `lonminorlocator_kw, latminorlocator_kw`: As with `lonlocator_kw`, and `latlocator_kw` but for the "minor" gridlines. +- `lonlabels, latlabels, labels`: Whether to add non-inline longitude and latitude gridline labels, and on which sides of the map. +- `loninline, latinline, inlinelabels`: *For cartopy axes only.* Whether to add inline longitude and latitude gridline labels. +- `rotatelabels`: *For cartopy axes only.* Whether to rotate non-inline gridline labels so that they automatically follow the map boundary curvature. +- `labelrotation`: The rotation angle in degrees for both longitude and latitude tick labels. +- `lonlabelrotation`: The rotation angle in degrees for longitude tick labels. +- `latlabelrotation`: The rotation angle in degrees for latitude tick labels. +- `labelpad`: *For cartopy axes only.* The padding between non-inline gridline labels and the map boundary. +- `dms`: *For cartopy axes only.* Whether the default locators and formatters should use "minutes" and "seconds" for gridline labels on small scales rather than decimal degrees. +- `lonformatter, latformatter`: Formatter used to style longitude and latitude gridline labels. +- `lonformatter_kw, latformatter_kw`: Keyword arguments passed to the [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `land, ocean, coast, rivers, lakes, borders, innerborders`: Toggles various geographic features. +- `reso`: *For cartopy axes only.* The resolution of geographic features. +- `color`: The color for the axes edge. +- `gridcolor`: The color for the gridline labels. +- `labelcolor`: The color for the gridline labels (`gridlabelcolor` is also allowed). +- `labelsize`: The font size for the gridline labels (`gridlabelsize` is also allowed). +- `labelweight`: The font weight for the gridline labels (`gridlabelweight` is also allowed). +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- _14 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html)""" + ... + + def _sync_shared_tick_state(self, which: str, *, copy_major_locator: bool=False, copy_minor_locator: bool=False, copy_major_formatter: bool=False) -> None: + """Copy explicit tick-state changes from this axis to shared GeoAxes siblings.""" + ... + + def hawkeye(self, xy: Sequence[float], size: float | Sequence[float], *, transform: Any='axes', anchor: str | Sequence[float]='upper right', anchor_transform: Any='axes', aspect: str | float='projection', extent: Optional[Sequence[float]]=None, extent_transform: Any='map', relation: str='auto', indicator: bool=True, connector: bool | str=False, shape: str='box', target: str='box', indicator_kw: Optional[Mapping[str, Any]]=None, **kwargs: Any) -> 'GeoAxes': + """Add a transform-anchored geographic callout inset. + +Parameters +---------- +- `xy`: The parent-axes coordinate at which to anchor the inset. +- `size`: The requested inset width and height as fractions of the parent axes box. +- `transform`: Coordinate system for *xy*. +- `anchor`: The inset point placed at *xy*. +- `anchor_transform`: Coordinate system for a float-tuple `anchor`. +- `aspect`: The inset aspect. +- `grid`: Whether to draw gridlines in the inset. +- `extent`: The geographic scope ``(west, east, south, north)`` displayed by the inset. +- `extent_transform`: Coordinate system for *extent*. +- `relation`: Whether the inset is a zoomed detail of the parent or an overview containing the parent extent. +- `indicator`: Whether to outline *extent* on the parent map when an extent is supplied. +- `connector`: The connector presentation. +- `shape, target`: The inset clipping shape and target marker shape. +- `indicator_kw`: Patch properties for the extent outline and connector lines. +- `**kwargs`: Passed to `~Axes.inset_axes`. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html#ultraplot.axes.GeoAxes.hawkeye)""" + ... + + def _resolve_hawkeye_spec(self, xy: Sequence[float], size: float | Sequence[float], transform: Any, anchor: str | Sequence[float], anchor_transform: Any, extent: Optional[Sequence[float]], extent_transform: Any, relation: str, connector: bool | str, shape: str, target: str) -> '_HawkeyeSpec': + """Validate and normalize raw hawkeye arguments into a `_HawkeyeSpec`.""" + ... + + def _resolve_hawkeye_xy_transform(self, transform: Any) -> Any: + """Resolve the *xy* transform, accepting projection names. + +Reserved names (``'axes'``, ``'data'``, ``'figure'``, ``'subfigure'``, +``'map'``), matplotlib transforms, and cartopy CRS instances are handled +by `_get_transform`. Any other string is treated as a projection +name and resolved to a cartopy CRS so *xy* can be given in arbitrary +projected coordinates.""" + ... + + def _build_hawkeye_inset(self, spec: '_HawkeyeSpec', aspect: str | float, **kwargs: Any) -> 'GeoAxes': + """Create the inset axes and configure its extent, aspect, and boundary.""" + ... + + def _add_hawkeye_indicator(self, inset: 'GeoAxes', spec: '_HawkeyeSpec', indicator_kw: Optional[Mapping[str, Any]], color: Any) -> None: + """Draw the extent indicator patch and any connectors onto the hawkeye.""" + ... + + @override + def _sharey_limits(self, sharey: 'GeoAxes') -> None: + ... + + @override + def _sharex_limits(self, sharex: 'GeoAxes') -> None: + ... + + def _share_limits_with(self, other: 'GeoAxes', which: str) -> None: + """Safely share limits and tickers without resetting things.""" + ... + + def _is_rectilinear(self) -> bool: + ... + + def __share_axis_setup(self, other: 'GeoAxes', *, which: str, labels: bool, limits: bool) -> None: + ... + + @override + def _sharey_setup(self, sharey: 'GeoAxes', *, labels: bool=True, limits: bool=True) -> None: + """Configure shared axes accounting for panels. The input is the +'parent' axes, from which this one will draw its properties.""" + ... + + @override + def _sharex_setup(self, sharex: 'GeoAxes', *, labels: bool=True, limits: bool=True) -> None: + ... + + def _toggle_ticks(self, label: Any, which: str) -> None: + """Toggle x/y tick positions from geo label specifications. + +Accepts the same `labels` forms as format(), including booleans, strings, +and boolean/string sequences. Only sides relevant to the requested axis +are considered: bottom/top for ``which='x'`` and left/right for +``which='y'``.""" + ... + + def _set_gridliner_adapter(self, which: str, adapter: Optional[_GridlinerAdapter]) -> None: + ... + + def _get_gridliner_adapter(self, which: str) -> Optional[_GridlinerAdapter]: + ... + + def _gridliner_adapter(self, which: str, *, create: bool=True) -> Optional[_GridlinerAdapter]: + """Return a cached gridliner adapter, optionally creating it via the backend +builder when missing.""" + ... + + def _iter_gridliner_adapters(self, which: str) -> Iterator[_GridlinerAdapter]: + """Yield available gridliner adapters for the requested tick selection.""" + ... + + def _gridliner_tick_positions(self, axis: str, *, which: str='major') -> np.ndarray: + """Return tick positions from the backend gridliner for a given axis.""" + ... + + @override + def tick_params(self, *args: Any, **kwargs: Any) -> Any: + """Apply tick parameters and mirror a subset of settings onto the backend +gridliner artists so gridline labels respond to common tick tweaks.""" + ... + + def _apply_axis_sharing(self) -> None: + """Enforce the "shared" axis labels and axis tick labels. If this is not +called at drawtime, "shared" labels can be inadvertantly turned off. + +Notes: + - Critical to apply labels to *shared* axes attributes rather than testing + extents or we end up sharing labels with twin axes. + - Similar to how align_super_labels() calls apply_title_above(), this is called + inside align_axis_labels() so we align the correct text. + - The "panel sharing group" refers to axes and panels *above* the bottommost + or to the *right* of the leftmost panel. But the sharing level used for + the leftmost and bottommost is the *figure* sharing level.""" + ... + + def _apply_aspect_and_adjust_panels(self, *, tol: float=1e-09) -> None: + """Apply aspect and then align panels to the adjusted axes box. + +Notes +----- +Cartopy and basemap use different tolerances when detecting whether +apply_aspect() actually changed the axes position.""" + ... + + def _compute_span_extent(self, side: Incomplete, panel: Incomplete, gs: Incomplete, p_r1: Incomplete, p_r2: Incomplete, p_c1: Incomplete, p_c2: Incomplete) -> tuple[float, float] | None: + """If the panel spans beyond the parent's SubplotSpec, compute the visual +extent (min, max) along the span axis from all non-panel axes in range. +Returns None if not a span override or no valid extent found.""" + ... + + @staticmethod + def _compute_adjusted_panel_pos(side: Incomplete, panel_pos: Incomplete, span_extent: Incomplete, original_pos: Incomplete, main_pos: Incomplete, sx: Incomplete, sy: Incomplete, tol: Incomplete) -> Incomplete: + """Compute the new [x0, y0, width, height] for a panel on the given side, +accounting for aspect-adjusted main axes and optional span extent. +Returns the new position list, or None for unknown sides.""" + ... + + def _adjust_panel_positions(self, *, tol: float=1e-09) -> None: + """Adjust panel positions to align with the aspect-constrained main axes. +After apply_aspect() shrinks the main axes, panels should flank the actual +map boundaries rather than the full gridspec allocation.""" + ... + + def _get_gridliner_labels(self, bottom: bool | str | None=None, top: bool | str | None=None, left: bool | str | None=None, right: bool | str | None=None) -> dict[str, list[mtext.Text]]: + ... + + def _update_title_position(self, renderer: Any) -> None: + """Optionally anchor the a-b-c label to the unadjusted subplot slot.""" + ... + + def _toggle_gridliner_labels(self, labeltop: bool | str | None=None, labelbottom: bool | str | None=None, labelleft: bool | str | None=None, labelright: bool | str | None=None, geo: bool | str | None=None) -> None: + """Toggle visibility of gridliner labels for each direction via the backend +adapter. + +Parameters +---------- +labeltop, labelbottom, labelleft, labelright : bool or None + Whether to show labels on each side. If None, do not change. +geo : optional + Not used in this method.""" + ... + + @override + def _is_ticklabel_on(self, side: str) -> bool: + """Check if tick labels are visible on the requested side via the backend adapter.""" + ... + + def _clear_edge_lon_labels(self) -> None: + ... + + def _sync_edge_lon_labels(self) -> None: + """Ensure cartopy top longitude labels include the endpoints when requested.""" + ... + + def _clear_edge_lat_labels(self) -> None: + ... + + def _sync_edge_lat_labels(self) -> None: + """Ensure cartopy left/right latitude labels include the endpoints when requested.""" + ... + + def _prune_corner_labels(self) -> bool: + """Drop endpoint labels at the map corners to reduce crowding.""" + ... + + @override + def draw(self, renderer: Any=None, *args: Any, **kwargs: Any) -> None: + """Draw the Artist (and its children) using the given renderer. + +This has no effect if the artist is not visible (`.Artist.get_visible` +returns False). + +Parameters +---------- +renderer : [RendererBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.RendererBase.html) subclass. + +Notes +----- +This method is overridden in the Artist subclasses.""" + ... + + def _get_lonticklocs(self, which: str='major') -> np.ndarray: + """Retrieve longitude tick locations.""" + ... + + def _get_latticklocs(self, which: str='major') -> np.ndarray: + """Retrieve latitude tick locations.""" + ... + + def _set_view_intervals(self, extent: Sequence[float]) -> None: + """Update view intervals for lon and lat axis.""" + ... + + @staticmethod + def _to_label_array(arg: Any, lon: bool=True) -> list[bool | None]: + """Convert labels argument to length-5 boolean array.""" + ... + + def _format_init_basemap_boundary(self) -> None: + """Initialize basemap boundaries before format triggers gridline work. + +Basemap can create a hidden boundary when gridlines are drawn before the +map boundary is initialized, so we force initialization here.""" + ... + + def _format_rc_context(self, kwargs: MutableMapping[str, Any], *, ticklen: Any, labelcolor: Any, labelsize: Any, labelweight: Any) -> tuple[dict[str, Any], int, Any]: + """Pop rc overrides and prepare context settings for format().""" + ... + + def _format_normalize_label_inputs(self, *, labels: Any, lonlabels: Any, latlabels: Any, loninline: bool | None, latinline: bool | None, inlinelabels: bool | None) -> tuple[Any, Any]: + """Normalize label inputs before rc context is applied.""" + ... + + def _format_resolve_label_arrays(self, *, labels: Any, lonlabels: Any, latlabels: Any) -> tuple[Any, Any, list[bool | None], list[bool | None]]: + """Resolve label toggles and return label arrays for gridliners.""" + ... + + def _format_update_latmax(self, latmax: float | None) -> None: + """Update the latitude gridline cutoff.""" + ... + + def _format_update_major_locators(self, *, lonlocator: Any, lonlines: Any, latlocator: Any, latlines: Any, lonlocator_kw: MutableMapping | None, lonlines_kw: MutableMapping | None, latlocator_kw: MutableMapping | None, latlines_kw: MutableMapping | None) -> None: + """Update major longitude/latitude locators.""" + ... + + def _format_update_minor_locators(self, *, lonminorlocator: Any, lonminorlines: Any, latminorlocator: Any, latminorlines: Any, lonminorlocator_kw: MutableMapping | None, lonminorlines_kw: MutableMapping | None, latminorlocator_kw: MutableMapping | None, latminorlines_kw: MutableMapping | None) -> None: + """Update minor longitude/latitude locators.""" + ... + + def _format_resolve_gridline_params(self, *, loninline: bool | None, latinline: bool | None, inlinelabels: bool | None, rotatelabels: bool | None, labelrotation: float | None, lonlabelrotation: float | None, latlabelrotation: float | None, labelpad: Any, dms: bool | None, nsteps: int | None) -> tuple[bool | None, bool | None, bool | None, float | None, float | None, Any, bool | None, int | None]: + """Resolve gridline-related parameters with rc defaults.""" + ... + + def _format_update_formatters(self, *, lonformatter: Any, latformatter: Any, lonformatter_kw: MutableMapping | None, latformatter_kw: MutableMapping | None, dms: bool | None) -> None: + """Update longitude/latitude formatters and DMS flags.""" + ... + + def _format_apply_grid_updates(self, *, lonlim: tuple[float | None, float | None] | None, latlim: tuple[float | None, float | None] | None, boundinglat: float | None, longrid: bool | None, latgrid: bool | None, longridminor: bool | None, latgridminor: bool | None, lonarray: Sequence[bool | None], latarray: Sequence[bool | None], loninline: bool | None, latinline: bool | None, rotatelabels: bool | None, lonlabelrotation: float | None, latlabelrotation: float | None, labelpad: Any, nsteps: int | None) -> tuple[tuple[float | None, float | None], tuple[float | None, float | None]]: + """Apply extent, features, and gridline updates for format().""" + ... + + def _format_apply_ticklen(self, *, lonlim: tuple[float | None, float | None], latlim: tuple[float | None, float | None], boundinglat: float | None, ticklen: Any, lonticklen: Any, latticklen: Any) -> None: + """Apply tick length updates, including any extent refresh for geoticks.""" + ... + + def format(self, *, aspect: str | float | None=None, abcanchor: str | None=None, extent: str | None=None, round: bool | None=None, lonlim: tuple[float | None, float | None] | None=None, latlim: tuple[float | None, float | None] | None=None, boundinglat: float | None=None, longrid: bool | None=None, latgrid: bool | None=None, longridminor: bool | None=None, latgridminor: bool | None=None, ticklen: Any=None, lonticklen: Any=None, latticklen: Any=None, latmax: float | None=None, nsteps: int | None=None, lonlocator: Any=None, lonlines: Any=None, latlocator: Any=None, latlines: Any=None, lonminorlocator: Any=None, lonminorlines: Any=None, latminorlocator: Any=None, latminorlines: Any=None, lonlocator_kw: MutableMapping | None=None, lonlines_kw: MutableMapping | None=None, latlocator_kw: MutableMapping | None=None, latlines_kw: MutableMapping | None=None, lonminorlocator_kw: MutableMapping | None=None, lonminorlines_kw: MutableMapping | None=None, latminorlocator_kw: MutableMapping | None=None, latminorlines_kw: MutableMapping | None=None, lonformatter: Any=None, latformatter: Any=None, lonformatter_kw: MutableMapping | None=None, latformatter_kw: MutableMapping | None=None, labels: Any=None, latlabels: Any=None, lonlabels: Any=None, rotatelabels: bool | None=None, labelrotation: float | None=None, lonlabelrotation: float | None=None, latlabelrotation: float | None=None, loninline: bool | None=None, latinline: bool | None=None, inlinelabels: bool | None=None, dms: bool | None=None, labelpad: Any=None, labelcolor: Any=None, labelsize: Any=None, labelweight: Any=None, **kwargs: Any) -> None: + """Modify map limits, longitude and latitude gridlines, geographic features, and more. + +Parameters +---------- +- `aspect`: The map aspect ratio. +- `abcanchor`: The coordinate box used for the a-b-c label. +- `round`: *For polar cartopy axes only*. +- `extent`: *For cartopy axes only*. +- `lonlim, latlim`: *For cartopy axes only.* The approximate longitude and latitude boundaries of the map, applied with `~cartopy.mpl.geoaxes.GeoAxes.set_extent`. +- `boundinglat`: *For cartopy axes only.* The edge latitude for the circle bounding North Pole and South Pole-centered projections. +- `longrid, latgrid, grid`: Whether to draw longitude and latitude gridlines. +- `longridminor, latgridminor, gridminor`: Whether to draw "minor" longitude and latitude lines. +- `lonticklen, latticklen, ticklen`: Major tick lengths for the longitudinal (x) and latitude (y) axis. +- `latmax`: The maximum absolute latitude for gridlines. +- `nsteps`: *For cartopy axes only.* The number of interpolation steps used to draw gridlines. +- `lonlocator, latlocator`: Used to determine the longitude and latitude gridline locations. +- `lonlocator_kw, latlocator_kw`: Keyword arguments passed to the [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `lonminorlocator, latminorlocator`: As with `lonlocator` and `latlocator` but for the "minor" gridlines. +- `lonminorlocator_kw, latminorlocator_kw`: As with `lonlocator_kw`, and `latlocator_kw` but for the "minor" gridlines. +- `lonlabels, latlabels, labels`: Whether to add non-inline longitude and latitude gridline labels, and on which sides of the map. +- `loninline, latinline, inlinelabels`: *For cartopy axes only.* Whether to add inline longitude and latitude gridline labels. +- `rotatelabels`: *For cartopy axes only.* Whether to rotate non-inline gridline labels so that they automatically follow the map boundary curvature. +- `labelrotation`: The rotation angle in degrees for both longitude and latitude tick labels. +- `lonlabelrotation`: The rotation angle in degrees for longitude tick labels. +- `latlabelrotation`: The rotation angle in degrees for latitude tick labels. +- `labelpad`: *For cartopy axes only.* The padding between non-inline gridline labels and the map boundary. +- `dms`: *For cartopy axes only.* Whether the default locators and formatters should use "minutes" and "seconds" for gridline labels on small scales rather than decimal degrees. +- `lonformatter, latformatter`: Formatter used to style longitude and latitude gridline labels. +- `lonformatter_kw, latformatter_kw`: Keyword arguments passed to the [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `land, ocean, coast, rivers, lakes, borders, innerborders`: Toggles various geographic features. +- `reso`: *For cartopy axes only.* The resolution of geographic features. +- `color`: The color for the axes edge. +- `gridcolor`: The color for the gridline labels. +- `labelcolor`: The color for the gridline labels (`gridlabelcolor` is also allowed). +- `labelsize`: The font size for the gridline labels (`gridlabelsize` is also allowed). +- `labelweight`: The font weight for the gridline labels (`gridlabelweight` is also allowed). +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- `abcloc, titleloc`: Strings indicating the location for the a-b-c label and main title. +- `abcborder, titleborder`: Whether to draw a white border around titles and a-b-c labels positioned inside the axes. +- _21 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html#ultraplot.axes.GeoAxes.format)""" + ... + + def choropleth(self, geometries: Sequence[Any], values: Sequence[Any] | None=None, *, transform: Any=None, country: bool=False, country_reso: str | None=None, country_territories: bool | None=None, colorbar: Any=None, colorbar_kw: MutableMapping[str, Any] | None=None, missing_kw: MutableMapping[str, Any] | None=None, **kwargs: Any) -> mcollections.PatchCollection: + """Draw polygon geometries colored by numeric values. + +Parameters +---------- +- `geometries`: Sequence of polygon-like shapely geometries. +- `values`: Numeric values mapped to colors. +- `transform`: The input coordinate system for `geometries`. +- `country`: Interpret `geometries` as country identifiers and resolve them to Natural Earth polygons before plotting. +- `country_reso`: The Natural Earth country resolution used when `country=True`. +- `country_territories`: Whether to keep distant territories for multi-part country geometries when `country=True`. +- `missing_kw`: Style applied to geometries whose values are missing or non-finite. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html#ultraplot.axes.GeoAxes.choropleth)""" + ... + + def _add_geoticks(self, x_or_y: str, itick: Any, ticklen: Any) -> None: + """Add tick marks to the geographic axes. + +Parameters +---------- +x_or_y : {'x', 'y'} + The axis to add ticks to ('x' for longitude, 'y' for latitude). +itick, ticklen : unit-spec, default: [tick.len](https://ultraplot.readthedocs.io/en/stable/search.html?q=tick.len) + Major tick lengths for the x and y axis. + If float, units are points. If string, interpreted by [units](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.utils.units.html). + Use the argument `ticklen` to set both at once. + +Notes +----- +This method handles proper tick mark drawing for geographic projections +while respecting the current gridline settings.""" + ... + + def _add_gridline_labels(self, ax: maxis.Axis, gl: tuple[GridlineDict, GridlineDict], padding: float | int=8) -> None: + """This function is intended for the Basemap backend +and mirrors the label placement behavior of Cartopy. +See: https://cartopy.readthedocs.io/stable/reference/generated/cartopy.mpl.gridliner.Gridliner.html""" + ... + + @property + def gridlines_major(self) -> Any: + """The cartopy `~cartopy.mpl.gridliner.Gridliner` +used for major gridlines or a 2-tuple containing the +(longitude, latitude) major gridlines returned by +basemap's `drawmeridians` +and `drawparallels`. +This can be used for customization and debugging.""" + ... + + @property + def gridlines_minor(self) -> Any: + """The cartopy `~cartopy.mpl.gridliner.Gridliner` +used for minor gridlines or a 2-tuple containing the +(longitude, latitude) minor gridlines returned by +basemap's `drawmeridians` +and `drawparallels`. +This can be used for customization and debugging.""" + ... + + @property + def projection(self) -> Any: + """The cartopy `~cartopy.crs.Projection` or basemap `~mpl_toolkits.basemap.Basemap` +instance associated with this axes.""" + ... + + @projection.setter + def projection(self, map_projection: Any) -> None: + """The cartopy `~cartopy.crs.Projection` or basemap `~mpl_toolkits.basemap.Basemap` +instance associated with this axes.""" + ... + +class _CartopyAxes(GeoAxes, _GeoAxes): + """Axes subclass for plotting cartopy projections.""" + _name = 'cartopy' + _name_aliases = ('geo', 'geographic') + _proj_class = Projection + _PANEL_TOL = 1e-09 + _proj_north = (pproj.NorthPolarStereo, pproj.NorthPolarGnomonic, pproj.NorthPolarAzimuthalEquidistant, pproj.NorthPolarLambertAzimuthalEqualArea) + _proj_south = (pproj.SouthPolarStereo, pproj.SouthPolarGnomonic, pproj.SouthPolarAzimuthalEquidistant, pproj.SouthPolarLambertAzimuthalEqualArea) + _proj_polar = _proj_north + _proj_south + + def __init__(self, *args: Any, map_projection: Any=None, **kwargs: Any) -> None: + """Parameters +---------- +map_projection : ~cartopy.crs.Projection + The map projection. +*args, **kwargs + Passed to `GeoAxes`.""" + ... + + @staticmethod + def _get_circle_path(N: int=100) -> mpath.Path: + """Return a circle [Path](https://matplotlib.org/stable/api/_as_gen/matplotlib.path.Path.html) used as the outline for polar +stereographic, azimuthal equidistant, Lambert conformal, and gnomonic +projections. This was developed from [this cartopy example](https://cartopy.readthedocs.io/v0.25.0.post2/gallery/lines_and_polygons/always_circular_stereo.html).""" + ... + + def _get_global_extent(self) -> list[float]: + """Return the global extent with meridian properly shifted.""" + ... + + def _get_lon0(self) -> float: + """Get the central longitude. Default is ``0``.""" + ... + + def gridlines(self, crs: Any=None, draw_labels: bool | str | None=False, xlocs: mticker.Locator | Sequence[float] | None=None, ylocs: mticker.Locator | Sequence[float] | None=None, dms: bool=False, x_inline: bool | None=None, y_inline: bool | None=None, auto_inline: bool=True, xformatter: Any=None, yformatter: Any=None, xlim: Sequence[float] | None=None, ylim: Sequence[float] | None=None, rotate_labels: bool | float | None=None, xlabel_style: MutableMapping[str, Any] | None=None, ylabel_style: MutableMapping[str, Any] | None=None, labels_bbox_style: MutableMapping[str, Any] | None=None, xpadding: float | None=5, ypadding: float | None=5, offset_angle: float=25, auto_update: bool | None=None, formatter_kwargs: MutableMapping[str, Any] | None=None, **kwargs: Any) -> _CartopyGridlinerProtocol: + """Override cartopy gridlines to use a local Gridliner subclass.""" + ... + + def _init_gridlines(self) -> _CartopyGridlinerProtocol: + """Create "major" and "minor" gridliners managed by ultraplot.""" + ... + + def _build_gridliner_adapter(self, which: str='major') -> Optional[_GridlinerAdapter]: + ... + + def _update_background(self, **kwargs: Any) -> None: + """Update the map background patches. This is called in `Axes.format`.""" + ... + + def _update_boundary(self, round: bool | None=None) -> None: + """Update the map boundary path.""" + ... + + def _update_extent_mode(self, extent: str | None=None, boundinglat: float | None=None) -> None: + """Update the extent mode.""" + ... + + def _update_extent(self, lonlim: tuple[float | None, float | None] | None=None, latlim: tuple[float | None, float | None] | None=None, boundinglat: float | None=None) -> None: + """Set the projection extent.""" + ... + + def _update_features(self) -> None: + """Update geographic features.""" + ... + + def _update_gridlines(self, gl: _CartopyGridlinerProtocol, which: str='major', longrid: bool | None=None, latgrid: bool | None=None, nsteps: int | None=None) -> None: + """Update gridliner object with axis locators, and toggle gridlines on and off.""" + ... + + def _update_major_gridlines(self, longrid: bool | None=None, latgrid: bool | None=None, lonarray: Sequence[bool | None] | None=None, latarray: Sequence[bool | None] | None=None, loninline: bool | None=None, latinline: bool | None=None, labelpad: Any=None, rotatelabels: bool | None=None, lonlabelrotation: float | None=None, latlabelrotation: float | None=None, nsteps: int | None=None) -> None: + """Update major gridlines.""" + ... + + def _update_minor_gridlines(self, longrid: bool | None=None, latgrid: bool | None=None, nsteps: int | None=None) -> None: + """Update minor gridlines.""" + ... + + def get_extent(self, crs: Any=None) -> Sequence[float]: + ... + + @override + def draw(self, renderer: Any=None, *args: Any, **kwargs: Any) -> None: + """Override draw to adjust panel positions for cartopy axes. + +Cartopy's apply_aspect() can shrink the main axes to enforce the projection +aspect ratio. Panels occupy separate gridspec slots, so we reposition them +after the main axes has applied its aspect but before the panel axes are drawn.""" + ... + + def get_tightbbox(self, renderer: Any, *args: Any, **kwargs: Any) -> Any: + """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` subclass + 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 : bool, 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. + +for_layout_only : default: False + The bounding box will *not* include the x-extent of the title and + the xlabel, or the y-extent of the ylabel. + +Returns +------- +`.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""" + ... + + def set_extent(self, extent: Sequence[float], crs: Any=None) -> Any: + ... + + def set_global(self) -> Any: + ... + +class _BasemapAxes(GeoAxes): + """Axes subclass for plotting basemap projections.""" + _name = 'basemap' + _proj_class = Basemap + _proj_north = ('npaeqd', 'nplaea', 'npstere') + _proj_south = ('spaeqd', 'splaea', 'spstere') + _proj_polar = _proj_north + _proj_south + _proj_non_rectangular = _proj_polar + ('ortho', 'geos', 'nsper', 'moll', 'hammer', 'robin', 'eck4', 'kav7', 'mbtfpq', 'sinu', 'vandg') + _PANEL_TOL = 1e-06 + + def __init__(self, *args: Any, map_projection: Any=None, **kwargs: Any) -> None: + """Parameters +---------- +map_projection : ~mpl_toolkits.basemap.Basemap + The map projection. +*args, **kwargs + Passed to `GeoAxes`.""" + ... + + def get_tightbbox(self, renderer: Any, *args: Any, **kwargs: Any) -> Any: + """Get tight bounding box, adjusting panel positions after aspect is applied. + +This ensures panels are properly aligned when saving figures, as apply_aspect() +may be called during the rendering process.""" + ... + + @override + def draw(self, renderer: Any=None, *args: Any, **kwargs: Any) -> None: + """Override draw to adjust panel positions for basemap axes. + +Basemap projections also rely on apply_aspect() and can shrink the main axes; +panels must be repositioned to flank the visible map boundaries.""" + ... + + def _turnoff_tick_labels(self, locator: GridlineDict) -> None: + """For GeoAxes with are dealing with a duality. Basemap axes behave differently than Cartopy axes and vice versa. UltraPlot abstracts away from these by providing GeoAxes. For basemap axes we need to turn off the tick labels as they will be handles by GeoAxis""" + ... + + def _get_lon0(self) -> float: + """Get the central longitude.""" + ... + + @staticmethod + def _iter_gridlines(dict_: GridlineDict | None) -> Iterator[Any]: + """Iterate over longitude latitude lines.""" + ... + + def _build_gridliner_adapter(self, which: str='major') -> Optional[_GridlinerAdapter]: + ... + + def _update_background(self, **kwargs: Any) -> None: + """Update the map boundary patches. This is called in `Axes.format`.""" + ... + + def _update_boundary(self, round: bool | None=None) -> None: + """No-op. Boundary mode cannot be changed in basemap.""" + ... + + def _update_extent_mode(self, extent: str | None=None, boundinglat: float | None=None) -> None: + """No-op. Extent mode cannot be changed in basemap.""" + ... + + def _update_extent(self, lonlim: tuple[float | None, float | None] | None=None, latlim: tuple[float | None, float | None] | None=None, boundinglat: float | None=None) -> None: + """No-op. Map bounds cannot be changed in basemap.""" + ... + + def _update_features(self) -> None: + """Update geographic features.""" + ... + + def _update_gridlines(self, which: str='major', longrid: bool | None=None, latgrid: bool | None=None, lonarray: Sequence[bool | None] | None=None, latarray: Sequence[bool | None] | None=None, lonlabelrotation: float | None=None, latlabelrotation: float | None=None) -> None: + """Apply changes to the basemap axes.""" + ... + + def _update_major_gridlines(self, longrid: bool | None=None, latgrid: bool | None=None, lonarray: Sequence[bool | None] | None=None, latarray: Sequence[bool | None] | None=None, loninline: bool | None=None, latinline: bool | None=None, rotatelabels: bool | None=None, lonlabelrotation: float | None=None, latlabelrotation: float | None=None, labelpad: Any=None, nsteps: int | None=None) -> None: + """Update major gridlines.""" + ... + + def _update_minor_gridlines(self, longrid: bool | None=None, latgrid: bool | None=None, nsteps: int | None=None) -> None: + """Update minor gridlines.""" + ... + +def _is_platecarree_crs(transform: Any) -> bool: + """Return whether `transform` represents plain longitude-latitude coordinates.""" + ... + +def _choropleth_close_path(vertices: Any) -> mpath.Path | None: + """Convert a single polygon ring into a closed path.""" + ... + +def _choropleth_iter_rings(geometry: Any) -> Iterator[Any]: + """Yield polygon rings from shapely-like polygon geometries.""" + ... + +def _choropleth_project_vertices(ax: GeoAxes, vertices: Any, *, transform: Any=None) -> np.ndarray: + """Project polygon-ring vertices into the target map coordinate system.""" + ... + +def _choropleth_geometry_path(ax: GeoAxes, geometry: Any, *, transform: Any=None) -> mpath.Path | None: + """Convert a polygon geometry to a projected matplotlib path.""" + ... + +def _choropleth_country_inputs(geometries: Any, values: Any, *, transform: Any=None, resolution: str='110m', include_far: bool=False) -> tuple[list[Any], Any, Any]: + """Resolve country identifiers into polygon geometries.""" + ... + +def _choropleth_edge_collection_kw(kw: Mapping[str, Any], *, zorder: float, explicit_zorder: bool=False) -> dict[str, Any] | None: + """Return edge-only collection settings when polygon outlines should overlay features.""" + ... + +def _is_rectilinear_projection(ax: Any) -> bool: + """Check if the axis has a flat projection (works with Cartopy).""" + ... diff --git a/ultraplot/axes/plot.py b/ultraplot/axes/plot.py index acb4a7a63..e2a615d03 100644 --- a/ultraplot/axes/plot.py +++ b/ultraplot/axes/plot.py @@ -111,7 +111,7 @@ coordinates. Otherwise, the `y` coordinates are ``np.arange(0, y.shape[0])`` and the `x` coordinates are ``np.arange(0, y.shape[1])``. * For ``pcolor`` and ``pcolormesh``, calculate coordinate *edges* using - `~ultraplot.utils.edges` or `:func:`~ultraplot.utils.edges2d`` if *centers* were provided. + `~ultraplot.utils.edges` or :func:`~ultraplot.utils.edges2d` if *centers* were provided. For all other methods, calculate coordinate *centers* if *edges* were provided. * If the `x` or `y` coordinates are `pint.Quantity`, auto-add the pint unit registry to matplotlib's unit registry using `~pint.UnitRegistry.setup_matplotlib`. If the @@ -1185,11 +1185,12 @@ Parameters ---------- %(plot.args_1d_{which})s -stemlinewdith: str, default `rc["lollipop.stemlinewidth"]` -stemcolor: str, default `rc["lollipop.stemcolor"]` - Line color of the lines connecting the dots to the {which}-axis. Defaults to `rc["lollipop.linecolor"]`. -stemlinestyle: str, default: `rc["lollipop.stemlinestyle"]` - The style of the lines connecting the dots to the {which}-axis. Defaults to `rc["lollipop.linestyle"]`. +stemlinewidth : str, default: :rc:`lollipop.stemlinewidth` + The width of the lines connecting the dots to the {which}-axis. +stemcolor : str, default: :rc:`lollipop.stemcolor` + Line color of the lines connecting the dots to the {which}-axis. Defaults to :rc:`lollipop.linecolor`. +stemlinestyle : str, default: :rc:`lollipop.stemlinestyle` + The style of the lines connecting the dots to the {which}-axis. Defaults to :rc:`lollipop.linestyle`. s, size, ms, markersize : float or array-like or unit-spec, optional The marker size area(s). If this is an array matching the shape of `x` and `y`, the units are scaled by `smin` and `smax`. If this contains unit string(s), it @@ -1695,13 +1696,13 @@ layout : callable or dict, optional A layout function or a precomputed dict mapping nodes to 2D positions. If a function is given, it is called as ``layout(g, **layout_kw)`` to compute positions. See :func:`networkx.drawing.nx_pylab.draw` for more information. -nodes : bool or iterable, default: rc["graph.draw_nodes"] +nodes : bool or iterable, default: :rc:`graph.draw_nodes` Which nodes to draw. If `True`, all nodes are drawn. If an iterable is provided, only the specified nodes are included. This effectively acts as `nodelist` in :func:`networkx.drawing.nx_pylab.draw_networkx_nodes`. -edges : bool or iterable, default: rc["graph.draw_edges"] +edges : bool or iterable, default: :rc:`graph.draw_edges` Which edges to draw. If `True`, all edges are drawn. If an iterable of edge tuples is provided, only those edges are included. This effectively acts as `edgelist` in :func:`networkx.drawing.nx_pylab.draw_networkx_edges`. -labels : bool or iterable, default: `rc["graph.draw_labels`] +labels : bool or iterable, default: :rc:`graph.draw_labels` Whether to show node labels. If `True`, labels are drawn using node names. If an iterable is given, only those nodes are labeled. layout_kw : dict, default: {} @@ -2486,6 +2487,7 @@ def ribbon( topic_label_box=topic_label_box, ) + @docstring._snippet_manager def circos( self, sectors: Mapping[str, Any], @@ -2741,6 +2743,7 @@ def radar(self, *args, **kwargs): """ return self.radar_chart(*args, **kwargs) + @docstring._snippet_manager def circos( self, sectors: Mapping[str, Any], diff --git a/ultraplot/axes/plot.pyi b/ultraplot/axes/plot.pyi new file mode 100644 index 000000000..cfedc189d --- /dev/null +++ b/ultraplot/axes/plot.pyi @@ -0,0 +1,3332 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The second-level axes subclass used for all ultraplot figures. +Implements plotting method overrides. +""" +from _typeshed import Incomplete +import contextlib +import inspect +import itertools +import re +import sys +from collections.abc import Callable, Iterable +from numbers import Integral, Number +from typing import Any, Iterable, Mapping, Optional, Sequence, TypeAlias, Union +import matplotlib as mpl +import matplotlib.artist as martist +import matplotlib.axes as maxes +import matplotlib.cbook as cbook +import matplotlib.cm as mcm +import matplotlib.collections as mcollections +import matplotlib.colors as mcolors +import matplotlib.container as mcontainer +import matplotlib.contour as mcontour +import matplotlib.image as mimage +import matplotlib.lines as mlines +import matplotlib.patches as mpatches +import matplotlib.pyplot as mplt +import matplotlib.ticker as mticker +import numpy as np +import numpy.ma as ma +from numpy.typing import ArrayLike +from packaging import version +from .. import colors as pcolors +from .. import constructor, utils +from ..config import rc +from ..internals import _get_aliases, _not_none, _pop_kwargs, _pop_params, _pop_props, _version_mpl, context, docstring, guides, ic, inputs, warnings +from ..utils import units +from . import base +try: + from cartopy.crs import PlateCarree +except ModuleNotFoundError: + PlateCarree = object +__all__ = ['PlotAxes'] +EDGEWIDTH = 0.3 +DataInput: TypeAlias = ArrayLike +ColorTupleRGB: TypeAlias = tuple[float, float, float] +ColorTupleRGBA: TypeAlias = tuple[float, float, float, float] +ColorInput: TypeAlias = DataInput | str | ColorTupleRGB | ColorTupleRGBA | None +ParsedColor: TypeAlias = DataInput | list[str] | str | None +_args_1d_docstring = ... +_args_1d_multi_docstring = ... +_args_2d_docstring = ... +_args_1d_shared_docstring = ... +_args_2d_shared_docstring = ... +_curved_quiver_docstring = ... +_sankey_docstring = ... +_chord_docstring = ... +_radar_docstring = ... +_circos_docstring = ... +_phylogeny_docstring = ... +_circos_bed_docstring = ... +_guide_docstring = ... +_inbounds_docstring = ... +_error_means_docstring = ... +_error_bars_docstring = ... +_error_shading_docstring = ... +_cycle_docstring = ... +_cmap_norm_docstring = ... +_log_doc = '\nPlot {kind}\n\nUltraPlot is optimized for visualizing logarithmic scales by default. For cases with large differences in magnitude,\nwe recommend setting `rc["formatter.log"] = True` to enhance axis label formatting.\n{matplotlib_doc}\n' +_vmin_vmax_docstring = ... +_manual_levels_docstring = ... +_auto_levels_docstring = ... +_label_docstring = ... +_labels_1d_docstring = ... +_labels_2d_docstring = ... +_negpos_docstring = ... +_plot_docstring = ... +_step_docstring = ... +_stem_docstring = ... +_lines_docstring = ... +_parametric_docstring = ... +_scatter_docstring = ... +_beeswarm_docstring = ... +_bar_docstring = ... +_lollipop_docstring = ... +_fill_docstring = ... +_boxplot_docstring = ... +_violinplot_docstring = ... +_ridgeline_docstring = ... +_hist_docstring = ... +_weights_docstring = ... +_hist2d_docstring = ... +_bins_docstring = ... +_pie_docstring = ... +_contour_docstring = ... +_graph_docstring = ... +_pcolor_docstring = ... +_heatmap_descrip = '\ngrid boxes with formatting suitable for heatmaps. Ensures square grid\nboxes, adds major ticks to the center of each grid box, disables minor\nticks and gridlines, and sets :rcraw:`cmap.discrete` to ``False`` by default\n'.strip() +_heatmap_aspect = "\naspect : {'equal', 'auto'} or float, default: :rc:`image.aspet`\n Modify the axes aspect ratio. The aspect ratio is of particular relevance for\n heatmaps since it may lead to non-square grid boxes. This parameter is a shortcut\n for calling `~matplotlib.axes.set_aspect`. The options are as follows:\n\n * Number: The data aspect ratio.\n * ``'equal'``: A data aspect ratio of 1.\n * ``'auto'``: Allows the data aspect ratio to change depending on\n the layout. In general this results in non-square grid boxes.\n".rstrip() +_show_docstring = ... +_flow_docstring = ... + +def _get_vert(vert: Incomplete=None, orientation: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Get the orientation specified as either `vert` or `orientation`. This is +used internally by various helper functions.""" + ... + +def _parse_vert(vert: Incomplete=None, orientation: Incomplete=None, default_vert: Incomplete=None, default_orientation: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Interpret both 'vert' and 'orientation' and add to outgoing keyword args +if a default is provided.""" + ... + +def _parse_kde_kw(kde_kw: Incomplete=None, *, points: Incomplete=None, weights: Incomplete=None) -> Incomplete: + """Split `kde_kw` into the keyword arguments that control the kernel density +estimate, i.e. those accepted by [_dist_kde](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.internals.inputs._dist_kde.html), and +the remaining line properties meant for [plot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html). The +`points` and `weights` arguments supply defaults from the parent command.""" + ... + +def _get_hist_colors(res: Incomplete, n: Incomplete) -> Incomplete: + """Return one color per column of a histogram drawn by +[hist](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.hist.html), so that overlays can be colored to match.""" + ... + +class PlotAxes(base.Axes): + """The second lowest-level [Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html) subclass used by ultraplot. +Implements all plotting overrides.""" + + def curved_quiver(self, x: np.ndarray, y: np.ndarray, u: np.ndarray, v: np.ndarray, linewidth: Optional[float]=None, color: Optional[Union[str, Any]]=None, cmap: Optional[Any]=None, norm: Optional[Any]=None, arrowsize: Optional[float]=None, arrowstyle: Optional[str]=None, transform: Optional[Any]=None, zorder: Optional[int]=None, start_points: Optional[np.ndarray]=None, scale: Optional[float]=None, grains: Optional[int]=None, density: Optional[int]=None, arrow_at_end: Optional[bool]=None, colorbar: Optional[str]=None, colorbar_kw: Optional[dict[str, Any]]=None) -> Incomplete: + """Draws curved vector field arrows (streamlines with arrows) for 2D vector fields. + +Parameters +---------- +x, y : 1D or 2D arrays + Grid coordinates. +u, v : 2D arrays + Vector components. +color : color or 2D array, optional + Streamline color. +density : float or (float, float), optional + Controls the closeness of streamlines. +grains : int or (int, int), optional + Number of seed points in x and y. +linewidth : float or 2D array, optional + Width of streamlines. +cmap, norm : optional + Colormap and normalization for array colors. +colorbar, colorbar_kw : optional + Add a colorbar for array-valued streamline colors. +arrowsize : float, optional + Arrow size scaling. +arrowstyle : str, optional + Arrow style specification. +transform : optional + Matplotlib transform. +zorder : float, optional + Z-order for lines/arrows. +start_points : (N, 2) array, optional + Starting points for streamlines. + +Returns +------- +CurvedQuiverSet + Container with attributes: + - lines: LineCollection of streamlines + - arrows: PatchCollection of arrows + +Notes +----- +The implementation of this function is based on the `dfm_tools` repository. +Original file: https://github.com/Deltares/dfm_tools/blob/829e76f48ebc42460aae118cc190147a595a5f26/dfm_tools/modplot.py""" + ... + + def sankey(self, flows: Any, labels: Optional[Sequence[str]]=None, orientations: Optional[Sequence[int]]=None, pathlengths: Optional[Union[float, Sequence[float]]]=None, trunklength: Optional[float]=None, patchlabel: Optional[str]=None, *, nodes: Any=None, links: Any=None, node_kw: Optional[Mapping[str, Any]]=None, flow_kw: Optional[Mapping[str, Any]]=None, label_kw: Optional[Mapping[str, Any]]=None, node_label_kw: Optional[Mapping[str, Any]]=None, flow_label_kw: Optional[Mapping[str, Any]]=None, node_label_box: Optional[Union[bool, Mapping[str, Any]]]=None, style: Optional[str]=None, node_order: Optional[Sequence[Any]]=None, layer_order: Optional[Sequence[int]]=None, group_cycle: Optional[Sequence[Any]]=None, flow_other: Optional[float]=None, other_label: Optional[str]=None, value_format: Optional[Union[str, Callable[[float], str]]]=None, node_label_outside: Optional[Union[bool, str]]=None, node_label_offset: Optional[float]=None, flow_sort: Optional[bool]=None, flow_label_pos: Optional[float]=None, node_labels: Optional[bool]=None, flow_labels: Optional[bool]=None, align: Optional[str]=None, layers: Optional[Mapping[Any, int]]=None, scale: Optional[float]=None, unit: Optional[str]=None, format: Optional[str]=None, gap: Optional[float]=None, radius: Optional[float]=None, shoulder: Optional[float]=None, offset: Optional[float]=None, head_angle: Optional[float]=None, margin: Optional[float]=None, tolerance: Optional[float]=None, prior: Optional[int]=None, connect: Optional[tuple[int, int]]=None, rotation: Optional[float]=None, **kwargs: Any) -> Any: + """Draw a Sankey diagram. + +Parameters +---------- +- `flows`: If a numeric sequence, use Matplotlib's Sankey implementation. +- `nodes`: Node identifiers or dicts with ``id``/``label``/``color`` keys. +- `labels`: Labels for each flow in Matplotlib's Sankey mode. +- `orientations`: Flow orientations (-1: down, 0: right, 1: up) for Matplotlib's Sankey. +- `pathlengths`: Path lengths for each flow in Matplotlib's Sankey. +- `trunklength`: Length of the trunk between the input and output flows. +- `patchlabel`: Label for the main patch in Matplotlib's Sankey mode. +- `scale, unit, format, gap, radius, shoulder, offset, head_angle, margin, tolerance`: Passed to [matplotlib.sankey.Sankey](https://matplotlib.org/stable/api/_as_gen/matplotlib.sankey.Sankey.html). +- `prior`: Index of a prior diagram to connect to. +- `connect`: Flow indices for the prior and current diagram connection. +- `rotation`: Rotation angle in degrees. +- `node_kw, flow_kw, label_kw`: Style dictionaries for the layered Sankey renderer. +- `node_label_kw, flow_label_kw`: Label style dictionaries for node and flow labels in layered mode. +- `node_label_box`: If ``True``, draw a rounded box behind node labels. +- `style`: Built-in styling presets for layered mode. +- `node_order`: Explicit node ordering for layered mode. +- `layer_order`: Explicit layer ordering for layered mode. +- `group_cycle`: Cycle for flow group colors (defaults to flow cycle). +- `flow_other`: Aggregate flows below this threshold into a single ``other_label``. +- `other_label`: Label for the aggregated flow target. +- `value_format`: Formatter for flow labels when not explicitly provided. +- `node_label_outside`: Place node labels outside narrow nodes. +- `node_label_offset`: Offset for outside node labels (axes-relative units). +- `flow_sort`: Whether to sort flows by target position to reduce crossings. +- `flow_label_pos`: Horizontal placement for single flow labels (0 to 1 along the ribbon). +- `node_labels, flow_labels`: Whether to draw node or flow labels in layered mode. +- `align`: Vertical alignment for nodes within each layer in layered mode. +- `layers`: Manual layer assignments for nodes in layered mode. +- `**kwargs`: Patch properties passed to [matplotlib.sankey.Sankey.add](https://matplotlib.org/stable/api/_as_gen/matplotlib.sankey.Sankey.add.html) in Matplotlib mode. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.sankey)""" + ... + + def ribbon(self, data: Any, *, id_col: str='id', period_col: str='period', topic_col: str='topic', value_col: str | None=None, period_order: Sequence[Any] | None=None, topic_order: Sequence[Any] | None=None, group_map: Mapping[Any, Any] | None=None, group_order: Sequence[Any] | None=None, group_colors: Mapping[Any, Any] | None=None, xmargin: Optional[float]=None, ymargin: Optional[float]=None, row_height_ratio: Optional[float]=None, node_width: Optional[float]=None, flow_curvature: Optional[float]=None, flow_alpha: Optional[float]=None, show_topic_labels: Optional[bool]=None, topic_label_offset: Optional[float]=None, topic_label_size: Optional[float]=None, topic_label_box: Optional[bool]=None) -> dict[str, Any]: + """Draw a fixed-row, top-aligned ribbon flow diagram from long-form records. + +Parameters +---------- +data : pandas.DataFrame or mapping-like + Long-form records with entity id, period, and topic columns. +id_col, period_col, topic_col : str, optional + Column names for entity id, period, and topic. +value_col : str, optional + Optional weight column. If omitted, each record is weighted as 1. +period_order, topic_order : sequence, optional + Explicit ordering for periods and topic rows. +group_map : mapping, optional + Topic-to-group mapping used for grouped ordering and colors. +group_order : sequence, optional + Group ordering for row arrangement. +group_colors : mapping, optional + Group-to-color mapping. Missing groups use the patch color cycle. +xmargin, ymargin : float, optional + Plot-space margins in normalized axes coordinates. +row_height_ratio : float, optional + Scale factor controlling row occupancy by nodes/flows. +node_width : float, optional + Node column width in normalized axes coordinates. +flow_curvature : float, optional + Bezier curvature for ribbons. +flow_alpha : float, optional + Ribbon alpha. +show_topic_labels : bool, optional + Whether to draw topic labels on the right. +topic_label_offset : float, optional + Offset for right-side topic labels. +topic_label_size : float, optional + Topic label font size. +topic_label_box : bool, optional + Whether to draw white backing boxes behind topic labels. + +Returns +------- +dict + Mapping of created artists and resolved orders.""" + ... + + def circos(self, sectors: Mapping[str, Any], *, start: float=0, end: float=360, space: float | Sequence[float]=0, endspace: bool=True, sector2clockwise: Mapping[str, bool] | None=None, show_axis_for_debug: bool=False, plot: bool=False, tooltip: bool=False) -> Incomplete: + """Create a Circos instance using pyCirclize. + +Parameters +---------- +sectors : mapping + Sector name and size (or range) mapping. +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +space : float or sequence of float, optional + Space degrees between sectors. +endspace : bool, optional + If True, insert space after the final sector. +sector2clockwise : dict, optional + Override clockwise settings per sector. +show_axis_for_debug : bool, optional + Show the polar axis for debug layout. +plot : bool, optional + If True, immediately render the circos figure on this axes. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def phylogeny(self, tree_data: Any, *, start: Optional[float]=None, end: Optional[float]=None, r_lim: Optional[tuple[float, float]]=None, format: Optional[str]=None, outer: Optional[bool]=None, align_leaf_label: Optional[bool]=None, ignore_branch_length: Optional[bool]=None, leaf_label_size: Optional[float]=None, leaf_label_rmargin: Optional[float]=None, reverse: Optional[bool]=None, ladderize: Optional[bool]=None, line_kw: Optional[Mapping[str, Any]]=None, label_formatter: Optional[Callable[[str], str]]=None, align_line_kw: Optional[Mapping[str, Any]]=None, tooltip: bool=False) -> Incomplete: + """Draw a phylogenetic tree using pyCirclize. + +Parameters +---------- +tree_data : str, Path, or Tree + Tree data (file, URL, Tree object, or tree string). +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +r_lim : 2-tuple of float, optional + Tree track radius limits (0 to 100). +format : str, optional + Tree format (`newick`, `phyloxml`, `nexus`, `nexml`, `cdao`). +outer : bool, optional + If True, plot tree on the outer side. +align_leaf_label : bool, optional + If True, align leaf labels. +ignore_branch_length : bool, optional + Ignore branch lengths when plotting. +leaf_label_size : float, optional + Leaf label size. +leaf_label_rmargin : float, optional + Leaf label radius margin. +reverse : bool, optional + Reverse tree direction. +ladderize : bool, optional + Ladderize tree. +line_kw, align_line_kw : dict-like, optional + Keyword arguments for tree line styling. +label_formatter : callable, optional + Formatter for leaf labels. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos, pycirclize.TreeViz + The Circos instance and TreeViz helper.""" + ... + + def circos_bed(self, bed_file: Any, *, start: float=0, end: float=360, space: float | Sequence[float]=0, endspace: bool=True, sector2clockwise: Mapping[str, bool] | None=None, plot: bool=False, tooltip: bool=False) -> Incomplete: + """Create a Circos instance from a BED file using pyCirclize. + +Parameters +---------- +bed_file : str or Path + BED file describing chromosome ranges. +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +space : float or sequence of float, optional + Space degrees between sectors. +endspace : bool, optional + If True, insert space after the final sector. +sector2clockwise : dict, optional + Override clockwise settings per sector. +plot : bool, optional + If True, immediately render the circos figure on this axes. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def bed(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Alias for `~PlotAxes.circos_bed`.""" + ... + + def chord_diagram(self, matrix: Any, *, start: Optional[float]=None, end: Optional[float]=None, space: Optional[Union[float, Sequence[float]]]=None, endspace: Optional[bool]=None, r_lim: Optional[tuple[float, float]]=None, cmap: Any=None, link_cmap: Optional[list[tuple[str, str, str]]]=None, ticks_interval: Optional[int]=None, order: Optional[Union[str, list[str]]]=None, label_kw: Optional[Mapping[str, Any]]=None, ticks_kw: Optional[Mapping[str, Any]]=None, link_kw: Optional[Mapping[str, Any]]=None, link_kw_handler: Optional[Callable[[str, str], Optional[Mapping[str, Any]]]]=None, tooltip: bool=False) -> Incomplete: + """Draw a chord diagram using pyCirclize. + +Parameters +---------- +matrix : str, Path, pandas.DataFrame, or Matrix + Input matrix for the chord diagram. +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +space : float or sequence of float, optional + Space degrees between sectors. +endspace : bool, optional + If True, insert space after the final sector. +r_lim : 2-tuple of float, optional + Outer track radius limits (0 to 100). +cmap : str or dict, optional + Colormap name or name-to-color mapping for sectors and links. If omitted, + UltraPlot's color cycle is used. +link_cmap : list of (from, to, color), optional + Override link colors. +ticks_interval : int, optional + Tick interval for sector tracks. If None, no ticks are shown. +order : {'asc', 'desc'} or list, optional + Node ordering strategy or explicit node order. +label_kw, ticks_kw, link_kw : dict-like, optional + Keyword arguments passed to pyCirclize for labels, ticks, and links. +link_kw_handler : callable, optional + Callback to customize per-link keyword arguments. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def chord(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Alias for `~PlotAxes.chord_diagram`.""" + ... + + def radar_chart(self, table: Any, *, r_lim: Optional[tuple[float, float]]=None, vmin: Optional[float]=None, vmax: Optional[float]=None, fill: Optional[bool]=None, marker_size: Optional[int]=None, bg_color: Optional[str]=None, circular: Optional[bool]=None, cmap: Any=None, show_grid_label: Optional[bool]=None, grid_interval_ratio: Optional[float]=None, grid_line_kw: Optional[Mapping[str, Any]]=None, grid_label_kw: Optional[Mapping[str, Any]]=None, grid_label_formatter: Optional[Callable[[float], str]]=None, label_kw_handler: Optional[Callable[[str], Mapping[str, Any]]]=None, line_kw_handler: Optional[Callable[[str], Mapping[str, Any]]]=None, marker_kw_handler: Optional[Callable[[str], Mapping[str, Any]]]=None) -> Incomplete: + """Draw a radar chart using pyCirclize. + +Parameters +---------- +table : str, Path, pandas.DataFrame, or RadarTable + Input table for the radar chart. +r_lim : 2-tuple of float, optional + Radar chart radius limits (0 to 100). +vmin, vmax : float, optional + Value range for the radar chart. +fill : bool, optional + Whether to fill the radar polygons. +marker_size : int, optional + Marker size for radar points. +bg_color : color-spec or None, optional + Background fill color. +circular : bool, optional + Whether to draw circular grid lines. +cmap : str or dict, optional + Colormap name or row-name-to-color mapping. If omitted, UltraPlot's + color cycle is used. +show_grid_label : bool, optional + Whether to show radial grid labels. +grid_interval_ratio : float or None, optional + Grid interval ratio (0 to 1). +grid_line_kw, grid_label_kw : dict-like, optional + Keyword arguments passed to pyCirclize for grid lines and labels. +grid_label_formatter : callable, optional + Formatter for grid label values. +label_kw_handler, line_kw_handler, marker_kw_handler : callable, optional + Per-series styling callbacks passed to pyCirclize. + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def radar(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Alias for `~PlotAxes.radar_chart`.""" + ... + + def circos(self, sectors: Mapping[str, Any], *, start: float=0, end: float=360, space: float | Sequence[float]=0, endspace: bool=True, sector2clockwise: Mapping[str, bool] | None=None, show_axis_for_debug: bool=False, plot: bool=False, tooltip: bool=False) -> Incomplete: + """Create a Circos instance using pyCirclize. + +Parameters +---------- +sectors : mapping + Sector name and size (or range) mapping. +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +space : float or sequence of float, optional + Space degrees between sectors. +endspace : bool, optional + If True, insert space after the final sector. +sector2clockwise : dict, optional + Override clockwise settings per sector. +show_axis_for_debug : bool, optional + Show the polar axis for debug layout. +plot : bool, optional + If True, immediately render the circos figure on this axes. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def phylogeny(self, tree_data: Any, *, start: Optional[float]=None, end: Optional[float]=None, r_lim: Optional[tuple[float, float]]=None, format: Optional[str]=None, outer: Optional[bool]=None, align_leaf_label: Optional[bool]=None, ignore_branch_length: Optional[bool]=None, leaf_label_size: Optional[float]=None, leaf_label_rmargin: Optional[float]=None, reverse: Optional[bool]=None, ladderize: Optional[bool]=None, line_kw: Optional[Mapping[str, Any]]=None, label_formatter: Optional[Callable[[str], str]]=None, align_line_kw: Optional[Mapping[str, Any]]=None, tooltip: bool=False) -> Incomplete: + """Draw a phylogenetic tree using pyCirclize. + +Parameters +---------- +tree_data : str, Path, or Tree + Tree data (file, URL, Tree object, or tree string). +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +r_lim : 2-tuple of float, optional + Tree track radius limits (0 to 100). +format : str, optional + Tree format (`newick`, `phyloxml`, `nexus`, `nexml`, `cdao`). +outer : bool, optional + If True, plot tree on the outer side. +align_leaf_label : bool, optional + If True, align leaf labels. +ignore_branch_length : bool, optional + Ignore branch lengths when plotting. +leaf_label_size : float, optional + Leaf label size. +leaf_label_rmargin : float, optional + Leaf label radius margin. +reverse : bool, optional + Reverse tree direction. +ladderize : bool, optional + Ladderize tree. +line_kw, align_line_kw : dict-like, optional + Keyword arguments for tree line styling. +label_formatter : callable, optional + Formatter for leaf labels. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos, pycirclize.TreeViz + The Circos instance and TreeViz helper.""" + ... + + def circos_bed(self, bed_file: Any, *, start: float=0, end: float=360, space: float | Sequence[float]=0, endspace: bool=True, sector2clockwise: Mapping[str, bool] | None=None, plot: bool=False, tooltip: bool=False) -> Incomplete: + """Create a Circos instance from a BED file using pyCirclize. + +Parameters +---------- +bed_file : str or Path + BED file describing chromosome ranges. +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +space : float or sequence of float, optional + Space degrees between sectors. +endspace : bool, optional + If True, insert space after the final sector. +sector2clockwise : dict, optional + Override clockwise settings per sector. +plot : bool, optional + If True, immediately render the circos figure on this axes. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def bed(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Alias for `~PlotAxes.circos_bed`.""" + ... + + def chord_diagram(self, matrix: Any, *, start: Optional[float]=None, end: Optional[float]=None, space: Optional[Union[float, Sequence[float]]]=None, endspace: Optional[bool]=None, r_lim: Optional[tuple[float, float]]=None, cmap: Any=None, link_cmap: Optional[list[tuple[str, str, str]]]=None, ticks_interval: Optional[int]=None, order: Optional[Union[str, list[str]]]=None, label_kw: Optional[Mapping[str, Any]]=None, ticks_kw: Optional[Mapping[str, Any]]=None, link_kw: Optional[Mapping[str, Any]]=None, link_kw_handler: Optional[Callable[[str, str], Optional[Mapping[str, Any]]]]=None, tooltip: bool=False) -> Incomplete: + """Draw a chord diagram using pyCirclize. + +Parameters +---------- +matrix : str, Path, pandas.DataFrame, or Matrix + Input matrix for the chord diagram. +start, end : float, optional + Plot start and end degrees (-360 <= start < end <= 360). +space : float or sequence of float, optional + Space degrees between sectors. +endspace : bool, optional + If True, insert space after the final sector. +r_lim : 2-tuple of float, optional + Outer track radius limits (0 to 100). +cmap : str or dict, optional + Colormap name or name-to-color mapping for sectors and links. If omitted, + UltraPlot's color cycle is used. +link_cmap : list of (from, to, color), optional + Override link colors. +ticks_interval : int, optional + Tick interval for sector tracks. If None, no ticks are shown. +order : {'asc', 'desc'} or list, optional + Node ordering strategy or explicit node order. +label_kw, ticks_kw, link_kw : dict-like, optional + Keyword arguments passed to pyCirclize for labels, ticks, and links. +link_kw_handler : callable, optional + Callback to customize per-link keyword arguments. +tooltip : bool, optional + Enable interactive tooltips (requires ipympl). + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def chord(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Alias for `~PlotAxes.chord_diagram`.""" + ... + + def radar_chart(self, table: Any, *, r_lim: Optional[tuple[float, float]]=None, vmin: Optional[float]=None, vmax: Optional[float]=None, fill: Optional[bool]=None, marker_size: Optional[int]=None, bg_color: Optional[str]=None, circular: Optional[bool]=None, cmap: Any=None, show_grid_label: Optional[bool]=None, grid_interval_ratio: Optional[float]=None, grid_line_kw: Optional[Mapping[str, Any]]=None, grid_label_kw: Optional[Mapping[str, Any]]=None, grid_label_formatter: Optional[Callable[[float], str]]=None, label_kw_handler: Optional[Callable[[str], Mapping[str, Any]]]=None, line_kw_handler: Optional[Callable[[str], Mapping[str, Any]]]=None, marker_kw_handler: Optional[Callable[[str], Mapping[str, Any]]]=None) -> Incomplete: + """Draw a radar chart using pyCirclize. + +Parameters +---------- +table : str, Path, pandas.DataFrame, or RadarTable + Input table for the radar chart. +r_lim : 2-tuple of float, optional + Radar chart radius limits (0 to 100). +vmin, vmax : float, optional + Value range for the radar chart. +fill : bool, optional + Whether to fill the radar polygons. +marker_size : int, optional + Marker size for radar points. +bg_color : color-spec or None, optional + Background fill color. +circular : bool, optional + Whether to draw circular grid lines. +cmap : str or dict, optional + Colormap name or row-name-to-color mapping. If omitted, UltraPlot's + color cycle is used. +show_grid_label : bool, optional + Whether to show radial grid labels. +grid_interval_ratio : float or None, optional + Grid interval ratio (0 to 1). +grid_line_kw, grid_label_kw : dict-like, optional + Keyword arguments passed to pyCirclize for grid lines and labels. +grid_label_formatter : callable, optional + Formatter for grid label values. +label_kw_handler, line_kw_handler, marker_kw_handler : callable, optional + Per-series styling callbacks passed to pyCirclize. + +Returns +------- +pycirclize.Circos + The underlying Circos instance.""" + ... + + def radar(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Alias for `~PlotAxes.radar_chart`.""" + ... + + def _call_native(self, name: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Call the plotting method and redirect internal calls to native methods.""" + ... + + def _call_negpos(self, name: Incomplete, x: Incomplete, *ys: Incomplete, negcolor: Incomplete=None, poscolor: Incomplete=None, colorkey: Incomplete='facecolor', use_where: Incomplete=False, use_zero: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Call the plotting method separately for "negative" and "positive" data.""" + ... + + def _add_auto_labels(self, obj: Incomplete, cobj: Incomplete=None, labels: Incomplete=False, labels_kw: Incomplete=None, fmt: Incomplete=None, formatter: Incomplete=None, formatter_kw: Incomplete=None, precision: Incomplete=None) -> None: + """Add number labels. Default formatter is [SimpleFormatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ticker.SimpleFormatter.html) +with a default maximum precision of ``3`` decimal places.""" + ... + + def _add_quadmesh_labels(self, obj: Incomplete, fmt: Incomplete, *, c: Incomplete=None, color: Incomplete=None, colors: Incomplete=None, size: Incomplete=None, fontsize: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add labels to QuadMesh cells with support for shade-dependent text colors. +Values are inferred from the unnormalized mesh cell color.""" + ... + + def _add_collection_labels(self, obj: Incomplete, fmt: Incomplete, *, c: Incomplete=None, color: Incomplete=None, colors: Incomplete=None, size: Incomplete=None, fontsize: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add labels to pcolor boxes with support for shade-dependent text colors. +Values are inferred from the unnormalized grid box color.""" + ... + + def _add_contour_labels(self, obj: Incomplete, cobj: Incomplete, fmt: Incomplete, *, c: Incomplete=None, color: Incomplete=None, colors: Incomplete=None, size: Incomplete=None, fontsize: Incomplete=None, inline_spacing: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add labels to contours with support for shade-dependent filled contour labels. +Text color is inferred from filled contour object and labels are always drawn +on unfilled contour object (otherwise errors crop up).""" + ... + + def _add_error_bars(self, x: Incomplete, y: Incomplete, *_: Incomplete, distribution: Incomplete=None, default_barstds: Incomplete=False, default_boxstds: Incomplete=False, default_barpctiles: Incomplete=False, default_boxpctiles: Incomplete=False, default_marker: Incomplete=False, bars: Incomplete=None, boxes: Incomplete=None, barstd: Incomplete=None, barstds: Incomplete=None, barpctile: Incomplete=None, barpctiles: Incomplete=None, bardata: Incomplete=None, boxstd: Incomplete=None, boxstds: Incomplete=None, boxpctile: Incomplete=None, boxpctiles: Incomplete=None, boxdata: Incomplete=None, capsize: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add up to 2 error indicators: thick "boxes" and thin "bars". The ``default`` +keywords toggle default range indicators when distributions are passed.""" + ... + + def _add_error_shading(self, x: Incomplete, y: Incomplete, *_: Incomplete, distribution: Incomplete=None, color_key: Incomplete='color', shade: Incomplete=None, shadestd: Incomplete=None, shadestds: Incomplete=None, shadepctile: Incomplete=None, shadepctiles: Incomplete=None, shadedata: Incomplete=None, fade: Incomplete=None, fadestd: Incomplete=None, fadestds: Incomplete=None, fadepctile: Incomplete=None, fadepctiles: Incomplete=None, fadedata: Incomplete=None, shadelabel: Incomplete=False, fadelabel: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Add up to 2 error indicators: more opaque "shading" and less opaque "fading".""" + ... + + def _fix_contour_edges(self, method: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Fix the filled contour edges by secretly adding solid contours with +the same input data.""" + ... + + def _fix_sticky_edges(self, objs: Incomplete, axis: Incomplete, *args: Incomplete, only: Incomplete=None) -> None: + """Fix sticky edges for the input artists using the minimum and maximum of the +input coordinates. This is used to copy `bar` behavior to `area` and `lines`.""" + ... + + @staticmethod + def _fix_patch_edges(obj: Incomplete, edgefix: Incomplete=None, default_linewidth: float | None=None, **kwargs: Incomplete) -> None: + """Fix white lines between between filled patches and fix issues +with colormaps that are transparent. If keyword args passed by user +include explicit edge properties then we skip this step.""" + ... + + @contextlib.contextmanager + def _keep_grid_bools(self) -> Incomplete: + """Preserve the gridline booleans during the operation. This prevents `pcolor` +methods from disabling grids (mpl < 3.5) and emitting warnings (mpl >= 3.5).""" + ... + + def _inbounds_extent(self, *, inbounds: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Capture the `inbounds` keyword arg and return data limit +extents if it is ``True``. Otherwise return ``None``. When +``_inbounds_xylim`` gets ``None`` it will silently exit.""" + ... + + def _inbounds_vlim(self, x: Incomplete, y: Incomplete, z: Incomplete, *, to_centers: Incomplete=False) -> Incomplete: + """Restrict the sample data used for automatic `vmin` and `vmax` selection +based on the existing x and y axis limits.""" + ... + + def _inbounds_xylim(self, extents: Incomplete, x: Incomplete, y: Incomplete, **kwargs: Incomplete) -> None: + """Restrict the `dataLim` to exclude out-of-bounds data when x (y) limits +are fixed and we are determining default y (x) limits. This modifies +the mutable input `extents` to support iteration over columns.""" + ... + + def _add_kde_lines(self, xs: Incomplete, *, edges: Incomplete, colors: Incomplete, density: Incomplete=None, stack: Incomplete=False, orientation: Incomplete='vertical', points: Incomplete=None, bw_method: Incomplete=None, weights: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add a gaussian kernel density estimate line for each column of `xs`, drawn +in `colors` and passing `**kwargs` to [plot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.plot.html). + +Unless `density` is ``True`` each estimate is rescaled from a probability +density to the bin counts implied by the histogram bin `edges`. Stacked +histograms share a single evaluation grid so that the estimates accumulate +the way the bin counts do. Remaining arguments go to +[_dist_kde](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.internals.inputs._dist_kde.html).""" + ... + + def _parse_1d_args(self, x: Incomplete, *ys: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Interpret positional arguments for all 1D plotting commands.""" + ... + + def _parse_1d_format(self, x: Incomplete, *ys: Incomplete, zerox: Incomplete=False, autox: Incomplete=True, autoy: Incomplete=True, autoformat: Incomplete=None, autoreverse: Incomplete=True, autolabels: Incomplete=True, autovalues: Incomplete=False, autoguide: Incomplete=True, label: Incomplete=None, labels: Incomplete=None, value: Incomplete=None, values: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Try to retrieve default coordinates from array-like objects and apply default +formatting. Also update the keyword arguments.""" + ... + + def _parse_2d_args(self, x: Incomplete, y: Incomplete, *zs: Incomplete, globe: Incomplete=False, edges: Incomplete=False, allow1d: Incomplete=False, transpose: Incomplete=None, order: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Interpret positional arguments for all 2D plotting commands.""" + ... + + def _parse_2d_format(self, x: Incomplete, y: Incomplete, *zs: Incomplete, autoformat: Incomplete=None, autoguide: Incomplete=True, autoreverse: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Try to retrieve default coordinates from array-like objects and apply default +formatting. Also apply optional transpose and update the keyword arguments.""" + ... + + def _parse_color(self, x: DataInput, y: DataInput, c: ColorInput, *, apply_cycle: bool=True, infer_rgb: bool=False, force_cmap: bool=False, **kwargs: Any) -> tuple[ParsedColor, dict[str, Any]]: + """Parse either a colormap or color cycler. Colormap will be discrete and fade +to subwhite luminance by default. Returns a HEX string if needed so we don't +get ambiguous color warnings. Used with scatter, streamplot, quiver, barbs.""" + ... + + def _scatter_c_is_scalar_data(self, x: DataInput, y: DataInput, c: ColorInput) -> bool: + """Return whether scatter ``c=`` should be treated as scalar data. + +Matplotlib treats 1D numeric arrays matching the point count as values to +be colormapped, even though short float sequences can also look like an +RGBA tuple to ``is_color_like``. Preserve explicit RGB/RGBA arrays via the +existing ``N x 3``/``N x 4`` path and reserve this override for the 1D +numeric case only.""" + ... + + def _parse_cmap(self, *args: Incomplete, cmap: Incomplete=None, cmap_kw: Incomplete=None, c: Incomplete=None, color: Incomplete=None, colors: Incomplete=None, norm: Incomplete=None, norm_kw: Incomplete=None, extend: Incomplete=None, vmin: Incomplete=None, vmax: Incomplete=None, discrete: Incomplete=None, default_cmap: Incomplete=None, default_discrete: Incomplete=True, skip_autolev: Incomplete=False, min_levels: Incomplete=None, plot_lines: Incomplete=False, plot_contours: Incomplete=False, center_levels: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Parse colormap and normalizer arguments. + +Parameters +---------- +c, color, colors : sequence of color-spec, optional + Build a `DiscreteColormap` from the input color(s). +cmap, cmap_kw : optional + Colormap specs. +norm, norm_kw : optional + Normalize specs. +extend : optional + The colormap extend setting. +vmin, vmax : float, optional + The normalization range. +sequential, diverging, cyclic, qualitative : bool, optional + Toggle various colormap types. +discrete : bool, optional + Whether to apply `DiscreteNorm` to the colormap. +default_discrete : bool, optional + The default `discrete`. Depends on plotting method. +skip_autolev : bool, optional + Whether to skip automatic level generation. +min_levels : int, optional + The minimum number of valid levels. 1 for line contour plots 2 otherwise. +plot_lines : bool, optional + Whether these are lines. If so the default monochromatic luminance is 90. +plot_contours : bool, optional + Whether these are contours. If so then a discrete of `True` is required.""" + ... + + def _parse_cycle(self, ncycle: Incomplete=None, *, cycle: Incomplete=None, cycle_kw: Incomplete=None, cycle_manually: Incomplete=None, return_cycle: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Parse property cycle-related arguments. + +Parameters +---------- +ncycle : int, optional + The number of samples to draw for the cycle. +cycle : cycle-spec, optional + The property cycle specifier. +cycle_kw : dict-like, optional + The property cycle keyword arguments +cycle_manually : dict-like, optional + Mapping of property cycle keys to plotting function keys. Used + to translate property cycle line properties to scatter properties. +return_cycle : bool, optional + Whether to simply return the property cycle or apply it. The cycle is + only applied (and therefore reset) if it differs from the current one.""" + ... + + def _parse_level_lim(self, *args: Incomplete, vmin: Incomplete=None, vmax: Incomplete=None, robust: Incomplete=None, inbounds: Incomplete=None, negative: Incomplete=None, positive: Incomplete=None, symmetric: Incomplete=None, to_centers: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Return a suitable vmin and vmax based on the input data. + +Parameters +---------- +*args + The sample data. +vmin, vmax : float, optional + The user input minimum and maximum. +robust : bool, optional + Whether to limit the default range to exclude outliers. +inbounds : bool, optional + Whether to filter to in-bounds data. +negative, positive, symmetric : bool, optional + Whether limits should be negative, positive, or symmetric. +to_centers : bool, optional + Whether to convert coordinates to 'centers'. + +Returns +------- +vmin, vmax : float + The minimum and maximum. +**kwargs + Unused arguemnts.""" + ... + + def _parse_level_num(self, *args: Incomplete, levels: Incomplete=None, locator: Incomplete=None, locator_kw: Incomplete=None, vmin: Incomplete=None, vmax: Incomplete=None, norm: Incomplete=None, norm_kw: Incomplete=None, extend: Incomplete=None, symmetric: Incomplete=None, center_levels: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return a suitable level list given the input data, normalizer, +locator, and vmin and vmax. + +Parameters +---------- +*args + The sample data. Passed to `_parse_level_lim`. +levels : int + The approximate number of levels. +locator, locator_kw + The tick locator used to draw levels. +vmin, vmax : float, optional + The minimum and maximum values passed to the tick locator. +norm, norm_kw : optional + The continuous normalizer. Affects the default locator used to draw levels. +extend : str, optional + The extend setting. Affects level trimming settings. +symmetric : bool, optional + Whether the resulting levels should be symmetric about zero. + +Returns +------- +levels : list of float + The level edges. +**kwargs + Unused arguments.""" + ... + + def _parse_level_vals(self, *args: Incomplete, N: Incomplete=None, levels: Incomplete=None, values: Incomplete=None, extend: Incomplete=None, positive: Incomplete=False, negative: Incomplete=False, nozero: Incomplete=False, norm: Incomplete=None, norm_kw: Incomplete=None, vmin: Incomplete=None, vmax: Incomplete=None, skip_autolev: Incomplete=False, min_levels: Incomplete=None, center_levels: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return levels resulting from a wide variety of keyword options. + +Parameters +---------- +*args + The sample data. Passed to `_parse_level_lim`. +N + Shorthand for `levels`. +levels : int or sequence of float, optional + The levels list or (approximate) number of levels to create. +values : int or sequence of float, optional + The level center list or (approximate) number of level centers to create. +positive, negative, nozero : bool, optional + Whether to remove out non-positive, non-negative, and zero-valued + levels. The latter is useful for single-color contour plots. +norm, norm_kw : optional + Passed to `Norm`. Used to possibly infer levels or to convert values. +vmin, vmax : float, optional + The user input normalization range. +skip_autolev : bool, optional + Whether to skip automatic level generation. +min_levels : int, optional + The minimum number of levels allowed. + +Returns +------- +levels : list of float + The level edges. +explicit_limits : bool + Whether the user explicitly provided `vmin` and/or `vmax`. +**kwargs + Unused arguments.""" + ... + + @staticmethod + def _parse_level_norm(levels: Incomplete, norm: Incomplete, cmap: Incomplete, *, extend: Incomplete=None, min_levels: Incomplete=None, discrete_ticks: Incomplete=None, discrete_labels: Incomplete=None, center_levels: Incomplete=None, explicit_limits: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Create a [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) or [BoundaryNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.BoundaryNorm.html) +from the input colormap and normalizer. + +Parameters +---------- +levels : sequence of float + The level boundaries. +norm : [Normalize](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.Normalize.html) + The continuous normalizer. +cmap : [Colormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.Colormap.html) + The colormap. +extend : str, optional + The extend setting. +min_levels : int, optional + The minimum number of levels. +discrete_ticks : array-like, optional + The colorbar locations to tick. +discrete_labels : array-like, optional + The colorbar tick labels. +explicit_limits : bool, optional + Whether `vmin`/`vmax` were explicitly provided by the user. + +Returns +------- +norm : [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) or [Normalize](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.Normalize.html) + The discrete normalizer, or the original continuous normalizer when + line contours have explicit limits or use qualitative color lists. +cmap : [Colormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.Colormap.html) + The possibly-modified colormap. +kwargs + Unused arguments.""" + ... + + def _apply_plot(self, *pairs: Incomplete, vert: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Plot standard lines.""" + ... + + def line(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot standard lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `mean, means`: Whether to plot the means of each column for 2D `y` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `y` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `shade`: Shorthand for `shadestd`. +- `shadestd, shadestds, shadepctile, shadepctiles, shadedata`: As with `barstd`, `barpctile`, and `bardata`, but using *shading* to indicate the error range. +- `fade`: Shorthand for `fadestd`. +- `fadestd, fadestds, fadepctile, fadepctiles, fadedata`: As with `shadestd`, `shadepctile`, and `shadedata`, but for an additional, more faded, *secondary* shaded region. +- `shadec, shadecolor, fadec, fadecolor`: Colors for the different shaded regions. +- `shadez, shadezorder, fadez, fadezorder`: The "zorder" for the different shaded regions. +- `shadea, shadealpha, fadea, fadealpha`: The opacity for the different shaded regions. +- `shadelw, shadelinewidth, fadelw, fadelinewidth`: The edge line width for the shading patches. +- `shdeec, shadeedgecolor, fadeec, fadeedgecolor`: The edge color for the shading patches. +- `shadelabel, fadelabel`: Labels for the shaded regions to be used as separate legend entries. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- _6 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.line)""" + ... + + def linex(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot standard lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `mean, means`: Whether to plot the means of each column for 2D `x` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `x` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `shade`: Shorthand for `shadestd`. +- `shadestd, shadestds, shadepctile, shadepctiles, shadedata`: As with `barstd`, `barpctile`, and `bardata`, but using *shading* to indicate the error range. +- `fade`: Shorthand for `fadestd`. +- `fadestd, fadestds, fadepctile, fadepctiles, fadedata`: As with `shadestd`, `shadepctile`, and `shadedata`, but for an additional, more faded, *secondary* shaded region. +- `shadec, shadecolor, fadec, fadecolor`: Colors for the different shaded regions. +- `shadez, shadezorder, fadez, fadezorder`: The "zorder" for the different shaded regions. +- `shadea, shadealpha, fadea, fadealpha`: The opacity for the different shaded regions. +- `shadelw, shadelinewidth, fadelw, fadelinewidth`: The edge line width for the shading patches. +- `shdeec, shadeedgecolor, fadeec, fadeedgecolor`: The edge color for the shading patches. +- `shadelabel, fadelabel`: Labels for the shaded regions to be used as separate legend entries. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- _6 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.linex)""" + ... + + def _apply_lollipop(self, xs: Incomplete, hs: Incomplete, ws: Incomplete, bs: Incomplete, *, horizontal: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Lollipop graphs are an alternative way to visualize bar charts. We can utilize the bar internal mechanics to generate the charts and then replace the look with the lollipop graphs""" + ... + + def beeswarm(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Beeswarm plot with [SHAP-style](https://shap.readthedocs.io/en/latest/generated/shap.plots.beeswarm.html#shap.plots.beeswarm) feature value coloring. + +Parameters +---------- +- `data`: The data to be plotted. +- `levels`: The levels to use for the beeswarm plot. +- `n_bins`: Number of bins to use to reduce the overlap between points. +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `median, medians`: Whether to plot the medians of each column for 2D `y` coordinates. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `shadestd, shadestds, shadepctile, shadepctiles, shadedata`: As with `barstd`, `barpctile`, and `bardata`, but using *shading* to indicate the error range. +- `fade`: Shorthand for `fadestd`. +- _11 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.beeswarm)""" + ... + + def _apply_beeswarm(self, data: np.ndarray, levels: np.ndarray=None, feature_values: np.ndarray=None, ss: float | np.ndarray=None, orientation: str='horizontal', n_bins: int=50, **kwargs: Incomplete) -> mcollections.Collection: + ... + + def lollipop(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual or group lollipop graphs. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `stemlinewidth`: The width of the lines connecting the dots to the x-axis. +- `stemcolor`: Line color of the lines connecting the dots to the x-axis. +- `stemlinestyle`: The style of the lines connecting the dots to the x-axis. +- `s, size, ms, markersize`: The marker size area(s). +- `c, color, colors, mc, markercolor, markercolors, fc, facecolor, facecolors`: The marker color(s). +- `smin, smax`: The minimum and maximum marker size area in units ``points ** 2``. +- `area_size`: Whether the marker sizes `s` are scaled by area or by radius. +- `absolute_size`: Whether `s` should be taken to represent "absolute" marker sizes in units ``points`` or ``points ** 2`` or "relative" marker sizes scaled by `smin` and `smax`. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `lw, linewidth, linewidths, mew, markeredgewidth, markeredgewidths`: The marker edge width(s). +- `edgecolors, markeredgecolor, markeredgecolors`: The marker edge color(s). +- _32 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.lollipop)""" + ... + + def lollipoph(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual or group lollipop graphs. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `stemlinewidth`: The width of the lines connecting the dots to the x-axis. +- `stemcolor`: Line color of the lines connecting the dots to the x-axis. +- `stemlinestyle`: The style of the lines connecting the dots to the x-axis. +- `s, size, ms, markersize`: The marker size area(s). +- `c, color, colors, mc, markercolor, markercolors, fc, facecolor, facecolors`: The marker color(s). +- `smin, smax`: The minimum and maximum marker size area in units ``points ** 2``. +- `area_size`: Whether the marker sizes `s` are scaled by area or by radius. +- `absolute_size`: Whether `s` should be taken to represent "absolute" marker sizes in units ``points`` or ``points ** 2`` or "relative" marker sizes scaled by `smin` and `smax`. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `lw, linewidth, linewidths, mew, markeredgewidth, markeredgewidths`: The marker edge width(s). +- `edgecolors, markeredgecolor, markeredgecolors`: The marker edge color(s). +- _32 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.lollipoph)""" + ... + + def loglog(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot loglog + +UltraPlot is optimized for visualizing logarithmic scales by default. For cases with large differences in magnitude, +we recommend setting `rc["formatter.log"] = True` to enhance axis label formatting. +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 the concepts and +parameters of plot can be used here as well. + +The additional parameters *base*, *subs* and *nonpositive* control the +x/y-axis properties. They are just forwarded to `.Axes.set_xscale` and +`.Axes.set_yscale`. To use different properties on the x-axis and the +y-axis, use e.g. +``ax.set_xscale("log", base=10); ax.set_yscale("log", base=2)``. + +Parameters +---------- +base : float, default: 10 + Base of the logarithm. + +subs : sequence, optional + The location of the minor 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. + +nonpositive : {'mask', 'clip'}, default: 'clip' + Non-positive values can be masked as invalid, or clipped to a very + small positive number. + +**kwargs + All parameters supported by `.plot`. + +Returns +------- +list of `.Line2D` + Objects representing the plotted data. + +Notes +----- + +.. note:: + + This is the [pyplot wrapper](https://ultraplot.readthedocs.io/en/stable/search.html?q=pyplot_interface) for `.axes.Axes.loglog`.""" + ... + + def semilogy(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot semilogy + +UltraPlot is optimized for visualizing logarithmic scales by default. For cases with large differences in magnitude, +we recommend setting `rc["formatter.log"] = True` to enhance axis label formatting. +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 the concepts and parameters of plot can +be used here as well. + +The additional parameters *base*, *subs*, and *nonpositive* control the +y-axis properties. They are just forwarded to `.Axes.set_yscale`. + +Parameters +---------- +base : float, default: 10 + Base of the y logarithm. + +subs : 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. + +nonpositive : {'mask', 'clip'}, default: 'clip' + Non-positive values in y can be masked as invalid, or clipped to a + very small positive number. + +**kwargs + All parameters supported by `.plot`. + +Returns +------- +list of `.Line2D` + Objects representing the plotted data. + +Notes +----- + +.. note:: + + This is the [pyplot wrapper](https://ultraplot.readthedocs.io/en/stable/search.html?q=pyplot_interface) for `.axes.Axes.semilogy`.""" + ... + + def semilogx(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot semilogx + +UltraPlot is optimized for visualizing logarithmic scales by default. For cases with large differences in magnitude, +we recommend setting `rc["formatter.log"] = True` to enhance axis label formatting. +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 the concepts and parameters of plot can +be used here as well. + +The additional parameters *base*, *subs*, and *nonpositive* control the +x-axis properties. They are just forwarded to `.Axes.set_xscale`. + +Parameters +---------- +base : float, default: 10 + Base of the x logarithm. + +subs : 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. + +nonpositive : {'mask', 'clip'}, default: 'clip' + Non-positive values in x can be masked as invalid, or clipped to a + very small positive number. + +**kwargs + All parameters supported by `.plot`. + +Returns +------- +list of `.Line2D` + Objects representing the plotted data. + +Notes +----- + +.. note:: + + This is the [pyplot wrapper](https://ultraplot.readthedocs.io/en/stable/search.html?q=pyplot_interface) for `.axes.Axes.semilogx`.""" + ... + + def plot(self, *args: Any, scalex: bool=..., scaley: bool=..., data: Any=..., **kwargs: Any) -> list[Any]: + """Plot standard lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `mean, means`: Whether to plot the means of each column for 2D `y` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `y` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `shade`: Shorthand for `shadestd`. +- `shadestd, shadestds, shadepctile, shadepctiles, shadedata`: As with `barstd`, `barpctile`, and `bardata`, but using *shading* to indicate the error range. +- `fade`: Shorthand for `fadestd`. +- `fadestd, fadestds, fadepctile, fadepctiles, fadedata`: As with `shadestd`, `shadepctile`, and `shadedata`, but for an additional, more faded, *secondary* shaded region. +- `shadec, shadecolor, fadec, fadecolor`: Colors for the different shaded regions. +- `shadez, shadezorder, fadez, fadezorder`: The "zorder" for the different shaded regions. +- `shadea, shadealpha, fadea, fadealpha`: The opacity for the different shaded regions. +- `shadelw, shadelinewidth, fadelw, fadelinewidth`: The edge line width for the shading patches. +- `shdeec, shadeedgecolor, fadeec, fadeedgecolor`: The edge color for the shading patches. +- `shadelabel, fadelabel`: Labels for the shaded regions to be used as separate legend entries. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- _9 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.plot)""" + ... + + def plotx(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot standard lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `mean, means`: Whether to plot the means of each column for 2D `x` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `x` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `shade`: Shorthand for `shadestd`. +- `shadestd, shadestds, shadepctile, shadepctiles, shadedata`: As with `barstd`, `barpctile`, and `bardata`, but using *shading* to indicate the error range. +- `fade`: Shorthand for `fadestd`. +- `fadestd, fadestds, fadepctile, fadepctiles, fadedata`: As with `shadestd`, `shadepctile`, and `shadedata`, but for an additional, more faded, *secondary* shaded region. +- `shadec, shadecolor, fadec, fadecolor`: Colors for the different shaded regions. +- `shadez, shadezorder, fadez, fadezorder`: The "zorder" for the different shaded regions. +- `shadea, shadealpha, fadea, fadealpha`: The opacity for the different shaded regions. +- `shadelw, shadelinewidth, fadelw, fadelinewidth`: The edge line width for the shading patches. +- `shdeec, shadeedgecolor, fadeec, fadeedgecolor`: The edge color for the shading patches. +- `shadelabel, fadelabel`: Labels for the shaded regions to be used as separate legend entries. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- _6 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.plotx)""" + ... + + def _apply_step(self, *pairs: Incomplete, vert: Incomplete=True, where: Incomplete='pre', **kwargs: Incomplete) -> Incomplete: + """Plot the steps.""" + ... + + def step(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot step lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [step](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.step.html). +- `x`: 1D sequence of x positions. +- `y`: 1D sequence of y levels. +- `fmt`: A format string, e.g. +- `where`: Define where the steps should be placed: - 'pre': The y value is continued constantly to the left from every *x* position, i.e. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.step)""" + ... + + def stepx(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot step lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [step](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.step.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.stepx)""" + ... + + def _apply_stem(self, x: Incomplete, y: Incomplete, *, linefmt: Incomplete=None, markerfmt: Incomplete=None, basefmt: Incomplete=None, orientation: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Plot stem lines and markers.""" + ... + + def stem(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot stem lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [stem](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.stem.html). +- `locs`: For vertical stem plots, the x-positions of the stems. +- `heads`: For vertical stem plots, the y-values of the stem heads. +- `linefmt`: A string defining the color and/or linestyle of the vertical lines: ========= ============= Character Line Style ========= ============= ``'-'`` solid line ``'--'`` dashed line… +- `markerfmt`: A string defining the color and/or shape of the markers at the stem heads. +- `basefmt`: A format string defining the properties of the baseline. +- `orientation`: The orientation of the stems. +- `bottom`: The y/x-position of the baseline (depending on *orientation*). +- `label`: The label to use for the stems in legends. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.stem)""" + ... + + def stemx(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot stem lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [stem](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.stem.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.stemx)""" + ... + + def parametric(self, x: Incomplete, y: Incomplete, c: Incomplete, *, interp: Incomplete=0, scalex: Incomplete=True, scaley: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Plot a parametric line. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `c, color, colors, values, labels`: The parametric coordinate(s). +- `interp`: Interpolate to this many additional points between the parametric coordinates. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `scalex, scaley`: Whether the view limits are adapted to the data limits. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Valid [LineCollection](https://matplotlib.org/stable/api/_as_gen/matplotlib.collections.LineCollection.html) properties. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.parametric)""" + ... + + def _apply_lines(self, xs: Incomplete, ys1: Incomplete, ys2: Incomplete, colors: Incomplete, *, vert: Incomplete=True, stack: Incomplete=None, stacked: Incomplete=None, negpos: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Plot vertical or hotizontal lines at each point.""" + ... + + def vlines(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot vertical lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `stack, stacked`: Whether to "stack" lines from successive columns of y data or plot lines on top of each other. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `negpos`: Whether to shade lines where ``ymax >= ymin`` with `poscolor` and where ``ymax < ymin`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive lines. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [vlines](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.vlines.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.vlines)""" + ... + + def hlines(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot horizontal lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `stack, stacked`: Whether to "stack" lines from successive columns of x data or plot lines on top of each other. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The width of the line(s). +- `linestyle`: The style of the line(s). +- `color`: The color of the line(s). +- `alpha`: The opacity of the line(s). +- `negpos`: Whether to shade lines where ``ymax >= ymin`` with `poscolor` and where ``ymax < ymin`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive lines. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [hlines](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.hlines.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.hlines)""" + ... + + def _parse_markersize(self, s: Incomplete, *, smin: Incomplete=None, smax: Incomplete=None, area_size: Incomplete=True, absolute_size: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Scale the marker sizes with optional keyword args.""" + ... + + def _apply_scatter(self, xs: Incomplete, ys: Incomplete, ss: Incomplete, cc: Incomplete, *, vert: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Apply scatter or scatterx markers.""" + ... + + def scatter(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot markers with flexible keyword arguments. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `s, size, ms, markersize`: The marker size area(s). +- `c, color, colors, mc, markercolor, markercolors, fc, facecolor, facecolors`: The marker color(s). +- `smin, smax`: The minimum and maximum marker size area in units ``points ** 2``. +- `area_size`: Whether the marker sizes `s` are scaled by area or by radius. +- `absolute_size`: Whether `s` should be taken to represent "absolute" marker sizes in units ``points`` or ``points ** 2`` or "relative" marker sizes scaled by `smin` and `smax`. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `lw, linewidth, linewidths, mew, markeredgewidth, markeredgewidths`: The marker edge width(s). +- `edgecolors, markeredgecolor, markeredgecolors`: The marker edge color(s). +- `mean, means`: Whether to plot the means of each column for 2D `y` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `y` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- _38 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.scatter)""" + ... + + def scatterx(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot markers with flexible keyword arguments. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `s, size, ms, markersize`: The marker size area(s). +- `c, color, colors, mc, markercolor, markercolors, fc, facecolor, facecolors`: The marker color(s). +- `smin, smax`: The minimum and maximum marker size area in units ``points ** 2``. +- `area_size`: Whether the marker sizes `s` are scaled by area or by radius. +- `absolute_size`: Whether `s` should be taken to represent "absolute" marker sizes in units ``points`` or ``points ** 2`` or "relative" marker sizes scaled by `smin` and `smax`. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `lw, linewidth, linewidths, mew, markeredgewidth, markeredgewidths`: The marker edge width(s). +- `edgecolors, markeredgecolor, markeredgecolors`: The marker edge color(s). +- `mean, means`: Whether to plot the means of each column for 2D `x` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `x` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- _29 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.scatterx)""" + ... + + def _apply_fill(self, xs: Incomplete, ys1: Incomplete, ys2: Incomplete, where: Incomplete, *, vert: Incomplete=True, negpos: Incomplete=None, stack: Incomplete=None, stacked: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Apply area shading using `fill_between` or `fill_betweenx`. + +This is the internal implementation for `fill_between`, `fill_betweenx`, +`area`, and `areax`. + +Parameters +---------- +xs, ys1, ys2 : array-like + The x and y coordinates for the shaded regions. +where : array-like, optional + A boolean mask for the points that should be shaded. +vert : bool, optional + The orientation of the shading. If `True` (default), `fill_between` + is used. If `False`, `fill_betweenx` is used. +negpos : bool, optional + Whether to use different colors for positive and negative shades. +stack : bool, optional + Whether to stack shaded regions. +**kwargs + Additional keyword arguments passed to the matplotlib fill function. + +Notes +----- +Special handling for plots from external packages (e.g., seaborn): + +When this method is used in a context where plots are generated by +an external library like seaborn, it tags the resulting polygons +(e.g., confidence intervals) as "synthetic". This is done unless a +user explicitly provides a label. + +Synthetic artists are marked with `_ultraplot_synthetic=True` and given +a label starting with an underscore (e.g., `_ultraplot_fill`). This +prevents them from being automatically included in legends, keeping the +legend clean and focused on user-specified elements. + +Seaborn internally generates tags like "y", "ymin", and "ymax" for +vertical fills, and "x", "xmin", "xmax" for horizontal fills. UltraPlot +recognizes these and treats them as synthetic unless a different label +is provided.""" + ... + + def area(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual, grouped, or overlaid shading patches. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `stack, stacked`: Whether to "stack" area patches from successive columns of y data or plot area patches on top of each other. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `where`: A boolean mask for the points that should be shaded. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `negpos`: Whether to shade patches where ``y2 >= y1`` with `poscolor` and where ``y2 < y1`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive patches. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [fill_between](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.fill_between.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.area)""" + ... + + def areax(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual, grouped, or overlaid shading patches. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `stack, stacked`: Whether to "stack" area patches from successive columns of x data or plot area patches on top of each other. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `where`: A boolean mask for the points that should be shaded. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `negpos`: Whether to shade patches where ``y2 >= y1`` with `poscolor` and where ``y2 < y1`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive patches. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [fill_betweenx](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.fill_betweenx.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.areax)""" + ... + + def fill_between(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual, grouped, or overlaid shading patches. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `stack, stacked`: Whether to "stack" area patches from successive columns of y data or plot area patches on top of each other. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `where`: A boolean mask for the points that should be shaded. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `negpos`: Whether to shade patches where ``y2 >= y1`` with `poscolor` and where ``y2 < y1`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive patches. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [fill_between](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.fill_between.html). +- `x`: The x coordinates of the nodes defining the curves. +- `y1`: The y coordinates of the nodes defining the first curve. +- `y2`: The y coordinates of the nodes defining the second curve. +- `interpolate`: This option is only relevant if *where* is used and the two curves are crossing each other. +- `step`: Define *step* if the filling should be a step function, i.e. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.fill_between)""" + ... + + def fill_betweenx(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual, grouped, or overlaid shading patches. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `stack, stacked`: Whether to "stack" area patches from successive columns of x data or plot area patches on top of each other. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `where`: A boolean mask for the points that should be shaded. +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `negpos`: Whether to shade patches where ``y2 >= y1`` with `poscolor` and where ``y2 < y1`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive patches. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [fill_betweenx](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.fill_betweenx.html). +- `y`: The y coordinates of the nodes defining the curves. +- `x1`: The x coordinates of the nodes defining the first curve. +- `x2`: The x coordinates of the nodes defining the second curve. +- `interpolate`: This option is only relevant if *where* is used and the two curves are crossing each other. +- `step`: Define *step* if the filling should be a step function, i.e. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.fill_betweenx)""" + ... + + def graph(self, g: Incomplete, layout: Union[str, dict, Callable]=None, nodes: Union[None, bool, Iterable]=None, edges: Union[None, bool, Iterable]=None, labels: Union[None, bool, Iterable]=None, layout_kw: Optional[dict]=None, node_kw: Optional[dict]=None, edge_kw: Optional[dict]=None, label_kw: Optional[dict]=None, rescale: Union[None, bool]=None) -> Incomplete: + """Plot a networkx graph with flexible node, edge, and label options. + +Parameters +---------- +- `g`: The graph object to be plotted. +- `layout`: A layout function or a precomputed dict mapping nodes to 2D positions. +- `nodes`: Which nodes to draw. +- `edges`: Which edges to draw. +- `labels`: Whether to show node labels. +- `layout_kw`: Keyword arguments passed to the layout function, if `layout` is callable, see [networkx's drawing functions](https://networkx.org/documentation/stable/reference/drawing.html) for… +- `node_kw`: Additional keyword arguments passed to the node drawing function (see [networkx.drawing.nx_pylab.draw_networkx_nodes](https://networkx.org/documentation/stable/search.html?q=networkx.drawing.nx_pylab.draw_networkx_nodes)). +- `edge_kw`: Additional keyword arguments passed to the edge drawing function. +- `label_kw`: Additional keyword arguments passed to the label drawing function, such as font size, font color, background color, alignment, etc (see… +- `rescale`: When set to none it checks for `rc["graph.rescale"]` which defaults to `True`. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.graph)""" + ... + + @staticmethod + def _convert_bar_width(x: Incomplete, width: Incomplete=1) -> Incomplete: + """Convert bar plot widths from relative to coordinate spacing. Relative +widths are much more convenient for users.""" + ... + + def _apply_bar(self, xs: Incomplete, hs: Incomplete, ws: Incomplete, bs: Incomplete, *, absolute_width: Incomplete=None, stack: Incomplete=None, stacked: Incomplete=None, negpos: Incomplete=False, orientation: Incomplete='vertical', **kwargs: Incomplete) -> Incomplete: + """Apply bar or barh command. Support default "minima" at zero.""" + ... + + def _add_bar_labels(self, container: Incomplete, *, orientation: Incomplete='horizontal', **kwargs: Incomplete) -> Incomplete: + """Automatically add bar labels and rescale the +limits to produce a striking visual image.""" + ... + + def bar(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual, grouped, or stacked bars. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `width`: The width(s) of the bars. +- `bottom`: The coordinate(s) of the bottom edge of the bars. +- `absolute_width`: Whether to make the `width` units *absolute*. +- `stack, stacked`: Whether to "stack" bars from successive columns of y data or plot bars side-by-side in groups. +- `bar_labels`: Whether to show the height values for vertical bars or width values for horizontal bars. +- `bar_labels_kw`: Keywords to format the bar_labels, see [bar_label](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar_label.html). +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `negpos`: Whether to shade bars where ``height >= 0`` with `poscolor` and where ``height < 0`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive bars. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `mean, means`: Whether to plot the means of each column for 2D `y` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `y` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- _17 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.bar)""" + ... + + def barh(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot individual, grouped, or stacked bars. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `width`: The width(s) of the bars. +- `left`: The coordinate(s) of the left edge of the bars. +- `absolute_width`: Whether to make the `width` units *absolute*. +- `stack, stacked`: Whether to "stack" bars from successive columns of x data or plot bars side-by-side in groups. +- `bar_labels`: Whether to show the height values for vertical bars or width values for horizontal bars. +- `bar_labels_kw`: Keywords to format the bar_labels, see [bar_label](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.bar_label.html). +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `negpos`: Whether to shade bars where ``height >= 0`` with `poscolor` and where ``height < 0`` with `negcolor`. +- `negcolor, poscolor`: Colors to use for the negative and positive bars. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `mean, means`: Whether to plot the means of each column for 2D `x` coordinates. +- `median, medians`: Whether to plot the medians of each column for 2D `x` coordinates. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `inbounds`: Whether to restrict the default `y` (`x`) axis limits to account for only in-bounds data when the `x` (`y`) axis limits have been locked. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- _17 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.barh)""" + ... + + def pie(self, x: Incomplete, explode: Incomplete, *, labelpad: Incomplete=None, labeldistance: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Plot a pie chart. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `labelpad, labeldistance`: The distance at which labels are drawn in radial coordinates. +- `x`: The wedge sizes. +- `explode`: If not *None*, is a ``len(x)`` array which specifies the fraction of the radius with which to offset each wedge. +- `labels`: A sequence of strings providing the labels for each wedge +- `colors`: A sequence of colors through which the pie chart will cycle. +- `hatch`: Hatching pattern applied to all pie wedges or sequence of patterns through which the chart will cycle. +- `autopct`: If not *None*, *autopct* is a string or function used to label the wedges with their numeric value. +- `pctdistance`: The relative distance along the radius at which the text generated by *autopct* is drawn. +- `labeldistance`: The relative distance along the radius at which the labels are drawn. +- `shadow`: If bool, whether to draw a shadow beneath the pie. +- `startangle`: The angle by which the start of the pie is rotated, counterclockwise from the x-axis. +- `radius`: The radius of the pie. +- `counterclock`: Specify fractions direction, clockwise or counterclockwise. +- `wedgeprops`: Dict of arguments passed to each `.patches.Wedge` of the pie. +- `textprops`: Dict of arguments to pass to the text objects. +- `center`: The coordinates of the center of the chart. +- `frame`: Plot Axes frame with the chart if true. +- `rotatelabels`: Rotate each label to the angle of the corresponding slice if true. +- `normalize`: When *True*, always make a full pie by normalizing x so that ``sum(x) == 1``. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.pie)""" + ... + + @staticmethod + def _parse_box_violin(fillcolor: Incomplete, fillalpha: Incomplete, edgecolor: Incomplete, **kw: Incomplete) -> Incomplete: + """Parse common boxplot and violinplot arguments.""" + ... + + def _boxplot_has_shared_tick_axis(self, axis_name: str) -> bool: + """Return whether the boxplot tick axis is shared with sibling axes.""" + ... + + def _apply_boxplot_tick_manager(self, axis_name: str, positions: Iterable[Any], tick_labels: Optional[Iterable[Any]]=None) -> None: + """Apply fixed tick locations/labels without appending duplicates on shared axes.""" + ... + + def _apply_boxplot(self, x: Incomplete, y: Incomplete, *, mean: Incomplete=None, means: Incomplete=None, vert: Incomplete=True, fill: Incomplete=None, filled: Incomplete=None, marker: Incomplete=None, markersize: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Apply the box plot.""" + ... + + def box(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot vertical boxes and whiskers with a nice default style. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `fill`: Whether to fill the box with a color. +- `mean, means`: If ``True``, this passes ``showmeans=True`` and ``meanline=True`` to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `m, marker, ms, markersize`: Marker style and size for the 'fliers', i.e. +- `meanls, medianls, meanlinestyle, medianlinestyle, meanlinestyles, medianlinestyles`: Line style for the mean and median lines drawn across the box. +- `boxlw, caplw, whiskerlw, flierlw, meanlw, medianlw, boxlinewidth, caplinewidth, meanlinewidth, medianlinewidth, whiskerlinewidth, flierlinewidth, boxlinewidths, caplinewidths, meanlinewidths, medianlinewidths, whiskerlinewidths, flierlinewidths`: Line width of various boxplot components. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `**kwargs`: Passed to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.box)""" + ... + + def boxh(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot horizontal boxes and whiskers with a nice default style. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `fill`: Whether to fill the box with a color. +- `mean, means`: If ``True``, this passes ``showmeans=True`` and ``meanline=True`` to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `m, marker, ms, markersize`: Marker style and size for the 'fliers', i.e. +- `meanls, medianls, meanlinestyle, medianlinestyle, meanlinestyles, medianlinestyles`: Line style for the mean and median lines drawn across the box. +- `boxlw, caplw, whiskerlw, flierlw, meanlw, medianlw, boxlinewidth, caplinewidth, meanlinewidth, medianlinewidth, whiskerlinewidth, flierlinewidth, boxlinewidths, caplinewidths, meanlinewidths, medianlinewidths, whiskerlinewidths, flierlinewidths`: Line width of various boxplot components. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `**kwargs`: Passed to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.boxh)""" + ... + + def boxplot(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot vertical boxes and whiskers with a nice default style. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `fill`: Whether to fill the box with a color. +- `mean, means`: If ``True``, this passes ``showmeans=True`` and ``meanline=True`` to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `m, marker, ms, markersize`: Marker style and size for the 'fliers', i.e. +- `meanls, medianls, meanlinestyle, medianlinestyle, meanlinestyles, medianlinestyles`: Line style for the mean and median lines drawn across the box. +- `boxlw, caplw, whiskerlw, flierlw, meanlw, medianlw, boxlinewidth, caplinewidth, meanlinewidth, medianlinewidth, whiskerlinewidth, flierlinewidth, boxlinewidths, caplinewidths, meanlinewidths, medianlinewidths, whiskerlinewidths, flierlinewidths`: Line width of various boxplot components. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `**kwargs`: Passed to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). +- `x`: The input data. +- `notch`: Whether to draw a notched boxplot (`True`), or a rectangular boxplot (`False`). +- `sym`: The default symbol for flier points. +- `vert`: Use *orientation* instead. +- `orientation`: If 'horizontal', plots the boxes horizontally. +- `whis`: The position of the whiskers. +- `bootstrap`: Specifies whether to bootstrap the confidence intervals around the median for notched boxplots. +- `usermedians`: A 1D array-like of length ``len(x)``. +- `conf_intervals`: A 2D array-like of shape ``(len(x), 2)``. +- `positions`: The positions of the boxes. +- `widths`: The widths of the boxes. +- `patch_artist`: If `False` produces boxes with the Line2D artist. +- `tick_labels`: The tick labels of each boxplot. +- `manage_ticks`: If True, the tick locations and labels will be adjusted to match the boxplot positions. +- `autorange`: 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… +- `meanline`: 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). +- `zorder`: The zorder of the boxplot. +- `showcaps`: Show the caps on the ends of whiskers. +- _11 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.boxplot)""" + ... + + def boxploth(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot horizontal boxes and whiskers with a nice default style. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `fill`: Whether to fill the box with a color. +- `mean, means`: If ``True``, this passes ``showmeans=True`` and ``meanline=True`` to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `m, marker, ms, markersize`: Marker style and size for the 'fliers', i.e. +- `meanls, medianls, meanlinestyle, medianlinestyle, meanlinestyles, medianlinestyles`: Line style for the mean and median lines drawn across the box. +- `boxlw, caplw, whiskerlw, flierlw, meanlw, medianlw, boxlinewidth, caplinewidth, meanlinewidth, medianlinewidth, whiskerlinewidth, flierlinewidth, boxlinewidths, caplinewidths, meanlinewidths, medianlinewidths, whiskerlinewidths, flierlinewidths`: Line width of various boxplot components. +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `**kwargs`: Passed to [matplotlib.axes.Axes.boxplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.boxplot.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.boxploth)""" + ... + + def _apply_violinplot(self, x: Incomplete, y: Incomplete, vert: Incomplete=True, mean: Incomplete=None, means: Incomplete=None, median: Incomplete=None, medians: Incomplete=None, showmeans: Incomplete=None, showmedians: Incomplete=None, showextrema: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Apply the violinplot.""" + ... + + def violin(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot vertical violins with a nice default style matching [this matplotlib example](https://matplotlib.org/stable/gallery/statistics/customized_violin.html). + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `showmeans, showmedians`: Interpreted as ``means=True`` and ``medians=True`` when passed. +- `showextrema`: Interpreted as ``barpctiles=True`` when passed (i.e. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `**kwargs`: Passed to [matplotlib.axes.Axes.violinplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.violinplot.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.violin)""" + ... + + def violinh(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot horizontal violins with a nice default style matching [this matplotlib example](https://matplotlib.org/stable/gallery/statistics/customized_violin.html). + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `showmeans, showmedians`: Interpreted as ``means=True`` and ``medians=True`` when passed. +- `showextrema`: Interpreted as ``barpctiles=True`` when passed (i.e. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `**kwargs`: Passed to [matplotlib.axes.Axes.violinplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.violinplot.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.violinh)""" + ... + + def violinplot(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot vertical violins with a nice default style matching [this matplotlib example](https://matplotlib.org/stable/gallery/statistics/customized_violin.html). + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `showmeans, showmedians`: Interpreted as ``means=True`` and ``medians=True`` when passed. +- `showextrema`: Interpreted as ``barpctiles=True`` when passed (i.e. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `**kwargs`: Passed to [matplotlib.axes.Axes.violinplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.violinplot.html). +- `dataset`: The input data. +- `positions`: The positions of the violins; i.e. +- `vert`: Use *orientation* instead. +- `orientation`: If 'horizontal', plots the violins horizontally. +- `widths`: The maximum width of each violin in units of the *positions* axis. +- `showmeans`: Whether to show the mean with a line. +- `showmedians`: Whether to show the median with a line. +- `quantiles`: 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. +- _3 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.violinplot)""" + ... + + def violinploth(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot horizontal violins with a nice default style matching [this matplotlib example](https://matplotlib.org/stable/gallery/statistics/customized_violin.html). + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `showmeans, showmedians`: Interpreted as ``means=True`` and ``medians=True`` when passed. +- `showextrema`: Interpreted as ``barpctiles=True`` when passed (i.e. +- `bars`: Shorthand for `barstd`, `barstds`. +- `barstd, barstds`: Valid only if `mean` or `median` is ``True``. +- `barpctile, barpctiles`: Valid only if `mean` or `median` is ``True``. +- `bardata`: Valid only if `mean` and `median` are ``False``. +- `boxes`: Shorthand for `boxstd`, `boxstds`. +- `boxstd, boxstds, boxpctile, boxpctiles, boxdata`: As with `barstd`, `barpctile`, and `bardata`, but for *thicker error bars* representing a smaller interval than the thin error bars. +- `capsize`: The cap size for thin error bars in points. +- `barz, barzorder, boxz, boxzorder`: The "zorder" for the thin and thick error bars. +- `barc, barcolor, boxc, boxcolor`: Colors for the thin and thick error bars. +- `barlw, barlinewidth, boxlw, boxlinewidth`: Line widths for the thin and thick error bars, in points. +- `boxm, boxmarker`: Whether to draw a small marker in the middle of the box denoting the mean or median position. +- `boxms, boxmarkersize`: The marker size for the `boxmarker` marker in points ** 2. +- `boxmc, boxmarkercolor, boxmec, boxmarkeredgecolor`: Color, face color, and edge color for the `boxmarker` marker. +- `**kwargs`: Passed to [matplotlib.axes.Axes.violinplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.violinplot.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.violinploth)""" + ... + + def _apply_ridgeline(self, data: Incomplete, labels: Incomplete=None, positions: Incomplete=None, height: Incomplete=None, overlap: Incomplete=0.5, kde_kw: Incomplete=None, points: Incomplete=None, hist: Incomplete=False, bins: Incomplete='auto', histtype: Incomplete=None, fill: Incomplete=True, alpha: Incomplete=1.0, linewidth: Incomplete=1.5, edgecolor: Incomplete='black', facecolor: Incomplete=None, cmap: Incomplete=None, vert: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Apply ridgeline plot (joyplot). + +Parameters +---------- +- `data`: List of distributions to plot as ridges. +- `labels`: Labels for each distribution. +- `positions`: Y-coordinates for continuous positioning mode. +- `height`: Height of each ridge in Y-axis units (continuous mode only). +- `overlap`: Amount of overlap between ridges (0-1). +- `kde_kw`: Settings for the kernel density estimate. +- `points`: Number of points to evaluate the KDE at. +- `hist`: If True, use histograms instead of kernel density estimation. +- `bins`: Bin specification for histograms. +- `histtype`: Rendering style for histogram ridgelines. +- `fill`: Whether to fill the area under each curve. +- `alpha`: Transparency of filled areas. +- `linewidth`: Width of the ridge lines. +- `edgecolor`: Color of the ridge lines. +- `facecolor`: Fill color(s). +- `cmap`: Colormap to use for coloring ridges. +- `vert`: If True, ridges are horizontal (traditional ridgeline plot). +- `**kwargs`: Additional keyword arguments passed to fill_between or fill_betweenx.""" + ... + + def ridgeline(self, data: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Create a vertical ridgeline plot (also known as a joyplot). + +Parameters +---------- +- `data`: List of distributions to plot. +- `labels`: Labels for each distribution. +- `positions`: Y-coordinates for positioning each ridge. +- `height`: Height of each ridge in Y-axis units. +- `overlap`: Amount of overlap between ridges, from 0 (no overlap) to 1 (full overlap). +- `kde_kw`: Settings for the kernel density estimate. +- `points`: Number of evaluation points for KDE curves. +- `hist`: If True, uses histograms instead of kernel density estimation. +- `bins`: Bin specification for histograms. +- `fill`: Whether to fill the area under each density curve. +- `alpha`: Transparency level for filled areas (0=transparent, 1=opaque). +- `linewidth`: Width of the outline for each ridge. +- `edgecolor`: Color of the ridge outlines. +- `facecolor`: Fill color(s) for the ridges. +- `cmap`: Colormap name or object to use for coloring ridges. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.ridgeline)""" + ... + + def ridgelineh(self, data: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Create a horizontal ridgeline plot (also known as a joyplot). + +Parameters +---------- +- `data`: List of distributions to plot. +- `labels`: Labels for each distribution. +- `positions`: Y-coordinates for positioning each ridge. +- `height`: Height of each ridge in Y-axis units. +- `overlap`: Amount of overlap between ridges, from 0 (no overlap) to 1 (full overlap). +- `kde_kw`: Settings for the kernel density estimate. +- `points`: Number of evaluation points for KDE curves. +- `hist`: If True, uses histograms instead of kernel density estimation. +- `bins`: Bin specification for histograms. +- `fill`: Whether to fill the area under each density curve. +- `alpha`: Transparency level for filled areas (0=transparent, 1=opaque). +- `linewidth`: Width of the outline for each ridge. +- `edgecolor`: Color of the ridge outlines. +- `facecolor`: Fill color(s) for the ridges. +- `cmap`: Colormap name or object to use for coloring ridges. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.ridgelineh)""" + ... + + def _apply_hist(self, xs: Incomplete, bins: Incomplete, *, width: Incomplete=None, rwidth: Incomplete=None, stack: Incomplete=None, stacked: Incomplete=None, fill: Incomplete=None, filled: Incomplete=None, histtype: Incomplete=None, orientation: Incomplete='vertical', kde: Incomplete=False, kde_kw: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Apply the histogram.""" + ... + + def hist(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot vertical histograms. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `bins`: The bin count or exact bin edges. +- `weights`: The weights associated with each point. +- `histtype`: The histogram type. +- `width, rwidth`: The bar width(s) for bar-type histograms relative to the bin size. +- `stack, stacked`: Whether to "stack" successive columns of x data for bar-type histograms or show side-by-side in groups. +- `kde`: Whether to overlay a gaussian kernel density estimate of each column of data. +- `kde_kw`: Settings for the kernel density estimate. +- `fill, filled`: Whether to "fill" step-type histograms or just plot the edges. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [hist](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.hist.html). +- `x`: Input values, this takes either a single array or a sequence of arrays which are not required to be of the same length. +- `range`: The lower and upper range of the bins. +- `density`: If ``True``, draw and return a probability density: each bin will display the bin's raw count divided by the total number of counts *and the bin width* (``density = counts /… +- `cumulative`: If ``True``, then a histogram is computed where each bin gives the counts in that bin plus all bins for smaller values. +- `bottom`: Location of the bottom of each bin, i.e. +- `align`: The horizontal alignment of the histogram bars. +- `orientation`: If 'horizontal', `~.Axes.barh` will be used for bar-type histograms and the *bottom* kwarg will be the left edges. +- `rwidth`: The relative width of the bars as a fraction of the bin width. +- `log`: If ``True``, the histogram axis will be set to a log scale. +- `color`: Color or sequence of colors, one per dataset. +- _2 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.hist)""" + ... + + def histh(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot horizontal histograms. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `bins`: The bin count or exact bin edges. +- `weights`: The weights associated with each point. +- `histtype`: The histogram type. +- `width, rwidth`: The bar width(s) for bar-type histograms relative to the bin size. +- `stack, stacked`: Whether to "stack" successive columns of x data for bar-type histograms or show side-by-side in groups. +- `kde`: Whether to overlay a gaussian kernel density estimate of each column of data. +- `kde_kw`: Settings for the kernel density estimate. +- `fill, filled`: Whether to "fill" step-type histograms or just plot the edges. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cycle`: The cycle specifer, passed to the [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html) constructor. +- `cycle_kw`: Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). +- `linewidth`: The edge width of the patch(es). +- `linestyle`: The edge style of the patch(es). +- `edgecolor`: The edge color of the patch(es). +- `facecolor`: The face color of the patch(es). +- `alpha`: The opacity of the patch(es). +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label, value`: The single legend label or colorbar coordinate to be used for this plotted element. +- `labels, values`: The legend labels or colorbar coordinates used for each plotted element. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [hist](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.hist.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.histh)""" + ... + + def hist2d(self, x: Incomplete, y: Incomplete, bins: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot a standard 2D histogram. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `bins`: The bin count or exact bin edges for each dimension or both dimensions. +- `weights`: The weights associated with each point. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- `formatter_kw`: Keyword arguments passed to [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `precision`: The maximum number of decimal places for number labels generated with the default formatter [Simpleformatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ticker.Simpleformatter.html). +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- _7 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.hist2d)""" + ... + + def hexbin(self, x: Incomplete, y: Incomplete, weights: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot a 2D hexagonally binned histogram. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `weights`: The weights associated with each point. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- `formatter_kw`: Keyword arguments passed to [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `precision`: The maximum number of decimal places for number labels generated with the default formatter [Simpleformatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ticker.Simpleformatter.html). +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [hexbin](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.hexbin.html). +- _14 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.hexbin)""" + ... + + def contour(self, x: Incomplete, y: Incomplete, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot contour lines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of the line contours. +- `linestyles`: The style of the line contours. +- `edgecolors`: The color of the line contours. +- `alpha`: The opacity of the contours. +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- `formatter_kw`: Keyword arguments passed to [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- _20 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.contour)""" + ... + + def contourf(self, x: Incomplete, y: Incomplete, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot filled contours. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of the line contours. +- `linestyles`: The style of the line contours. +- `edgecolors`: The color of the line contours. +- `alpha`: The opacity of the contours. +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- `formatter_kw`: Keyword arguments passed to [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- _20 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.contourf)""" + ... + + def pcolor(self, x: Incomplete, y: Incomplete, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot irregular grid boxes. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of lines between grid boxes. +- `linestyles`: The style of lines between grid boxes. +- `edgecolors`: The color of lines between grid boxes. +- `alpha`: The opacity of the grid boxes. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- _14 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.pcolor)""" + ... + + def pcolormesh(self, x: Incomplete, y: Incomplete, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot regular grid boxes. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of lines between grid boxes. +- `linestyles`: The style of lines between grid boxes. +- `edgecolors`: The color of lines between grid boxes. +- `alpha`: The opacity of the grid boxes. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- _14 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.pcolormesh)""" + ... + + def pcolorfast(self, x: Incomplete, y: Incomplete, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot grid boxes quickly. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of lines between grid boxes. +- `linestyles`: The style of lines between grid boxes. +- `edgecolors`: The color of lines between grid boxes. +- `alpha`: The opacity of the grid boxes. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- _11 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.pcolorfast)""" + ... + + def heatmap(self, *args: Incomplete, aspect: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Plot grid boxes with formatting suitable for heatmaps. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `aspect`: Modify the axes aspect ratio. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of lines between grid boxes. +- `linestyles`: The style of lines between grid boxes. +- `edgecolors`: The color of lines between grid boxes. +- `alpha`: The opacity of the grid boxes. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- _8 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.heatmap)""" + ... + + def barbs(self, x: Incomplete, y: Incomplete, u: Incomplete, v: Incomplete, c: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot wind barbs. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `c, color, colors`: The colors of the wind barbs passed as either a keyword argument or a fifth positional argument. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `**kwargs`: Passed to [matplotlib.axes.Axes.barbs](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.barbs.html) +- `X, Y`: The x and y coordinates of the barb locations. +- `U, V`: The x and y components of the barb shaft. +- `C`: Numeric data that defines the barb colors by colormapping via *norm* and *cmap*. +- `length`: Length of the barb in points; the other parts of the barb are scaled against this. +- `pivot`: The part of the arrow that is anchored to the *X*, *Y* grid. +- `barbcolor`: The color of all parts of the barb except for the flags. +- `flagcolor`: The color of any flags on the barb. +- `sizes`: A dictionary of coefficients specifying the ratio of a given feature to the length of the barb. +- _4 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.barbs)""" + ... + + def quiver(self, x: Incomplete, y: Incomplete, u: Incomplete, v: Incomplete, c: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot quiver arrows. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `c, color, colors`: The colors of the quiver arrows passed as either a keyword argument or a fifth positional argument. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `**kwargs`: Passed to [matplotlib.axes.Axes.quiver](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.quiver.html) +- `X, Y`: The x and y coordinates of the arrow locations. +- `U, V`: The x and y direction components of the arrow vectors. +- `C`: Numeric data that defines the arrow colors by colormapping via *norm* and *cmap*. +- `angles`: Method for determining the angle of the arrows. +- `pivot`: The part of the arrow that is anchored to the *X*, *Y* grid. +- `scale`: Scales the length of the arrow inversely. +- `scale_units`: The physical image unit, which is used for rendering the scaled arrow data *U*, *V*. +- `units`: Affects the arrow size (except for the length). +- _7 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.quiver)""" + ... + + def stream(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot streamlines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `c, color, colors`: The colors of the streamlines passed as either a keyword argument or a fifth positional argument. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `**kwargs`: Passed to [matplotlib.axes.Axes.streamplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.streamplot.html) + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.stream)""" + ... + + def streamplot(self, x: Incomplete, y: Incomplete, u: Incomplete, v: Incomplete, c: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot streamlines. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `c, color, colors`: The colors of the streamlines passed as either a keyword argument or a fifth positional argument. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `**kwargs`: Passed to [matplotlib.axes.Axes.streamplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.streamplot.html) +- `x, y`: Evenly spaced strictly increasing arrays to make a grid. +- `u, v`: *x* and *y*-velocities. +- `density`: Controls the closeness of streamlines. +- `linewidth`: The width of the streamlines. +- `color`: The streamline color. +- `arrowsize`: Scaling factor for the arrow size. +- `arrowstyle`: Arrow style specification. +- `minlength`: Minimum length of streamline in axes coordinates. +- _5 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.streamplot)""" + ... + + def tricontour(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot contour lines on a triangular grid. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of the line contours. +- `linestyles`: The style of the line contours. +- `edgecolors`: The color of the line contours. +- `alpha`: The opacity of the contours. +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- `formatter_kw`: Keyword arguments passed to [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- _13 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.tricontour)""" + ... + + def tricontourf(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot filled contours on a triangular grid. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of the line contours. +- `linestyles`: The style of the line contours. +- `edgecolors`: The color of the line contours. +- `alpha`: The opacity of the contours. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- _15 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.tricontourf)""" + ... + + def tripcolor(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot triangular grid boxes. + +Parameters +---------- +- `*args`: The data passed as positional or keyword arguments. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `transpose`: Whether to transpose the input data. +- `order`: Alternative to `transpose`. +- `globe`: For [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html) only. +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `linewidths`: The width of lines between grid boxes. +- `linestyles`: The style of lines between grid boxes. +- `edgecolors`: The color of lines between grid boxes. +- `alpha`: The opacity of the grid boxes. +- `edgefix`: Whether to fix the common issue where white lines appear between adjacent patches in saved vector graphics (this can slow down figure rendering). +- `label`: The legend label to be used for this object. +- `labels`: Whether to apply labels to contours and grid boxes. +- `labels_kw`: Ignored if `labels` is ``False``. +- `formatter, fmt`: The [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) used to format number labels. +- _12 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.tripcolor)""" + ... + + def imshow(self, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot an image. + +Parameters +---------- +- `z`: The data passed as a positional argument or keyword argument. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [matplotlib.axes.Axes.imshow](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.imshow.html). +- `X`: The image data. +- `colorizer`: The Colorizer object used to map color to data. +- `aspect`: The aspect ratio of the Axes. +- `interpolation`: The interpolation method used. +- `interpolation_stage`: Supported values: - 'data': Interpolation is carried out on the data provided by the user This is useful if interpolating between pixels during upsampling. +- `alpha`: The alpha blending value, between 0 (transparent) and 1 (opaque). +- `origin`: Place the [0, 0] index of the array in the upper left or lower left corner of the Axes. +- _5 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.imshow)""" + ... + + def matshow(self, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot a matrix. + +Parameters +---------- +- `z`: The data passed as a positional argument or keyword argument. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [matplotlib.axes.Axes.matshow](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.matshow.html). +- `Z`: The matrix to be displayed. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.matshow)""" + ... + + def spy(self, z: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot a sparcity pattern. + +Parameters +---------- +- `z`: The data passed as a positional argument or keyword argument. +- `data`: A dict-like dataset container (e.g., [DataFrame](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html) or [Dataset](https://docs.xarray.dev/en/stable/generated/xarray.Dataset.html)). +- `autoformat`: Whether the `x` axis labels, `y` axis labels, axis formatters, axes titles, legend titles, and colorbar labels are automatically configured when a [Series](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.html)… +- `cmap`: The colormap specifer, passed to the [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html) constructor function. +- `cmap_kw`: Passed to [Colormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html). +- `c, color, colors`: The color(s) used to create a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). +- `norm`: The data value normalizer, passed to the [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html) constructor function. +- `norm_kw`: Passed to [Norm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html). +- `extend`: Direction for drawing colorbar "extensions" indicating out-of-bounds data on the end of the colorbar. +- `discrete`: If ``False``, then [DiscreteNorm](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html) is not applied to the colormap. +- `sequential, diverging, cyclic, qualitative`: Boolean arguments used if `cmap` is not passed. +- `vmin, vmax`: The minimum and maximum color scale values used with the `norm` normalizer. +- `N`: Shorthand for `levels`. +- `levels`: The number of level edges or a sequence of level edges. +- `values`: The number of level centers or a sequence of level centers. +- `center_levels`: If set to true, the discrete color bar bins will be centered on the level values instead of using the level values as the edges of the discrete bins. +- `robust`: If ``True`` and `vmin` or `vmax` were not provided, they are determined from the 2nd and 98th data percentiles rather than the minimum and maximum. +- `inbounds`: If ``True`` and `vmin` or `vmax` were not provided, when axis limits have been explicitly restricted with [set_xlim](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlim.html) or… +- `locator`: The locator used to determine level locations if `levels` or `values` were not already passed as lists. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `symmetric`: If ``True``, the normalization range or discrete colormap levels are symmetric about zero. +- `positive`: If ``True``, the normalization range or discrete colormap levels are positive with a minimum at zero. +- `negative`: If ``True``, the normaliation range or discrete colormap levels are negative with a minimum at zero. +- `nozero`: If ``True``, ``0`` is removed from the level list. +- `colorbar`: If not ``None``, this is a location specifying where to draw an *inset* or *outer* colorbar from the resulting object(s). +- `colorbar_kw`: Extra keyword args for the call to [colorbar](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.colorbar). +- `legend`: Location specifying where to draw an *inset* or *outer* legend from the resulting object(s). +- `legend_kw`: Extra keyword args for the call to [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.legend). +- `**kwargs`: Passed to [matplotlib.axes.Axes.spy](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.spy.html). +- `Z`: The array to be plotted. +- `precision`: If *precision* is 0, any non-zero value will be plotted. +- `aspect`: The aspect ratio of the Axes. +- `origin`: Place the [0, 0] index of the array in the upper left or lower left corner of the Axes. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.spy)""" + ... + + def _iter_arg_pairs(self, *args: Incomplete) -> Incomplete: + """Iterate over ``[x1,] y1, [fmt1,] [x2,] y2, [fmt2,] ...`` input.""" + ... + + def _iter_arg_cols(self, *args: Incomplete, label: Incomplete=None, labels: Incomplete=None, values: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Iterate over columns of positional arguments.""" + ... + _level_parsers = (_parse_level_vals, _parse_level_num, _parse_level_lim) diff --git a/ultraplot/axes/plot_types/__init__.pyi b/ultraplot/axes/plot_types/__init__.pyi new file mode 100644 index 000000000..9d22fbe63 --- /dev/null +++ b/ultraplot/axes/plot_types/__init__.pyi @@ -0,0 +1,3 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +from _typeshed import Incomplete diff --git a/ultraplot/axes/plot_types/circlize.pyi b/ultraplot/axes/plot_types/circlize.pyi new file mode 100644 index 000000000..400802122 --- /dev/null +++ b/ultraplot/axes/plot_types/circlize.pyi @@ -0,0 +1,62 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Helpers for pyCirclize-backed circular plots. +""" +from _typeshed import Incomplete +import itertools +import sys +from pathlib import Path +from typing import Any, Callable, Mapping, Optional, Sequence, Union +from matplotlib.projections.polar import PolarAxes as MplPolarAxes +from ... import constructor +from ...config import rc +_PYCIRCLIZE_RC_LEAKS = ('savefig.bbox', 'savefig.pad_inches', 'svg.fonttype') + +def _import_pycirclize() -> Incomplete: + """Import pycirclize without letting it restyle the session. + +``pycirclize.config`` runs ``mpl.rcParams.update(...)`` at import time, +setting ``savefig.bbox='tight'`` and ``savefig.pad_inches=0.5``. Since the +import is lazy, the first chord, radar, phylogeny or circos plot in a +session would otherwise silently change the size and padding of every +figure saved afterwards.""" + ... + +def _import_pycirclize_unguarded() -> Incomplete: + ... + +def _unwrap_axes(ax: Incomplete, label: str) -> Incomplete: + ... + +def _ensure_polar(ax: Incomplete, label: str) -> Incomplete: + ... + +def _cycle_colors(n: int) -> list[str]: + ... + +def _resolve_chord_defaults(matrix: Any, cmap: Any) -> Incomplete: + ... + +def _resolve_radar_defaults(table: Any, cmap: Any) -> Incomplete: + ... + +def circos(ax: Incomplete, sectors: Mapping[str, Any], *, start: float=0, end: float=360, space: float | Sequence[float]=0, endspace: bool=True, sector2clockwise: Mapping[str, bool] | None=None, show_axis_for_debug: bool=False, plot: bool=False, tooltip: bool=False) -> Incomplete: + """Create a pyCirclize Circos instance (optionally plot immediately).""" + ... + +def chord_diagram(ax: Incomplete, matrix: Any, *, start: Optional[float]=None, end: Optional[float]=None, space: Optional[Union[float, Sequence[float]]]=None, endspace: Optional[bool]=None, r_lim: Optional[tuple[float, float]]=None, cmap: Any=None, link_cmap: Optional[list[tuple[str, str, str]]]=None, ticks_interval: Optional[int]=None, order: Optional[Union[str, list[str]]]=None, label_kw: Optional[Mapping[str, Any]]=None, ticks_kw: Optional[Mapping[str, Any]]=None, link_kw: Optional[Mapping[str, Any]]=None, link_kw_handler: Incomplete=None, tooltip: bool=False) -> Incomplete: + """Render a chord diagram using pyCirclize on the provided polar axes.""" + ... + +def radar_chart(ax: Incomplete, table: Any, *, r_lim: Optional[tuple[float, float]]=None, vmin: Optional[float]=None, vmax: Optional[float]=None, fill: Optional[bool]=None, marker_size: Optional[int]=None, bg_color: Optional[str]=None, circular: Optional[bool]=None, cmap: Any=None, show_grid_label: Optional[bool]=None, grid_interval_ratio: Optional[float]=None, grid_line_kw: Optional[Mapping[str, Any]]=None, grid_label_kw: Optional[Mapping[str, Any]]=None, grid_label_formatter: Incomplete=None, label_kw_handler: Incomplete=None, line_kw_handler: Incomplete=None, marker_kw_handler: Incomplete=None) -> Incomplete: + """Render a radar chart using pyCirclize on the provided polar axes.""" + ... + +def phylogeny(ax: Incomplete, tree_data: Any, *, start: Optional[float]=None, end: Optional[float]=None, r_lim: Optional[tuple[float, float]]=None, format: Optional[str]=None, outer: Optional[bool]=None, align_leaf_label: Optional[bool]=None, ignore_branch_length: Optional[bool]=None, leaf_label_size: Optional[float]=None, leaf_label_rmargin: Optional[float]=None, reverse: Optional[bool]=None, ladderize: Optional[bool]=None, line_kw: Optional[Mapping[str, Any]]=None, label_formatter: Incomplete=None, align_line_kw: Optional[Mapping[str, Any]]=None, tooltip: bool=False) -> Incomplete: + """Render a phylogenetic tree using pyCirclize on the provided polar axes.""" + ... + +def circos_bed(ax: Incomplete, bed_file: Any, *, start: float=0, end: float=360, space: float | Sequence[float]=0, endspace: bool=True, sector2clockwise: Mapping[str, bool] | None=None, plot: bool=False, tooltip: bool=False) -> Incomplete: + """Create a Circos instance from a BED file (optionally plot immediately).""" + ... diff --git a/ultraplot/axes/plot_types/curved_quiver.pyi b/ultraplot/axes/plot_types/curved_quiver.pyi new file mode 100644 index 000000000..a23c31ba1 --- /dev/null +++ b/ultraplot/axes/plot_types/curved_quiver.pyi @@ -0,0 +1,156 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +from _typeshed import Incomplete +__all__ = ['CurvedQuiverSolver', 'CurvedQuiverSet'] +from typing import Callable +from dataclasses import dataclass +from matplotlib.streamplot import StreamplotSet +import numpy as np + +@dataclass +class CurvedQuiverSet(StreamplotSet): + lines: object + arrows: object + +@dataclass +class _CurvedQuiverTrajectory: + x: list[float] + y: list[float] + hit_edge: bool + end_direction: tuple[float, float] | None + +class _DomainMap(object): + """Map representing different coordinate systems. + +Coordinate definitions: +* axes-coordinates goes from 0 to 1 in the domain. +* data-coordinates are specified by the input x-y coordinates. +* grid-coordinates goes from 0 to N and 0 to M for an N x M grid, + where N and M match the shape of the input data. +* mask-coordinates goes from 0 to N and 0 to M for an N x M mask, + where N and M are user-specified to control the density of + streamlines. + +This class also has methods for adding trajectories to the +StreamMask. Before adding a trajectory, run `start_trajectory` to +keep track of regions crossed by a given trajectory. Later, if you +decide the trajectory is bad (e.g., if the trajectory is very +short) just call `undo_trajectory`.""" + + def __init__(self, grid: Incomplete, mask: Incomplete) -> None: + ... + + def grid2mask(self, xi: float, yi: float) -> tuple[int, int]: + """Return nearest space in mask-coords from given grid-coords.""" + ... + + def mask2grid(self, xm: int, ym: int) -> tuple[float, float]: + ... + + def data2grid(self, xd: float, yd: float) -> tuple[float, float]: + ... + + def grid2data(self, xg: float, yg: float) -> tuple[float, float]: + ... + + def start_trajectory(self, xg: float, yg: float) -> None: + ... + + def reset_start_point(self, xg: float, yg: float) -> None: + ... + + def update_trajectory(self, xg: float, yg: float) -> None: + ... + + def undo_trajectory(self) -> None: + ... + +class _CurvedQuiverGrid(object): + """Grid of data.""" + + def __init__(self, x: np.ndarray, y: np.ndarray) -> None: + ... + + @property + def shape(self) -> tuple[int, int]: + ... + + def within_grid(self, xi: float, yi: float) -> bool: + """Return True if point is a valid index of grid.""" + ... + +class _StreamMask(object): + """Mask to keep track of discrete regions crossed by streamlines. + +The resolution of this grid determines the approximate spacing +between trajectories. Streamlines are only allowed to pass through +zeroed cells: When a streamline enters a cell, that cell is set to +1, and no new streamlines are allowed to enter.""" + + def __init__(self, density: float | int) -> None: + ... + + def __getitem__(self, *args: Incomplete) -> Incomplete: + ... + + def _start_trajectory(self, xm: int, ym: int) -> Incomplete: + """Start recording streamline trajectory""" + ... + + def _undo_trajectory(self) -> Incomplete: + """Remove current trajectory from mask""" + ... + + def _update_trajectory(self, xm: int, ym: int) -> None: + """Update current trajectory position in mask. + +If the new position has already been filled, raise +`InvalidIndexError`.""" + ... + +class _CurvedQuiverTerminateTrajectory(Exception): + pass + +class CurvedQuiverSolver: + + def __init__(self, x: np.ndarray, y: np.ndarray, density: float | tuple[float, float]) -> None: + ... + + def get_integrator(self, u: np.ndarray, v: np.ndarray, minlength: float, resolution: float, magnitude: np.ndarray) -> Callable[[float, float], _CurvedQuiverTrajectory | None]: + ... + + def integrate_rk12(self, x0: float, y0: float, f: Callable[[float, float], tuple[float, float]], resolution: float, magnitude: np.ndarray) -> tuple[list[float], list[float], bool]: + """2nd-order Runge-Kutta algorithm with adaptive step size. + +This method is also referred to as the improved Euler's method, or +Heun's method. This method is favored over higher-order methods +because: + +1. To get decent looking trajectories and to sample every mask cell +on the trajectory we need a small timestep, so a lower order +solver doesn't hurt us unless the data is *very* high +resolution. In fact, for cases where the user inputs data +smaller or of similar grid size to the mask grid, the higher +order corrections are negligible because of the very fast linear +interpolation used in `interpgrid`. + +2. For high resolution input data (i.e. beyond the mask +resolution), we must reduce the timestep. Therefore, an +adaptive timestep is more suited to the problem as this would be +very hard to judge automatically otherwise. + +This integrator is about 1.5 - 2x as fast as both the RK4 and RK45 +solvers in most setups on my machine. I would recommend removing +the other two to keep things simple.""" + ... + + def euler_step(self, xf_traj: Incomplete, yf_traj: Incomplete, f: Incomplete) -> Incomplete: + """Simple Euler integration step that extends streamline to boundary.""" + ... + + def interpgrid(self, a: Incomplete, xi: Incomplete, yi: Incomplete) -> Incomplete: + """Fast 2D, linear interpolation on an integer grid""" + ... + + def gen_starting_points(self, x: Incomplete, y: Incomplete, grains: Incomplete) -> Incomplete: + ... diff --git a/ultraplot/axes/plot_types/ribbon.pyi b/ultraplot/axes/plot_types/ribbon.pyi new file mode 100644 index 000000000..0dbd7e3a7 --- /dev/null +++ b/ultraplot/axes/plot_types/ribbon.pyi @@ -0,0 +1,20 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Top-aligned ribbon flow diagram helper. +""" +from _typeshed import Incomplete +from collections import Counter, defaultdict +from collections.abc import Mapping, Sequence +from typing import Any +import numpy as np +import pandas as pd +from matplotlib import patches as mpatches +from matplotlib import path as mpath + +def _ribbon_path(x0: float, y0: float, x1: float, y1: float, thickness: float, curvature: float) -> mpath.Path: + ... + +def ribbon_diagram(ax: Any, data: Any, *, id_col: str, period_col: str, topic_col: str, value_col: str | None=None, period_order: Sequence[Any] | None=None, topic_order: Sequence[Any] | None=None, group_map: Mapping[Any, Any] | None=None, group_order: Sequence[Any] | None=None, group_colors: Mapping[Any, Any] | None=None, xmargin: float, ymargin: float, row_height_ratio: float, node_width: float, flow_curvature: float, flow_alpha: float, show_topic_labels: bool, topic_label_offset: float, topic_label_size: float, topic_label_box: bool) -> dict[str, Any]: + """Build a fixed-row, top-aligned ribbon flow diagram from long-form assignments.""" + ... diff --git a/ultraplot/axes/plot_types/sankey.pyi b/ultraplot/axes/plot_types/sankey.pyi new file mode 100644 index 000000000..232764d7f --- /dev/null +++ b/ultraplot/axes/plot_types/sankey.pyi @@ -0,0 +1,105 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +from _typeshed import Incomplete +from dataclasses import dataclass +from typing import Any, Callable, Mapping, Optional, Sequence, Union +from matplotlib import colors as mcolors +from matplotlib import patches as mpatches +from matplotlib import path as mpath +from ...config import rc +from ...internals import _not_none + +@dataclass +class SankeyDiagram: + nodes: dict[Any, mpatches.Patch] + flows: list[mpatches.PathPatch] + labels: dict[Any, Any] + layout: dict[str, Any] + +def _tint(color: Any, amount: float) -> tuple[float, float, float]: + """Return a lightened version of a base color.""" + ... + +def _normalize_nodes(nodes: Any, flows: Sequence[Mapping[str, Any]]) -> tuple[dict[Any, dict[str, Any]], list[Any]]: + """Normalize node definitions into a map and stable order list.""" + ... + +def _normalize_flows(flows: Any) -> list[dict[str, Any]]: + """Normalize flow definitions into a list of dicts.""" + ... + +def _assign_layers(flows: Sequence[Mapping[str, Any]], nodes: Sequence[Any], layers: Mapping[Any, int] | None) -> dict[Any, int]: + """Assign layer indices for nodes using a DAG topological pass.""" + ... + +def _compute_layout(nodes: Sequence[Any], flows: Sequence[Mapping[str, Any]], *, node_pad: float, node_width: float, align: str, layers: Mapping[Any, int] | None, margin: float, layer_order: Sequence[int] | None=None) -> tuple[dict[str, Any], dict[Any, list[dict[str, Any]]], dict[Any, list[dict[str, Any]]], dict[Any, float]]: + """Compute node and flow layout geometry in axes-relative coordinates.""" + ... + +def _ribbon_path(x0: float, y0: float, x1: float, y1: float, thickness: float, curvature: float) -> mpath.Path: + """Build a closed Bezier path for a ribbon segment.""" + ... + +def _bezier_point(p0: float, p1: float, p2: float, p3: float, t: float) -> float: + """Evaluate a cubic Bezier coordinate at t in [0, 1].""" + ... + +def _flow_label_point(x0: float, y0: float, x1: float, y1: float, thickness: float, curvature: float, frac: float) -> tuple[float, float]: + """Return a point along the flow centerline for label placement.""" + ... + +def _apply_style(style: str | None, *, flow_cycle: Sequence[Any] | None, node_facecolor: Any, flow_alpha: float, flow_curvature: float, node_label_box: bool | Mapping[str, Any] | None, node_label_kw: Mapping[str, Any]) -> dict[str, Any]: + """Apply a named style preset and merge overrides.""" + ... + +def _apply_flow_other(flows: list[dict[str, Any]], flow_other: float | None, other_label: str) -> list[dict[str, Any]]: + """Aggregate small flows into a single 'Other' target per source.""" + ... + +def _ensure_nodes(nodes: Any, flows: Sequence[Mapping[str, Any]], node_order: Sequence[Any] | None) -> tuple[dict[Any, dict[str, Any]], list[Any]]: + """Ensure all flow endpoints exist in nodes and validate ordering.""" + ... + +def _assign_flow_colors(flows: Sequence[Mapping[str, Any]], flow_cycle: Sequence[Any] | None, group_cycle: Sequence[Any] | None) -> dict[Any, Any]: + """Assign colors to flows by group or source.""" + ... + +def _sort_flows(flows: Sequence[Mapping[str, Any]], node_order: Sequence[Any], layout: Mapping[str, Any]) -> list[dict[str, Any]]: + """Sort flows by target position to reduce crossings.""" + ... + +def _flow_label_text(flow: Mapping[str, Any], value_format: str | Callable[[float], str] | None) -> str: + """Resolve the text for a flow label.""" + ... + +def _flow_label_frac(idx: int, count: int, base: float) -> float: + """Return alternating label positions around the midpoint.""" + ... + +def _prepare_inputs(*, nodes: Any, flows: Any, flow_other: float | None, other_label: str, node_order: Sequence[Any] | None, style: str | None, flow_cycle: Sequence[Any] | None, node_facecolor: Any, flow_alpha: float, flow_curvature: float, node_label_box: bool | Mapping[str, Any] | None, node_label_kw: Mapping[str, Any], group_cycle: Sequence[Any] | None) -> tuple[list[dict[str, Any]], dict[Any, dict[str, Any]], list[Any], dict[str, Any], dict[Any, Any]]: + """Normalize inputs, apply style, and assign colors.""" + ... + +def _validate_layer_order(layer_order: Sequence[int] | None, flows: Sequence[Mapping[str, Any]], node_order: Sequence[Any], layers: Mapping[Any, int] | None) -> None: + """Validate that layer_order is consistent with computed layers.""" + ... + +def _layer_positions(layout: Mapping[str, Any], layer_order: Sequence[int] | None) -> tuple[dict[Any, int], dict[int, int]]: + """Return layer maps and positions for label placement.""" + ... + +def _label_box(node_label_box: bool | Mapping[str, Any] | None) -> dict[str, Any] | None: + """Return a bbox dict for node labels, if requested.""" + ... + +def _draw_flows(ax: Incomplete, *, flows: Sequence[Mapping[str, Any]], node_order: Sequence[Any], layout: Mapping[str, Any], flow_color_map: Mapping[Any, Any], flow_kw: Mapping[str, Any], label_kw: Mapping[str, Any], flow_label_kw: Mapping[str, Any], flow_labels: bool, value_format: str | Callable[[float], str] | None, flow_label_pos: float, flow_alpha: float, flow_curvature: float) -> tuple[list[mpatches.PathPatch], dict[Any, Any]]: + """Draw flow ribbons and optional labels.""" + ... + +def _draw_nodes(ax: Incomplete, *, node_order: Sequence[Any], node_map: Mapping[Any, Mapping[str, Any]], layout: Mapping[str, Any], layer_map: Mapping[Any, int], layer_position: Mapping[int, int], node_facecolor: Any, node_kw: Mapping[str, Any], label_kw: Mapping[str, Any], node_label_kw: Mapping[str, Any], node_label_box: bool | Mapping[str, Any] | None, node_labels: bool, node_label_outside: bool | str, node_label_offset: float) -> tuple[dict[Any, mpatches.Patch], dict[Any, Any]]: + """Draw node rectangles and optional labels.""" + ... + +def sankey_diagram(ax: Incomplete, *, nodes: Any=None, flows: Any=None, layers: Optional[Mapping[Any, int]]=None, flow_cycle: Optional[Sequence[Any]]=None, group_cycle: Optional[Sequence[Any]]=None, node_order: Optional[Sequence[Any]]=None, layer_order: Optional[Sequence[int]]=None, style: Optional[str]=None, flow_other: Optional[float]=None, other_label: Optional[str]=None, value_format: Optional[Union[str, Callable[[float], str]]]=None, node_pad: Optional[float]=None, node_width: Optional[float]=None, node_kw: Optional[Mapping[str, Any]]=None, flow_kw: Optional[Mapping[str, Any]]=None, label_kw: Optional[Mapping[str, Any]]=None, node_label_kw: Optional[Mapping[str, Any]]=None, flow_label_kw: Optional[Mapping[str, Any]]=None, node_label_box: Optional[Union[bool, Mapping[str, Any]]]=None, node_labels: Optional[bool]=None, flow_labels: Optional[bool]=None, flow_sort: Optional[bool]=None, flow_label_pos: Optional[float]=None, node_label_outside: Optional[Union[bool, str]]=None, node_label_offset: Optional[float]=None, align: Optional[str]=None, margin: Optional[float]=None, flow_alpha: Optional[float]=None, flow_curvature: Optional[float]=None, node_facecolor: Optional[Any]=None) -> SankeyDiagram: + """Render a layered Sankey diagram with optional labels.""" + ... diff --git a/ultraplot/axes/polar.pyi b/ultraplot/axes/polar.pyi new file mode 100644 index 000000000..7621f0c5f --- /dev/null +++ b/ultraplot/axes/polar.pyi @@ -0,0 +1,250 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Polar axes using azimuth and radius instead of *x* and *y*. +""" +from _typeshed import Incomplete +import inspect +try: + from typing import override +except: + from typing_extensions import override +import matplotlib.projections.polar as mpolar +import matplotlib.transforms as mtransforms +import numpy as np +from matplotlib.font_manager import FontProperties +from .. import constructor +from .. import ticker as pticker +from ..config import rc +from ..internals import _not_none, _pop_rc, docstring, ic +from . import plot, shared +__all__ = ['PolarAxes'] +_POLAR_LABEL_NPOINTS = 50 +_POLAR_LABEL_FULL_HALFSPAN_DEG = 15.0 +_POLAR_LABEL_SECTOR_FRAC = 0.8 +_format_docstring = ... + +class PolarAxes(shared._SharedAxes, plot.PlotAxes, mpolar.PolarAxes): + """Axes subclass for plotting in polar coordinates. Adds the `~PolarAxes.format` +method and overrides several existing methods. + +Important +--------- +This axes subclass can be used by passing ``proj='polar'`` +to axes-creation commands like [add_axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_axes), +[add_subplot](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_subplot), and [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots).""" + _name = 'polar' + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `*args`: Passed to [matplotlib.axes.Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html). +- `r0`: The radial origin. +- `theta0`: The zero azimuth location. +- `thetadir`: The positive azimuth direction. +- `thetamin, thetamax`: The lower and upper azimuthal bounds in degrees. +- `thetalim`: Specifies `thetamin` and `thetamax` at once. +- `rmin, rmax`: The inner and outer radial limits. +- `rlim`: Specifies `rmin` and `rmax` at once. +- `rborder`: Whether to draw the polar axes border. +- `thetagrid, rgrid, grid`: Whether to draw major gridlines for the azimuthal and radial axis. +- `thetagridminor, rgridminor, gridminor`: Whether to draw minor gridlines for the azimuthal and radial axis. +- `thetagridcolor, rgridcolor, gridcolor`: Color for the major and minor azimuthal and radial gridlines. +- `thetalocator, rlocator`: Used to determine the azimuthal and radial gridline positions. +- `thetalocator_kw, rlocator_kw`: The azimuthal and radial locator settings. +- `thetaminorlocator, rminorlocator`: As for `thetalocator`, `rlocator`, but for the minor gridlines. +- `thetaminorticks, rminorticks`: Aliases for `thetaminorlocator`, `rminorlocator`. +- `rlabelpos`: The azimuth at which radial coordinates are labeled. +- `thetaformatter, rformatter`: Used to determine the azimuthal and radial label format. +- `thetalabels, rlabels`: Aliases for `thetaformatter`, `rformatter`. +- `thetaformatter_kw, rformatter_kw`: The azimuthal and radial label formatter settings. +- `thetalabel, rlabel`: Polar-aware axis labels rendered via [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html). +- `thetalabelloc`: Center theta angle (in degrees) for ``thetalabel``. +- `rlabelloc`: Where to place ``rlabel``. +- `thetalabel_kw, rlabel_kw`: Additional [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html) settings for the polar-aware labels (e.g. +- `color`: Color for the axes edge. +- `labelcolor, gridlabelcolor`: Color for the gridline labels. +- `labelpad, gridlabelpad`: The padding between the axes edge and the radial and azimuthal labels. +- `labelsize, gridlabelsize`: Font size for the gridline labels. +- `labelweight, gridlabelweight`: Font weight for the gridline labels. +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- `abcloc, titleloc`: Strings indicating the location for the a-b-c label and main title. +- `abcborder, titleborder`: Whether to draw a white border around titles and a-b-c labels positioned inside the axes. +- `abcbbox, titlebbox`: Whether to draw a white bbox around titles and a-b-c labels positioned inside the axes. +- `abcpad`: Horizontal offset to shift the a-b-c label position. +- `abc_kw, title_kw`: Additional settings used to update the a-b-c label and title with ``text.update()``. +- _9 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html)""" + ... + + @override + def _apply_axis_sharing(self) -> Incomplete: + ... + + def _update_formatter(self, x: Incomplete, *, formatter: Incomplete=None, formatter_kw: Incomplete=None) -> None: + """Update the gridline label formatter.""" + ... + + def _update_limits(self, x: Incomplete, *, min_: Incomplete=None, max_: Incomplete=None, lim: Incomplete=None) -> None: + """Update the limits.""" + ... + + def _update_locators(self, x: Incomplete, *, locator: Incomplete=None, locator_kw: Incomplete=None, minorlocator: Incomplete=None, minorlocator_kw: Incomplete=None) -> None: + """Update the gridline locator.""" + ... + + def _get_directed_thetalim(self) -> tuple[float, float]: + """Return the directed theta interval in degrees from the raw x-limits.""" + ... + + @staticmethod + def _is_full_circle_thetalim(thetamin: Incomplete, thetamax: Incomplete) -> Incomplete: + """Return whether the directed theta interval spans a full circle.""" + ... + + def _polar_tick_clearance_in(self, axis: Incomplete) -> Incomplete: + """Tick mark + tick pad + ~font height(s), in inches.""" + ... + + def _build_thetalabel_curve(self, loc: Incomplete, total_pad_in: Incomplete) -> Incomplete: + """Curve along the outer arc at r = rmax + delta_r (data coords). The +radial offset is computed in data space so clearance is angle- +independent — figure-space ScaledTranslation undershoots when the +outward direction points toward a tight bbox edge (e.g. 180–230°).""" + ... + + def _get_sector_rlabel_outside_sign(self, rpos: Incomplete) -> float: + """Return the sign that offsets a sector rlabel outside the wedge.""" + ... + + def _resolve_rlabel_geometry(self, loc: Incomplete, rlabelpos: Incomplete) -> tuple[float, float]: + """Resolve ``(rpos, sign)`` for the radial label given ``rlabelloc`` and +an optional explicit ``rlabelpos``. On a full circle, ``loc`` flips +the perpendicular offset; on a sector with no explicit ``rlabelpos``, +``loc`` instead selects the spoke (``thetamin`` vs ``thetamax``) and +the perpendicular sign is auto-chosen to fall outside the wedge.""" + ... + + def _get_rlabel_right_normal(self, rad: Incomplete) -> Incomplete: + """Return the display-space right normal for the radial spoke at ``rad``.""" + ... + + def _build_rlabel_curve(self, loc: Incomplete, pad_in: Incomplete, rlabelpos: Incomplete) -> Incomplete: + """Curve along the radial spoke from rmin to rmax with a perpendicular +ScaledTranslation offset so the label clears the r-tick labels.""" + ... + + def _refresh_polar_label_geometry(self, kind: Incomplete) -> None: + """Refresh the stored curve and transform for an existing polar label.""" + ... + + def _update_polar_label(self, kind: Incomplete, text: Incomplete, *, loc: Incomplete=None, labelpad: Incomplete=None, rlabelpos: Incomplete=None, **kwargs: Incomplete) -> None: + """Apply a polar-aware axis label along the outer arc (`thetalabel`) or +along the radial spoke (`rlabel`), both via CurvedText.""" + ... + + @override + def draw(self, renderer: Incomplete=None, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Draw the Artist (and its children) using the given renderer. + +This has no effect if the artist is not visible (`.Artist.get_visible` +returns False). + +Parameters +---------- +renderer : [RendererBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.RendererBase.html) subclass. + +Notes +----- +This method is overridden in the Artist subclasses.""" + ... + + @override + def get_tightbbox(self, renderer: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """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` subclass + 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 : bool, 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. + +for_layout_only : default: False + The bounding box will *not* include the x-extent of the title and + the xlabel, or the y-extent of the ylabel. + +Returns +------- +`.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""" + ... + + def format(self, *, r0: Incomplete=None, theta0: Incomplete=None, thetadir: Incomplete=None, thetamin: Incomplete=None, thetamax: Incomplete=None, thetalim: Incomplete=None, rmin: Incomplete=None, rmax: Incomplete=None, rlim: Incomplete=None, thetagrid: Incomplete=None, rgrid: Incomplete=None, thetagridminor: Incomplete=None, rgridminor: Incomplete=None, thetagridcolor: Incomplete=None, rgridcolor: Incomplete=None, rlabelpos: Incomplete=None, rscale: Incomplete=None, rborder: Incomplete=None, thetalocator: Incomplete=None, rlocator: Incomplete=None, thetalines: Incomplete=None, rlines: Incomplete=None, thetalocator_kw: Incomplete=None, rlocator_kw: Incomplete=None, thetaminorlocator: Incomplete=None, rminorlocator: Incomplete=None, thetaminorlines: Incomplete=None, rminorlines: Incomplete=None, thetaminorlocator_kw: Incomplete=None, rminorlocator_kw: Incomplete=None, thetaformatter: Incomplete=None, rformatter: Incomplete=None, thetalabels: Incomplete=None, rlabels: Incomplete=None, thetaformatter_kw: Incomplete=None, rformatter_kw: Incomplete=None, labelpad: Incomplete=None, labelsize: Incomplete=None, labelcolor: Incomplete=None, labelweight: Incomplete=None, thetalabel: Incomplete=None, rlabel: Incomplete=None, thetalabelloc: Incomplete=None, rlabelloc: Incomplete=None, thetalabel_kw: Incomplete=None, rlabel_kw: Incomplete=None, **kwargs: Incomplete) -> None: + """Modify axes limits, radial and azimuthal gridlines, and more. + +Parameters +---------- +- `r0`: The radial origin. +- `theta0`: The zero azimuth location. +- `thetadir`: The positive azimuth direction. +- `thetamin, thetamax`: The lower and upper azimuthal bounds in degrees. +- `thetalim`: Specifies `thetamin` and `thetamax` at once. +- `rmin, rmax`: The inner and outer radial limits. +- `rlim`: Specifies `rmin` and `rmax` at once. +- `rborder`: Whether to draw the polar axes border. +- `thetagrid, rgrid, grid`: Whether to draw major gridlines for the azimuthal and radial axis. +- `thetagridminor, rgridminor, gridminor`: Whether to draw minor gridlines for the azimuthal and radial axis. +- `thetagridcolor, rgridcolor, gridcolor`: Color for the major and minor azimuthal and radial gridlines. +- `thetalocator, rlocator`: Used to determine the azimuthal and radial gridline positions. +- `thetalocator_kw, rlocator_kw`: The azimuthal and radial locator settings. +- `thetaminorlocator, rminorlocator`: As for `thetalocator`, `rlocator`, but for the minor gridlines. +- `thetaminorticks, rminorticks`: Aliases for `thetaminorlocator`, `rminorlocator`. +- `rlabelpos`: The azimuth at which radial coordinates are labeled. +- `thetaformatter, rformatter`: Used to determine the azimuthal and radial label format. +- `thetalabels, rlabels`: Aliases for `thetaformatter`, `rformatter`. +- `thetaformatter_kw, rformatter_kw`: The azimuthal and radial label formatter settings. +- `thetalabel, rlabel`: Polar-aware axis labels rendered via [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html). +- `thetalabelloc`: Center theta angle (in degrees) for ``thetalabel``. +- `rlabelloc`: Where to place ``rlabel``. +- `thetalabel_kw, rlabel_kw`: Additional [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html) settings for the polar-aware labels (e.g. +- `color`: Color for the axes edge. +- `labelcolor, gridlabelcolor`: Color for the gridline labels. +- `labelpad, gridlabelpad`: The padding between the axes edge and the radial and azimuthal labels. +- `labelsize, gridlabelsize`: Font size for the gridline labels. +- `labelweight, gridlabelweight`: Font weight for the gridline labels. +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- `abcloc, titleloc`: Strings indicating the location for the a-b-c label and main title. +- `abcborder, titleborder`: Whether to draw a white border around titles and a-b-c labels positioned inside the axes. +- `abcbbox, titlebbox`: Whether to draw a white bbox around titles and a-b-c labels positioned inside the axes. +- `abcpad`: Horizontal offset to shift the a-b-c label position. +- `abc_kw, title_kw`: Additional settings used to update the a-b-c label and title with ``text.update()``. +- `titlepad`: The padding for the inner and outer titles and a-b-c labels. +- _17 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html#ultraplot.axes.PolarAxes.format)""" + ... diff --git a/ultraplot/axes/shared.pyi b/ultraplot/axes/shared.pyi new file mode 100644 index 000000000..f0a5292db --- /dev/null +++ b/ultraplot/axes/shared.pyi @@ -0,0 +1,48 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +An axes used to jointly format Cartesian and polar axes. +""" +from _typeshed import Incomplete +import numpy as np +from ..config import rc +from ..internals import ic +from ..internals import _pop_kwargs +from ..utils import _fontsize_to_pt, _not_none, units +from ..axes import Axes +try: + from typing import override +except ImportError: + from typing_extensions import override + +class _SharedAxes(object): + """Mix-in class with methods shared between [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html) +and [PolarAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html).""" + + @staticmethod + def _min_max_lim(key: Incomplete, min_: Incomplete=None, max_: Incomplete=None, lim: Incomplete=None) -> Incomplete: + """Translate and standardize minimum, maximum, and limit keyword arguments.""" + ... + + def _update_background(self, **kwargs: Incomplete) -> Incomplete: + """Update the background patch.""" + ... + + def _update_frame(self, x: Incomplete, *, edgecolor: Incomplete=None, linewidth: Incomplete=None, tickcolor: Incomplete=None, tickwidth: Incomplete=None, tickwidthratio: Incomplete=None) -> None: + """Update the axis frame, including spines and tick line appearance.""" + ... + + def _update_ticks(self, x: Incomplete, *, grid: Incomplete=None, gridminor: Incomplete=None, gridpad: Incomplete=None, gridcolor: Incomplete=None, ticklen: Incomplete=None, ticklenratio: Incomplete=None, tickdir: Incomplete=None, tickcolor: Incomplete=None, labeldir: Incomplete=None, labelpad: Incomplete=None, labelcolor: Incomplete=None, labelsize: Incomplete=None, labelweight: Incomplete=None) -> None: + """Update the gridlines and labels. Set `gridpad` to ``True`` to use grid padding.""" + ... + + @override + def sharex(self, other: Incomplete) -> Incomplete: + ... + + @override + def sharey(self, other: Incomplete) -> Incomplete: + ... + + def _share_axis_with(self, other: 'Axes', *, which: str) -> TypeError | None: + ... diff --git a/ultraplot/axes/taylor.pyi b/ultraplot/axes/taylor.pyi new file mode 100644 index 000000000..3f2bf7e41 --- /dev/null +++ b/ultraplot/axes/taylor.pyi @@ -0,0 +1,195 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Taylor diagram axes. +""" +from _typeshed import Incomplete +import inspect +import matplotlib.projections.polar as mpolar +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +import numpy as np +from ..config import rc +from ..internals import _not_none, _pop_rc, docstring +from .polar import PolarAxes +__all__ = ['TaylorAxes'] +_format_docstring = ... + +class TaylorAxes(PolarAxes): + """Axes subclass for Taylor diagrams. + +Important +--------- +This axes subclass can be used by passing ``proj='taylor'`` to +axes-creation commands like [add_axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_axes), +[add_subplot](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_subplot), and +[subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots).""" + _name = 'taylor' + _name_aliases = () + _default_corrs = np.array((1.0, 0.95, 0.9, 0.8, 0.6, 0.4, 0.2, 0.0)) + _quadrant_aliases = {'1': 1, 'i': 1, 'ur': 1, 'upper right': 1, 'upright': 1, '2': 2, 'ii': 2, 'ul': 2, 'upper left': 2, 'upleft': 2, '3': 3, 'iii': 3, 'll': 3, 'lower left': 3, 'lowleft': 3, '4': 4, 'iv': 4, 'lr': 4, 'lower right': 4, 'lowright': 4, 'upside down': 4} + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `*args`: Passed to [matplotlib.axes.Axes](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.html). +- `xlabel, ylabel`: Labels for the standard-deviation axes. +- `corrlabel`: Label for the correlation-coefficient grid. +- `thetaunit`: Units used for the angular grid labels. +- `quadrant`: The quadrant used for the Taylor diagram. +- `corrlocator, corrlines, corrticks`: Correlation coefficients used for the angular gridlines. +- `labelcolor, labelsize, labelweight`: Label text properties. +- `r0`: The radial origin. +- `theta0`: The zero azimuth location. +- `thetadir`: The positive azimuth direction. +- `thetamin, thetamax`: The lower and upper azimuthal bounds in degrees. +- `thetalim`: Specifies `thetamin` and `thetamax` at once. +- `rmin, rmax`: The inner and outer radial limits. +- `rlim`: Specifies `rmin` and `rmax` at once. +- `rborder`: Whether to draw the polar axes border. +- `thetagrid, rgrid, grid`: Whether to draw major gridlines for the azimuthal and radial axis. +- `thetagridminor, rgridminor, gridminor`: Whether to draw minor gridlines for the azimuthal and radial axis. +- `thetagridcolor, rgridcolor, gridcolor`: Color for the major and minor azimuthal and radial gridlines. +- `thetalocator, rlocator`: Used to determine the azimuthal and radial gridline positions. +- `thetalocator_kw, rlocator_kw`: The azimuthal and radial locator settings. +- `thetaminorlocator, rminorlocator`: As for `thetalocator`, `rlocator`, but for the minor gridlines. +- `thetaminorticks, rminorticks`: Aliases for `thetaminorlocator`, `rminorlocator`. +- `rlabelpos`: The azimuth at which radial coordinates are labeled. +- `thetaformatter, rformatter`: Used to determine the azimuthal and radial label format. +- `thetalabels, rlabels`: Aliases for `thetaformatter`, `rformatter`. +- `thetaformatter_kw, rformatter_kw`: The azimuthal and radial label formatter settings. +- `thetalabel, rlabel`: Polar-aware axis labels rendered via [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html). +- `thetalabelloc`: Center theta angle (in degrees) for ``thetalabel``. +- `rlabelloc`: Where to place ``rlabel``. +- `thetalabel_kw, rlabel_kw`: Additional [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html) settings for the polar-aware labels (e.g. +- `color`: Color for the axes edge. +- `labelcolor, gridlabelcolor`: Color for the gridline labels. +- `labelpad, gridlabelpad`: The padding between the axes edge and the radial and azimuthal labels. +- `labelsize, gridlabelsize`: Font size for the gridline labels. +- `labelweight, gridlabelweight`: Font weight for the gridline labels. +- `title`: The axes title. +- _15 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.TaylorAxes.html)""" + ... + + @staticmethod + def correlation_to_angle(correlation: Incomplete) -> Incomplete: + """Convert correlation coefficients to Taylor-diagram polar angles.""" + ... + + @classmethod + def _parse_quadrant(cls, quadrant: Incomplete) -> int | None: + """Normalize Taylor quadrant input.""" + ... + + @staticmethod + def _quadrant_bounds(quadrant: Incomplete) -> tuple[int, int]: + """Return theta bounds in degrees for a Taylor quadrant.""" + ... + + def _correlation_to_theta(self, correlation: Incomplete) -> Incomplete: + """Convert correlation coefficients to displayed polar angles.""" + ... + + def plot_corr(self, correlation: Incomplete, stddev: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot values specified as correlation coefficient and standard deviation.""" + ... + + def scatter_corr(self, correlation: Incomplete, stddev: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Scatter values specified as correlation coefficient and standard deviation.""" + ... + + def get_tightbbox(self, renderer: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Return a stable tight bbox before the first draw. + +Matplotlib's polar radial axis can report a spurious far-left bbox for +Taylor's quarter-sector view before the first draw. This feeds back into +UltraPlot's reference-width autosizing and creates excessive left margin.""" + ... + + def set_xlabel(self, xlabel: Incomplete, fontdict: Incomplete=None, labelpad: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Set the Taylor x label while keeping the native polar label hidden.""" + ... + + def set_ylabel(self, ylabel: Incomplete, fontdict: Incomplete=None, labelpad: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Set the Taylor y label while keeping the native polar label hidden.""" + ... + + def _apply_taylor_defaults(self) -> None: + """Apply the fixed quarter-polar Taylor diagram defaults.""" + ... + + def _ensure_taylor_artists(self) -> None: + """Create Taylor-specific label artists on demand.""" + ... + + def _format_correlation(self, value: Incomplete) -> str: + """Format one angular tick according to the active Taylor theta unit.""" + ... + + def _update_taylor_label_positions(self, labelpad: Incomplete=None) -> None: + """Update fixed Taylor label locations.""" + ... + + def _update_taylor_labels(self, *, xlabel: Incomplete=None, ylabel: Incomplete=None, corrlabel: Incomplete=None, labelpad: Incomplete=None, labelcolor: Incomplete=None, labelsize: Incomplete=None, labelweight: Incomplete=None, xlabel_kw: Incomplete=None, ylabel_kw: Incomplete=None, corrlabel_kw: Incomplete=None) -> None: + """Update Taylor-specific axis labels.""" + ... + + def _update_taylor_ticks(self, corrs: Incomplete=None) -> None: + """Update angular grid labels from correlation coefficients.""" + ... + + def _update_taylor_std_ticklabels(self) -> None: + """Duplicate radial tick labels onto the vertical standard-deviation axis.""" + ... + + def draw(self, renderer: Incomplete=None, *args: Incomplete, **kwargs: Incomplete) -> None: + """Draw after refreshing Taylor-specific standard-deviation tick labels.""" + ... + + def format(self, *, xlabel: Incomplete=None, ylabel: Incomplete=None, corrlabel: Incomplete=None, thetaunit: Incomplete=None, quadrant: Incomplete=None, corrlocator: Incomplete=None, corrlines: Incomplete=None, corrticks: Incomplete=None, xlabel_kw: Incomplete=None, ylabel_kw: Incomplete=None, corrlabel_kw: Incomplete=None, labelpad: Incomplete=None, labelcolor: Incomplete=None, labelsize: Incomplete=None, labelweight: Incomplete=None, **kwargs: Incomplete) -> None: + """Modify Taylor diagram labels, correlation gridlines, and polar settings. + +Parameters +---------- +- `xlabel, ylabel`: Labels for the standard-deviation axes. +- `corrlabel`: Label for the correlation-coefficient grid. +- `thetaunit`: Units used for the angular grid labels. +- `quadrant`: The quadrant used for the Taylor diagram. +- `corrlocator, corrlines, corrticks`: Correlation coefficients used for the angular gridlines. +- `labelcolor, labelsize, labelweight`: Label text properties. +- `r0`: The radial origin. +- `theta0`: The zero azimuth location. +- `thetadir`: The positive azimuth direction. +- `thetamin, thetamax`: The lower and upper azimuthal bounds in degrees. +- `thetalim`: Specifies `thetamin` and `thetamax` at once. +- `rmin, rmax`: The inner and outer radial limits. +- `rlim`: Specifies `rmin` and `rmax` at once. +- `rborder`: Whether to draw the polar axes border. +- `thetagrid, rgrid, grid`: Whether to draw major gridlines for the azimuthal and radial axis. +- `thetagridminor, rgridminor, gridminor`: Whether to draw minor gridlines for the azimuthal and radial axis. +- `thetagridcolor, rgridcolor, gridcolor`: Color for the major and minor azimuthal and radial gridlines. +- `thetalocator, rlocator`: Used to determine the azimuthal and radial gridline positions. +- `thetalocator_kw, rlocator_kw`: The azimuthal and radial locator settings. +- `thetaminorlocator, rminorlocator`: As for `thetalocator`, `rlocator`, but for the minor gridlines. +- `thetaminorticks, rminorticks`: Aliases for `thetaminorlocator`, `rminorlocator`. +- `rlabelpos`: The azimuth at which radial coordinates are labeled. +- `thetaformatter, rformatter`: Used to determine the azimuthal and radial label format. +- `thetalabels, rlabels`: Aliases for `thetaformatter`, `rformatter`. +- `thetaformatter_kw, rformatter_kw`: The azimuthal and radial label formatter settings. +- `thetalabel, rlabel`: Polar-aware axis labels rendered via [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html). +- `thetalabelloc`: Center theta angle (in degrees) for ``thetalabel``. +- `rlabelloc`: Where to place ``rlabel``. +- `thetalabel_kw, rlabel_kw`: Additional [CurvedText](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html) settings for the polar-aware labels (e.g. +- `color`: Color for the axes edge. +- `labelcolor, gridlabelcolor`: Color for the gridline labels. +- `labelpad, gridlabelpad`: The padding between the axes edge and the radial and azimuthal labels. +- `labelsize, gridlabelsize`: Font size for the gridline labels. +- `labelweight, gridlabelweight`: Font weight for the gridline labels. +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- _23 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.TaylorAxes.html#ultraplot.axes.TaylorAxes.format)""" + ... diff --git a/ultraplot/axes/three.pyi b/ultraplot/axes/three.pyi new file mode 100644 index 000000000..55c8473d1 --- /dev/null +++ b/ultraplot/axes/three.pyi @@ -0,0 +1,51 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The "3D" axes class. +""" +from _typeshed import Incomplete +from . import base, shared +try: + from mpl_toolkits.mplot3d import Axes3D +except ImportError: + Axes3D = object + +class ThreeAxes(shared._SharedAxes, base.Axes, Axes3D): + """Simple mix-in of [ultraplot.axes.Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html) with `~mpl_toolkits.mplot3d.axes3d.Axes3D`. + +Important +--------- +Note that this subclass does *not* implement the [PlotAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html) +plotting overrides. This axes subclass can be used by passing ``proj='3d'`` or +``proj='three'`` to axes-creation commands like [add_axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_axes), +[add_subplot](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_subplot), and [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots).""" + _name = 'three' + _name_aliases = ('3d',) + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Build an Axes in a figure. + +Parameters +---------- +- `fig`: The Axes is built in the `.Figure` *fig*. +- `*args`: ``*args`` can be a single ``(left, bottom, width, height)`` rectangle or a single `.Bbox`. +- `sharex, sharey`: The x- or y-`~.matplotlib.axis` is shared with the x- or y-axis in the input `~.axes.Axes`. +- `frameon`: Whether the Axes frame is visible. +- `box_aspect`: Set a fixed aspect for the Axes box, i.e. +- `forward_navigation_events`: Control whether pan/zoom events are passed through to Axes below this one. +- `**kwargs`: Other optional keyword arguments: Properties: adjustable: {'box', 'datalim'} agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m… + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.ThreeAxes.html)""" + ... + + def graph(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Draw network graphs on 3D projections.""" + ... + + def draw(self, renderer: Incomplete) -> None: + """Draw while suppressing exact surfaces replaced by navigation proxies.""" + ... + + def plot_surface(self, X: Incomplete, Y: Incomplete, Z: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Plot a surface and register a lazy private interaction preview.""" + ... diff --git a/ultraplot/colorbar.pyi b/ultraplot/colorbar.pyi new file mode 100644 index 000000000..4c6c9fcd7 --- /dev/null +++ b/ultraplot/colorbar.pyi @@ -0,0 +1,103 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +from _typeshed import Incomplete +from dataclasses import dataclass +from typing import Any, Iterable, MutableMapping, Optional, Tuple, Union +from numbers import Number +import numpy as np +import matplotlib.axes as maxes +import matplotlib.cm as mcm +import matplotlib.colorbar as mcolorbar +import matplotlib.colors as mcolors +import matplotlib.contour as mcontour +import matplotlib.figure as mfigure +import matplotlib.ticker as mticker +import matplotlib.offsetbox as moffsetbox +import matplotlib.patches as mpatches +import matplotlib.transforms as mtransforms +import matplotlib.text as mtext +from packaging import version +from . import constructor, colors as pcolors +from .internals import _not_none, _pop_params, guides, warnings +from .config import rc, _version_mpl +from .ultralayout import KIWI_AVAILABLE, ColorbarLayoutSolver +from . import ticker as pticker +from .utils import units +ColorbarLabelKw = dict[str, Any] +ColorbarTickKw = dict[str, Any] + +@dataclass(frozen=True) +class _TextKw: + kw_label: ColorbarLabelKw + kw_ticklabels: ColorbarTickKw + +class UltraColorbar: + """Centralized colorbar builder for axes.""" + + def __init__(self, axes: maxes.Axes) -> None: + ... + + def add(self, mappable: Any, values: Optional[Iterable[float]]=None, *, loc: Optional[str]=None, align: Optional[str]=None, space: Optional[Union[float, str]]=None, pad: Optional[Union[float, str]]=None, width: Optional[Union[float, str]]=None, length: Optional[Union[float, str]]=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, shrink: Optional[Union[float, str]]=None, label: Optional[str]=None, title: Optional[str]=None, reverse: bool=False, rotation: Optional[float]=None, grid: Optional[bool]=None, edges: Optional[bool]=None, drawedges: Optional[bool]=None, extend: Optional[str]=None, extendsize: Optional[Union[float, str]]=None, extendfrac: Optional[float]=None, ticks: Optional[Iterable[float]]=None, locator: Optional[Any]=None, locator_kw: Optional[dict[str, Any]]=None, format: Optional[str]=None, formatter: Optional[Any]=None, ticklabels: Optional[Iterable[str]]=None, formatter_kw: Optional[dict[str, Any]]=None, minorticks: Optional[bool]=None, minorlocator: Optional[Any]=None, minorlocator_kw: Optional[dict[str, Any]]=None, tickminor: Optional[bool]=None, ticklen: Optional[Union[float, str]]=None, ticklenratio: Optional[float]=None, tickdir: Optional[str]=None, tickdirection: Optional[str]=None, tickwidth: Optional[Union[float, str]]=None, tickwidthratio: Optional[float]=None, ticklabelsize: Optional[float]=None, ticklabelweight: Optional[str]=None, ticklabelcolor: Optional[str]=None, labelloc: Optional[str]=None, labellocation: Optional[str]=None, labelsize: Optional[float]=None, labelweight: Optional[str]=None, labelcolor: Optional[str]=None, c: Optional[str]=None, color: Optional[str]=None, lw: Optional[Union[float, str]]=None, linewidth: Optional[Union[float, str]]=None, edgefix: Optional[bool]=None, rasterized: Optional[bool]=None, frame: Optional[bool]=None, frameon: Optional[bool]=None, outline: Union[bool, None]=None, labelrotation: Optional[Union[str, float]]=None, center_levels: Optional[bool]=None, **kwargs: Incomplete) -> mcolorbar.Colorbar: + """The driver function for adding axes colorbars.""" + ... + +def _build_label_tick_kwargs(*, labelsize: Optional[float], labelweight: Optional[str], labelcolor: Optional[str], ticklabelsize: Optional[float], ticklabelweight: Optional[str], ticklabelcolor: Optional[str], rotation: Optional[float]) -> _TextKw: + ... + +def _resolve_mappable(mappable: Any, values: Optional[Iterable[float]], cax: maxes.Axes, kwargs: dict[str, Any]) -> tuple[mcm.ScalarMappable, dict[str, Any]]: + ... + +def _resolve_extendfrac(*, extendsize: Optional[Union[float, str]], extendfrac: Optional[float], cax: maxes.Axes, vertical: bool) -> float: + ... + +def _resolve_locators(*, mappable: mcm.ScalarMappable, formatter: Optional[Any], formatter_kw: dict[str, Any], locator: Optional[Any], locator_kw: dict[str, Any], minorlocator: Optional[Any], minorlocator_kw: dict[str, Any], tickminor: Optional[bool], vertical: bool) -> tuple[mcolors.Normalize, mticker.Formatter, Optional[Any], Optional[Any], bool]: + ... + +def _get_axis_for(labelloc: Optional[str], loc: Optional[str], *, ax: maxes.Axes, orientation: Optional[str]) -> maxes.Axes: + """Helper function to determine the axis for a label. +Particularly used for colorbars but can be used for other purposes""" + ... + +def _determine_label_rotation(labelrotation: Union[str, Number], labelloc: str, orientation: str, kw_label: MutableMapping) -> None: + """Note we update kw_label in place.""" + ... + +def _resolve_label_rotation(labelrotation: str | Number, *, labelloc: str, orientation: str) -> float: + ... + +def _measure_label_points(label: str, rotation: float, fontsize: float, figure: Incomplete) -> Optional[Tuple[float, float]]: + ... + +def _measure_text_artist_points(text: mtext.Text, figure: Incomplete) -> Optional[Tuple[float, float]]: + ... + +def _measure_ticklabel_extent_points(axis: Incomplete, figure: Incomplete) -> Optional[Tuple[float, float]]: + ... + +def _measure_text_overhang_axes(text: mtext.Text, axes: Incomplete) -> Optional[Tuple[float, float, float, float]]: + ... + +def _measure_ticklabel_overhang_axes(axis: Incomplete, axes: Incomplete) -> Optional[Tuple[float, float, float, float]]: + ... + +def _get_colorbar_long_axis(colorbar: mcolorbar.Colorbar) -> Incomplete: + ... + +def _register_inset_colorbar_reflow(fig: mfigure.Figure) -> None: + ... + +def _solve_inset_colorbar_bounds(*, axes: maxes.Axes, loc: str, orientation: str, length: float, width: float, xpad: float, ypad: float, ticklocation: str, labelloc: Optional[str], label: Optional[str], labelrotation: Optional[Union[str, float]], tick_fontsize: float, label_fontsize: float) -> Tuple[list[float], list[float]]: + ... + +def _anchor_inset_colorbar_bounds(bounds_inset: list[float], bounds_frame: list[float], loc: str, bbox_to_anchor: Incomplete) -> Tuple[list[float], list[float]]: + """Align an inset colorbar footprint to a legend-style anchor box.""" + ... + +def _legacy_inset_colorbar_bounds(*, axes: maxes.Axes, loc: str, orientation: str, length: float, width: float, xpad: float, ypad: float, ticklocation: str, labelloc: Optional[str], label: Optional[str], labelrotation: Optional[Union[str, float]], tick_fontsize: float, label_fontsize: float) -> Tuple[list[float], list[float]]: + ... + +def _apply_inset_colorbar_layout(axes: maxes.Axes, *, bounds_inset: list[float], bounds_frame: list[float], frame: Optional[mpatches.FancyBboxPatch]) -> None: + ... + +def _reflow_inset_colorbar_frame(colorbar: mcolorbar.Colorbar, *, labelloc: Optional[str], ticklen: float, renderer: Incomplete=None) -> None: + ... diff --git a/ultraplot/colors.pyi b/ultraplot/colors.pyi new file mode 100644 index 000000000..21bb78f31 --- /dev/null +++ b/ultraplot/colors.pyi @@ -0,0 +1,1191 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Various colormap classes and colormap normalization classes. +""" +from _typeshed import Incomplete +import functools +import itertools +import json +import os +import re +from collections.abc import MutableMapping +from numbers import Integral, Number +from xml.etree import ElementTree +import matplotlib as mpl +import matplotlib.cm as mcm +import matplotlib.colors as mcolors +import numpy as np +import numpy.ma as ma +from .config import rc + +def _cycle_handler(value: Incomplete) -> Incomplete: + """Handler for the 'cycle' rc setting.""" + ... +from .internals import _kwargs_to_args, _not_none, _pop_props, docstring, ic, inputs, warnings +from .utils import set_alpha, to_hex, to_rgb, to_rgba, to_xyz, to_xyza +try: + from typing import override +except: + from typing_extensions import override +__all__ = ['DiscreteColormap', 'ContinuousColormap', 'PerceptualColormap', 'DiscreteNorm', 'DivergingNorm', 'SegmentedNorm', 'ColorDatabase', 'ColormapDatabase'] +DEFAULT_NAME = '_no_name' +DEFAULT_SPACE = 'hsl' +_regex_hex = '#(?:[0-9a-fA-F]{3,4}){2}' +REGEX_HEX_MULTI = re.compile(_regex_hex) +REGEX_HEX_SINGLE = ... +REGEX_ADJUST = re.compile('\\A(light|dark|medium|pale|charcoal)?\\s*(gr[ea]y[0-9]?)?\\Z') +CMAPS_CYCLIC = ... +CMAPS_DIVERGING = ... +CMAPS_REMOVED = {'Blue0': '0.6.0', 'Cool': '0.6.0', 'Warm': '0.6.0', 'Hot': '0.6.0', 'Floral': '0.6.0', 'Contrast': '0.6.0', 'Sharp': '0.6.0', 'Viz': '0.6.0'} +CMAPS_RENAMED = {'GrayCycle': ('MonoCycle', '0.6.0'), 'Blue1': ('Blues1', '0.7.0'), 'Blue2': ('Blues2', '0.7.0'), 'Blue3': ('Blues3', '0.7.0'), 'Blue4': ('Blues4', '0.7.0'), 'Blue5': ('Blues5', '0.7.0'), 'Blue6': ('Blues6', '0.7.0'), 'Blue7': ('Blues7', '0.7.0'), 'Blue8': ('Blues8', '0.7.0'), 'Blue9': ('Blues9', '0.7.0'), 'Green1': ('Greens1', '0.7.0'), 'Green2': ('Greens2', '0.7.0'), 'Green3': ('Greens3', '0.7.0'), 'Green4': ('Greens4', '0.7.0'), 'Green5': ('Greens5', '0.7.0'), 'Green6': ('Greens6', '0.7.0'), 'Green7': ('Greens7', '0.7.0'), 'Green8': ('Greens8', '0.7.0'), 'Orange1': ('Yellows1', '0.7.0'), 'Orange2': ('Yellows2', '0.7.0'), 'Orange3': ('Yellows3', '0.7.0'), 'Orange4': ('Oranges2', '0.7.0'), 'Orange5': ('Oranges1', '0.7.0'), 'Orange6': ('Oranges3', '0.7.0'), 'Orange7': ('Oranges4', '0.7.0'), 'Orange8': ('Yellows4', '0.7.0'), 'Brown1': ('Browns1', '0.7.0'), 'Brown2': ('Browns2', '0.7.0'), 'Brown3': ('Browns3', '0.7.0'), 'Brown4': ('Browns4', '0.7.0'), 'Brown5': ('Browns5', '0.7.0'), 'Brown6': ('Browns6', '0.7.0'), 'Brown7': ('Browns7', '0.7.0'), 'Brown8': ('Browns8', '0.7.0'), 'Brown9': ('Browns9', '0.7.0'), 'RedPurple1': ('Reds1', '0.7.0'), 'RedPurple2': ('Reds2', '0.7.0'), 'RedPurple3': ('Reds3', '0.7.0'), 'RedPurple4': ('Reds4', '0.7.0'), 'RedPurple5': ('Reds5', '0.7.0'), 'RedPurple6': ('Purples1', '0.7.0'), 'RedPurple7': ('Purples2', '0.7.0'), 'RedPurple8': ('Purples3', '0.7.0')} +COLORS_OPEN = {} +COLORS_XKCD = {} +COLORS_KEEP = ... +COLORS_REMOVE = ('shit', 'poop', 'poo', 'pee', 'piss', 'puke', 'vomit', 'snot', 'booger', 'bile', 'diarrhea', 'icky', 'sickly') +COLORS_REPLACE = (('/', ' '), ("'s", 's'), ('egg blue', 'egg'), ('grey', 'gray'), ('ochre', 'ocher'), ('forrest', 'forest'), ('ocre', 'ocher'), ('kelley', 'kelly'), ('reddish', 'red'), ('purplish', 'purple'), ('pinkish', 'pink'), ('yellowish', 'yellow'), ('bluish', 'blue'), ('greyish', 'grey'), ('ish', ''), ('bluey', 'blue'), ('greeny', 'green'), ('reddy', 'red'), ('pinky', 'pink'), ('purply', 'purple'), ('purpley', 'purple'), ('yellowy', 'yellow'), ('orangey', 'orange'), ('browny', 'brown'), ('minty', 'mint'), ('grassy', 'grass'), ('mossy', 'moss'), ('dusky', 'dusk'), ('rusty', 'rust'), ('muddy', 'mud'), ('sandy', 'sand'), ('leafy', 'leaf'), ('dusty', 'dust'), ('dirty', 'dirt'), ('peachy', 'peach'), ('stormy', 'storm'), ('cloudy', 'cloud'), ('grayblue', 'gray blue'), ('bluegray', 'gray blue'), ('lightblue', 'light blue'), ('yellowgreen', 'yellow green'), ('yelloworange', 'yellow orange')) +_N_docstring = ... +_alpha_docstring = ... +_cyclic_docstring = ... +_gamma_docstring = ... +_space_docstring = ... +_name_docstring = ... +_ratios_docstring = ... +_from_list_docstring = ... + +def _clip_colors(colors: Incomplete, clip: Incomplete=True, gray: Incomplete=0.2, warn: Incomplete=False) -> Incomplete: + """Clip impossible colors rendered in an HSL-to-RGB colorspace +conversion. Used by `PerceptualColormap`. + +Parameters +---------- +colors : sequence of 3-tuple + The RGB colors. +clip : bool, optional + If `clip` is ``True`` (the default), RGB channel values >1 are + clipped to 1. Otherwise, the color is masked out as gray. +gray : float, optional + The identical RGB channel values (gray color) to be used if + `clip` is ``True``. +warn : bool, optional + Whether to issue warning when colors are clipped.""" + ... + +def _get_channel(color: Incomplete, channel: Incomplete, space: Incomplete='hcl') -> Incomplete: + """Get the hue, saturation, or luminance channel value from the input color. The +color name `color` can optionally be a string with the format ``'color+x'`` +or ``'color-x'``, where `x` is the offset from the channel value. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +channel : optional + The HCL channel to be retrieved. +space : optional + The colorspace for the corresponding channel value. + +Returns +------- +value : float + The channel value.""" + ... + +def _make_segment_data(values: Incomplete, coords: Incomplete=None, ratios: Incomplete=None) -> Incomplete: + """Return a segmentdata array or callable given the input colors +and coordinates. + +Parameters +---------- +values : sequence of float + The channel values. +coords : sequence of float, optional + The segment coordinates. +ratios : sequence of float, optional + The relative length of each segment transition.""" + ... + +def _make_lookup_table(N: Incomplete, data: Incomplete, gamma: Incomplete=1.0, inverse: Incomplete=False) -> Incomplete: + """Generate lookup tables of HSL values given specified gradations. + +Parameters +---------- +- `N`: Number of points in the colormap lookup table. +- `data`: Sequence of `(x, y_0, y_1)` tuples specifying channel jumps (from `y_0` to `y_1`) and `x` coordinate of those jumps (ranges between 0 and 1). +- `gamma`: To obtain channel values between coordinates `x_i` and `x_{i+1}` in rows `i` and `i+1` of `data` we use the formula: y = y_{1,i} + w_i^{\\gamma_i}*(y_{0,i+1} - y_{1,i}) where… +- `inverse`: If ``True``, `w_i^{\\gamma_i}` is replaced with `1 - (1 - w_i)^{\\gamma_i}` -- that is, when `gamma` is greater than 1, this weights colors toward *higher* channel values instead of…""" + ... + +def _load_colors(path: Incomplete, warn_on_failure: Incomplete=True) -> Incomplete: + """Read colors from the input file. + +Parameters +---------- +warn_on_failure : bool, optional + If ``True``, issue a warning when loading fails instead of raising an error.""" + ... + +def _standardize_colors(input: Incomplete, space: Incomplete, margin: Incomplete) -> Incomplete: + """Standardize the input colors. + +Parameters +---------- +input : dict + The colors. +space : optional + The colorspace used to filter colors. +margin : optional + The proportional margin required for unique colors (e.g. 0.1 + is 36 hue units, 10 saturation units, 10 luminance units).""" + ... + +class _Colormap(object): + """Mixin class used to add some helper methods.""" + + def _get_data(self, ext: Incomplete, alpha: Incomplete=True) -> Incomplete: + """Return a string containing the colormap colors for saving. + +Parameters +---------- +ext : {'hex', 'txt', 'rgb'} + The filename extension. +alpha : bool, optional + Whether to include an opacity column.""" + ... + + def _make_name(self, suffix: Incomplete=None) -> Incomplete: + """Generate a default colormap name. Do not append more than one +leading underscore or more than one identical suffix.""" + ... + + def _parse_path(self, path: Incomplete, ext: Incomplete=None, subfolder: Incomplete=None) -> Incomplete: + """Parse the user input path. + +Parameters +---------- +path : path-like, optional + The file path. +ext : str + The default extension. +subfolder : str, optional + The subfolder.""" + ... + + @staticmethod + def _pop_args(*args: Incomplete, names: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Pop the name as a first positional argument or keyword argument. +Supports matplotlib-style ``Colormap(name, data, N)`` input +algongside more intuitive ``Colormap(data, name, N)`` input.""" + ... + + @classmethod + def _from_file(cls, path: Incomplete, warn_on_failure: Incomplete=False) -> Incomplete: + """Read generalized colormap and color cycle files.""" + ... + +class ContinuousColormap(mcolors.LinearSegmentedColormap, _Colormap): + """Replacement for [LinearSegmentedColormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html).""" + + def __str__(self) -> str: + ... + + def __repr__(self) -> str: + ... + + def __init__(self, *args: Incomplete, gamma: Incomplete=1, alpha: Incomplete=None, cyclic: Incomplete=False, **kwargs: Incomplete) -> None: + """Parameters +---------- +segmentdata : dict-like + Dictionary containing the keys ``'red'``, ``'green'``, ``'blue'``, and + (optionally) ``'alpha'``. The shorthands ``'r'``, ``'g'``, ``'b'``, + and ``'a'`` are also acceptable. The key values can be callable + functions that return channel values given a colormap index, or + 3-column arrays indicating the coordinates and channel transitions. See + [matplotlib.colors.LinearSegmentedColormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html) for a detailed explanation. +name : str, default: '_no_name' + The colormap name. This can also be passed as the first + positional string argument. +N : int, default: [image.lut](https://ultraplot.readthedocs.io/en/stable/search.html?q=image.lut) + Number of points in the colormap lookup table. +gamma : float, optional + Gamma scaling used for the *x* coordinates. +alpha : float, optional + The opacity for the entire colormap. This overrides + the input opacities. +cyclic : bool, optional + Whether the colormap is cyclic. If ``True``, this changes how the leftmost + and rightmost color levels are selected, and `extend` can only be + ``'neither'`` (a warning will be issued otherwise). + +Other parameters +---------------- +**kwargs + Passed to [matplotlib.colors.LinearSegmentedColormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html). + +See also +-------- +DiscreteColormap +matplotlib.colors.LinearSegmentedColormap +ultraplot.constructor.Colormap""" + ... + + def append(self, *args: Incomplete, ratios: Incomplete=None, name: Incomplete=None, N: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return the concatenation of this colormap with the +input colormaps. + +Parameters +---------- +*args + Instances of `ContinuousColormap`. +ratios : sequence of float, optional + Relative extent of each component colormap in the + merged colormap. Length must equal ``len(args) + 1``. + For example, ``cmap1.append(cmap2, ratios=(2, 1))`` generates + a colormap with the left two-thrids containing colors from + ``cmap1`` and the right one-third containing colors from ``cmap2``. +name : str, optional + The colormap name. Default is to merge each name with underscores and + prepend a leading underscore, for example ``_name1_name2``. +N : int, optional + The number of points in the colormap lookup table. Default is + to sum the length of each lookup table. + +Other parameters +---------------- +**kwargs + Passed to `ContinuousColormap.copy` + or `PerceptualColormap.copy`. + +Returns +------- +ContinuousColormap + The colormap. + +See also +-------- +DiscreteColormap.append""" + ... + + def cut(self, cut: Incomplete=None, name: Incomplete=None, left: Incomplete=None, right: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return a version of the colormap with the center "cut out". +This is great for making the transition from "negative" to "positive" +in a diverging colormap more distinct. + +Parameters +---------- +cut : float, optional + The proportion to cut from the center of the colormap. For example, + ``cut=0.1`` cuts the central 10%%, or ``cut=-0.1`` fills the central 10%% + of the colormap with the current central color (usually white). +name : str, default: '_name_copy' + The new colormap name. +left, right : float, default: 0, 1 + The colormap indices for the "leftmost" and "rightmost" + colors. See `~ContinuousColormap.truncate` for details. +right : float, optional + The colormap index for the new "rightmost" color. Must fall between + +Other parameters +---------------- +**kwargs + Passed to `ContinuousColormap.copy` or `PerceptualColormap.copy`. + +Returns +------- +ContinuousColormap + The colormap. + +See also +-------- +ContinuousColormap.truncate +DiscreteColormap.truncate""" + ... + + def reversed(self, name: Incomplete=None, **kwargs: Incomplete) -> ContinuousColormap: + """Return a reversed copy of the colormap. + +Parameters +---------- +name : str, default: '_name_r' + The new colormap name. + +Other parameters +---------------- +**kwargs + Passed to `ContinuousColormap.copy` + or `PerceptualColormap.copy`. + +See also +-------- +matplotlib.colors.LinearSegmentedColormap.reversed""" + ... + + def save(self, path: Incomplete=None, alpha: Incomplete=True) -> None: + """Save the colormap data to a file. + +Parameters +---------- +path : path-like, optional + The output filename. If not provided, the colormap is saved in the + ``cmaps`` subfolder in [user_folder](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.user_folder) + under the filename ``name.json`` (where ``name`` is the colormap + name). Valid extensions are shown in the below table. + + =================== ========================================== + Extension Description + =================== ========================================== + ``.json`` JSON database of the channel segment data. + ``.hex`` Comma-delimited list of HEX strings. + ``.rgb``, ``.txt`` 3-4 column table of channel values. + =================== ========================================== + +alpha : bool, optional + Whether to include an opacity column for ``.rgb`` + and ``.txt`` files. + +See also +-------- +DiscreteColormap.save""" + ... + + def set_alpha(self, alpha: Incomplete, coords: Incomplete=None, ratios: Incomplete=None) -> None: + """Set the opacity for the entire colormap or set up an opacity gradation. + +Parameters +---------- +alpha : float or sequence of float + If float, this is the opacity for the entire colormap. If sequence of + float, the colormap traverses these opacity values. +coords : sequence of float, optional + Colormap coordinates for the opacity values. The first and last + coordinates must be ``0`` and ``1``. If `alpha` is not scalar, the + default coordinates are ``np.linspace(0, 1, len(alpha))``. +ratios : sequence of float, optional + Relative extent of each opacity transition segment. Length should + equal ``len(alpha) + 1``. For example + ``cmap.set_alpha((1, 1, 0), ratios=(2, 1))`` creates a transtion from + 100 percent to 0 percent opacity in the right *third* of the colormap. + +See also +-------- +DiscreteColormap.set_alpha""" + ... + + def set_cyclic(self, b: Incomplete) -> None: + """Set whether this colormap is "cyclic". See `ContinuousColormap` for details.""" + ... + + def shifted(self, shift: Incomplete=180, name: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return a cyclicaly shifted version of the colormap. If the colormap +cyclic property is set to ``False`` a warning will be raised. + +Parameters +---------- +shift : float, default: 180 + The number of degrees to shift, out of 360 degrees. +name : str, default: '_name_s' + The new colormap name. + +Other parameters +---------------- +**kwargs + Passed to `ContinuousColormap.copy` or `PerceptualColormap.copy`. + +See also +-------- +DiscreteColormap.shifted""" + ... + + def truncate(self, left: Incomplete=None, right: Incomplete=None, name: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return a truncated version of the colormap. + +Parameters +---------- +left : float, default: 0 + The colormap index for the new "leftmost" color. Must fall between ``0`` + and ``1``. For example, ``left=0.1`` cuts the leftmost 10%% of the colors. +right : float, default: 1 + The colormap index for the new "rightmost" color. Must fall between ``0`` + and ``1``. For example, ``right=0.9`` cuts the leftmost 10%% of the colors. +name : str, default: '_name_copy' + The new colormap name. + +Other parameters +---------------- +**kwargs + Passed to `ContinuousColormap.copy` + or `PerceptualColormap.copy`. + +See also +-------- +DiscreteColormap.truncate""" + ... + + def copy(self, name: Incomplete=None, segmentdata: Incomplete=None, N: Incomplete=None, *, alpha: Incomplete=None, gamma: Incomplete=None, cyclic: Incomplete=None) -> ContinuousColormap: + """Return a new colormap with relevant properties copied from this one +if they were not provided as keyword arguments. + +Parameters +---------- +name : str, default: '_name_copy' + The new colormap name. +segmentdata, N, alpha, gamma, cyclic : optional + See `ContinuousColormap`. If not provided, these are copied + from the current colormap. + +See also +-------- +DiscreteColormap.copy +PerceptualColormap.copy""" + ... + + def to_discrete(self, samples: Incomplete=10, name: Incomplete=None, **kwargs: Incomplete) -> DiscreteColormap: + """Convert the `ContinuousColormap` to a `DiscreteColormap` by drawing +samples from the colormap. + +Parameters +---------- +samples : int or sequence of float, optional + If integer, draw samples at the colormap coordinates + ``np.linspace(0, 1, samples)``. If sequence of float, + draw samples at the specified points. +name : str, default: '_name_copy' + The new colormap name. + +Other parameters +---------------- +**kwargs + Passed to `DiscreteColormap`. + +See also +-------- +PerceptualColormap.to_continuous""" + ... + + @classmethod + def from_file(cls, path: Incomplete, *, warn_on_failure: Incomplete=False) -> Incomplete: + """Load colormap from a file. + +Parameters +---------- +path : path-like + The file path. Valid file extensions are shown in the below table. + + =================== ========================================== + Extension Description + =================== ========================================== + ``.json`` JSON database of the channel segment data. + ``.hex`` Comma-delimited list of HEX strings. + ``.rgb``, ``.txt`` 3-4 column table of channel values. + =================== ========================================== + +warn_on_failure : bool, optional + If ``True``, issue a warning when loading fails instead of + raising an error. + +See also +-------- +DiscreteColormap.from_file""" + ... + + @classmethod + def from_list(cls, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Make a `ContinuousColormap` from a sequence of colors. + +Parameters +---------- +colors : sequence of color-spec or tuple + If a sequence of RGB[A] tuples or color strings, the colormap + transitions evenly from ``colors[0]`` at the left-hand side + to ``colors[-1]`` at the right-hand side. + + If a sequence of (float, color-spec) tuples, the float values are the + coordinate of each transition and must range from 0 to 1. This + can be used to divide the colormap range unevenly. +name : str, default: '_no_name' + The colormap name. This can also be passed as the first + positional string argument. +ratios : sequence of float, optional + Relative extents of each color transition. Must have length + ``len(colors) - 1``. Larger numbers indicate a slower + transition, smaller numbers indicate a faster transition. + For example, ``('red', 'blue', 'green')`` with ``ratios=(2, 1)`` + creates a colormap with the transition from red to blue taking + *twice as long* as the transition from blue to green. + +Other parameters +---------------- +**kwargs + Passed to `ContinuousColormap`. + +Returns +------- +ContinuousColormap + The colormap. + +See also +-------- +matplotlib.colors.LinearSegmentedColormap.from_list +PerceptualColormap.from_list""" + ... + +class DiscreteColormap(mcolors.ListedColormap, _Colormap): + """Replacement for [ListedColormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.ListedColormap.html).""" + + def __str__(self) -> str: + ... + + def __repr__(self) -> str: + ... + + @property + def monochrome(self) -> bool: + """Whether every color is identical, normalized to a Python boolean.""" + ... + + @monochrome.setter + def monochrome(self, value: Incomplete) -> None: + """Whether every color is identical, normalized to a Python boolean.""" + ... + + def __init__(self, colors: Incomplete, name: Incomplete=None, N: Incomplete=None, alpha: Incomplete=None, **kwargs: Incomplete) -> None: + """Parameters +---------- +colors : sequence of color-spec, optional + The colormap colors. +name : str, default: '_no_name' + The colormap name. +N : int, default: ``len(colors)`` + The number of levels. The color list is truncated or wrapped + to match this length. +alpha : float, optional + The opacity for the colormap colors. This overrides the + input color opacities. + +Other parameters +---------------- +**kwargs + Passed to [ListedColormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.ListedColormap.html). + +See also +-------- +ContinuousColormap +matplotlib.colors.ListedColormap +ultraplot.constructor.Colormap""" + ... + + def append(self, *args: Incomplete, name: Incomplete=None, N: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Append arbitrary colormaps onto this colormap. + +Parameters +---------- +*args + Instances of `DiscreteColormap`. +name : str, optional + The new colormap name. Default is to merge each name with underscores and + prepend a leading underscore, for example ``_name1_name2``. +N : int, optional + The number of points in the colormap lookup table. Default is + the number of colors in the concatenated lists. + +Other parameters +---------------- +**kwargs + Passed to `~DiscreteColormap.copy`. + +See also +-------- +ContinuousColormap.append""" + ... + + def save(self, path: Incomplete=None, alpha: Incomplete=True) -> None: + """Save the colormap data to a file. + +Parameters +---------- +path : path-like, optional + The output filename. If not provided, the colormap is saved in the + ``cycles`` subfolder in [user_folder](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.user_folder) + under the filename ``name.hex`` (where ``name`` is the color cycle + name). Valid extensions are described in the below table. + + ================== ========================================== + Extension Description + ================== ========================================== + ``.hex`` Comma-delimited list of HEX strings. + ``.rgb``, ``.txt`` 3-4 column table of channel values. + ================== ========================================== + +alpha : bool, optional + Whether to include an opacity column for ``.rgb`` + and ``.txt`` files. + +See also +-------- +ContinuousColormap.save""" + ... + + def set_alpha(self, alpha: Incomplete) -> None: + """Set the opacity for the entire colormap. + +Parameters +---------- +alpha : float + The opacity. + +See also +-------- +ContinuousColormap.set_alpha""" + ... + + def reversed(self, name: Incomplete=None, **kwargs: Incomplete) -> DiscreteColormap: + """Return a reversed version of the colormap. + +Parameters +---------- +name : str, default: '_name_r' + The new colormap name. + +Other parameters +---------------- +**kwargs + Passed to `DiscreteColormap.copy` + +See also +-------- +matplotlib.colors.ListedColormap.reversed""" + ... + + def shifted(self, shift: Incomplete=1, name: Incomplete=None) -> Incomplete: + """Return a cyclically shifted version of the colormap. + +Parameters +---------- +shift : float, default: 1 + The number of list indices to shift. +name : str, eefault: '_name_s' + The new colormap name. + +See also +-------- +ContinuousColormap.shifted""" + ... + + def truncate(self, left: Incomplete=None, right: Incomplete=None, name: Incomplete=None) -> Incomplete: + """Return a truncated version of the colormap. + +Parameters +---------- +left : float, default: None + The colormap index for the new "leftmost" color. Must fall between ``0`` + and ``self.N``. For example, ``left=2`` drops the first two colors. +right : float, default: None + The colormap index for the new "rightmost" color. Must fall between ``0`` + and ``self.N``. For example, ``right=4`` keeps the first four colors. +name : str, default: '_name_copy' + The new colormap name. + +See also +-------- +ContinuousColormap.truncate""" + ... + + def copy(self, colors: Incomplete=None, name: Incomplete=None, N: Incomplete=None, *, alpha: Incomplete=None) -> DiscreteColormap: + """Return a new colormap with relevant properties copied from this one +if they were not provided as keyword arguments. + +Parameters +---------- +name : str, default: '_name_copy' + The new colormap name. +colors, N, alpha : optional + See `DiscreteColormap`. If not provided, + these are copied from the current colormap. + +See also +-------- +ContinuousColormap.copy +PerceptualColormap.copy""" + ... + + @classmethod + def from_file(cls, path: Incomplete, *, warn_on_failure: Incomplete=False) -> Incomplete: + """Load color cycle from a file. + +Parameters +---------- +path : path-like + The file path. Valid file extensions are shown in the below table. + + ================== ========================================== + Extension Description + ================== ========================================== + ``.hex`` Comma-delimited list of HEX strings. + ``.rgb``, ``.txt`` 3-4 column table of channel values. + ================== ========================================== + +warn_on_failure : bool, optional + If ``True``, issue a warning when loading fails instead of + raising an error. + +See also +-------- +ContinuousColormap.from_file""" + ... + +class PerceptualColormap(ContinuousColormap): + """A `ContinuousColormap` with linear transitions across hue, saturation, +and luminance rather than red, blue, and green.""" + + def __init__(self, *args: Incomplete, space: Incomplete=None, clip: Incomplete=True, gamma: Incomplete=None, gamma1: Incomplete=None, gamma2: Incomplete=None, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `segmentdata`: Dictionary containing the keys ``'hue'``, ``'saturation'``, ``'luminance'``, and (optionally) ``'alpha'``. +- `name`: The colormap name. +- `N`: Number of points in the colormap lookup table. +- `space`: The hue, saturation, luminance-style colorspace to use for interpreting the channels. +- `clip`: Whether to "clip" impossible colors (i.e. +- `gamma`: Set `gamma1` and `gamma2` to this identical value. +- `gamma1`: If greater than 1, make low saturation colors more prominent. +- `gamma2`: If greater than 1, make high luminance colors more prominent. +- `alpha`: The opacity for the entire colormap. +- `cyclic`: Whether the colormap is cyclic. +- `**kwargs`: Passed to `matploitlib.colors.LinearSegmentedColormap`. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.PerceptualColormap.html)""" + ... + + def _init(self) -> None: + """As with [LinearSegmentedColormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html), but convert +each value in the lookup table from ``self._space`` to RGB.""" + ... + + def set_gamma(self, gamma: Incomplete=None, gamma1: Incomplete=None, gamma2: Incomplete=None) -> None: + """Set the gamma value(s) for the luminance and saturation transitions. + +Parameters +---------- +gamma : float, optional + Set `gamma1` and `gamma2` to this identical value. +gamma1 : float, optional + If greater than 1, make low saturation colors more prominent. If + less than 1, make high saturation colors more prominent. Similar to + the [HCLWizard](http://hclwizard.org:64230/hclwizard/) option. +gamma2 : float, optional + If greater than 1, make high luminance colors more prominent. If + less than 1, make low luminance colors more prominent. Similar to + the [HCLWizard](http://hclwizard.org:64230/hclwizard/) option.""" + ... + + def copy(self, name: Incomplete=None, segmentdata: Incomplete=None, N: Incomplete=None, *, alpha: Incomplete=None, gamma: Incomplete=None, cyclic: Incomplete=None, clip: Incomplete=None, gamma1: Incomplete=None, gamma2: Incomplete=None, space: Incomplete=None) -> PerceptualColormap: + """Return a new colormap with relevant properties copied from this one +if they were not provided as keyword arguments. + +Parameters +---------- +name : str, default: '_name_copy' + The new colormap name. +segmentdata, N, alpha, clip, cyclic, gamma, gamma1, gamma2, space : optional + See `PerceptualColormap`. If not provided, + these are copied from the current colormap. + +See also +-------- +DiscreteColormap.copy +ContinuousColormap.copy""" + ... + + def to_continuous(self, name: Incomplete=None, **kwargs: Incomplete) -> ContinuousColormap: + """Convert the `PerceptualColormap` to a standard `ContinuousColormap`. +This is used to merge such colormaps. + +Parameters +---------- +name : str, default: '_name_copy' + The new colormap name. + +Other parameters +---------------- +**kwargs + Passed to `ContinuousColormap`. + +See also +-------- +ContinuousColormap.to_discrete""" + ... + + @classmethod + def from_color(cls, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Return a simple monochromatic "sequential" colormap that blends from white +or near-white to the input color. + +Parameters +---------- +color : color-spec + RGB tuple, hex string, or named color string. +name : str, default: '_no_name' + The colormap name. This can also be passed as the first + positional string argument. +space : {'hsl', 'hpl', 'hcl', 'hsv'}, optional + The hue, saturation, luminance-style colorspace to use for interpreting + the channels. See [this page](http://www.hsluv.org/comparison/) for + a full description. +l, s, a, c + Shorthands for `luminance`, `saturation`, `alpha`, and `chroma`. +luminance : float or color-spec, default: 100 + If float, this is the luminance channel strength on the left-hand + side of the colormap. If RGB[A] tuple, hex string, or named color + string, the luminance is inferred from the color. +saturation, alpha : float or color-spec, optional + As with `luminance`, except the default `saturation` and the default + `alpha` are the channel values taken from `color`. +chroma + Alias for `saturation`. + +Other parameters +---------------- +**kwargs + Passed to `PerceptualColormap.from_hsl`. + +Returns +------- +PerceptualColormap + The colormap. + +See also +-------- +PerceptualColormap.from_hsl +PerceptualColormap.from_list""" + ... + + @classmethod + def from_hsl(cls, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Make a `~PerceptualColormap` by specifying the hue, saturation, and luminance transitions individually. + +Parameters +---------- +- `space`: The hue, saturation, luminance-style colorspace to use for interpreting the channels. +- `name`: The colormap name. +- `ratios`: Relative extents of each color transition. +- `hue`: Hue channel value or sequence of values. +- `saturation`: As with `hue`, but for the saturation channel. +- `luminance`: As with `hue`, but for the luminance channel. +- `alpha`: As with `hue`, but for the alpha (opacity) channel. +- `chroma`: Alias for `saturation`. +- `**kwargs`: Passed to `PerceptualColormap`. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.PerceptualColormap.html#ultraplot.colors.PerceptualColormap.from_hsl)""" + ... + + @classmethod + def from_list(cls, *args: Incomplete, adjust_grays: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Make a `PerceptualColormap` from a sequence of colors. + +Parameters +---------- +- `colors`: If a sequence of RGB[A] tuples or color strings, the colormap transitions evenly from ``colors[0]`` at the left-hand side to ``colors[-1]`` at the right-hand side. +- `name`: The colormap name. +- `ratios`: Relative extents of each color transition. +- `adjust_grays`: Whether to adjust the hues of grayscale colors (including ``'white'``, ``'black'``, and the ``'grayN'`` open-color colors) to the hues of the preceding and subsequent colors in the… +- `**kwargs`: Passed to `PerceptualColormap`. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.PerceptualColormap.html#ultraplot.colors.PerceptualColormap.from_list)""" + ... + +def _interpolate_scalar(x: Incomplete, x0: Incomplete, x1: Incomplete, y0: Incomplete, y1: Incomplete) -> Incomplete: + """Interpolate between two points.""" + ... + +def _interpolate_extrapolate_vector(xq: Incomplete, x: Incomplete, y: Incomplete) -> Incomplete: + """Interpolate between two vectors. Similar to [numpy.interp](https://numpy.org/doc/stable/reference/generated/numpy.interp.html) except this +does not truncate out-of-bounds values (i.e. this is reversible).""" + ... + +def _sanitize_levels(levels: Incomplete, minsize: Incomplete=2) -> Incomplete: + """Ensure the levels are monotonic. If they are descending, reverse them.""" + ... + +class DiscreteNorm(mcolors.BoundaryNorm): + """Meta-normalizer that discretizes the possible color values returned by +arbitrary continuous normalizers given a sequence of level boundaries.""" + + def __init__(self, levels: Incomplete, norm: Incomplete=None, unique: Incomplete=None, step: Incomplete=None, clip: Incomplete=False, ticks: Incomplete=None, labels: Incomplete=None) -> None: + """Parameters +---------- +- `levels`: The level boundaries. +- `norm`: The normalizer used to transform `levels` and data values passed to `~DiscreteNorm.__call__` before discretization. +- `unique`: Which out-of-bounds regions should be assigned unique colormap colors. +- `step`: The intensity of the transition to out-of-bounds colors as a fraction of the adjacent step between in-bounds colors. +- `clip`: Whether to clip values falling outside of the level bins. +- `ticks`: Default tick values to use for colorbars drawn with this normalizer. +- `labels`: Default tick labels to use for colorbars drawn with this normalizer. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteNorm.html)""" + ... + + def __call__(self, value: Incomplete, clip: Incomplete=None) -> Incomplete: + """Normalize data values to 0-1. + +Parameters +---------- +value : numeric + The data to be normalized. +clip : bool, default: ``self.clip`` + Whether to clip values falling outside of the level bins.""" + ... + + def inverse(self, value: Incomplete) -> Incomplete: + """Raise an error. + +Raises +------ +ValueError + Inversion after discretization is impossible.""" + ... + + @property + def descending(self) -> bool: + """Boolean indicating whether the levels are descending.""" + ... + +class SegmentedNorm(mcolors.Normalize): + """Normalizer that scales data linearly with respect to the +interpolated index in an arbitrary monotonic level sequence.""" + + def __init__(self, levels: Incomplete, vmin: Incomplete=None, vmax: Incomplete=None, clip: Incomplete=False) -> None: + """Parameters +---------- +levels : sequence of float + The level boundaries. Must be monotonically increasing + or decreasing. +vmin : float, optional + Ignored but included for consistency with other normalizers. + Set to the minimum of `levels`. +vmax : float, optional + Ignored but included for consistency with other normalizers. + Set to the minimum of `levels`. +clip : bool, optional + Whether to clip values falling outside of the minimum + and maximum of `levels`. + +See also +-------- +ultraplot.constructor.Norm +ultraplot.colors.DiscreteNorm + +Note +---- +The algorithm this normalizer uses to select normalized values +in-between level list indices is adapted from the algorithm +[LinearSegmentedColormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.LinearSegmentedColormap.html) uses to select channel +values in-between segment data points (hence the name `SegmentedNorm`). + +Example +------- +In the below example, unevenly spaced levels are passed to +[contourf](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.contourf.html), resulting in the automatic +application of `SegmentedNorm`. + +>>> import ultraplot as uplt +>>> import numpy as np +>>> levels = [1, 2, 5, 10, 20, 50, 100, 200, 500, 1000] +>>> data = 10 ** (3 * np.random.rand(10, 10)) +>>> fig, ax = uplt.subplots() +>>> ax.contourf(data, levels=levels)""" + ... + + def __call__(self, value: Incomplete, clip: Incomplete=None) -> Incomplete: + """Normalize the data values to 0-1. Inverse of `~SegmentedNorm.inverse`. + +Parameters +---------- +value : numeric + The data to be normalized. +clip : bool, default: ``self.clip`` + Whether to clip values falling outside of the minimum and maximum levels.""" + ... + + def inverse(self, value: Incomplete) -> Incomplete: + """Inverse of `~SegmentedNorm.__call__`. + +Parameters +---------- +value : numeric + The data to be un-normalized.""" + ... + +class DivergingNorm(mcolors.Normalize): + """Normalizer that ensures some central data value lies at the central +colormap color. The default central value is ``0``.""" + + def __str__(self) -> str: + ... + + def __init__(self, vcenter: Incomplete=0, vmin: Incomplete=None, vmax: Incomplete=None, fair: Incomplete=True, clip: Incomplete=None) -> None: + """Parameters +---------- +vcenter : float, default: 0 + The data value corresponding to the central colormap position. +vmin : float, optional + The minimum data value. +vmax : float, optional + The maximum data value. +fair : bool, optional + If ``True`` (default), the speeds of the color gradations on either side + of the center point are equal, but colormap colors may be omitted. If + ``False``, all colormap colors are included, but the color gradations on + one side may be faster than the other side. ``False`` should be used with + great care, as it may result in a misleading interpretation of your data. +clip : bool, optional + Whether to clip values falling outside of `vmin` and `vmax`. + +See also +-------- +ultraplot.constructor.Norm""" + ... + + def __call__(self, value: Incomplete, clip: Incomplete=None) -> Incomplete: + """Normalize the data values to 0-1. + +Parameters +---------- +value : numeric + The data to be normalized. +clip : bool, default: ``self.clip`` + Whether to clip values falling outside of `vmin` and `vmax`.""" + ... + + def autoscale_None(self, z: Incomplete) -> None: + """Get vmin and vmax, and then clip at vcenter.""" + ... + +def _init_color_database() -> Incomplete: + """Initialize the subclassed database.""" + ... + +def _init_cmap_database() -> Incomplete: + """Initialize the subclassed database.""" + ... + +def _get_cmap_subtype(name: Incomplete, subtype: Incomplete) -> Incomplete: + """Get a colormap belonging to a particular class. If none are found then raise +a useful error message that omits colormaps from other classes.""" + ... + +def _translate_cmap(cmap: Incomplete, lut: Incomplete=None, cyclic: Incomplete=None, listedthresh: Incomplete=None) -> Incomplete: + """Translate the input argument to a ultraplot colormap subclass. Auto-detect +cyclic colormaps based on names and re-apply default lookup table size.""" + ... + +class _ColorCache(dict): + """Replacement for the native color cache.""" + + def __getitem__(self, key: Incomplete) -> Incomplete: + """Get the standard color, colormap color, or color cycle color.""" + ... + + def _get_rgba(self, arg: Incomplete, alpha: Incomplete) -> Incomplete: + """Try to get the color from the registered colormap or color cycle.""" + ... + +class ColorDatabase(MutableMapping, dict): + """Dictionary subclass used to replace the builtin matplotlib color database. +See `~ColorDatabase.__getitem__` for details.""" + _colors_replace = (('grey', 'gray'), ('ochre', 'ocher'), ('kelley', 'kelly')) + + def __delitem__(self, key: Incomplete) -> None: + ... + + def __init__(self, mapping: Incomplete=None) -> None: + """Parameters +---------- +mapping : dict-like, optional + The colors.""" + ... + + def __getitem__(self, key: Incomplete) -> Incomplete: + """Get a color. Translates ``grey`` into ``gray`` and supports retrieving +colors "on-the-fly" from registered colormaps and color cycles. + +* For a colormap, use e.g. ``color=('Blues', 0.8)``. + The number is the colormap index, and must be between 0 and 1. +* For a color cycle, use e.g. ``color=('colorblind', 2)``. + The number is the color list index. + +This works everywhere that colors are used in matplotlib, for +example as `color`, `edgecolor`, or `facecolor` keyword arguments +passed to [PlotAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html) commands.""" + ... + + def __setitem__(self, key: Incomplete, value: Incomplete) -> None: + """Add a color. Translates ``grey`` into ``gray`` and clears the +cache. The color must be a string.""" + ... + + def _parse_key(self, key: Incomplete) -> str: + """Parse the color key. Currently this just translates grays.""" + ... + + @property + def cache(self) -> _ColorCache: + ... + +class ColormapDatabase(mcm.ColormapRegistry): + """Dictionary subclass used to replace the matplotlib +colormap registry. See `~ColormapDatabase.__getitem__` and +`~ColormapDatabase.__setitem__` for details.""" + _regex_grays = re.compile('\\A(grays)(_r|_s)*\\Z', flags=re.IGNORECASE) + _regex_suffix = re.compile('(_r|_s)*\\Z', flags=re.IGNORECASE) + + def __init__(self, kwargs: Incomplete) -> None: + """Parameters +---------- +kwargs : dict-like + The source dictionary.""" + ... + + def _translate_deprecated(self, key: Incomplete) -> Incomplete: + """Check if a colormap has been deprecated.""" + ... + + def _translate_key(self, original_key: Incomplete, mirror: Incomplete=True) -> str: + """Return the sanitized colormap name. Used for lookups and assignments.""" + ... + + def _has_item(self, key: Incomplete) -> Incomplete: + ... + + def _load_and_register_cmap(self, key: Incomplete, value: Incomplete) -> Incomplete: + """Load a colormap from a file and register it.""" + ... + + def get_cmap(self, cmap: Incomplete) -> Incomplete: + """Return a color map specified through *cmap*. + +Parameters +---------- +cmap : str or [Colormap](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.Colormap.html) or None + + - if a `.Colormap`, return it + - if a string, look it up in ``mpl.colormaps`` + - if None, return the Colormap defined in [image.cmap](https://ultraplot.readthedocs.io/en/stable/search.html?q=image.cmap) + +Returns +------- +Colormap""" + ... + + def __getitem__(self, key: Incomplete) -> Incomplete: + """Get the colormap with flexible input keys.""" + ... + + @override + def register(self, cmap: Incomplete, *, name: Incomplete=None, force: Incomplete=False) -> Incomplete: + """Add the colormap after validating and converting.""" + ... + + def register_lazy(self, name: Incomplete, path: Incomplete, type: Incomplete, is_default: Incomplete=False) -> None: + """Register a colormap to be loaded lazily from a file.""" + ... +_cmap_database = _init_cmap_database() +_color_database = _init_color_database() diff --git a/ultraplot/config.py b/ultraplot/config.py index af66ed6f9..e8a5faef8 100644 --- a/ultraplot/config.py +++ b/ultraplot/config.py @@ -838,6 +838,7 @@ def __init__(self, local=True, user=True, default=True, **kwargs): self._setting_handlers = {} self._init(local=local, user=user, default=default, **kwargs) + @docstring._snippet_manager def register_handler( self, name: str, func: Callable[[Any], Dict[str, Any]] ) -> None: diff --git a/ultraplot/config.pyi b/ultraplot/config.pyi new file mode 100644 index 000000000..b44bfcd68 --- /dev/null +++ b/ultraplot/config.pyi @@ -0,0 +1,629 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Tools for setting up ultraplot and configuring global settings. +See the [configuration guide](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_config) for details. +""" +from _typeshed import Incomplete +import logging +import os +import re +import sys +from collections import namedtuple +from collections.abc import MutableMapping +from numbers import Real +from typing import Any, Callable, Dict +import cycler +import matplotlib as mpl +import matplotlib.colors as mcolors +import matplotlib.font_manager as mfonts +import matplotlib.mathtext +import matplotlib.style.core as mstyle +import numpy as np +from matplotlib import RcParams +from .internals import _not_none, _pop_kwargs, _pop_props, _translate_grid, _version_mpl, docstring, ic, rcsetup, warnings +__all__ = ['Configurator', 'rc', 'rc_ultraplot', 'rc_matplotlib', 'use_style', 'config_inline_backend', 'register_cmaps', 'register_cycles', 'register_colors', 'register_fonts'] +COLORS_KEEP = ('red', 'green', 'blue', 'cyan', 'yellow', 'magenta', 'white', 'black') +_ULTRAPLOT_STYLES = {'poster': {'font.size': 14, 'axes.titlesize': 18, 'axes.labelsize': 16, 'xtick.labelsize': 13, 'ytick.labelsize': 13, 'legend.fontsize': 13, 'figure.titlesize': 20, 'lines.linewidth': 2.0, 'lines.markersize': 6, 'figure.facecolor': 'none', 'savefig.facecolor': 'none', 'savefig.edgecolor': 'none'}, 'dark_background': {'figure.facecolor': '#000000', 'figure.edgecolor': '#000000', 'axes.facecolor': '#000000', 'axes.edgecolor': '#cbd5e1', 'axes.labelcolor': '#f8fafc', 'text.color': '#f8fafc', 'xtick.color': '#cbd5e1', 'ytick.color': '#cbd5e1', 'grid.color': '#475569', 'grid.alpha': 0.35, 'legend.facecolor': '#000000', 'legend.edgecolor': '#475569', 'savefig.facecolor': '#000000', 'savefig.edgecolor': '#000000', 'axes.prop_cycle': cycler.cycler(color=('#60a5fa', '#f59e0b', '#34d399', '#f472b6', '#a78bfa', '#f87171'))}} +_rc_docstring = ... +_shared_docstring = ... +_cmap_exts_docstring = ... +_cycle_exts_docstring = ... +_color_docstring = ... +_font_docstring = ... +_register_docstring = ... +_rc_register_handler_docstring = ... + +def _init_user_file() -> Incomplete: + """Initialize .ultraplotrc file.""" + ... + +def _init_user_folders() -> Incomplete: + """Initialize .ultraplot folder.""" + ... + +def _get_data_folders(folder: Incomplete, user: Incomplete=True, local: Incomplete=True, default: Incomplete=True, reverse: Incomplete=False) -> Incomplete: + """Return data folder paths in reverse order of precedence.""" + ... + +def _iter_data_objects(folder: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Iterate over input objects and files in the data folders that should be +registered. Also yield an index indicating whether these are user files.""" + ... + +def _filter_style_dict(rcdict: Incomplete, warn: Incomplete=True) -> Incomplete: + """Filter out blacklisted style parameters.""" + ... + +def _get_default_style_dict() -> Incomplete: + """Get the default rc parameters dictionary with deprecated parameters filtered.""" + ... + +def _get_style_dict(style: Incomplete, filter: Incomplete=True) -> Incomplete: + """Return a dictionary of settings belonging to the requested style(s). If `filter` +is ``True``, invalid style parameters like `backend` are filtered out.""" + ... + +def _infer_ultraplot_dict(kw_params: Incomplete) -> Incomplete: + """Infer values for ultraplot's "added" parameters from stylesheet parameters.""" + ... + +def config_inline_backend(fmt: Incomplete=None) -> None: + """Set up the ipython [inline backend display format](https://ipython.readthedocs.io/en/stable/interactive/magics.html#magic-matplotlib) +and ensure that inline figures always look the same as saved figures. +This runs the following ipython magic commands: + +.. code-block:: ipython + + %%config InlineBackend.figure_formats = rc['inlineformat'] + %%config InlineBackend.rc = {} # never override rc settings + %%config InlineBackend.close_figures = True # cells start with no active figures + %%config InlineBackend.print_figure_kwargs = {'bbox_inches': None} + +When the inline backend is inactive or unavailable, this has no effect. +This function is called when you modify the [inlineformat](https://ultraplot.readthedocs.io/en/stable/search.html?q=inlineformat) property. + +Parameters +---------- +fmt : str or sequence, default: [inlineformat](https://ultraplot.readthedocs.io/en/stable/search.html?q=inlineformat) + The inline backend file format or a list thereof. Valid formats + include ``'jpg'``, ``'png'``, ``'svg'``, ``'pdf'``, and ``'retina'``. + +See also +-------- +Configurator""" + ... + +def use_style(style: Incomplete) -> None: + """Apply the [matplotlib style(s)](https://matplotlib.org/stable/tutorials/introductory/customizing.html) +with [matplotlib.style.use](https://matplotlib.org/stable/api/_as_gen/matplotlib.style.use.html). This function is +called when you modify the [style](https://ultraplot.readthedocs.io/en/stable/search.html?q=style) property. + +Parameters +---------- +style : str or sequence or dict-like + The matplotlib style name(s) or stylesheet filename(s), or dictionary(s) + of settings. Use ``'default'`` to apply matplotlib default settings and + ``'original'`` to include settings from your user ``matplotlibrc`` file. + +See also +-------- +Configurator +matplotlib.style.use""" + ... + +def register_cmaps(*args: Incomplete, user: Incomplete=None, local: Incomplete=None, default: Incomplete=False) -> None: + """Register named colormaps. This is called on import. + +Parameters +---------- +*args : path-spec or [ContinuousColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ContinuousColormap.html), optional + The colormaps to register. These can be file paths containing + RGB data or [ContinuousColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ContinuousColormap.html) instances. By default, + if positional arguments are passed, then `user` is set to ``False``. + + Valid file extensions are listed in the below table. Note that colormaps + are registered according to their filenames -- for example, ``name.xyz`` + will be registered as ``'name'``. + + =================== ========================================== + Extension Description + =================== ========================================== + ``.json`` JSON database of the channel segment data. + ``.hex`` Comma-delimited list of HEX strings. + ``.rgb``, ``.txt`` 3-4 column table of channel values. + =================== ========================================== + +user : bool, optional + Whether to reload colormaps from `~Configurator.user_folder`. Default is + ``False`` if positional arguments were passed and ``True`` otherwise. +local : bool, optional + Whether to reload colormaps from `~Configurator.local_folders`. Default is + ``False`` if positional arguments were passed and ``True`` otherwise. +default : bool, default: False + Whether to reload the default colormaps packaged with ultraplot. + Default is always ``False``. + +See also +-------- +register_cycles +register_colors +register_fonts +ultraplot.demos.show_cmaps""" + ... + +def register_cycles(*args: Incomplete, user: Incomplete=None, local: Incomplete=None, default: Incomplete=False) -> None: + """Register named color cycles. This is called on import. + +Parameters +---------- +*args : path-spec or [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html), optional + The color cycles to register. These can be file paths containing + RGB data or [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html) instances. By default, + if positional arguments are passed, then `user` is set to ``False``. + + Valid file extensions are listed in the below table. Note that color cycles + are registered according to their filenames -- for example, ``name.xyz`` + will be registered as ``'name'``. + + ================== ========================================== + Extension Description + ================== ========================================== + ``.hex`` Comma-delimited list of HEX strings. + ``.rgb``, ``.txt`` 3-4 column table of channel values. + ================== ========================================== + +user : bool, optional + Whether to reload color cycles from `~Configurator.user_folder`. Default is + ``False`` if positional arguments were passed and ``True`` otherwise. +local : bool, optional + Whether to reload color cycles from `~Configurator.local_folders`. Default is + ``False`` if positional arguments were passed and ``True`` otherwise. +default : bool, default: False + Whether to reload the default color cycles packaged with ultraplot. + Default is always ``False``. + +See also +-------- +register_cmaps +register_colors +register_fonts +ultraplot.demos.show_cycles""" + ... + +def register_colors(*args: Incomplete, user: Incomplete=None, local: Incomplete=None, default: Incomplete=False, space: Incomplete=None, margin: Incomplete=None, **kwargs: Incomplete) -> None: + """Register named colors. + +Parameters +---------- +- `*args`: The colors to register. +- `user`: Whether to reload colors from `~Configurator.user_folder`. +- `local`: Whether to reload colors from `~Configurator.local_folders`. +- `default`: Whether to reload the default colors packaged with ultraplot. +- `space`: The colorspace used to pick "perceptually distinct" colors from the [XKCD color survey](https://xkcd.com/color/rgb/). +- `margin`: The margin used to pick "perceptually distinct" colors from the [XKCD color survey](https://xkcd.com/color/rgb/). +- `**kwargs`: Additional color name specifications passed as keyword arguments rather than positional argument dictionaries. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.register_colors.html)""" + ... + +def register_fonts(*args: Incomplete, user: Incomplete=True, local: Incomplete=True, default: Incomplete=False) -> None: + """Register font families. This is called on import. + +Parameters +---------- +*args : path-like, optional + The font files to add. By default, if positional arguments are passed, then + `user` is set to ``False``. Files must have the extensions ``.ttf`` or ``.otf``. + See [this link](https://gree2.github.io/python/2015/04/27/python-change-matplotlib-font-on-mac) + for a guide on converting other font files to ``.ttf`` and ``.otf``. +user : bool, optional + Whether to reload fonts from `~Configurator.user_folder`. Default is + ``False`` if positional arguments were passed and ``True`` otherwise. +local : bool, optional + Whether to reload fonts from `~Configurator.local_folders`. Default is + ``False`` if positional arguments were passed and ``True`` otherwise. +default : bool, default: False + Whether to reload the default fonts packaged with ultraplot. + Default is always ``False``. + +See also +-------- +register_cmaps +register_cycles +register_colors +ultraplot.demos.show_fonts""" + ... + +class Configurator(MutableMapping, dict): + """A dictionary-like class for managing [matplotlib settings](https://matplotlib.org/stable/tutorials/introductory/customizing.html) +stored in `rc_matplotlib` and [ultraplot settings](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_rcultraplot) +stored in `rc_ultraplot`. This class is instantiated as the `rc` object +on import. See the [user guide](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_config) for details.""" + + def __repr__(self) -> str: + ... + + def __str__(self) -> str: + ... + + def __iter__(self) -> Incomplete: + ... + + def __len__(self) -> int: + ... + + def __delitem__(self, key: Incomplete) -> Incomplete: + ... + + def __delattr__(self, attr: Incomplete) -> Incomplete: + ... + + def __init__(self, local: Incomplete=True, user: Incomplete=True, default: Incomplete=True, **kwargs: Incomplete) -> None: + """Parameters +---------- +local : bool, default: True + Whether to load settings from the `~Configurator.local_files` file. +user : bool, default: True + Whether to load settings from the `~Configurator.user_file` file. +default : bool, default: True + Whether to reload built-in default ultraplot settings.""" + ... + + def register_handler(self, name: str, func: Callable[[Any], Dict[str, Any]]) -> None: + """Register a callback function to be executed when a setting is modified. + +This is an extension point for "special" settings that require complex +logic or have side-effects, such as updating other matplotlib settings. +It is used internally to decouple the configuration system from other +subsystems and avoid circular imports. + +Parameters +---------- +name : str + The name of the setting (e.g., ``'cycle'``). +func : callable + The handler function to be executed. The function must accept a + single positional argument, which is the new `value` of the + setting, and must return a dictionary. The keys of the dictionary + should be valid ``matplotlib`` rc setting names, and the values + will be applied to the ``rc_matplotlib`` object. + +Example +------- +>>> def _cycle_handler(value): +... # ... logic to create a cycler object from the value ... +... return {'axes.prop_cycle': new_cycler} +>>> rc.register_handler('cycle', _cycle_handler)""" + ... + + def __getitem__(self, key: Incomplete) -> Incomplete: + """Return an `rc_matplotlib` or `rc_ultraplot` setting using dictionary notation +(e.g., ``value = uplt.rc[name]``).""" + ... + + def __setitem__(self, key: Incomplete, value: Incomplete) -> None: + """Modify an `rc_matplotlib` or `rc_ultraplot` setting using dictionary notation +(e.g., ``uplt.rc[name] = value``).""" + ... + + def __getattr__(self, attr: Incomplete) -> Incomplete: + """Return an `rc_matplotlib` or `rc_ultraplot` setting using "dot" notation +(e.g., ``value = uplt.rc.name``).""" + ... + + def __setattr__(self, attr: Incomplete, value: Incomplete) -> None: + """Modify an `rc_matplotlib` or `rc_ultraplot` setting using "dot" notation +(e.g., ``uplt.rc.name = value``).""" + ... + + def __enter__(self) -> None: + """Apply settings from the most recent context block.""" + ... + + def __exit__(self, *args: Incomplete) -> None: + """Restore settings from the most recent context block.""" + ... + + def _init(self, *, local: Incomplete, user: Incomplete, default: Incomplete) -> None: + """Initialize the configurator.""" + ... + + @staticmethod + def _validate_key(key: Incomplete, value: Incomplete=None) -> Incomplete: + """Validate setting names and handle `rc_ultraplot` deprecations.""" + ... + + @staticmethod + def _validate_value(key: Incomplete, value: Incomplete) -> Incomplete: + """Validate setting values and convert numpy ndarray to list if possible.""" + ... + + def _get_item_context(self, key: Incomplete, mode: Incomplete=None) -> Incomplete: + """As with `~Configurator.__getitem__` but the search is limited based +on the context mode and ``None`` is returned if the key is not found.""" + ... + + def _get_item_dicts(self, key: Incomplete, value: Incomplete) -> Incomplete: + """Return dictionaries for updating the `rc_ultraplot` and `rc_matplotlib` +properties associated with this key. Used when setting items, entering +context blocks, or loading files.""" + ... + + @staticmethod + def _get_axisbelow_zorder(axisbelow: Incomplete) -> float: + """Convert the `axisbelow` string to its corresponding `zorder`.""" + ... + + def _get_background_props(self, patch_kw: Incomplete=None, native: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Return background properties, optionally filtering the output dictionary +based on the context.""" + ... + + def _get_gridline_bool(self, grid: Incomplete=None, axis: Incomplete=None, which: Incomplete='major', native: Incomplete=True) -> Incomplete: + """Return major and minor gridline toggles from ``axes.grid``, ``axes.grid.which``, +and ``axes.grid.axis``, optionally returning `None` based on the context.""" + ... + + def _get_gridline_props(self, which: Incomplete='major', native: Incomplete=True, rebuild: Incomplete=False) -> Incomplete: + """Return gridline properties, optionally filtering the output dictionary +based on the context.""" + ... + + def _get_label_props(self, native: Incomplete=True, **kwargs: Incomplete) -> Incomplete: + """Return the axis label properties, optionally filtering the output dictionary +based on the context.""" + ... + + def _get_loc_string(self, string: Incomplete, axis: Incomplete=None, native: Incomplete=True) -> Incomplete: + """Return `tickloc` and `spineloc` location strings from the `rc` boolean toggles, +optionally returning `None` based on the context.""" + ... + + def _get_tickline_props(self, axis: Incomplete=None, which: Incomplete='major', native: Incomplete=True, rebuild: Incomplete=False) -> Incomplete: + """Return the tick line properties, optionally filtering the output dictionary +based on the context.""" + ... + + def _get_ticklabel_props(self, axis: Incomplete=None, native: Incomplete=True, rebuild: Incomplete=False) -> Incomplete: + """Return the tick label properties, optionally filtering the output dictionary +based on the context.""" + ... + + @staticmethod + def local_files() -> Incomplete: + """Return locations of files named ``ultraplotrc`` in this directory and in parent +directories. "Hidden" files with a leading dot are also recognized. These are +automatically loaded when ultraplot is imported. + +See also +-------- +Configurator.user_file +Configurator.local_folders""" + ... + + @staticmethod + def local_folders(subfolder: Incomplete=None) -> Incomplete: + """Return locations of folders named ``ultraplot_cmaps``, ``ultraplot_cycles``, +``ultraplot_colors``, and ``ultraplot_fonts`` in this directory and in parent +directories. "Hidden" folders with a leading dot are also recognized. Files +in these directories are automatically loaded when ultraplot is imported. + +See also +-------- +Configurator.user_folder +Configurator.local_files""" + ... + + @staticmethod + def _config_folder() -> str: + """Get the XDG ultraplot folder.""" + ... + + @staticmethod + def user_file() -> str: + """Return location of the default ultraplotrc file. On Linux, this is either +``$XDG_CONFIG_HOME/ultraplot/ultraplotrc`` or ``~/.config/ultraplot/ultraplotrc`` +if the [XDG directory](https://wiki.archlinux.org/title/XDG_Base_Directory) +is unset. On other operating systems, this is ``~/.ultraplot/ultraplotrc``. The +location ``~/.ultraplotrc`` or ``~/.ultraplot/ultraplotrc`` is always returned if the +file exists, regardless of the operating system. If multiple valid locations +are found, a warning is raised. + +See also +-------- +Configurator.user_folder +Configurator.local_files""" + ... + + @staticmethod + def user_folder(subfolder: Incomplete=None) -> str: + """Return location of the default ultraplot folder. On Linux, this +is either ``$XDG_CONFIG_HOME/ultraplot`` or ``~/.config/ultraplot`` +if the [XDG directory](https://wiki.archlinux.org/title/XDG_Base_Directory) +is unset. On other operating systems, this is ``~/.ultraplot``. The location +``~/.ultraplot`` is always returned if the folder exists, regardless of the +operating system. If multiple valid locations are found, a warning is raised. + +See also +-------- +Configurator.user_file +Configurator.local_folders""" + ... + + def context(self, *args: Incomplete, mode: Incomplete=0, file: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Temporarily modify the rc settings in a "with as" block. + +Parameters +---------- +- `*args`: Dictionaries of `rc` keys and values. +- `file`: Filename from which settings should be loaded. +- `**kwargs`: `rc` names and values passed as keyword arguments. +- `mode`: The context mode. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.context)""" + ... + + def category(self, cat: Incomplete, *, trimcat: Incomplete=True, context: Incomplete=False) -> Incomplete: + """Return a dictionary of settings beginning with the substring ``cat + '.'``. +Optionally limit the search to the context level. + +Parameters +---------- +cat : str, optional + The `rc` setting category. +trimcat : bool, default: True + Whether to trim ``cat`` from the key names in the output dictionary. +context : bool, default: False + If ``True``, then settings not found in the context dictionaries + are omitted from the output dictionary. See `~Configurator.context`. + +See also +-------- +Configurator.find +Configurator.fill""" + ... + + def fill(self, props: Incomplete, *, context: Incomplete=False) -> Incomplete: + """Return a dictionary filled with settings whose names match the string values +in the input dictionary. Optionally limit the search to the context level. + +Parameters +---------- +props : dict-like + Dictionary whose values are setting names -- for example + ``rc.fill({'edgecolor': 'axes.edgecolor', 'facecolor': 'axes.facecolor'})``. +context : bool, default: False + If ``True``, then settings not found in the context dictionaries + are omitted from the output dictionary. See `~Configurator.context`. + +See also +-------- +Configurator.category +Configurator.find""" + ... + + def find(self, key: Incomplete, *, context: Incomplete=False) -> Incomplete: + """Return a single setting. Optionally limit the search to the context level. + +Parameters +---------- +key : str + The single setting name. +context : bool, default: False + If ``True``, then ``None`` is returned if the setting is not found + in the context dictionaries. See `~Configurator.context`. + +See also +-------- +Configurator.category +Configurator.fill""" + ... + + def update(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Update several settings at once. + +Parameters +---------- +*args : str or dict-like, optional + A dictionary containing `rc` keys and values. You can also pass + a "category" name as the first argument, in which case all + settings are prepended with ``'category.'``. For example, + ``rc.update('axes', labelsize=20, titlesize=20)`` changes the + [axes.labelsize](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.labelsize) and [axes.titlesize](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.titlesize) settings. +**kwargs + `rc` keys and values passed as keyword arguments. + If the name has dots, simply omit them. + +See also +-------- +Configurator.category +Configurator.fill""" + ... + + def reset(self, local: Incomplete=True, user: Incomplete=True, default: Incomplete=True, **kwargs: Incomplete) -> None: + """Reset the configurator to its initial state. + +Parameters +---------- +local : bool, default: True + Whether to load settings from the `~Configurator.local_files` file. +user : bool, default: True + Whether to load settings from the `~Configurator.user_file` file. +default : bool, default: True + Whether to reload built-in default ultraplot settings.""" + ... + + def _load_file(self, path: Incomplete) -> Incomplete: + """Return dictionaries of ultraplot and matplotlib settings loaded from the file.""" + ... + + def load(self, path: Incomplete) -> None: + """Load settings from the specified file. + +Parameters +---------- +path : path-like + The file path. + +See also +-------- +Configurator.save""" + ... + + @staticmethod + def _save_rst(path: Incomplete) -> None: + """Create an RST table file. Used for online docs.""" + ... + + @staticmethod + def _save_yaml(path: Incomplete, user_dict: Incomplete=None, *, comment: Incomplete=False, description: Incomplete=False) -> None: + """Create a YAML file. Used for online docs and default and user-generated +ultraplotrc files. Extra settings can be passed with the input dictionary.""" + ... + + def save(self, path: Incomplete=None, user: Incomplete=True, comment: Incomplete=None, backup: Incomplete=True, description: Incomplete=False) -> None: + """Save the current settings to a ``ultraplotrc`` file. This writes +the default values commented out plus the values that *differ* +from the defaults at the top of the file. + +Parameters +---------- +path : path-like, default: 'ultraplotrc' + The file name and/or directory. The default file name is ``ultraplotrc`` + and the default directory is the current directory. +user : bool, default: True + If ``True`` then settings that have been `~Configurator.changed` from + the ultraplot defaults are shown uncommented at the top of the file. +backup : bool, default: True + Whether to "backup" an existing file by renaming with the suffix ``.bak`` + or overwrite an existing file. +comment : bool, optional + Whether to comment out the default settings. If not passed + this takes the same value as `user`. +description : bool, default: False + Whether to include descriptions of each setting (as seen in the + [user guide table](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_rctable)) as comments. + +See also +-------- +Configurator.load +Configurator.changed""" + ... + + @property + def _context_mode(self) -> Incomplete: + """Return the highest (least permissive) context mode.""" + ... + + @property + def changed(self) -> Incomplete: + """A dictionary of settings that have changed from the ultraplot defaults. + +See also +-------- +Configurator.save""" + ... +rc_matplotlib = mpl.rcParams +rc_ultraplot = rcsetup._rc_ultraplot_default.copy() +rc = Configurator() diff --git a/ultraplot/constructor.pyi b/ultraplot/constructor.pyi new file mode 100644 index 000000000..bfa65f350 --- /dev/null +++ b/ultraplot/constructor.pyi @@ -0,0 +1,254 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The constructor functions used to build class instances from simple shorthand arguments. +""" +from _typeshed import Incomplete +import copy +import os +import re +from functools import partial +from numbers import Number +from typing import Callable, Iterator, TypeVar +import cycler +import matplotlib.colors as mcolors +import matplotlib.dates as mdates +import matplotlib.font_manager as mfonts +import matplotlib.projections.polar as mpolar +import matplotlib.scale as mscale +import matplotlib.ticker as mticker +from matplotlib.ft2font import FT2Font +import numpy as np +from . import colors as pcolors +from . import proj as pproj +from . import scale as pscale +from . import ticker as pticker +from .config import rc +from .internals import _not_none, _pop_props, _version_cartopy, _version_mpl, ic, warnings +from .utils import to_hex, to_rgba +try: + from mpl_toolkits.basemap import Basemap +except ImportError: + Basemap = object +try: + import cartopy.crs as ccrs + from cartopy.crs import Projection +except ModuleNotFoundError: + ccrs = None + Projection = object +__all__ = ['Proj', 'Locator', 'Formatter', 'Scale', 'Colormap', 'Norm', 'Cycle'] +DEFAULT_CYCLE_SAMPLES = 10 +DEFAULT_CYCLE_LUMINANCE = 90 +_RegistryValue = TypeVar('_RegistryValue') + +class _RefreshingRegistry(dict[str, _RegistryValue]): + """Dictionary-like registry that rebuilds itself before reads. + +This keeps constructor registries aligned with modules that may be reloaded +in-place during tests or interactive use.""" + + def __init__(self, factory: Callable[[], dict[str, _RegistryValue]]) -> None: + ... + + def _refresh(self) -> None: + ... + + def __contains__(self, key: object) -> bool: + ... + + def __getitem__(self, key: str) -> _RegistryValue: + ... + + def __iter__(self) -> Iterator[str]: + ... + + def __len__(self) -> int: + ... + + def get(self, key: str, default: _RegistryValue | None=None) -> _RegistryValue | None: + ... + + def items(self) -> Incomplete: + ... + + def keys(self) -> Incomplete: + ... + + def values(self) -> Incomplete: + ... + + def copy(self) -> dict[str, _RegistryValue]: + ... + +def _build_norm_registry() -> dict[str, type[mcolors.Normalize]]: + ... + +def _build_locator_registry() -> dict[str, object]: + ... + +def _get_dms_symbol_kwargs() -> dict[str, str]: + """Return ASCII DMS symbols when the active font lacks prime glyphs.""" + ... + +def _build_formatter_registry() -> dict[str, object]: + ... +NORMS = _RefreshingRegistry(_build_norm_registry) +LOCATORS = _RefreshingRegistry(_build_locator_registry) +FORMATTERS = _RefreshingRegistry(_build_formatter_registry) +SCALES = mscale._scale_mapping +SCALES_PRESETS = {'quadratic': ('power', 2), 'cubic': ('power', 3), 'quartic': ('power', 4), 'height': ('exp', np.e, -1 / 7, 1013.25, True), 'pressure': ('exp', np.e, -1 / 7, 1013.25, False), 'db': ('exp', 10, 1, 0.1, True), 'idb': ('exp', 10, 1, 0.1, False), 'np': ('exp', np.e, 1, 1, True), 'inp': ('exp', np.e, 1, 1, False)} +PROJ_DEFAULTS = {'geos': {'lon_0': 0}, 'eck4': {'lon_0': 0}, 'moll': {'lon_0': 0}, 'hammer': {'lon_0': 0}, 'kav7': {'lon_0': 0}, 'sinu': {'lon_0': 0}, 'vandg': {'lon_0': 0}, 'mbtfpq': {'lon_0': 0}, 'robin': {'lon_0': 0}, 'ortho': {'lon_0': 0, 'lat_0': 0}, 'nsper': {'lon_0': 0, 'lat_0': 0}, 'aea': {'lon_0': 0, 'lat_0': 90, 'width': 15000000.0, 'height': 15000000.0}, 'eqdc': {'lon_0': 0, 'lat_0': 90, 'width': 15000000.0, 'height': 15000000.0}, 'cass': {'lon_0': 0, 'lat_0': 90, 'width': 15000000.0, 'height': 15000000.0}, 'gnom': {'lon_0': 0, 'lat_0': 90, 'width': 15000000.0, 'height': 15000000.0}, 'poly': {'lon_0': 0, 'lat_0': 0, 'width': 10000000.0, 'height': 10000000.0}, 'npaeqd': {'lon_0': 0, 'boundinglat': 10}, 'nplaea': {'lon_0': 0, 'boundinglat': 10}, 'npstere': {'lon_0': 0, 'boundinglat': 10}, 'spaeqd': {'lon_0': 0, 'boundinglat': -10}, 'splaea': {'lon_0': 0, 'boundinglat': -10}, 'spstere': {'lon_0': 0, 'boundinglat': -10}, 'lcc': {'lon_0': 0, 'lat_0': 40, 'lat_1': 35, 'lat_2': 45, 'width': 20000000.0, 'height': 15000000.0}, 'tmerc': {'lon_0': 0, 'lat_0': 0, 'width': 10000000.0, 'height': 10000000.0}, 'merc': {'llcrnrlat': -80, 'urcrnrlat': 84, 'llcrnrlon': -180, 'urcrnrlon': 180}, 'omerc': {'lat_0': 0, 'lon_0': 0, 'lat_1': -10, 'lat_2': 10, 'lon_1': 0, 'lon_2': 0, 'width': 10000000.0, 'height': 10000000.0}} +if ccrs is None: + PROJS = {} +else: + PROJS = {'aitoff': pproj.Aitoff, 'hammer': pproj.Hammer, 'kav7': pproj.KavrayskiyVII, 'wintri': pproj.WinkelTripel, 'npgnom': pproj.NorthPolarGnomonic, 'spgnom': pproj.SouthPolarGnomonic, 'npaeqd': pproj.NorthPolarAzimuthalEquidistant, 'spaeqd': pproj.SouthPolarAzimuthalEquidistant, 'nplaea': pproj.NorthPolarLambertAzimuthalEqualArea, 'splaea': pproj.SouthPolarLambertAzimuthalEqualArea} + PROJS_MISSING = {'aea': 'AlbersEqualArea', 'aeqd': 'AzimuthalEquidistant', 'cyl': 'PlateCarree', 'eck1': 'EckertI', 'eck2': 'EckertII', 'eck3': 'EckertIII', 'eck4': 'EckertIV', 'eck5': 'EckertV', 'eck6': 'EckertVI', 'eqc': 'PlateCarree', 'eqdc': 'EquidistantConic', 'eqearth': 'EqualEarth', 'euro': 'EuroPP', 'geos': 'Geostationary', 'gnom': 'Gnomonic', 'igh': 'InterruptedGoodeHomolosine', 'laea': 'LambertAzimuthalEqualArea', 'lcc': 'LambertConformal', 'lcyl': 'LambertCylindrical', 'merc': 'Mercator', 'mill': 'Miller', 'moll': 'Mollweide', 'npstere': 'NorthPolarStereo', 'nsper': 'NearsidePerspective', 'ortho': 'Orthographic', 'osgb': 'OSGB', 'osni': 'OSNI', 'pcarree': 'PlateCarree', 'robin': 'Robinson', 'rotpole': 'RotatedPole', 'sinu': 'Sinusoidal', 'spstere': 'SouthPolarStereo', 'stere': 'Stereographic', 'tmerc': 'TransverseMercator', 'utm': 'UTM'} + PROJS_TABLE = ... +FEATURES_CARTOPY = {'land': ('physical', 'land'), 'ocean': ('physical', 'ocean'), 'lakes': ('physical', 'lakes'), 'coast': ('physical', 'coastline'), 'rivers': ('physical', 'rivers_lake_centerlines'), 'borders': ('cultural', 'admin_0_boundary_lines_land'), 'innerborders': ('cultural', 'admin_1_states_provinces_lakes')} +FEATURES_BASEMAP = {'land': 'fillcontinents', 'coast': 'drawcoastlines', 'rivers': 'drawrivers', 'borders': 'drawcountries', 'innerborders': 'drawstates'} +RESOS_CARTOPY = {'lo': '110m', 'med': '50m', 'hi': '10m', 'x-hi': '10m', 'xx-hi': '10m'} +RESOS_BASEMAP = {'lo': 'c', 'med': 'l', 'hi': 'i', 'x-hi': 'h', 'xx-hi': 'f'} + +def _modify_colormap(cmap: Incomplete, *, cut: Incomplete, left: Incomplete, right: Incomplete, reverse: Incomplete, shift: Incomplete, alpha: Incomplete, samples: Incomplete) -> Incomplete: + """Modify colormap using a variety of methods.""" + ... + +def Colormap(*args: Incomplete, name: Incomplete=None, listmode: Incomplete='perceptual', filemode: Incomplete='continuous', discrete: Incomplete=False, cycle: Incomplete=None, save: Incomplete=False, save_kw: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Generate, retrieve, modify, and/or merge instances of [PerceptualColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.PerceptualColormap.html), [ContinuousColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ContinuousColormap.html), and [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html). + +Parameters +---------- +- `*args`: Positional arguments that individually generate colormaps. +- `name`: Name under which the final colormap is registered. +- `filemode`: Controls how colormaps are generated when you input list(s) of colors. +- `listmode`: Controls how colormaps are generated when you input sequence(s) of colors. +- `samples`: For [ContinuousColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ContinuousColormap.html)\\ s, this is used to generate [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html)\\ s with… +- `discrete`: If ``True``, when the final colormap is a [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html), we leave it alone, but when it is a [ContinuousColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ContinuousColormap.html), we always… +- `left, right`: Truncate the left or right edges of the colormap. +- `cut`: Cut out the center of the colormap. +- `reverse`: Reverse the colormap. +- `shift`: Cyclically shift the colormap. +- `a`: Shorthand for `alpha`. +- `alpha`: The opacity of the colormap or the opacity gradation. +- `hue, saturation, luminance`: The channel value(s) used to generate colormaps with [from_hsl](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.PerceptualColormap.html#ultraplot.colors.PerceptualColormap.from_hsl) and [from_color](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.PerceptualColormap.html#ultraplot.colors.PerceptualColormap.from_color). +- `chroma`: Alias for `saturation`. +- `cycle`: The registered cycle name used to interpret color strings like ``'C0'`` and ``'C2'``. +- `save`: Whether to call the colormap/color cycle save method, i.e. +- `save_kw`: Ignored if `save` is ``False``. +- `**kwargs`: Passed to [ultraplot.colors.ContinuousColormap.copy](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ContinuousColormap.html#ultraplot.colors.ContinuousColormap.copy), [ultraplot.colors.PerceptualColormap.copy](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.PerceptualColormap.html#ultraplot.colors.PerceptualColormap.copy), or [ultraplot.colors.DiscreteColormap.copy](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html#ultraplot.colors.DiscreteColormap.copy). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Colormap.html)""" + ... + +class Cycle(cycler.Cycler): + """Generate and merge `~cycler.Cycler` instances in a variety of ways. + +Parameters +---------- +- `*args`: Positional arguments control the *colors* in the `~cycler.Cycler` object. +- `N`: Shorthand for `samples`. +- `samples`: For [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html)\\ s, this is the number of colors to select. +- `c, color, colors`: A sequence of colors passed as keyword arguments. +- `linewidth, linestyle, dashes, alpha, marker, markersize, markeredgewidth, markeredgecolor, markerfacecolor`: Lists of [Line2D](https://matplotlib.org/stable/api/_as_gen/matplotlib.lines.Line2D.html) properties that can be added to the `~cycler.Cycler` instance. +- `**kwargs`: If the input is not already a `~cycler.Cycler` instance, these are passed to `Colormap` and used to build the [DiscreteColormap](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.DiscreteColormap.html) from which the cycler will… + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html)""" + + def __init__(self, *args: Incomplete, N: Incomplete=None, samples: Incomplete=None, name: Incomplete=None, **kwargs: Incomplete) -> None: + ... + + def _parse_basic_properties(self, kwargs: Incomplete) -> Incomplete: + """Parse and validate basic properties from kwargs.""" + ... + + def _handle_empty_args(self, props: Incomplete, kwargs: Incomplete) -> None: + """Handle case when no positional arguments are provided.""" + ... + + def _handle_cycler_args(self, args: Incomplete, props: Incomplete, kwargs: Incomplete) -> None: + """Handle case when arguments are cycler objects.""" + ... + + def _handle_colormap_args(self, args: Incomplete, props: Incomplete, kwargs: Incomplete, samples: Incomplete, name: Incomplete) -> None: + """Handle case when arguments are for creating a colormap.""" + ... + + def _create_colormap(self, args: Incomplete, name: Incomplete, samples: Incomplete, kwargs: Incomplete) -> Incomplete: + """Create a colormap from the given arguments.""" + ... + + def _is_all_cyclers(self, args: Incomplete) -> bool: + """Check if all arguments are Cycler objects.""" + ... + + def _build_cycler(self, dicts: Incomplete) -> None: + """Build the final cycler from the given dictionaries.""" + ... + + def __eq__(self, other: Incomplete) -> bool: + ... + + def get_next(self) -> Incomplete: + ... + +def Norm(norm: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Return an arbitrary [Normalize](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.Normalize.html) instance. + +Parameters +---------- +- `norm`: The normalizer specification. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Norm.html)""" + ... + +def Locator(locator: Incomplete, *args: Incomplete, discrete: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Return a [Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) instance. + +Parameters +---------- +- `locator`: The locator specification, interpreted as follows: * If a [Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) instance already, a `copy.copy` of the instance is returned. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Locator.html)""" + ... + +def Formatter(formatter: Incomplete, *args: Incomplete, date: Incomplete=False, index: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Return a [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) instance. + +Parameters +---------- +- `formatter`: The formatter specification, interpreted as follows: * If a [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) instance already, a `copy.copy` of the instance is returned. +- `date`: Toggles the behavior when `formatter` contains a ``'%%'`` sign (see above). +- `index`: Controls the behavior when `formatter` is a sequence of strings (see above). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Formatter.html)""" + ... + +def Scale(scale: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Return a [ScaleBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.ScaleBase.html) instance. + +Parameters +---------- +- `scale`: The axis scale specification. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Scale.html)""" + ... + +def _warn_basemap_deprecated() -> Incomplete: + """Warn that the basemap backend is deprecated.""" + ... + +def Proj(name: Incomplete, backend: Incomplete=None, lon0: Incomplete=None, lon_0: Incomplete=None, lat0: Incomplete=None, lat_0: Incomplete=None, lonlim: Incomplete=None, latlim: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return a `cartopy.crs.Projection` or `~mpl_toolkits.basemap.Basemap` instance. + +Parameters +---------- +- `name`: The projection name or projection class instance. +- `backend`: Whether to return a cartopy `~cartopy.crs.Projection` instance or a basemap `~mpl_toolkits.basemap.Basemap` instance. +- `lon0, lat0`: The central projection longitude and latitude. +- `lon_0, lat_0`: Aliases for `lon0`, `lat0`. +- `lonlim`: The longitude limits. +- `latlim`: The latitude limits. +- `**kwargs`: Passed to the cartopy `~cartopy.crs.Projection` or basemap `~mpl_toolkits.basemap.Basemap` class. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Proj.html)""" + ... diff --git a/ultraplot/demos.pyi b/ultraplot/demos.pyi new file mode 100644 index 000000000..35be61ad5 --- /dev/null +++ b/ultraplot/demos.pyi @@ -0,0 +1,223 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Functions for displaying colors and fonts. +""" +from _typeshed import Incomplete +import os +import re +import cycler +import matplotlib.colors as mcolors +import matplotlib.font_manager as mfonts +import numpy as np +from . import colors as pcolors +from . import constructor, ui +from .config import _get_data_folders, rc +from .internals import ic +from .internals import _not_none, _version_mpl, docstring, warnings +from .utils import to_rgb, to_xyz +__all__ = ['show_cmaps', 'show_channels', 'show_colors', 'show_colorspaces', 'show_cycles', 'show_fonts'] +FAMILY_TEXGYRE = ('TeX Gyre Heros', 'TeX Gyre Schola', 'TeX Gyre Bonum', 'TeX Gyre Termes', 'TeX Gyre Pagella', 'TeX Gyre Chorus', 'TeX Gyre Adventor', 'TeX Gyre Cursor') +COLOR_TABLE = {'base': mcolors.BASE_COLORS, 'css4': mcolors.CSS4_COLORS, 'opencolor': pcolors.COLORS_OPEN, 'xkcd': pcolors.COLORS_XKCD} +CYCLE_TABLE = {'Matplotlib defaults': ('default', 'classic'), 'Matplotlib stylesheets': ('colorblind', 'colorblind10', 'tableau', 'ggplot', '538', 'seaborn', 'bmh'), 'ColorBrewer2.0 qualitative': ('Accent', 'Dark2', 'Paired', 'Pastel1', 'Pastel2', 'Set1', 'Set2', 'Set3', 'tab10', 'tab20', 'tab20b', 'tab20c'), 'Other qualitative': ('FlatUI', 'Qual1', 'Qual2')} +CMAP_TABLE = {'Grayscale': ('Greys', 'Mono', 'MonoCycle'), 'Matplotlib sequential': ('viridis', 'plasma', 'inferno', 'magma', 'cividis'), 'Matplotlib cyclic': ('twilight',), 'Seaborn sequential': ('Rocket', 'Flare', 'Mako', 'Crest'), 'Seaborn diverging': ('IceFire', 'Vlag'), 'UltraPlot sequential': ('Fire', 'Stellar', 'Glacial', 'Dusk', 'Marine', 'Boreal', 'Sunrise', 'Sunset'), 'UltraPlot diverging': ('Div', 'NegPos', 'DryWet'), 'Other sequential': ('cubehelix', 'turbo'), 'Other diverging': ('BR', 'ColdHot', 'CoolWarm'), 'cmOcean sequential': ('Oxy', 'Thermal', 'Dense', 'Ice', 'Haline', 'Deep', 'Algae', 'Tempo', 'Speed', 'Turbid', 'Solar', 'Matter', 'Amp'), 'cmOcean diverging': ('Balance', 'Delta', 'Curl'), 'cmOcean cyclic': ('Phase',), 'Scientific colour maps sequential': ('batlow', 'batlowK', 'batlowW', 'devon', 'davos', 'oslo', 'lapaz', 'acton', 'lajolla', 'bilbao', 'tokyo', 'turku', 'bamako', 'nuuk', 'hawaii', 'buda', 'imola', 'oleron', 'bukavu', 'fes'), 'Scientific colour maps diverging': ('roma', 'broc', 'cork', 'vik', 'bam', 'lisbon', 'tofino', 'berlin', 'vanimo'), 'Scientific colour maps cyclic': ('romaO', 'brocO', 'corkO', 'vikO', 'bamO'), 'ColorBrewer2.0 sequential': ('Purples', 'Blues', 'Greens', 'Oranges', 'Reds', 'YlOrBr', 'YlOrRd', 'OrRd', 'PuRd', 'RdPu', 'BuPu', 'PuBu', 'PuBuGn', 'BuGn', 'GnBu', 'YlGnBu', 'YlGn'), 'ColorBrewer2.0 diverging': ('Spectral', 'PiYG', 'PRGn', 'BrBG', 'PuOr', 'RdGY', 'RdBu', 'RdYlBu', 'RdYlGn'), 'SciVisColor blues': ('Blues1', 'Blues2', 'Blues3', 'Blues4', 'Blues5', 'Blues6', 'Blues7', 'Blues8', 'Blues9', 'Blues10', 'Blues11'), 'SciVisColor greens': ('Greens1', 'Greens2', 'Greens3', 'Greens4', 'Greens5', 'Greens6', 'Greens7', 'Greens8'), 'SciVisColor yellows': ('Yellows1', 'Yellows2', 'Yellows3', 'Yellows4'), 'SciVisColor oranges': ('Oranges1', 'Oranges2', 'Oranges3', 'Oranges4'), 'SciVisColor browns': ('Browns1', 'Browns2', 'Browns3', 'Browns4', 'Browns5', 'Browns6', 'Browns7', 'Browns8', 'Browns9'), 'SciVisColor reds': ('Reds1', 'Reds2', 'Reds3', 'Reds4', 'Reds5'), 'SciVisColor purples': ('Purples1', 'Purples2', 'Purples3'), 'MATLAB': ('bone', 'cool', 'copper', 'autumn', 'flag', 'prism', 'jet', 'hsv', 'hot', 'spring', 'summer', 'winter', 'pink', 'gray'), 'GNUplot': ('gnuplot', 'gnuplot2', 'ocean', 'afmhot', 'rainbow'), 'GIST': ('gist_earth', 'gist_gray', 'gist_heat', 'gist_ncar', 'gist_rainbow', 'gist_stern', 'gist_yarg'), 'Other': ('binary', 'bwr', 'brg', 'Wistia', 'CMRmap', 'seismic', 'terrain', 'nipy_spectral', 'tab10', 'tab20', 'tab20b', 'tab20c')} +_colorbar_docstring = ... + +def show_channels(*args: Incomplete, N: Incomplete=100, rgb: Incomplete=False, saturation: Incomplete=True, minhue: Incomplete=0, maxsat: Incomplete=500, width: Incomplete=100, refwidth: Incomplete=1.7) -> Incomplete: + """Show how arbitrary colormap(s) vary with respect to the hue, chroma, +luminance, HSL saturation, and HPL saturation channels, and optionally +the red, blue and green channels. Adapted from [this example](https://matplotlib.org/stable/tutorials/colors/colormaps.html#lightness-of-matplotlib-colormaps). + +Parameters +---------- +*args : colormap-spec, default: [image.cmap](https://ultraplot.readthedocs.io/en/stable/search.html?q=image.cmap) + Positional arguments are colormap names or objects. +N : int, optional + The number of markers to draw for each colormap. +rgb : bool, optional + Whether to also show the red, green, and blue channels in the bottom row. +saturation : bool, optional + Whether to show the HSL and HPL saturation channels alongside the raw chroma. +minhue : float, optional + The minimum hue. This lets you rotate the hue plot cyclically. +maxsat : float, optional + The maximum saturation. Use this to truncate large saturation values. +width : int, optional + The width of each colormap line in points. +refwidth : int or str, optional + The width of each subplot. Passed to [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ui.subplots.html). + +Returns +------- +ultraplot.figure.Figure + The figure. +ultraplot.gridspec.SubplotGrid + The subplot grid. + +See also +-------- +show_cmaps +show_colorspaces""" + ... + +def show_colorspaces(*, luminance: Incomplete=None, saturation: Incomplete=None, hue: Incomplete=None, refwidth: Incomplete=2) -> Incomplete: + """Generate hue-saturation, hue-luminance, and luminance-saturation +cross-sections for the HCL, HSL, and HPL colorspaces. + +Parameters +---------- +luminance : float, default: 50 + If passed, saturation-hue cross-sections are drawn for + this luminance. Must be between ``0`` and ``100``. +saturation : float, optional + If passed, luminance-hue cross-sections are drawn for this + saturation. Must be between ``0`` and ``100``. +hue : float, optional + If passed, luminance-saturation cross-sections + are drawn for this hue. Must be between ``0`` and ``360``. +refwidth : str or float, optional + Average width of each subplot. Units are interpreted by + [units](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.utils.units.html). + +Returns +------- +ultraplot.figure.Figure + The figure. +ultraplot.gridspec.SubplotGrid + The subplot grid. + +See also +-------- +show_cmaps +show_channels""" + ... + +def _draw_bars(cmaps: Incomplete, *, source: Incomplete, unknown: Incomplete='User', include: Incomplete=None, ignore: Incomplete=None, length: Incomplete=4.0, width: Incomplete=0.2, N: Incomplete=None, rasterized: Incomplete=None) -> Incomplete: + """Draw colorbars for "colormaps" and "color cycles". This is called by +`show_cycles` and `show_cmaps`.""" + ... + +def show_cmaps(*args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Generate a table of the registered colormaps or the input colormaps categorized by source. + +Parameters +---------- +- `*args`: Colormap names or objects. +- `N`: The number of levels in each colorbar. +- `unknown`: Category name for colormaps that are unknown to ultraplot. +- `include`: Category names to be shown in the table. +- `ignore`: Used only if `include` was not passed. +- `length`: The length of each colorbar. +- `width`: The width of each colorbar. +- `rasterized`: Whether to rasterize the colorbar solids. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.demos.show_cmaps.html)""" + ... + +def show_cycles(*args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Generate a table of registered color cycles or the input color cycles +categorized by source. Adapted from [this example](http://matplotlib.org/stable/gallery/color/colormap_reference.html). + +Parameters +---------- +*args : colormap-spec, optional + Cycle names or objects. +unknown : str, default: 'User' + Category name for cycles that are unknown to ultraplot. + Set this to ``False`` to hide unknown colormaps. +include : str or sequence of str, default: None + Category names to be shown in the table. Use this to limit + the table to a subset of categories. Valid categories are + ``'Matplotlib defaults'``, ``'Matplotlib stylesheets'``, ``'ColorBrewer2.0 qualitative'``, ``'Other qualitative'``. +ignore : str or sequence of str, default: None + Used only if `include` was not passed. Category names to be removed + from the table. +length : unit-spec, optional + The length of each colorbar. + If float, units are inches. If string, interpreted by [units](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.utils.units.html). +width : float or str, optional + The width of each colorbar. + If float, units are inches. If string, interpreted by [units](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.utils.units.html). +rasterized : bool, default: [colorbar.rasterized](https://ultraplot.readthedocs.io/en/stable/search.html?q=colorbar.rasterized) + Whether to rasterize the colorbar solids. This increases rendering + time and decreases file sizes for vector graphics. + +Returns +------- +ultraplot.figure.Figure + The figure. +ultraplot.gridspec.SubplotGrid + The subplot grid. + +See also +-------- +show_cmaps +show_colors +show_fonts""" + ... + +def _filter_colors(hcl: Incomplete, ihue: Incomplete, nhues: Incomplete, minsat: Incomplete) -> Incomplete: + """Filter colors into categories. + +Parameters +---------- +hcl : tuple + The data. +ihue : int + The hue column. +nhues : int + The total number of hues. +minsat : float + The minimum saturation used for the "grays" column.""" + ... + +def show_colors(*, nhues: Incomplete=17, minsat: Incomplete=10, unknown: Incomplete='User', include: Incomplete=None, ignore: Incomplete=None) -> Incomplete: + """Generate tables of the registered color names. Adapted from +[this example](https://matplotlib.org/examples/color/named_colors.html). + +Parameters +---------- +nhues : int, optional + The number of breaks between hues for grouping "like colors" in the + color table. +minsat : float, optional + The threshold saturation, between ``0`` and ``100``, for designating + "gray colors" in the color table. +unknown : str, default: 'User' + Category name for color names that are unknown to ultraplot. + Set this to ``False`` to hide unknown color names. +include : str or sequence of str, default: None + Category names to be shown in the table. Use this to limit + the table to a subset of categories. Valid categories are + ``'base'``, ``'css4'``, ``'opencolor'``, ``'xkcd'``. +ignore : str or sequence of str, default: 'CSS4' + Used only if `include` was not passed. Category names to be removed + from the colormap table. + +Returns +------- +ultraplot.figure.Figure + The figure. +ultraplot.gridspec.SubplotGrid + The subplot grid.""" + ... + +def show_fonts(*args: Incomplete, family: Incomplete=None, user: Incomplete=None, text: Incomplete=None, math: Incomplete=False, fallback: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Generate a table of fonts. + +Parameters +---------- +- `*args`: The font specs, font names, or [FontProperties](https://matplotlib.org/stable/api/_as_gen/matplotlib.font_manager.FontProperties.html)\\ s to show. +- `family`: The family from which *available* fonts are shown. +- `user`: Whether to include fonts in [user_folder](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.user_folder) and [local_folders](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.config.Configurator.html#ultraplot.config.Configurator.local_folders) at the top of the table. +- `text`: The sample text shown for each font. +- `math`: Whether the default sample text should show non-math Latin characters or or math equations and Greek letters. +- `fallback`: Whether to use the fallback font [mathtext.fallback](https://ultraplot.readthedocs.io/en/stable/search.html?q=mathtext.fallback) for unavailable characters. +- `**kwargs`: Additional font properties passed to [FontProperties](https://matplotlib.org/stable/api/_as_gen/matplotlib.font_manager.FontProperties.html). +- `size`: The font size. +- `weight`: The font weight. +- `style`: The font style. +- `stretch`: The font stretch. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.demos.show_fonts.html)""" + ... diff --git a/ultraplot/externals/__init__.pyi b/ultraplot/externals/__init__.pyi new file mode 100644 index 000000000..a144a6951 --- /dev/null +++ b/ultraplot/externals/__init__.pyi @@ -0,0 +1,7 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +External utilities adapted for ultraplot. +""" +from _typeshed import Incomplete +from . import hsluv diff --git a/ultraplot/externals/hsluv.pyi b/ultraplot/externals/hsluv.pyi new file mode 100644 index 000000000..32f195e4c --- /dev/null +++ b/ultraplot/externals/hsluv.pyi @@ -0,0 +1,142 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for converting between colorspaces. Includes the following: + +* `rgb_to_hsl` (same as [matplotlib.colors.rgb_to_hsv](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.rgb_to_hsv.html)) +* `hsl_to_rgb` (same as [matplotlib.colors.hsv_to_rgb](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.hsv_to_rgb.html)) +* `hcl_to_rgb` +* `rgb_to_hcl` +* `hsluv_to_rgb` +* `rgb_to_hsluv` +* `hpluv_to_rgb` +* `rgb_to_hpluv` + +Note +---- +This file is adapted from [seaborn](https://github.com/mwaskom/seaborn/blob/master/seaborn/external/husl.py) +and [hsluv-python](https://github.com/hsluv/hsluv-python/blob/master/hsluv.py). +For more information on colorspaces see the +[CIULUV specification](https://en.wikipedia.org/wiki/CIELUV), the +[CIE 1931 colorspace](https://en.wikipedia.org/wiki/CIE_1931_color_space), +the [HCL colorspace](https://en.wikipedia.org/wiki/HCL_color_space), +and the [HSLuv system](http://www.hsluv.org/implementations/). +""" +from _typeshed import Incomplete +import math +from colorsys import hls_to_rgb, rgb_to_hls +m = [[3.2406, -1.5372, -0.4986], [-0.9689, 1.8758, 0.0415], [0.0557, -0.204, 1.057]] +m_inv = [[0.4124, 0.3576, 0.1805], [0.2126, 0.7152, 0.0722], [0.0193, 0.1192, 0.9505]] +refX = 0.95047 +refY = 1.0 +refZ = 1.08883 +refU = 0.19784 +refV = 0.46834 +lab_e = 0.008856 +lab_k = 903.3 + +def hsluv_to_rgb(h: Incomplete, s: Incomplete, l: Incomplete) -> Incomplete: + ... + +def hsluv_to_hex(h: Incomplete, s: Incomplete, l: Incomplete) -> Incomplete: + ... + +def rgb_to_hsluv(r: Incomplete, g: Incomplete, b: Incomplete) -> Incomplete: + ... + +def hex_to_hsluv(color: Incomplete) -> Incomplete: + ... + +def hpluv_to_rgb(h: Incomplete, s: Incomplete, l: Incomplete) -> Incomplete: + ... + +def hpluv_to_hex(h: Incomplete, s: Incomplete, l: Incomplete) -> Incomplete: + ... + +def rgb_to_hpluv(r: Incomplete, g: Incomplete, b: Incomplete) -> Incomplete: + ... + +def hex_to_hpluv(color: Incomplete) -> Incomplete: + ... + +def lchuv_to_rgb(l: Incomplete, c: Incomplete, h: Incomplete) -> Incomplete: + ... + +def rgb_to_lchuv(r: Incomplete, g: Incomplete, b: Incomplete) -> Incomplete: + ... + +def hsl_to_rgb(h: Incomplete, s: Incomplete, l: Incomplete) -> tuple[float, float, float]: + ... + +def rgb_to_hsl(r: Incomplete, g: Incomplete, b: Incomplete) -> tuple[float, float, float]: + ... + +def hcl_to_rgb(h: Incomplete, c: Incomplete, l: Incomplete) -> Incomplete: + ... + +def rgb_to_hcl(r: Incomplete, g: Incomplete, b: Incomplete) -> Incomplete: + ... + +def rgb_prepare(triple: Incomplete) -> Incomplete: + ... + +def rgb_to_hex(triple: Incomplete) -> Incomplete: + ... + +def hex_to_rgb(color: Incomplete) -> list[float]: + ... + +def max_chroma(L: Incomplete, H: Incomplete) -> Incomplete: + ... + +def hrad_extremum(L: Incomplete) -> float | None: + ... + +def max_chroma_pastel(L: Incomplete) -> Incomplete: + ... + +def hsluv_to_lchuv(triple: Incomplete) -> Incomplete: + ... + +def lchuv_to_hsluv(triple: Incomplete) -> Incomplete: + ... + +def hpluv_to_lchuv(triple: Incomplete) -> Incomplete: + ... + +def lchuv_to_hpluv(triple: Incomplete) -> Incomplete: + ... + +def dot_product(a: Incomplete, b: Incomplete) -> int: + ... + +def from_linear(c: Incomplete) -> Incomplete: + ... + +def to_linear(c: Incomplete) -> Incomplete: + ... + +def CIExyz_to_rgb(triple: Incomplete) -> Incomplete: + ... + +def rgb_to_CIExyz(triple: Incomplete) -> list[int]: + ... + +def CIEluv_to_lchuv(triple: Incomplete) -> Incomplete: + ... + +def lchuv_to_CIEluv(triple: Incomplete) -> Incomplete: + ... +gamma = 3.0 + +def CIEfunc(t: Incomplete) -> Incomplete: + ... + +def CIEfunc_inverse(t: Incomplete) -> Incomplete: + ... + +def CIExyz_to_CIEluv(triple: Incomplete) -> Incomplete: + ... + +def CIEluv_to_CIExyz(triple: Incomplete) -> Incomplete: + ... diff --git a/ultraplot/figure.py b/ultraplot/figure.py index 89c830bc1..8d6ceebf0 100644 --- a/ultraplot/figure.py +++ b/ultraplot/figure.py @@ -7,6 +7,7 @@ import inspect import os from contextlib import ExitStack +from typing import Callable, TypeVar, cast try: from typing import Any, Iterable, List, Optional, Tuple, Union @@ -50,6 +51,8 @@ "Figure", ] +_F = TypeVar("_F", bound=Callable[..., Any]) + def _any_not_none(*values): """Return whether at least one value is not ``None``.""" @@ -695,7 +698,7 @@ def _draw_context(): return canvas -def _clear_border_cache(func): +def _clear_border_cache(func: _F) -> _F: """ Decorator that clears the border cache after function execution. """ @@ -707,7 +710,7 @@ def wrapper(self, *args, **kwargs): delattr(self, "_cached_border_axes") return result - return wrapper + return cast(_F, wrapper) class Figure(mfigure.Figure): @@ -3387,28 +3390,28 @@ def add_axes(self, rect, **kwargs): @docstring._concatenate_inherited @docstring._snippet_manager - def add_subplot(self, *args, **kwargs): + def add_subplot(self, *args, **kwargs) -> paxes.Axes: """ %(figure.subplot)s """ return self._add_subplot(*args, **kwargs) @docstring._snippet_manager - def subplot(self, *args, **kwargs): # shorthand + def subplot(self, *args, **kwargs) -> paxes.Axes: # shorthand """ %(figure.subplot)s """ return self._add_subplot(*args, **kwargs) @docstring._snippet_manager - def add_subplots(self, *args, **kwargs): + def add_subplots(self, *args, **kwargs) -> pgridspec.SubplotGrid: """ %(figure.subplots)s """ return self._add_subplots(*args, **kwargs) @docstring._snippet_manager - def subplots(self, *args, **kwargs): + def subplots(self, *args, **kwargs) -> pgridspec.SubplotGrid: """ %(figure.subplots)s """ diff --git a/ultraplot/figure.pyi b/ultraplot/figure.pyi new file mode 100644 index 000000000..ab8fc62cc --- /dev/null +++ b/ultraplot/figure.pyi @@ -0,0 +1,1119 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The figure class used for all ultraplot figures. +""" +from _typeshed import Incomplete +import functools +import inspect +import os +from contextlib import ExitStack +from typing import Callable, TypeVar, cast +try: + from typing import Any, Iterable, List, Optional, Tuple, Union +except ImportError: + from typing_extensions import Any, Iterable, List, Optional, Tuple, Union +import matplotlib.axes as maxes +import matplotlib.figure as mfigure +import matplotlib.text as mtext +import matplotlib.transforms as mtransforms +import numpy as np +try: + from typing import override +except: + from typing_extensions import override +from . import axes as paxes +from .axes._formatting import axis_format_requires_layout, pop_axis_format_kwargs +from . import constructor +from . import gridspec as pgridspec +from . import legend as plegend +from .config import rc, rc_matplotlib +from .internals import _alias_kwargs, _not_none, _pop_params, _pop_rc, _translate_loc, context, docstring, ic, labels, warnings +from ._layout import _LayoutTransaction +from ._subplots import SubplotManager +from .utils import _Crawler, units +__all__ = ['Figure'] +_F = TypeVar('_F', bound=Callable[..., Any]) + +def _any_not_none(*values: Incomplete) -> Incomplete: + """Return whether at least one value is not ``None``.""" + ... +JOURNAL_SIZES = {'aaas1': '5.5cm', 'aaas2': '12cm', 'agu1': ('95mm', '115mm'), 'agu2': ('190mm', '115mm'), 'agu3': ('95mm', '230mm'), 'agu4': ('190mm', '230mm'), 'ams1': 3.2, 'ams2': 4.5, 'ams3': 5.5, 'ams4': 6.5, 'cop1': '8.3cm', 'cop2': '12cm', 'nat1': '89mm', 'nat2': '183mm', 'pnas1': '8.7cm', 'pnas2': '11.4cm', 'pnas3': '17.8cm'} +_figure_docstring = ... +_subplots_params_docstring = ... +_axes_params_docstring = ... +_subplots_docstring = ... +_subplot_docstring = ... +_axes_docstring = ... +_space_docstring = ... +_figure_semantic_legend_common_docstring = ... +_figure_entrylegend_docstring = ... +_figure_catlegend_docstring = ... +_figure_sizelegend_docstring = ... +_figure_numlegend_docstring = ... +_figure_geolegend_docstring = ... +_save_docstring = ... + +def _get_journal_size(preset: Incomplete) -> Incomplete: + """Return the width and height corresponding to the given preset.""" + ... + +def _add_canvas_preprocessor(canvas: Incomplete, method: Incomplete, cache: Incomplete=False) -> Incomplete: + """Return a pre-processer that can be used to override instance-level +canvas draw() and print_figure() methods. This applies tight layout +and aspect ratio-conserving adjustments and aligns labels. Required +so canvas methods instantiate renderers with the correct dimensions.""" + ... + +def _clear_border_cache(func: _F) -> _F: + """Decorator that clears the border cache after function execution.""" + ... + +class Figure(mfigure.Figure): + """The [Figure](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.html) subclass used by ultraplot.""" + _share_message = "Axis sharing level can be 0 or False (share nothing), 1 or 'labels' or 'labs' (share axis labels), 2 or 'limits' or 'lims' (share axis limits and axis labels), 3 or True (share axis limits, axis labels, and tick labels), 4 or 'all' (share axis labels and tick labels in the same gridspec rows and columns and share axis limits across all subplots), or 'auto' (start unshared and share only compatible axes)." + _space_message = 'To set the left, right, bottom, top, wspace, or hspace gridspec values, pass them as keyword arguments to uplt.figure() or uplt.subplots(). Please note they are now specified in physical units, with strings interpreted by uplt.units() and floats interpreted as font size-widths.' + _tight_message = "ultraplot uses its own tight layout algorithm that is activated by default. To disable it, set uplt.rc['subplots.tight'] to False or pass tight=False to uplt.subplots(). For details, see fig.auto_layout()." + _warn_interactive = True + + def __repr__(self) -> str: + """Return repr(self).""" + ... + + def __init__(self, *, refnum: Incomplete=None, refaspect: Incomplete=None, refwidth: Incomplete=None, refheight: Incomplete=None, figwidth: Incomplete=None, figheight: Incomplete=None, journal: Incomplete=None, sharex: Incomplete=None, sharey: Incomplete=None, share: Incomplete=None, spanx: Incomplete=None, spany: Incomplete=None, span: Incomplete=None, alignx: Incomplete=None, aligny: Incomplete=None, align: Incomplete=None, left: Incomplete=None, right: Incomplete=None, top: Incomplete=None, bottom: Incomplete=None, wspace: Incomplete=None, hspace: Incomplete=None, space: Incomplete=None, tight: Incomplete=None, outerpad: Incomplete=None, innerpad: Incomplete=None, panelpad: Incomplete=None, wpad: Incomplete=None, hpad: Incomplete=None, pad: Incomplete=None, wequal: Incomplete=None, hequal: Incomplete=None, equal: Incomplete=None, wgroup: Incomplete=None, hgroup: Incomplete=None, group: Incomplete=None, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `refnum`: The reference subplot number. +- `refaspect`: The reference subplot aspect ratio. +- `refwidth, refheight`: The width, height of the reference subplot. +- `figwidth, figheight`: The figure width and height. +- `figsize`: Tuple specifying the figure ``(width, height)``. +- `sharex, sharey, share`: The axis sharing "level" for the *x* axis, *y* axis, or both axes. +- `spanx, spany, span`: Whether to use "spanning" axis labels for the *x* axis, *y* axis, or both axes. +- `alignx, aligny, align`: Whether to ["align" axis labels](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/align_labels_demo.html) for the *x* axis, *y* axis, or both axes. +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, or both. +- `tight`: Whether automatic calls to `~Figure.auto_layout` should include [tight layout adjustments](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight). +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. +- `journal`: String corresponding to an academic journal standard used to control the figure width `figwidth` and, if specified, the figure height `figheight`. +- `leftlabels, toplabels, rightlabels, bottomlabels`: Labels for the subplots lying along the left, top, right, and bottom edges of the figure. +- `leftlabelpad, toplabelpad, rightlabelpad, bottomlabelpad`: : [leftlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.pad), [toplabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.pad), [rightlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.pad), [bottomlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.pad) The padding between the labels and the axes content. +- `leftlabelsharedpad, toplabelsharedpad, rightlabelsharedpad, bottomlabelsharedpad`: : [leftlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.sharedpad), [toplabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.sharedpad), [rightlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.sharedpad), [bottomlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.sharedpad) The padding between side labels and a shared spanning axis label on… +- `leftlabels_kw, toplabels_kw, rightlabels_kw, bottomlabels_kw`: Additional settings used to update the labels with ``text.update()``. +- `figtitle`: Alias for `suptitle`. +- `suptitle`: The figure "super" title, centered between the left edge of the leftmost subplot and the right edge of the rightmost subplot. +- `suptitlepad`: The padding between the super title and the axes content. +- `suptitle_kw`: Additional settings used to update the super title with ``text.update()``. +- `includepanels`: Whether to include panels when aligning figure "super titles" along the top of the subplot grid and when aligning the `spanx` *x* axis labels and `spany` *y* axis labels along the… +- `**kwargs`: Passed to [matplotlib.figure.Figure](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html)""" + ... + + def _init_figure_size(self, refnum: Incomplete, refaspect: Incomplete, refwidth: Incomplete, refheight: Incomplete, figwidth: Incomplete, figheight: Incomplete, journal: Incomplete) -> Incomplete: + """Resolve figure sizing from reference dimensions, journal presets, +and explicit figure dimensions. Sets sizing attributes on self and +returns the resolved (figwidth, figheight).""" + ... + + def _init_gridspec_params(self, **params: Incomplete) -> None: + """Validate and store gridspec spacing parameters.""" + ... + + def _init_tight_layout(self, tight: Incomplete, kwargs: Incomplete) -> None: + """Configure tight layout, suppressing native matplotlib layout engines.""" + ... + + @staticmethod + def _normalize_share(value: Incomplete) -> Incomplete: + """Normalize a share setting to an integer level and auto flag.""" + ... + + def _init_sharing(self, *, sharex: Incomplete, sharey: Incomplete, share: Incomplete, spanx: Incomplete, spany: Incomplete, span: Incomplete, alignx: Incomplete, aligny: Incomplete, align: Incomplete) -> None: + """Resolve share, span, and align settings.""" + ... + + def _init_figure_state(self, figwidth: Incomplete, figheight: Incomplete, kwargs: Incomplete) -> None: + """Initialize internal state, call matplotlib's Figure.__init__, +set up super labels, and apply initial formatting.""" + ... + + def _init_super_labels(self) -> None: + """Create the figure-level label artists and their style state. + +NOTE: Also called by `clear`, which discards every artist on the figure and +sets ``_suptitle`` to None. The labels must be rebuilt there or the next +``format(suptitle=...)`` raises on the missing artist.""" + ... + + def _invalidate_layout(self, *, reset: Incomplete=False) -> None: + """Mark automatic layout stale, optionally discarding persistent state.""" + ... + + def clear(self, keep_observers: Incomplete=False) -> None: + """Clear the figure, discarding all subplots, panels, and figure-level labels. + +Parameters +---------- +keep_observers : bool, default: False + Whether to retain the figure's observers, e.g. a GUI widget tracking + the axes. + +See also +-------- +matplotlib.figure.Figure.clear""" + ... + + @override + def draw(self, renderer: Incomplete) -> Incomplete: + """Draw the Artist (and its children) using the given renderer. + +This has no effect if the artist is not visible (`.Artist.get_visible` +returns False). + +Parameters +---------- +renderer : [RendererBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.RendererBase.html) subclass. + +Notes +----- +This method is overridden in the Artist subclasses.""" + ... + + @override + def draw_without_rendering(self) -> Incomplete: + """Draw without output while preserving figure dpi state.""" + ... + + def _blit_manager(self, *artists: Incomplete, bbox: Incomplete=None) -> Incomplete: + """Return a manager for efficient updates of changing artists. + +Parameters +---------- +*artists : [Artist](https://matplotlib.org/stable/api/_as_gen/matplotlib.artist.Artist.html) + Artists that will change between updates. +bbox : [Bbox](https://matplotlib.org/stable/api/_as_gen/matplotlib.transforms.Bbox.html) or object with a ``bbox`` attribute, optional + Region to cache and blit. By default, the union of the artists' + axes bounding boxes is used. + +Returns +------- +[_BlitManager](https://ultraplot.readthedocs.io/en/stable/api/ultraplot._animation._BlitManager.html) + Manager that restores the cached static background and redraws only + the supplied artists.""" + ... + + def _is_auto_share_mode(self, which: str) -> bool: + """Return whether a given axis uses auto-share mode.""" + ... + + def _axis_unit_signature(self, ax: Incomplete, which: str) -> tuple[str | None, bytes | str | None] | None: + """Return a lightweight signature for axis unit/converter compatibility.""" + ... + + def _share_axes_compatible(self, ref: Incomplete, other: Incomplete, which: str) -> Incomplete: + """Check whether two axes are compatible for sharing along one axis.""" + ... + + def _warn_incompatible_share(self, which: str, ref: Incomplete, other: Incomplete, reason: str) -> None: + """Warn once per figure for explicit incompatible sharing.""" + ... + + def _partition_share_axes(self, axes: Incomplete, which: str) -> Incomplete: + """Partition a candidate share list into compatible sub-groups.""" + ... + + def _iter_shared_groups(self, which: str, *, panels: bool=True) -> Incomplete: + """Yield unique shared groups for one axis direction.""" + ... + + def _join_shared_group(self, which: str, ref: Incomplete, other: Incomplete) -> None: + """Join an axis to a shared group and copy the shared axis state.""" + ... + + def _refresh_auto_share(self, which: Optional[str]=None) -> None: + """Recompute auto-sharing groups after local axis-state changes.""" + ... + + def _autoscale_shared_limits(self, which: str) -> None: + """Recompute shared data limits for each compatible shared-axis group.""" + ... + + def _snap_axes_to_pixel_grid(self, renderer: Incomplete) -> None: + """Snap visible axes bounds to the renderer pixel grid.""" + ... + + def _find_misaligned_spans(self, axes: List[paxes.Axes], *, tol: float=1e-09) -> List[Tuple[str, int, int, mtransforms.Bbox, mtransforms.Bbox, paxes.Axes]]: + """Identify spanning axes whose actual position differs from their +gridspec slot (e.g. because of an aspect constraint). + +Returns a list of ``(axis, start, stop, slot, pos, ref_ax)`` tuples +where *axis* is ``'y'`` for row-spanning or ``'x'`` for column-spanning.""" + ... + + def _remap_axes_to_span(self, axes: List[paxes.Axes], spans: List[Tuple[str, int, int, mtransforms.Bbox, mtransforms.Bbox, paxes.Axes]], *, tol: float=1e-09) -> None: + """Remap sibling axes so they align with the actual bounds of +spanning axes described by *spans*. Siblings with their own +fixed aspect are skipped since they have independent constraints.""" + ... + + def _align_spanning_axes(self, *, tol: float=1e-09) -> None: + """Align sibling subplots to spanning axes whose actual position +differs from their gridspec slot. + +When a subplot spans multiple rows or columns and is shrunk inside +its slot (e.g. by a fixed aspect ratio), the adjacent subplots keep +their full extent and visibly stick out. This method detects the +mismatch and remaps the sibling positions proportionally.""" + ... + + def _share_ticklabels(self, *, axis: str) -> None: + """Tick label sharing is determined at the figure level. While +each subplot controls the limits, we are dealing with the ticklabels +here as the complexity is easier to deal with. + axis: str 'x' or 'y', row or columns to update""" + ... + + def _label_key_map(self) -> Incomplete: + """Return a mapping for version-dependent label keys for Matplotlib tick params.""" + ... + + def _group_axes_by_axis(self, axes: Incomplete, axis: str) -> Incomplete: + """Group axes by row (x) or column (y). Panels included; invalid subplotspec skipped.""" + ... + + def _compute_baseline_tick_state(self, group_axes: Incomplete, axis: str, label_keys: Incomplete) -> Incomplete: + """Build a baseline ticklabel visibility dict from MAIN axes (panels excluded). +Returns (baseline_dict, skip_group: bool). Emits warnings when encountering +unsupported or mixed subplot types.""" + ... + + def _apply_border_mask(self, axi: Incomplete, baseline: dict, sides: tuple[str, str], outer_axes: Incomplete) -> Incomplete: + """Apply figure-border constraints and panel opposite-side suppression. +Keeps label key mapping per-axis for cartesian.""" + ... + + def _effective_share_level(self, axi: Incomplete, axis: str, sides: tuple[str, str]) -> int: + """Compute the effective share level for an axes, considering panel groups and +adjacent panels. Fixes the original variable leak by checking any relevant side.""" + ... + + def _set_ticklabel_state(self, axi: Incomplete, axis: str, state: dict) -> None: + """Apply the computed ticklabel state to cartesian or geo axes.""" + ... + + def _context_adjusting(self, cache: Incomplete=True) -> Incomplete: + """Prevent re-running auto layout steps due to draws triggered by figure +resizes. Otherwise can get infinite loops.""" + ... + + def _context_authorized(self) -> Incomplete: + """Prevent warning message when internally calling no-op methods. Otherwise +emit warnings to help new users.""" + ... + + @staticmethod + def _parse_backend(backend: Incomplete=None, basemap: Incomplete=None) -> Incomplete: + """Delegate to SubplotManager.""" + ... + + def _parse_proj(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate to SubplotManager.""" + ... + + def _get_align_axes(self, side: Incomplete) -> Incomplete: + """Return the main axes along the edge of the figure. + +For 'left'/'right': select one extreme axis per row (leftmost/rightmost). +For 'top'/'bottom': select one extreme axis per column (topmost/bottommost).""" + ... + + def _get_border_axes(self, *, same_type: Incomplete=False, force_recalculate: Incomplete=False) -> dict[str, list[paxes.Axes]]: + """Identifies axes located on the outer boundaries of the GridSpec layout. + +Returns a dictionary with keys 'top', 'bottom', 'left', 'right', each +containing a list of axes on that border.""" + ... + + def _get_align_coord(self, side: Incomplete, axs: Incomplete, align: Incomplete='center', includepanels: Incomplete=False) -> Incomplete: + """Return the figure coordinate for positioning spanning axis labels or super titles. + +Parameters +---------- +side : str + Side of the figure ('top', 'bottom', 'left', 'right'). +axs : list + List of axes to align across. +align : str, default 'center' + Horizontal alignment for x-axis positioning: 'left', 'center', or 'right'. + For y-axis positioning, always centers regardless of this parameter. +includepanels : bool, default False + Whether to include panel axes in the alignment calculation.""" + ... + + def _get_offset_coord(self, side: Incomplete, axs: Incomplete, renderer: Incomplete, *, pad: Incomplete=None, extra: Incomplete=None, include_subset_titles: Incomplete=True, exclude_spanning_axis_labels: Incomplete=False) -> Incomplete: + """Return the figure coordinate for offsetting super labels and super titles.""" + ... + + def _get_layout_axes_bbox(self, axes: Incomplete, renderer: Incomplete, *, include_subset_titles: Incomplete=True, use_cache: Incomplete=True) -> Incomplete: + """Return an axes bbox using the active relative-outset store.""" + ... + + def _get_layout_tightbbox(self, renderer: Incomplete) -> Incomplete: + """Return the figure tight bbox while reusing relative axes outsets. + +This mirrors matplotlib's ``Figure.get_tightbbox`` but routes axes +measurements through the active relative-outset store.""" + ... + + def _get_renderer(self) -> Incomplete: + """Get a renderer at all costs. See matplotlib's tight_layout.py.""" + ... + + def _add_axes_panel(self, ax: 'paxes.Axes', side: Optional[str]=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, **kwargs: Incomplete) -> 'paxes.Axes': + """Add an axes panel.""" + ... + + def _add_figure_panel(self, side: Optional[str]=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, **kwargs: Incomplete) -> 'paxes.Axes': + """Add a figure panel.""" + ... + + def _add_subplot(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate to SubplotManager.""" + ... + + def _unshare_axes(self) -> None: + ... + + def _toggle_axis_sharing(self, *, which: Incomplete='y', share: Incomplete=True, panels: Incomplete=False, children: Incomplete=False, hidden: Incomplete=False) -> None: + """Share or unshare axes in the figure along a given direction. + +Parameters: +- which: 'x', 'y', 'z', or 'view'. +- share: int indicating the levels (see above) +- panels: Whether to include panel axes. +- children: Whether to include child axes. +- hidden: Whether to include hidden axes.""" + ... + + def _add_subplots(self, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Delegate to SubplotManager.""" + ... + + def _align_axis_label(self, x: Incomplete) -> None: + """Align *x* and *y* axis labels in the perpendicular and parallel directions.""" + ... + + def _register_share_label_group(self, axes: Incomplete, *, target: Incomplete, source: Incomplete=None) -> None: + """Register an explicit label-sharing group for a subset of axes.""" + ... + + def _register_share_label_group_for_side(self, axes: Incomplete, *, target: Incomplete, side: Incomplete, source: Incomplete=None) -> None: + """Register a single label-sharing group for a given label side.""" + ... + + def _is_share_label_group_member(self, ax: Incomplete, axis: Incomplete) -> bool: + """Return True if the axes belongs to any explicit label-sharing group.""" + ... + + def _has_share_label_groups(self, axis: Incomplete) -> bool: + """Return True if there are any explicit label-sharing groups for an axis.""" + ... + + def _clear_share_label_groups(self, axes: Incomplete=None, *, target: Incomplete=None) -> None: + """Clear explicit label-sharing groups, optionally filtered by axes.""" + ... + + def _apply_share_label_groups(self, axis: Incomplete=None) -> None: + """Apply explicit label-sharing groups, overriding default label sharing.""" + ... + + def _align_super_labels(self, side: Incomplete, renderer: Incomplete) -> None: + """Adjust the position of super labels.""" + ... + + def _align_spanning_axis_labels(self, side: Incomplete, renderer: Incomplete, side_labels: Incomplete) -> None: + """Place spanning axis labels outside figure-level labels on the same side. + +Figure-level side labels describe individual rows or columns, while a +spanning axis label describes the whole group. The latter therefore has +lower visual priority and belongs farther from the axes.""" + ... + + def _align_super_title(self, renderer: Incomplete) -> None: + """Adjust the position of the super title based on user alignment preferences. + +Respects horizontal and vertical alignment settings from suptitle_kw parameters, +while applying sensible defaults when no custom alignment is provided.""" + ... + + @staticmethod + def _deduplicate_axes(axes: Iterable[paxes.Axes]) -> List[paxes.Axes]: + """Resolve panel parents and remove duplicates, preserving order.""" + ... + + @staticmethod + def _normalize_title_alignment(loc: str) -> str: + """Convert a *loc* string to a horizontal alignment for ``Text.set_ha``.""" + ... + + @staticmethod + def _resolve_title_props(fontdict: dict[str, Any] | None, kwargs: dict[str, Any]) -> dict[str, Any]: + """Build the property dict for a title from rc defaults, *fontdict*, +and extra *kwargs*.""" + ... + + def _update_subset_title(self, axes: Iterable[paxes.Axes], title: str | None, *, fontdict: dict[str, Any] | None=None, loc: str | None=None, pad: float | str | None=None, y: float | None=None, **kwargs: Any) -> mtext.Text: + """Create or update a title spanning a subset of subplots.""" + ... + + def _visible_subset_group_axes(self, group: dict[str, Any]) -> List[paxes.Axes]: + """Return visible axes from a subset-title group that belong to this figure.""" + ... + + def _get_subset_title_bbox(self, ax: paxes.Axes, renderer: Incomplete) -> mtransforms.Bbox | None: + """Return the union bbox for shared titles covering the given axes. + +Shared subset titles live above the subset's top edge, so they should +only contribute to the tight bounding boxes for axes that actually touch +that top boundary. Otherwise, multi-row subsets can incorrectly claim +the title as extra inter-row spacing.""" + ... + + def _align_subset_titles(self, renderer: Any) -> None: + """Update the positions of titles spanning subplot subsets.""" + ... + + def _update_axis_label(self, side: Incomplete, axs: Incomplete) -> None: + """Update the aligned axis label for the input axes.""" + ... + + def _update_super_labels(self, side: Incomplete, labels: Incomplete, **kwargs: Incomplete) -> None: + """Assign the figure super labels and update settings.""" + ... + + def _update_super_title(self, title: Incomplete, **kwargs: Incomplete) -> None: + """Assign the figure super title and update settings.""" + ... + + @staticmethod + def _iter_semantic_legend_axes(candidate: Incomplete) -> Incomplete: + """Yield axes objects from nested axis containers.""" + ... + + def _semantic_legend_axes(self, ax: Incomplete=None, ref: Incomplete=None) -> Incomplete: + """Pick an axes instance for semantic legend handle generation.""" + ... + + def entrylegend(self, entries: Incomplete, *, line: Incomplete=None, marker: Incomplete=None, color: Incomplete=None, linestyle: Incomplete=None, linewidth: Incomplete=None, markersize: Incomplete=None, alpha: Incomplete=None, markeredgecolor: Incomplete=None, markeredgewidth: Incomplete=None, markerfacecolor: Incomplete=None, handle_kw: Incomplete=None, add: Incomplete=True, **legend_kwargs: Incomplete) -> Incomplete: + """Build generic semantic legend entries and optionally add a figure legend. + +Parameters +---------- +entries + Entry specifications as handles, style dictionaries, or ``(label, spec)`` + pairs. + +Other parameters +---------------- +**legend_kwargs + Placement and legend styling keywords forwarded to + [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend) when ``add=True``. This includes figure legend + placement keywords like ``loc=``, ``ref=``, ``ax=``, ``rows=``, ``cols=``, and + ``span=``. Pass ``add=False`` to return ``(handles, labels)`` without drawing. + +Notes +----- +Handle generation currently reuses the semantic legend builder used by +[entrylegend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.entrylegend), then routes the final draw step through +[legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend).""" + ... + + def catlegend(self, categories: Incomplete, *, colors: Incomplete=None, markers: Incomplete=None, line: Incomplete=None, linestyle: Incomplete=None, linewidth: Incomplete=None, markersize: Incomplete=None, alpha: Incomplete=None, markeredgecolor: Incomplete=None, markeredgewidth: Incomplete=None, markerfacecolor: Incomplete=None, handle_kw: Incomplete=None, add: Incomplete=True, **legend_kwargs: Incomplete) -> Incomplete: + """Build categorical legend entries and optionally add a figure legend. + +Parameters +---------- +categories + Category labels used to generate legend handles. + +Other parameters +---------------- +**legend_kwargs + Placement and legend styling keywords forwarded to + [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend) when ``add=True``. This includes figure legend + placement keywords like ``loc=``, ``ref=``, ``ax=``, ``rows=``, ``cols=``, and + ``span=``. Pass ``add=False`` to return ``(handles, labels)`` without drawing. + +Notes +----- +Handle generation currently reuses the semantic legend builder used by +[catlegend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.catlegend), then routes the final draw step through +[legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend).""" + ... + + def sizelegend(self, levels: Incomplete, *, labels: Incomplete=None, color: Incomplete=None, marker: Incomplete=None, area: Incomplete=None, values: Incomplete=None, vmin: Incomplete=None, vmax: Incomplete=None, smin: Incomplete=None, smax: Incomplete=None, area_size: Incomplete=None, absolute_size: Incomplete=None, scale: Incomplete=None, minsize: Incomplete=None, fmt: Incomplete=None, alpha: Incomplete=None, markeredgecolor: Incomplete=None, markeredgewidth: Incomplete=None, markerfacecolor: Incomplete=None, handle_kw: Incomplete=None, add: Incomplete=True, **legend_kwargs: Incomplete) -> Incomplete: + """Build size legend entries and optionally add a figure legend. + +Parameters +---------- +levels + Numeric levels used to generate marker-size entries. +values, vmin, vmax, smin, smax, area_size, absolute_size + Optional scatter-style size scaling controls forwarded to + [sizelegend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.sizelegend). When omitted, a compatible UltraPlot + scatter artist can be used to infer the size scale automatically. + +Other parameters +---------------- +**legend_kwargs + Placement and legend styling keywords forwarded to + [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend) when ``add=True``. This includes figure legend + placement keywords like ``loc=``, ``ref=``, ``ax=``, ``rows=``, ``cols=``, and + ``span=``. Pass ``add=False`` to return ``(handles, labels)`` without drawing. + +Notes +----- +Handle generation currently reuses the semantic legend builder used by +[sizelegend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.sizelegend), then routes the final draw step through +[legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend). + +Pass ``labels=[...]`` or ``labels={level: label}`` to override the generated labels.""" + ... + + def numlegend(self, levels: Incomplete=None, *, vmin: Incomplete=None, vmax: Incomplete=None, n: Incomplete=None, cmap: Incomplete=None, norm: Incomplete=None, fmt: Incomplete=None, facecolor: Incomplete=None, edgecolor: Incomplete=None, linewidth: Incomplete=None, linestyle: Incomplete=None, alpha: Incomplete=None, handle_kw: Incomplete=None, add: Incomplete=True, **legend_kwargs: Incomplete) -> Incomplete: + """Build numeric-color legend entries and optionally add a figure legend. + +Parameters +---------- +levels + Numeric levels or number of levels. + +Other parameters +---------------- +**legend_kwargs + Placement and legend styling keywords forwarded to + [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend) when ``add=True``. This includes figure legend + placement keywords like ``loc=``, ``ref=``, ``ax=``, ``rows=``, ``cols=``, and + ``span=``. Pass ``add=False`` to return ``(handles, labels)`` without drawing. + +Notes +----- +Handle generation currently reuses the semantic legend builder used by +[numlegend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.numlegend), then routes the final draw step through +[legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend).""" + ... + + def geolegend(self, entries: Incomplete, labels: Incomplete=None, *, country_reso: Incomplete=None, country_territories: Incomplete=None, country_proj: Incomplete=None, handlesize: Incomplete=None, facecolor: Incomplete=None, edgecolor: Incomplete=None, linewidth: Incomplete=None, alpha: Incomplete=None, fill: Incomplete=None, add: Incomplete=True, **legend_kwargs: Incomplete) -> Incomplete: + """Build geometry legend entries and optionally add a figure legend. + +Parameters +---------- +entries + Geometry entries (mapping, ``(label, geometry)`` pairs, or geometries). +labels + Optional labels for geometry sequences. + +Other parameters +---------------- +**legend_kwargs + Placement and legend styling keywords forwarded to + [legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend) when ``add=True``. This includes figure legend + placement keywords like ``loc=``, ``ref=``, ``ax=``, ``rows=``, ``cols=``, and + ``span=``. Pass ``add=False`` to return ``(handles, labels)`` without drawing. + +Notes +----- +Handle generation currently reuses the semantic legend builder used by +[geolegend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.geolegend), then routes the final draw step through +[legend](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend).""" + ... + + def add_axes(self, rect: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Add a non-subplot axes to the figure. + +Parameters +---------- +- `rect`: The (left, bottom, width, height) dimensions of the axes in figure-relative coordinates. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `**kwargs`: Passed to the ultraplot class [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html), [ultraplot.axes.PolarAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html), [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html), or [ultraplot.axes.ThreeAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.ThreeAxes.html). +- `projection`: The projection type of the `~.axes.Axes`. +- `polar`: If True, equivalent to projection='polar'. +- `axes_class`: The `.axes.Axes` subclass that is instantiated. +- `sharex, sharey`: Share the x or y [axis](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.html) with sharex and/or sharey. +- `label`: A label for the returned Axes. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_axes)""" + ... + + def add_subplot(self, *args: Incomplete, **kwargs: Incomplete) -> paxes.Axes: + """Add a subplot axes to the figure. + +Parameters +---------- +- `*args`: The subplot location specifier. +- `number`: The axes number used for a-b-c labeling. +- `autoshare`: Whether to automatically share the *x* and *y* axes with subplots spanning the same rows and columns based on the figure-wide `sharex` and `sharey` settings. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `**kwargs`: Passed to the ultraplot class [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html), [ultraplot.axes.PolarAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html), [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html), or [ultraplot.axes.ThreeAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.ThreeAxes.html). +- `projection`: The projection type of the subplot (`~.axes.Axes`). +- `polar`: If True, equivalent to projection='polar'. +- `axes_class`: The `.axes.Axes` subclass that is instantiated. +- `sharex, sharey`: Share the x or y [axis](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.html) with sharex and/or sharey. +- `label`: A label for the returned Axes. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_subplot)""" + ... + + def subplot(self, *args: Incomplete, **kwargs: Incomplete) -> paxes.Axes: + """Add a subplot axes to the figure. + +Parameters +---------- +- `*args`: The subplot location specifier. +- `number`: The axes number used for a-b-c labeling. +- `autoshare`: Whether to automatically share the *x* and *y* axes with subplots spanning the same rows and columns based on the figure-wide `sharex` and `sharey` settings. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `**kwargs`: Passed to the ultraplot class [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html), [ultraplot.axes.PolarAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html), [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html), or [ultraplot.axes.ThreeAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.ThreeAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplot)""" + ... + + def add_subplots(self, *args: Incomplete, **kwargs: Incomplete) -> pgridspec.SubplotGrid: + """Add an arbitrary grid of subplots to the figure. + +Parameters +---------- +- `array`: The subplot grid specifier. +- `nrows, ncols`: The number of rows and columns in the subplot grid. +- `order`: Whether subplots are numbered in column-major (``'C'``) or row-major (``'F'``) order. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, and both, respectively. +- `wratios, hratios`: Passed to [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html), denotes the width and height ratios for the subplot grid. +- `wpad, hpad, pad`: The tight layout padding between columns, rows, and both, respectively. +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. +- `refnum`: The reference subplot number. +- `refaspect`: The reference subplot aspect ratio. +- `refwidth, refheight`: The width, height of the reference subplot. +- `figwidth, figheight`: The figure width and height. +- `figsize`: Tuple specifying the figure ``(width, height)``. +- `sharex, sharey, share`: The axis sharing "level" for the *x* axis, *y* axis, or both axes. +- `spanx, spany, span`: Whether to use "spanning" axis labels for the *x* axis, *y* axis, or both axes. +- `alignx, aligny, align`: Whether to ["align" axis labels](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/align_labels_demo.html) for the *x* axis, *y* axis, or both axes. +- `tight`: Whether automatic calls to `~Figure.auto_layout` should include [tight layout adjustments](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight). +- `journal`: String corresponding to an academic journal standard used to control the figure width `figwidth` and, if specified, the figure height `figheight`. +- `**kwargs`: Passed to the ultraplot class [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html), [ultraplot.axes.PolarAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html), [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html), or [ultraplot.axes.ThreeAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.ThreeAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.add_subplots)""" + ... + + def subplots(self, *args: Incomplete, **kwargs: Incomplete) -> pgridspec.SubplotGrid: + """Add an arbitrary grid of subplots to the figure. + +Parameters +---------- +- `array`: The subplot grid specifier. +- `nrows, ncols`: The number of rows and columns in the subplot grid. +- `order`: Whether subplots are numbered in column-major (``'C'``) or row-major (``'F'``) order. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, and both, respectively. +- `wratios, hratios`: Passed to [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html), denotes the width and height ratios for the subplot grid. +- `wpad, hpad, pad`: The tight layout padding between columns, rows, and both, respectively. +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. +- `refnum`: The reference subplot number. +- `refaspect`: The reference subplot aspect ratio. +- `refwidth, refheight`: The width, height of the reference subplot. +- `figwidth, figheight`: The figure width and height. +- `figsize`: Tuple specifying the figure ``(width, height)``. +- `sharex, sharey, share`: The axis sharing "level" for the *x* axis, *y* axis, or both axes. +- `spanx, spany, span`: Whether to use "spanning" axis labels for the *x* axis, *y* axis, or both axes. +- `alignx, aligny, align`: Whether to ["align" axis labels](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/align_labels_demo.html) for the *x* axis, *y* axis, or both axes. +- `tight`: Whether automatic calls to `~Figure.auto_layout` should include [tight layout adjustments](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight). +- `journal`: String corresponding to an academic journal standard used to control the figure width `figwidth` and, if specified, the figure height `figheight`. +- `**kwargs`: Passed to the ultraplot class [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html), [ultraplot.axes.PolarAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PolarAxes.html), [ultraplot.axes.GeoAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.GeoAxes.html), or [ultraplot.axes.ThreeAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.ThreeAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots)""" + ... + + def auto_layout(self, renderer: Incomplete=None, aspect: Incomplete=None, tight: Incomplete=None, resize: Incomplete=None) -> None: + """Automatically adjust the figure size and subplot positions. This is +triggered automatically whenever the figure is drawn. + +Parameters +---------- +renderer : [RendererBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.RendererBase.html), optional + The renderer. If ``None`` a default renderer will be produced. +aspect : bool, optional + Whether to update the figure size based on the reference subplot aspect + ratio. By default, this is ``True``. This only has an effect if the + aspect ratio is fixed (e.g., due to an image plot or geographic projection). +tight : bool, optional + Whether to update the figuer size and subplot positions according to + a "tight layout". By default, this takes on the value of `tight` passed + to `Figure`. If nothing was passed, it is [subplots.tight](https://ultraplot.readthedocs.io/en/stable/search.html?q=subplots.tight). +resize : bool, optional + If ``False``, the current figure dimensions are fixed and automatic + figure resizing is disabled. By default, the figure size may change + unless both `figwidth` and `figheight` or `figsize` were passed + to `~Figure.subplots`, `~Figure.set_size_inches` was called manually, + or the figure was resized manually with an interactive backend.""" + ... + + def format(self, axs: Incomplete=None, *, figtitle: Incomplete=None, suptitle: Incomplete=None, suptitle_kw: Incomplete=None, llabels: Incomplete=None, leftlabels: Incomplete=None, leftlabels_kw: Incomplete=None, rlabels: Incomplete=None, rightlabels: Incomplete=None, rightlabels_kw: Incomplete=None, blabels: Incomplete=None, bottomlabels: Incomplete=None, bottomlabels_kw: Incomplete=None, tlabels: Incomplete=None, toplabels: Incomplete=None, toplabels_kw: Incomplete=None, rowlabels: Incomplete=None, collabels: Incomplete=None, includepanels: Incomplete=None, **kwargs: Incomplete) -> None: + """Modify figure-wide labels and call ``format`` for the input axes. + +Parameters +---------- +- `axs`: The axes to format. +- `leftlabels, toplabels, rightlabels, bottomlabels`: Labels for the subplots lying along the left, top, right, and bottom edges of the figure. +- `leftlabelpad, toplabelpad, rightlabelpad, bottomlabelpad`: : [leftlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.pad), [toplabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.pad), [rightlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.pad), [bottomlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.pad) The padding between the labels and the axes content. +- `leftlabelsharedpad, toplabelsharedpad, rightlabelsharedpad, bottomlabelsharedpad`: : [leftlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.sharedpad), [toplabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.sharedpad), [rightlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.sharedpad), [bottomlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.sharedpad) The padding between side labels and a shared spanning axis label on… +- `leftlabels_kw, toplabels_kw, rightlabels_kw, bottomlabels_kw`: Additional settings used to update the labels with ``text.update()``. +- `figtitle`: Alias for `suptitle`. +- `suptitle`: The figure "super" title, centered between the left edge of the leftmost subplot and the right edge of the rightmost subplot. +- `suptitlepad`: The padding between the super title and the axes content. +- `suptitle_kw`: Additional settings used to update the super title with ``text.update()``. +- `includepanels`: Whether to include panels when aligning figure "super titles" along the top of the subplot grid and when aligning the `spanx` *x* axis labels and `spany` *y* axis labels along the… +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- `abcloc, titleloc`: Strings indicating the location for the a-b-c label and main title. +- `abcborder, titleborder`: Whether to draw a white border around titles and a-b-c labels positioned inside the axes. +- `abcbbox, titlebbox`: Whether to draw a white bbox around titles and a-b-c labels positioned inside the axes. +- `abcpad`: Horizontal offset to shift the a-b-c label position. +- `abc_kw, title_kw`: Additional settings used to update the a-b-c label and title with ``text.update()``. +- `titlepad`: The padding for the inner and outer titles and a-b-c labels. +- `titleabove`: Whether to try to put outer titles and a-b-c labels above panels, colorbars, or legends that are above the axes. +- `abctitlepad`: The horizontal padding between a-b-c labels and titles in the same location. +- `ltitle, ctitle, rtitle, ultitle, uctitle, urtitle, lltitle, lctitle, lrtitle`: Shorthands for the below keywords. +- `lowerlefttitle, lowercentertitle, lowerrighttitle`: Additional titles in specific positions (see `title` for details). +- `a, alpha, fc, facecolor, ec, edgecolor, lw, linewidth, ls, linestyle`: [axes.alpha](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.alpha) (default: 1.0), [axes.facecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.facecolor) (default: white), [axes.edgecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.edgecolor) (default: black), [axes.linewidth](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.linewidth) (default: 0.6), - Additional settings applied to… +- `aspect`: The data aspect ratio. +- `xlabel, ylabel`: The x and y axis labels. +- `xlabel_kw, ylabel_kw`: Additional axis label settings applied with [set_xlabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlabel.html) and [set_ylabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_ylabel.html). +- `xlim, ylim`: The x and y axis data limits. +- `xmin, ymin`: The x and y minimum data limits. +- `xmax, ymax`: The x and y maximum data limits. +- `xreverse, yreverse`: Whether to "reverse" the x and y axis direction. +- `xscale, yscale`: The x and y axis scales. +- `xscale_kw, yscale_kw`: The x and y axis scale settings. +- `xmargin, ymargin, margin`: The default margin between plotted content and the x and y axis spines in axes-relative coordinates. +- `xbounds, ybounds`: The x and y axis data bounds within which to draw the spines. +- `xtickrange, ytickrange`: The x and y axis data ranges within which major tick marks are labelled. +- `xwraprange, ywraprange`: The x and y axis data ranges with which major tick mark values are wrapped. +- _97 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.format)""" + ... + + def colorbar(self, mappable: Incomplete, values: Incomplete=None, loc: Optional[str]=None, location: Optional[str]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, span: Optional[Union[int, Tuple[int, int]]]=None, space: Optional[Union[float, str]]=None, pad: Optional[Union[float, str]]=None, width: Optional[Union[float, str]]=None, **kwargs: Incomplete) -> Incomplete: + """Add a colorbar along the side of the figure. + +Parameters +---------- +- `length`: The colorbar length. +- `shrink`: Alias for `length`. +- `width`: The colorbar width. +- `loc`: The colorbar location. +- `space`: The fixed space between the colorbar and the subplot grid edge. +- `pad`: The [tight layout padding](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) between the colorbar and the subplot grid. +- `span`: Integer(s) indicating the span of the colorbar across rows and columns of subplots. +- `align`: For outer colorbars only. +- `orientation`: The colorbar orientation. +- `norm`: Ignored if `mappable` is a [ScalarMappable](https://matplotlib.org/stable/api/_as_gen/matplotlib.cm.ScalarMappable.html). +- `norm_kw`: Ignored if `mappable` is a [ScalarMappable](https://matplotlib.org/stable/api/_as_gen/matplotlib.cm.ScalarMappable.html). +- `vmin, vmax`: Ignored if `mappable` is a [ScalarMappable](https://matplotlib.org/stable/api/_as_gen/matplotlib.cm.ScalarMappable.html). +- `label, title`: The colorbar label. +- `reverse`: Whether to reverse the direction of the colorbar. +- `rotation`: The tick label rotation. +- `grid, edges, drawedges`: Whether to draw "grid" dividers between each distinct color. +- `extend`: Direction for drawing colorbar "extensions" (i.e. +- `extendfrac`: The length of the colorbar "extensions" relative to the length of the colorbar. +- `extendsize`: The length of the colorbar "extensions" in physical units. +- `extendrect`: Whether to draw colorbar "extensions" as rectangles. +- `locator, ticks`: Used to determine the colorbar tick positions. +- `locator_kw`: Keyword arguments passed to [matplotlib.ticker.Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) class. +- `minorlocator_kw`: As with `locator_kw`, but for the minor ticks. +- `format, formatter, ticklabels`: The tick label format. +- `formatter_kw`: Keyword arguments passed to [matplotlib.ticker.Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) class. +- `frame, frameon`: For inset colorbars, indicates whether to draw a background "frame", just like [legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html). +- `tickminor`: Whether to add minor ticks using [minorticks_on](https://matplotlib.org/stable/api/_as_gen/matplotlib.colorbar.ColorbarBase.minorticks_on.html). +- `tickloc, ticklocation`: Where to draw tick marks on the colorbar. +- `tickdir, tickdirection`: Direction of major and minor colorbar ticks. +- `ticklen`: Major tick lengths for the colorbar ticks. +- `ticklenratio`: Relative scaling of `ticklen` used to determine minor tick lengths. +- `tickwidth`: Major tick widths for the colorbar ticks. +- `tickwidthratio`: Relative scaling of `tickwidth` used to determine minor tick widths. +- `ticklabelcolor, ticklabelsize, ticklabelweight`: The font color, size, and weight for colorbar tick labels +- `labelloc, labellocation`: The colorbar label location. +- `labelcolor, labelsize, labelweight`: The font color, size, and weight for the colorbar label. +- _22 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.colorbar)""" + ... + + def legend(self, handles: Incomplete=None, labels: Incomplete=None, loc: Incomplete=None, location: Incomplete=None, row: Incomplete=None, col: Incomplete=None, rows: Incomplete=None, cols: Incomplete=None, span: Incomplete=None, space: Incomplete=None, pad: Incomplete=None, width: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add a legend along the side of the figure. + +Parameters +---------- +- `handles`: List of matplotlib artists, or a list of lists of artist instances (see the `center` keyword). +- `labels`: A matching list of string labels or ``None`` placeholders, or a matching list of lists (see the `center` keyword). +- `loc`: The legend location. +- `space`: The fixed space between the legend and the subplot grid edge. +- `pad`: The [tight layout padding](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) between the legend and the subplot grid. +- `span`: Integer(s) indicating the span of the legend across rows and columns of subplots. +- `align`: For outer legends only. +- `width`: The space allocated for the legend box. +- `frame, frameon`: Toggles the legend frame. +- `ncol, ncols`: The number of columns. +- `order`: Whether legend handles are drawn in row-major (``'C'``) or column-major (``'F'``) order. +- `center`: Whether to center each legend row individually. +- `alphabetize`: Whether to alphabetize the legend entries according to the legend labels. +- `title, label`: The legend title. +- `fontsize, fontweight, fontcolor`: The font size, weight, and color for the legend text. +- `titlefontsize, titlefontweight, titlefontcolor`: The font size, weight, and color for the legend title. +- `borderpad, borderaxespad, handlelength, handleheight, handletextpad, labelspacing, columnspacing`: Various matplotlib [legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html) spacing arguments. +- `a, alpha, framealpha, fc, facecolor, framecolor, ec, edgecolor, ew, edgewidth`: See the full API documentation. +- `c, color, lw, linewidth, m, marker, ls, linestyle, dashes, ms, markersize`: Properties used to override the legend handles. +- `handle_kw`: Additional properties used to override legend handles, e.g. +- `handler_map`: A dictionary mapping instances or types to a legend handler. +- `**kwargs`: Passed to [legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.legend.html). +- `bbox_to_anchor`: Box that is used to position the legend in conjunction with *loc*. +- `ncols`: The number of columns that the legend has. +- `prop`: The font properties of the legend. +- `fontsize`: The font size of the legend. +- `labelcolor`: The color of the text in the legend. +- `numpoints`: The number of marker points in the legend when creating a legend entry for a `.Line2D` (line). +- `scatterpoints`: The number of marker points in the legend when creating a legend entry for a `.PathCollection` (scatter plot). +- `scatteryoffsets`: The vertical offset (relative to the font size) for the markers created for a scatter plot legend entry. +- `markerscale`: The relative size of legend markers compared to the originally drawn ones. +- `markerfirst`: If *True*, legend marker is placed to the left of the legend label. +- `reverse`: If *True*, the legend labels are displayed in reverse order from the input. +- `frameon`: Whether the legend should be drawn on a patch (frame). +- `fancybox`: Whether round edges should be enabled around the `.FancyBboxPatch` which makes up the legend's background. +- `shadow`: Whether to draw a shadow behind the legend. +- _17 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.legend)""" + ... + + def save(self, filename: Incomplete, **kwargs: Incomplete) -> None: + """Save the figure. + +Parameters +---------- +path : path-like, optional + The file path. User paths are expanded with `os.path.expanduser`. +**kwargs + Passed to [savefig](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.savefig.html) + +See also +-------- +Figure.save +Figure.savefig +matplotlib.figure.Figure.savefig""" + ... + + def savefig(self, filename: Incomplete, **kwargs: Incomplete) -> None: + """Save the figure. + +Parameters +---------- +- `path`: The file path. +- `**kwargs`: Passed to [savefig](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.savefig.html) +- `fname`: A path, or a Python file-like object, or possibly some backend-dependent object such as [matplotlib.backends.backend_pdf.PdfPages](https://matplotlib.org/stable/api/_as_gen/matplotlib.backends.backend_pdf.PdfPages.html). +- `transparent`: If *True*, the Axes patches will all be transparent; the Figure patch will also be transparent unless *facecolor* and/or *edgecolor* are specified via kwargs. +- `dpi`: The resolution in dots per inch. +- `format`: The file format, e.g. +- `metadata`: Key/value pairs to store in the image metadata. +- `bbox_inches`: Bounding box in inches: only the given portion of the figure is saved. +- `pad_inches`: Amount of padding in inches around the figure when bbox_inches is 'tight'. +- `facecolor`: The facecolor of the figure. +- `edgecolor`: The edgecolor of the figure. +- `backend`: Use a non-default backend to render the file, e.g. +- `orientation`: Currently only supported by the postscript backend. +- `papertype`: One of 'letter', 'legal', 'executive', 'ledger', 'a0' through 'a10', 'b0' through 'b10'. +- `bbox_extra_artists`: A list of extra artists that will be considered when the tight bbox is calculated. +- `pil_kwargs`: Additional keyword arguments that are passed to `PIL.Image.Image.save` when saving the figure. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.savefig)""" + ... + + def set_canvas(self, canvas: Incomplete) -> None: + """Set the figure canvas. Add monkey patches for the instance-level +[draw](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.FigureCanvasBase.draw.html) and +[print_figure](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.FigureCanvasBase.print_figure.html) methods. + +Parameters +---------- +canvas : [FigureCanvasBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.backend_bases.FigureCanvasBase.html) + The figure canvas. + +See also +-------- +matplotlib.figure.Figure.set_canvas + +Matplotlib documentation + + +Set the canvas that contains the figure + +Parameters +---------- +canvas : FigureCanvas""" + ... + + def _is_same_size(self, figsize: Incomplete, eps: Incomplete=None) -> Incomplete: + """Test if the figure size is unchanged up to some tolerance in inches.""" + ... + + def set_size_inches(self, w: Incomplete, h: Incomplete=None, *, forward: Incomplete=True, internal: Incomplete=False, eps: Incomplete=None) -> None: + """Set the figure size. If this is being called manually or from an interactive +backend, update the default layout with this fixed size. If the figure size is +unchanged or this is an internal call, do not update the default layout. + +Parameters +---------- +*args : float + The width and height passed as positional arguments or a 2-tuple. +forward : bool, optional + Whether to update the canvas. +internal : bool, optional + Whether this is an internal resize. +eps : float, optional + The deviation from the current size in inches required to treat this + as a user-triggered figure resize that fixes the layout. + +See also +-------- +matplotlib.figure.Figure.set_size_inches + +Matplotlib documentation + + +Set the figure size in inches. + +Call signatures:: + + fig.set_size_inches(w, h) # OR + fig.set_size_inches((w, h)) + +Parameters +---------- +w : (float, float) or float + Width and height in inches (if height not specified as a separate + argument) or width. +h : float + Height in inches. +forward : bool, default: True + If ``True``, the canvas size is automatically updated, e.g., + you can resize the figure window from the shell. + +See Also +-------- +matplotlib.figure.Figure.get_size_inches +matplotlib.figure.Figure.set_figwidth +matplotlib.figure.Figure.set_figheight + +Notes +----- +To transform from pixels to inches divide by `Figure.dpi`.""" + ... + + def _iter_axes(self, hidden: Incomplete=False, children: Incomplete=False, panels: Incomplete=True) -> Incomplete: + """Iterate over all axes and panels in the figure belonging to the +[Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html) class. Exclude inset and twin axes. + +Parameters +---------- +hidden : bool, optional + Whether to include "hidden" panels. +children : bool, optional + Whether to include child axes. Note this now includes "twin" axes. +panels : bool or str or sequence of str, optional + Whether to include panels or the panels to include.""" + ... + + @property + def gridspec(self) -> Incomplete: + """The single [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html) instance used for all +subplots in the figure. + +See also +-------- +ultraplot.figure.Figure.subplotgrid +ultraplot.gridspec.GridSpec.figure +ultraplot.gridspec.SubplotGrid.gridspec""" + ... + + @gridspec.setter + def gridspec(self, gs: Incomplete) -> None: + """The single [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html) instance used for all +subplots in the figure. + +See also +-------- +ultraplot.figure.Figure.subplotgrid +ultraplot.gridspec.GridSpec.figure +ultraplot.gridspec.SubplotGrid.gridspec""" + ... + + def _get_subplot(self, number: int) -> Incomplete: + """Return the subplot with the given *number*, or ``None``.""" + ... + + def _iter_subplots(self) -> Incomplete: + """Iterate over all numbered subplots.""" + ... + + @property + def subplotgrid(self) -> Incomplete: + """A [SubplotGrid](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html) containing the numbered subplots in the +figure. The subplots are ordered by increasing [number](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html#ultraplot.axes.Axes.number). + +See also +-------- +ultraplot.figure.Figure.gridspec +ultraplot.gridspec.SubplotGrid.figure""" + ... + + @property + def tight(self) -> Incomplete: + """Whether the [tight layout algorithm](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) is active for the +figure. This value is passed to [auto_layout](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.auto_layout) +every time the figure is drawn. Can be changed e.g. ``fig.tight = False``. + +See also +-------- +ultraplot.figure.Figure.auto_layout""" + ... + + @tight.setter + def tight(self, b: Incomplete) -> None: + ... + _format_signature = inspect.signature(format) + format = docstring._obfuscate_kwargs(format) diff --git a/ultraplot/gridspec.py b/ultraplot/gridspec.py index 89915645e..a0386bb87 100644 --- a/ultraplot/gridspec.py +++ b/ultraplot/gridspec.py @@ -9,7 +9,7 @@ from collections.abc import MutableSequence from functools import wraps from numbers import Integral -from typing import List, Optional, Tuple, Union +from typing import Any, Callable, List, Optional, Tuple, TypeVar, Union, cast, overload import matplotlib.axes as maxes import matplotlib.gridspec as mgridspec @@ -122,8 +122,23 @@ def _dummy_method(*args): return _dummy_method -def _apply_to_all(func=None, *, doc_key=None): - def decorator(f): +_F = TypeVar("_F", bound=Callable[..., object]) + + +@overload +def _apply_to_all(func: _F, *, doc_key: Optional[str] = None) -> _F: ... + + +@overload +def _apply_to_all( + func: None = None, *, doc_key: Optional[str] = None +) -> Callable[[_F], _F]: ... + + +def _apply_to_all( + func: Optional[_F] = None, *, doc_key: Optional[str] = None +) -> Union[_F, Callable[[_F], _F]]: + def decorator(f: _F) -> _F: @wraps(f) def wrapper(self, *args, **kwargs): objs = self._apply_command(f.__name__, *args, **kwargs) @@ -158,7 +173,7 @@ def wrapper(self, *args, **kwargs): wrapper.__doc__ = doc - return wrapper + return cast(_F, wrapper) if func is not None: return decorator(func) @@ -1817,7 +1832,7 @@ def locally_modified_subplot_params(self): wpad_total = property(lambda self: list(self._wpad_total)) -class SubplotGrid(MutableSequence, list): +class SubplotGrid(MutableSequence[paxes.Axes], list[paxes.Axes]): """ List-like, array-like object used to store subplots returned by `~ultraplot.figure.Figure.subplots`. 1D indexing uses the underlying list of @@ -1868,7 +1883,7 @@ def __init__(self, sequence=None, **kwargs): sequence = self._validate_item(sequence, scalar=False) super().__init__(sequence, **kwargs) - def __getattr__(self, attr): + def __getattr__(self, attr: str) -> Any: """ Get a missing attribute. Simply redirects to the axes if the `SubplotGrid` is singleton and raises an error otherwise. This can be convenient for @@ -1911,7 +1926,19 @@ def _iterate_subplots(*args, **kwargs): else: raise AttributeError(f"Found mixed types for attribute {attr!r}.") - def __getitem__(self, key): + @overload + def __getitem__(self, key: int) -> paxes.Axes: ... + + @overload + def __getitem__( + self, + key: Union[slice, List[int], np.ndarray, Tuple[Union[int, slice], ...]], + ) -> "SubplotGrid": ... + + def __getitem__( + self, + key: Union[int, slice, List[int], np.ndarray, Tuple[Union[int, slice], ...]], + ) -> Union[paxes.Axes, "SubplotGrid"]: """ Get an axes. @@ -2051,7 +2078,7 @@ def _validate_item(self, items, scalar=False): return items @docstring._snippet_manager - def format(self, **kwargs): + def format(self, **kwargs) -> None: """ Call the ``format`` command for the `~SubplotGrid.figure` and every axes in the grid. diff --git a/ultraplot/gridspec.pyi b/ultraplot/gridspec.pyi new file mode 100644 index 000000000..5ddd35436 --- /dev/null +++ b/ultraplot/gridspec.pyi @@ -0,0 +1,804 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The gridspec and subplot grid classes used throughout ultraplot. +""" +from _typeshed import Incomplete +import inspect +import itertools +import re +from collections.abc import MutableSequence +from functools import wraps +from numbers import Integral +from typing import Any, Callable, List, Optional, Tuple, TypeVar, Union, cast, overload +import matplotlib.axes as maxes +import matplotlib.gridspec as mgridspec +import matplotlib.transforms as mtransforms +import numpy as np +from . import axes as paxes +from .axes._formatting import pop_axis_format_kwargs +from .config import rc +from .internals import _not_none, _pop_rc, docstring, ic, warnings +from .utils import _fontsize_to_pt, units +try: + from . import ultralayout + ULTRA_AVAILABLE = True +except ImportError: + ultralayout = None + ULTRA_AVAILABLE = False +__all__ = ['GridSpec', 'SubplotGrid'] +_shared_docstring = ... +_scalar_docstring = ... +_vector_docstring = ... +_tight_docstring = ... + +def _disable_method(attr: Incomplete) -> Incomplete: + """Disable the inherited method.""" + ... +_F = TypeVar('_F', bound=Callable[..., object]) + +@overload +def _apply_to_all(func: _F, *, doc_key: Optional[str]=None) -> _F: + ... + +@overload +def _apply_to_all(func: None=None, *, doc_key: Optional[str]=None) -> Callable[[_F], _F]: + ... + +class _SubplotSpec(mgridspec.SubplotSpec): + """A thin [SubplotSpec](https://matplotlib.org/stable/api/_as_gen/matplotlib.gridspec.SubplotSpec.html) subclass with a nice string +representation and a few helper methods.""" + + def __repr__(self) -> Incomplete: + """Return repr(self).""" + ... + + def _get_geometry(self) -> Incomplete: + """Return the geometry and scalar indices relative to the "unhidden" non-panel +geometry. May trigger error if this is in a "hidden" panel slot.""" + ... + + def _get_rows_columns(self, ncols: Incomplete=None) -> Incomplete: + """Return the row and column indices. The resulting indices include +"hidden" panel rows and columns. See `GridSpec.get_grid_positions`.""" + ... + + def _get_grid_span(self, hidden: Incomplete=False) -> Incomplete: + """Retrieve the location of the subplot within the +gridspec. When hidden is False we only consider +the main plots, not the panels or colorbars.""" + ... + + def get_position(self, figure: Incomplete, return_all: Incomplete=False) -> Incomplete: + """Update the subplot position from ``figure.subplotpars``.""" + ... + +class GridSpec(mgridspec.GridSpec): + """A [GridSpec](https://matplotlib.org/stable/api/_as_gen/matplotlib.gridspec.GridSpec.html) subclass that permits variable spacing +between successive rows and columns and hides "panel slots" from indexing.""" + + def __repr__(self) -> str: + """Return repr(self).""" + ... + + def __getattr__(self, attr: Incomplete) -> None: + ... + + def __init__(self, nrows: Incomplete=1, ncols: Incomplete=1, layout_array: Incomplete=None, ultra_layout: Optional[bool]=None, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `nrows`: The number of rows in the subplot grid. +- `ncols`: The number of columns in the subplot grid. +- `layout_array`: 2D array specifying the subplot layout, where each unique integer represents a subplot and 0 represents empty space. +- `ultra_layout`: Whether to use the UltraLayout constraint solver. +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, and both, respectively. +- `wratios, hratios`: Passed to [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html), denotes the width and height ratios for the subplot grid. +- `wpad, hpad, pad`: The tight layout padding between columns, rows, and both, respectively. +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html)""" + ... + + def _get_ultra_position(self, subplot_num: Incomplete, figure: Incomplete) -> Incomplete: + """Get the position of a subplot using UltraLayout constraint-based positioning. + +Parameters +---------- +subplot_num : int + The subplot number (in total geometry indexing) +figure : Figure + The matplotlib figure instance + +Returns +------- +bbox : Bbox or None + The bounding box for the subplot, or None if kiwi layout fails""" + ... + + def _compute_ultra_positions(self) -> None: + """Compute subplot positions using UltraLayout and cache them.""" + ... + + def _get_ultra_layout_array(self) -> Incomplete: + """Return the layout array expanded to total geometry to include panels.""" + ... + + def __getitem__(self, key: Incomplete) -> _SubplotSpec: + """Get a [SubplotSpec](https://matplotlib.org/stable/api/_as_gen/matplotlib.gridspec.SubplotSpec.html). "Hidden" slots allocated for axes +panels, colorbars, and legends are ignored. For example, given a gridspec with +2 subplot rows, 3 subplot columns, and a "panel" row between the subplot rows, +calling ``gs[1, 1]`` returns a [SubplotSpec](https://matplotlib.org/stable/api/_as_gen/matplotlib.gridspec.SubplotSpec.html) corresponding +to the central subplot on the second row rather than a "panel" slot.""" + ... + + def _make_subplot_spec(self, key: Incomplete, includepanels: Incomplete=False) -> _SubplotSpec: + """Generate a subplotspec either ignoring panels or including panels.""" + ... + + def _encode_indices(self, *args: Incomplete, which: Incomplete=None, panel: Incomplete=False) -> Incomplete: + """Convert indices from the selected gridspec geometry into indices for the +total geometry. If `which` is not passed these should be flattened indices. +When `panel` is True, indices are interpreted relative to panel slots +along the specified axis; otherwise they refer to non-panel slots.""" + ... + + def _decode_indices(self, *args: Incomplete, which: Incomplete=None, panel: Incomplete=False) -> Incomplete: + """Convert indices from the total geometry into the selected gridspec +geometry. If `which` is not passed these should be flattened indices. +When `panel` is True, indices are interpreted relative to panel slots +along the specified axis; otherwise they refer to non-panel slots.""" + ... + + def _filter_indices(self, key: Incomplete, panel: Incomplete=False) -> Incomplete: + """Filter the vector attribute for "unhidden" or "hidden" slots.""" + ... + + def _get_indices(self, which: Incomplete=None, space: Incomplete=False, panel: Incomplete=False) -> list[int]: + """Get the indices associated with "unhidden" or "hidden" slots.""" + ... + + def _modify_subplot_geometry(self, newrow: Incomplete=None, newcol: Incomplete=None) -> None: + """Update the axes subplot specs by inserting rows and columns as specified.""" + ... + + def _parse_panel_arg(self, side: Incomplete, arg: Incomplete) -> Incomplete: + """Return the indices associated with a new figure panel on the specified side. +Try to find room in the current mosaic of figure panels.""" + ... + + def _parse_panel_arg_with_span(self, side: str, ax: 'paxes.Axes', span_override: Optional[Union[int, Tuple[int, int]]]) -> Tuple[str, int, slice]: + """Parse panel arg with span override. Uses ax for position, span for extent. + +Parameters +---------- +side : str + Panel side ('left', 'right', 'top', 'bottom') +ax : Axes + The axes to position the panel relative to +span_override : int or tuple + The span extent (1-indexed like subplot numbers) + +Returns +------- +slot : str + Panel slot identifier +iratio : int + Panel position index +span : slice + Encoded span slice for the panel extent""" + ... + + def _insert_panel_slot(self, side: str, arg: Incomplete, *, share: Optional[bool]=None, width: Optional[Union[float, str]]=None, space: Optional[Union[float, str]]=None, pad: Optional[Union[float, str]]=None, filled: bool=False, span_override: Optional[Union[int, Tuple[int, int]]]=None) -> tuple[_SubplotSpec, bool]: + """Insert a panel slot into the existing gridspec. The `side` is the panel side +and the `arg` is either an axes instance or the figure row-column span.""" + ... + + def _get_space(self, key: Incomplete) -> Incomplete: + """Return the currently active vector inner space or scalar outer space +accounting for both default values and explicit user overrides.""" + ... + + def _get_default_space(self, key: Incomplete, pad: Incomplete=None, share: Incomplete=None, title: Incomplete=True) -> Incomplete: + """Return suitable default scalar inner or outer space given a shared axes +setting. This is only relevant when "tight layout" is disabled.""" + ... + + def _get_tight_space(self, w: Incomplete) -> Incomplete: + """Get tight layout spaces between the input subplot rows or columns.""" + ... + + def _auto_layout_aspect(self) -> None: + """Update the underlying default aspect ratio.""" + ... + + def _auto_layout_tight(self, renderer: Incomplete) -> None: + """Update the underlying spaces with tight layout values. If `resize` is +``True`` and the auto figure size has changed then update the figure +size. Either way always update the subplot positions.""" + ... + + def _update_figsize(self) -> Incomplete: + """Return an updated auto layout figure size accounting for the +gridspec and figure parameters. May or may not need to be applied.""" + ... + + def _update_params(self, *, ultra_layout: Incomplete=None, left: Incomplete=None, bottom: Incomplete=None, right: Incomplete=None, top: Incomplete=None, wspace: Incomplete=None, hspace: Incomplete=None, space: Incomplete=None, wpad: Incomplete=None, hpad: Incomplete=None, pad: Incomplete=None, wequal: Incomplete=None, hequal: Incomplete=None, equal: Incomplete=None, wgroup: Incomplete=None, hgroup: Incomplete=None, group: Incomplete=None, outerpad: Incomplete=None, innerpad: Incomplete=None, panelpad: Incomplete=None, hratios: Incomplete=None, wratios: Incomplete=None, width_ratios: Incomplete=None, height_ratios: Incomplete=None) -> None: + """Update the user-specified properties.""" + ... + + def copy(self, **kwargs: Incomplete) -> GridSpec: + """Return a copy of the `GridSpec` with the [Figure](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html)-specific "panel slots" removed. + +Parameters +---------- +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, and both, respectively. +- `wratios, hratios`: Passed to [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html), denotes the width and height ratios for the subplot grid. +- `wpad, hpad, pad`: The tight layout padding between columns, rows, and both, respectively. +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html#ultraplot.gridspec.GridSpec.copy)""" + ... + + def get_geometry(self) -> Incomplete: + """Return the number of "unhidden" non-panel rows and columns in the grid +(see `GridSpec` for details). + +See also +-------- +GridSpec.get_panel_geometry +GridSpec.get_total_geometry""" + ... + + def get_panel_geometry(self) -> tuple[int, int]: + """Return the number of "hidden" panel rows and columns in the grid +(see `GridSpec` for details). + +See also +-------- +GridSpec.get_geometry +GridSpec.get_total_geometry""" + ... + + def get_total_geometry(self) -> Incomplete: + """Return the total number of "unhidden" and "hidden" rows and columns +in the grid (see `GridSpec` for details). + +See also +-------- +GridSpec.get_geometry +GridSpec.get_panel_geometry +GridSpec.get_grid_positions""" + ... + + def get_grid_positions(self, figure: Incomplete=None) -> Incomplete: + """Return the subplot grid positions allowing for variable inter-subplot +spacing and using physical units for the spacing terms. The resulting +positions include "hidden" panel rows and columns. + +Note +---- +The physical units for positioning grid cells are converted from em-widths to +inches when the `GridSpec` is instantiated. This means that subsequent changes +to [font.size](https://ultraplot.readthedocs.io/en/stable/search.html?q=font.size) will have no effect on the spaces. This is consistent +with [font.size](https://ultraplot.readthedocs.io/en/stable/search.html?q=font.size) having no effect on already-instantiated figures. + +See also +-------- +GridSpec.get_total_geometry""" + ... + + def update(self, **kwargs: Incomplete) -> None: + """Update the gridspec with arbitrary initialization keyword arguments and update the subplot positions. + +Parameters +---------- +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, and both, respectively. +- `wratios, hratios`: Passed to [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html), denotes the width and height ratios for the subplot grid. +- `wpad, hpad, pad`: The tight layout padding between columns, rows, and both, respectively. +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html#ultraplot.gridspec.GridSpec.update)""" + ... + + @property + def figure(self) -> Incomplete: + """The [ultraplot.figure.Figure](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html) uniquely associated with this `GridSpec`. +On assignment the gridspec parameters and figure size are updated. + +See also +-------- +ultraplot.gridspec.SubplotGrid.figure +ultraplot.figure.Figure.gridspec""" + ... + + @figure.setter + def figure(self, fig: Incomplete) -> None: + """The [ultraplot.figure.Figure](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html) uniquely associated with this `GridSpec`. +On assignment the gridspec parameters and figure size are updated. + +See also +-------- +ultraplot.gridspec.SubplotGrid.figure +ultraplot.figure.Figure.gridspec""" + ... + tight_layout = _disable_method('tight_layout') + subgridspec = _disable_method('subgridspec') + get_width_ratios = _disable_method('get_width_ratios') + get_height_ratios = _disable_method('get_height_ratios') + set_width_ratios = _disable_method('set_width_ratios') + set_height_ratios = _disable_method('set_height_ratios') + + def get_subplot_params(self, figure: Incomplete=None) -> Incomplete: + """Return the `.SubplotParams` for the GridSpec. + +In order of precedence the values are taken from + +- non-*None* attributes of the GridSpec +- the provided *figure* +- [figure.subplot.*](https://ultraplot.readthedocs.io/en/stable/search.html?q=figure.subplot.%2A) + +Note that the ``figure`` attribute of the GridSpec is always ignored.""" + ... + + def locally_modified_subplot_params(self) -> Incomplete: + """Return a list of the names of the subplot parameters explicitly set +in the GridSpec. + +This is a subset of the attributes of `.SubplotParams`.""" + ... + gridheight = ... + gridwidth = ... + panelheight = ... + panelwidth = ... + spaceheight = ... + spacewidth = ... + nrows = ... + ncols = ... + nrows_panel = ... + ncols_panel = ... + nrows_total = ... + ncols_total = ... + left = ... + bottom = ... + right = ... + top = ... + hratios = ... + wratios = ... + hratios_panel = ... + wratios_panel = ... + hratios_total = ... + wratios_total = ... + hspace = ... + wspace = ... + hspace_panel = ... + wspace_panel = ... + hspace_total = ... + wspace_total = ... + hpad = ... + wpad = ... + hpad_panel = ... + wpad_panel = ... + hpad_total = ... + wpad_total = ... + +class SubplotGrid(MutableSequence[paxes.Axes], list[paxes.Axes], paxes.PlotAxes): + """List-like, array-like object used to store subplots returned by +[subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots). 1D indexing uses the underlying list of +[Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html) while 2D indexing uses the `~SubplotGrid.gridspec`. +See `~SubplotGrid.__getitem__` for details.""" + + def __repr__(self) -> str: + ... + + def __str__(self) -> str: + ... + + def __len__(self) -> int: + ... + + def insert(self, key: Incomplete, value: Incomplete) -> None: + ... + + def __init__(self, sequence: Incomplete=None, **kwargs: Incomplete) -> None: + """Parameters +---------- +sequence : sequence + A sequence of [ultraplot.axes.Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html) subplots or their children. + +See also +-------- +ultraplot.ui.subplots +ultraplot.figure.Figure.subplots +ultraplot.figure.Figure.add_subplots""" + ... + + def __getattr__(self, attr: str) -> Any: + """Get a missing attribute. Simply redirects to the axes if the `SubplotGrid` +is singleton and raises an error otherwise. This can be convenient for +single-axes figures generated with [subplots](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.subplots).""" + ... + + @overload + def __getitem__(self, key: int) -> paxes.Axes: + """Get an axes. + +Parameters +---------- +key : int, slice, or 2-tuple + The index. If 1D then the axes in the corresponding + sublist are returned. If 2D then the axes that intersect + the corresponding `~SubplotGrid.gridspec` slots are returned. + +Returns +------- +axs : ultraplot.axes.Axes or SubplotGrid + The axes. If the index included slices then + another `SubplotGrid` is returned. + +Example +------- +>>> import ultraplot as uplt +>>> fig, axs = uplt.subplots(nrows=3, ncols=3) +>>> axs[5] # the subplot in the second row, third column +>>> axs[1, 2] # the subplot in the second row, third column +>>> axs[:, 0] # a SubplotGrid containing the subplots in the first column""" + ... + + @overload + def __getitem__(self, key: Union[slice, List[int], np.ndarray, Tuple[Union[int, slice], ...]]) -> 'SubplotGrid': + """Get an axes. + +Parameters +---------- +key : int, slice, or 2-tuple + The index. If 1D then the axes in the corresponding + sublist are returned. If 2D then the axes that intersect + the corresponding `~SubplotGrid.gridspec` slots are returned. + +Returns +------- +axs : ultraplot.axes.Axes or SubplotGrid + The axes. If the index included slices then + another `SubplotGrid` is returned. + +Example +------- +>>> import ultraplot as uplt +>>> fig, axs = uplt.subplots(nrows=3, ncols=3) +>>> axs[5] # the subplot in the second row, third column +>>> axs[1, 2] # the subplot in the second row, third column +>>> axs[:, 0] # a SubplotGrid containing the subplots in the first column""" + ... + + def __setitem__(self, key: Incomplete, value: Incomplete) -> Incomplete: + """Add an axes. + +Parameters +---------- +key : int or slice + The 1D index. +value : [ultraplot.axes.Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html) + The ultraplot subplot or its child or panel axes, + or a sequence thereof if the index was a slice.""" + ... + + def _validate_item(self, items: Incomplete, scalar: Incomplete=False) -> Incomplete: + """Validate assignments. Accept diverse iterable inputs.""" + ... + + def format(self, **kwargs: Incomplete) -> None: + """Call the ``format`` command for the `~SubplotGrid.figure` and every axes in the grid. + +Parameters +---------- +- `title`: The axes title. +- `abc`: The "a-b-c" subplot label style. +- `abcloc, titleloc`: Strings indicating the location for the a-b-c label and main title. +- `abcborder, titleborder`: Whether to draw a white border around titles and a-b-c labels positioned inside the axes. +- `abcbbox, titlebbox`: Whether to draw a white bbox around titles and a-b-c labels positioned inside the axes. +- `abcpad`: Horizontal offset to shift the a-b-c label position. +- `abc_kw, title_kw`: Additional settings used to update the a-b-c label and title with ``text.update()``. +- `titlepad`: The padding for the inner and outer titles and a-b-c labels. +- `titleabove`: Whether to try to put outer titles and a-b-c labels above panels, colorbars, or legends that are above the axes. +- `abctitlepad`: The horizontal padding between a-b-c labels and titles in the same location. +- `ltitle, ctitle, rtitle, ultitle, uctitle, urtitle, lltitle, lctitle, lrtitle`: Shorthands for the below keywords. +- `lowerlefttitle, lowercentertitle, lowerrighttitle`: Additional titles in specific positions (see `title` for details). +- `a, alpha, fc, facecolor, ec, edgecolor, lw, linewidth, ls, linestyle`: [axes.alpha](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.alpha) (default: 1.0), [axes.facecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.facecolor) (default: white), [axes.edgecolor](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.edgecolor) (default: black), [axes.linewidth](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.linewidth) (default: 0.6), - Additional settings applied to… +- `**kwargs`: Passed to the projection-specific ``format`` command for each axes. +- `leftlabels, toplabels, rightlabels, bottomlabels`: Labels for the subplots lying along the left, top, right, and bottom edges of the figure. +- `leftlabelpad, toplabelpad, rightlabelpad, bottomlabelpad`: : [leftlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.pad), [toplabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.pad), [rightlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.pad), [bottomlabel.pad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.pad) The padding between the labels and the axes content. +- `leftlabelsharedpad, toplabelsharedpad, rightlabelsharedpad, bottomlabelsharedpad`: : [leftlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=leftlabel.sharedpad), [toplabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=toplabel.sharedpad), [rightlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=rightlabel.sharedpad), [bottomlabel.sharedpad](https://ultraplot.readthedocs.io/en/stable/search.html?q=bottomlabel.sharedpad) The padding between side labels and a shared spanning axis label on… +- `leftlabels_kw, toplabels_kw, rightlabels_kw, bottomlabels_kw`: Additional settings used to update the labels with ``text.update()``. +- `figtitle`: Alias for `suptitle`. +- `suptitle`: The figure "super" title, centered between the left edge of the leftmost subplot and the right edge of the rightmost subplot. +- `suptitlepad`: The padding between the super title and the axes content. +- `suptitle_kw`: Additional settings used to update the super title with ``text.update()``. +- `includepanels`: Whether to include panels when aligning figure "super titles" along the top of the subplot grid and when aligning the `spanx` *x* axis labels and `spany` *y* axis labels along the… +- `aspect`: The data aspect ratio. +- `xlabel, ylabel`: The x and y axis labels. +- `xlabel_kw, ylabel_kw`: Additional axis label settings applied with [set_xlabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_xlabel.html) and [set_ylabel](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.set_ylabel.html). +- `xlim, ylim`: The x and y axis data limits. +- `xmin, ymin`: The x and y minimum data limits. +- `xmax, ymax`: The x and y maximum data limits. +- `xreverse, yreverse`: Whether to "reverse" the x and y axis direction. +- `xscale, yscale`: The x and y axis scales. +- `xscale_kw, yscale_kw`: The x and y axis scale settings. +- `xmargin, ymargin, margin`: The default margin between plotted content and the x and y axis spines in axes-relative coordinates. +- `xbounds, ybounds`: The x and y axis data bounds within which to draw the spines. +- `xtickrange, ytickrange`: The x and y axis data ranges within which major tick marks are labelled. +- `xwraprange, ywraprange`: The x and y axis data ranges with which major tick mark values are wrapped. +- _96 additional parameter groups are documented online._ + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html#ultraplot.gridspec.SubplotGrid.format)""" + ... + + def share_labels(self, *, axis: Incomplete='x') -> Incomplete: + """Register an explicit label-sharing group for this subset.""" + ... + + @property + def figure(self) -> Incomplete: + """The [ultraplot.figure.Figure](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html) uniquely associated with this `SubplotGrid`. +This is used with the `SubplotGrid.format` command. + +See also +-------- +ultraplot.gridspec.GridSpec.figure +ultraplot.gridspec.SubplotGrid.gridspec +ultraplot.figure.Figure.subplotgrid""" + ... + + @property + def gridspec(self) -> Incomplete: + """The [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html) uniquely associated with this `SubplotGrid`. +This is used to resolve 2D indexing. See `~SubplotGrid.__getitem__` for details. + +See also +-------- +ultraplot.figure.Figure.gridspec +ultraplot.gridspec.SubplotGrid.figure +ultraplot.gridspec.SubplotGrid.shape""" + ... + + @property + def shape(self) -> Incomplete: + """The shape of the [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html) associated with the grid. +See `~SubplotGrid.__getitem__` for details. + +See also +-------- +ultraplot.gridspec.SubplotGrid.gridspec""" + ... + + def _apply_command(self, name: Incomplete, *args: Incomplete, warn_on_skip: Incomplete=True, **kwargs: Incomplete) -> List[paxes.Axes]: + """Apply a command to all axes that support it. + +Parameters +---------- +name : str + The method name to call on each axes. +warn_on_skip : bool, optional + Whether to warn if some axes do not support the command. Default True. + +Returns +------- +list + List of results from axes where the command was applied.""" + ... + + def altx(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add an axis locked to the same location with a +distinct x axis for every axes in the grid. +This is an alias and arguably more intuitive name for +[twiny](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.twiny), which generates +two x axes with a shared ("twin") y axes. + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the x from keywords beginning with ``x`` -- for example + ``ax.altx(lim=(0, 10))`` is equivalent to ``ax.altx(xlim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.altx(loc='bottom')`` changes the default side from top to bottom. + +Returns +------- +SubplotGridultraplot.axes.CartesianAxesA grid of the resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old x axis on the bottom and the new x + axis on the top. +* Makes the old top spine invisible and the new bottom, left, + and right spines invisible. +* Adjusts the x axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new y axis limits and scales, and makes the + new y axis labels invisible.""" + ... + + def dualx(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add an axes locked to the same location whose x axis denotes equivalent coordinates in alternate units for every axes in the grid. + +Parameters +---------- +- `funcscale`: The scale used to transform units from the parent axis to the secondary axis. +- `**kwargs`: Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html#ultraplot.gridspec.SubplotGrid.dualx)""" + ... + + def twinx(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add an axis locked to the same location with a +distinct y axis for every axes in the grid. +This builds upon [matplotlib.axes.Axes.twinx](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.twinx.html). + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the y from keywords beginning with ``y`` -- for example + ``ax.alty(lim=(0, 10))`` is equivalent to ``ax.alty(ylim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.alty(loc='left')`` changes the default side from right to left. + +Returns +------- +SubplotGridultraplot.axes.CartesianAxesA grid of the resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old y axis on the left and the new y + axis on the right. +* Makes the old right spine invisible and the new left, bottom, + and top spines invisible. +* Adjusts the y axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new x axis limits and scales, and makes the + new x axis labels invisible.""" + ... + + def alty(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add an axis locked to the same location with a +distinct y axis for every axes in the grid. +This is an alias and arguably more intuitive name for +[twinx](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.twinx), which generates +two y axes with a shared ("twin") x axes. + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the y from keywords beginning with ``y`` -- for example + ``ax.alty(lim=(0, 10))`` is equivalent to ``ax.alty(ylim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.alty(loc='left')`` changes the default side from right to left. + +Returns +------- +SubplotGridultraplot.axes.CartesianAxesA grid of the resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old y axis on the left and the new y + axis on the right. +* Makes the old right spine invisible and the new left, bottom, + and top spines invisible. +* Adjusts the y axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new x axis limits and scales, and makes the + new x axis labels invisible.""" + ... + + def dualy(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add an axes locked to the same location whose y axis denotes equivalent coordinates in alternate units for every axes in the grid. + +Parameters +---------- +- `funcscale`: The scale used to transform units from the parent axis to the secondary axis. +- `**kwargs`: Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html#ultraplot.gridspec.SubplotGrid.dualy)""" + ... + + def twiny(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add an axis locked to the same location with a +distinct x axis for every axes in the grid. +This builds upon [matplotlib.axes.Axes.twiny](https://matplotlib.org/stable/api/_as_gen/matplotlib.axes.Axes.twiny.html). + +Parameters +---------- +**kwargs + Passed to [CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). Supports all valid + [format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html#ultraplot.axes.CartesianAxes.format) keywords. You can optionally + omit the x from keywords beginning with ``x`` -- for example + ``ax.altx(lim=(0, 10))`` is equivalent to ``ax.altx(xlim=(0, 10))``. + You can also change the default side for the axis spine, axis tick marks, + axis tick labels, and/or axis labels by passing ``loc`` keywords. For example, + ``ax.altx(loc='bottom')`` changes the default side from top to bottom. + +Returns +------- +SubplotGridultraplot.axes.CartesianAxesA grid of the resulting axes. + +Note +---- +This enforces the following default settings: + +* Places the old x axis on the bottom and the new x + axis on the top. +* Makes the old top spine invisible and the new bottom, left, + and right spines invisible. +* Adjusts the x axis tick, tick label, and axis label positions + according to the visible spine positions. +* Syncs the old and new y axis limits and scales, and makes the + new y axis labels invisible.""" + ... + + def panel(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add a panel axes for every axes in the grid. + +Parameters +---------- +- `side`: The panel location. +- `width`: The panel width. +- `space`: The fixed space between the panel and the subplot edge. +- `pad`: The [tight layout padding](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight) between the panel and the subplot. +- `span`: Integer(s) indicating the span of the panel across rows and columns of subplots. +- `share`: Whether to enable axis sharing between the *x* and *y* axes of the main subplot and the panel long axes for each panel in the "stack". +- `**kwargs`: Passed to [ultraplot.axes.CartesianAxes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.CartesianAxes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html#ultraplot.gridspec.SubplotGrid.panel)""" + ... + + def panel_axes(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + ... + + def inset(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + """Add an inset axes for every axes in the grid. + +Parameters +---------- +- `bounds`: The (left, bottom, width, height) coordinates for the axes. +- `transform`: The transform used to interpret the bounds. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `zorder`: The [zorder](https://matplotlib.org/stable/gallery/misc/zorder_demo.html) of the axes. +- `zoom`: Whether to draw lines indicating the inset zoom using `~Axes.indicate_inset_zoom`. +- `zoom_kw`: Passed to `~Axes.indicate_inset_zoom`. +- `**kwargs`: Passed to [ultraplot.axes.Axes](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.Axes.html). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.SubplotGrid.html#ultraplot.gridspec.SubplotGrid.inset)""" + ... + + def inset_axes(self, *args: Incomplete, **kwargs: Incomplete) -> 'SubplotGrid': + ... diff --git a/ultraplot/internals/__init__.pyi b/ultraplot/internals/__init__.pyi new file mode 100644 index 000000000..52398bd27 --- /dev/null +++ b/ultraplot/internals/__init__.pyi @@ -0,0 +1,43 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Internal utilities. +""" +from _typeshed import Incomplete +from importlib import import_module +from numbers import Integral, Real +import numpy as np +try: + from icecream import ic +except ImportError: + ic = ... +from . import warnings +from .kwargs import _alias_kwargs, _alias_maps, _get_aliases, _get_signature, _kwargs_to_args, _not_none, _pop_kwargs, _pop_params, _pop_props, _signature_cached, _INTERNAL_POP_PARAMS + +def _get_rc_matplotlib() -> Incomplete: + ... +_LAZY_ATTRS = {'benchmarks': ('benchmarks', None), 'context': ('context', None), 'docstring': ('docstring', None), 'fonts': ('fonts', None), 'guides': ('guides', None), 'inputs': ('inputs', None), 'labels': ('labels', None), 'rcsetup': ('rcsetup', None), 'versions': ('versions', None), 'warnings': ('warnings', None), '_version_mpl': ('versions', '_version_mpl'), '_version_cartopy': ('versions', '_version_cartopy'), 'UltraPlotWarning': ('warnings', 'UltraPlotWarning')} + +def _pop_rc(src: Incomplete, *, ignore_conflicts: Incomplete=True) -> Incomplete: + """Pop the rc setting names and mode for a `~Configurator.context` block.""" + ... + +def _translate_loc(loc: Incomplete, mode: Incomplete, *, default: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Translate the location string `loc` into a standardized form. The `mode` +must be a string for which there is a [mode.loc](https://ultraplot.readthedocs.io/en/stable/search.html?q=mode.loc) setting. Additional +options can be added with keyword arguments.""" + ... + +def _translate_grid(b: Incomplete, key: Incomplete) -> Incomplete: + """Translate an instruction to turn either major or minor gridlines on or off into a +boolean and string applied to [axes.grid](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.grid) and [axes.grid.which](https://ultraplot.readthedocs.io/en/stable/search.html?q=axes.grid.which).""" + ... + +def _resolve_lazy(name: Incomplete) -> Incomplete: + ... + +def __getattr__(name: Incomplete) -> Incomplete: + ... + +def __dir__() -> list[str]: + ... diff --git a/ultraplot/internals/benchmarks.pyi b/ultraplot/internals/benchmarks.pyi new file mode 100644 index 000000000..dd8b9c740 --- /dev/null +++ b/ultraplot/internals/benchmarks.pyi @@ -0,0 +1,21 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for benchmarking ultraplot performance. +""" +from _typeshed import Incomplete +import time +from . import ic +BENCHMARK = False + +class _benchmark(object): + """Context object for timing arbitrary blocks of code.""" + + def __init__(self, message: Incomplete) -> None: + ... + + def __enter__(self) -> None: + ... + + def __exit__(self, *args: Incomplete) -> None: + ... diff --git a/ultraplot/internals/context.pyi b/ultraplot/internals/context.pyi new file mode 100644 index 000000000..f73ed60fb --- /dev/null +++ b/ultraplot/internals/context.pyi @@ -0,0 +1,31 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for manging context. +""" +from _typeshed import Incomplete +from . import ic + +class _empty_context(object): + """A dummy context manager.""" + + def __init__(self) -> None: + ... + + def __enter__(self) -> None: + ... + + def __exit__(self, *args: Incomplete) -> None: + ... + +class _state_context(object): + """Temporarily modify attribute(s) for an arbitrary object.""" + + def __init__(self, obj: Incomplete, **kwargs: Incomplete) -> None: + ... + + def __enter__(self) -> None: + ... + + def __exit__(self, *args: Incomplete) -> None: + ... diff --git a/ultraplot/internals/docstring.py b/ultraplot/internals/docstring.py index 205e92bbf..5b3d8afbc 100644 --- a/ultraplot/internals/docstring.py +++ b/ultraplot/internals/docstring.py @@ -23,43 +23,46 @@ # ... print(*_iter_doc(uplt)) import inspect import re +from typing import Any, Callable, TypeVar, cast, overload from . import ic # noqa: F401 +_F = TypeVar("_F", bound=Callable[..., Any]) +_T = TypeVar("_T") -def _obfuscate_kwargs(func): + +def _obfuscate_kwargs(func: _F) -> _F: """ - Obfuscate keyword args. + Mark keyword arguments as compact in generated API documentation. """ return _obfuscate_signature(func, lambda **kwargs: None) -def _obfuscate_params(func): +def _obfuscate_params(func: _F) -> _F: """ - Obfuscate all parameters. + Mark all parameters as compact in generated API documentation. """ return _obfuscate_signature(func, lambda *args, **kwargs: None) -def _obfuscate_signature(func, dummy): +def _obfuscate_signature(func: _F, dummy: Callable[..., Any]) -> _F: """ - Obfuscate a misleading or incomplete call signature. - Instead users should inspect the parameter table. + Mark a misleading or incomplete signature as compact in generated docs. + + The callable's actual signature remains available to Python and language + servers; Sphinx reads the marker below when rendering API headings. """ - # Obfuscate signature by converting to *args **kwargs. Note this does - # not change behavior of function! Copy parameters from a dummy function - # because I'm too lazy to figure out inspect.Parameters API - # See: https://stackoverflow.com/a/33112180/4970632 - sig = inspect.signature(func) - sig_repl = inspect.signature(dummy) - func.__signature__ = sig.replace(parameters=tuple(sig_repl.parameters.values())) + # Keep the compact signature available to documentation tooling without + # changing the callable's runtime signature. Sphinx uses this marker to + # avoid filling API headings with inherited or dynamically routed options. + setattr(func, "__ultraplot_doc_signature__", str(inspect.signature(dummy))) return func -def _concatenate_inherited(func, prepend_summary=False): +def _concatenate_inherited(func: _F, prepend_summary: bool = False) -> _F: """ Concatenate docstrings from a matplotlib axes method with a ultraplot - axes method and obfuscate the call signature. + axes method and mark its generated-documentation signature as compact. """ import matplotlib.axes as maxes import matplotlib.figure as mfigure @@ -102,7 +105,7 @@ def _concatenate_inherited(func, prepend_summary=False): """ # Return docstring - # NOTE: Also obfuscate parameters to avoid partial coverage of call signatures + # Keep generated API headings compact to avoid showing partial call signatures. func.__doc__ = inspect.cleandoc(doc) func = _obfuscate_params(func) return func @@ -143,7 +146,13 @@ def __missing__(self, key): return dict.__getitem__(self, key) raise KeyError(key) - def __call__(self, obj): + @overload + def __call__(self, obj: str) -> str: ... + + @overload + def __call__(self, obj: _T) -> _T: ... + + def __call__(self, obj: _T | str) -> _T | str: """ Add snippets to the string or object using ``%(name)s`` substitution. Here ``%(name)s`` is used rather than ``.format`` to support invalid identifiers. @@ -151,9 +160,12 @@ def __call__(self, obj): if isinstance(obj, str): obj %= self # add snippets to a string else: - obj.__doc__ = inspect.getdoc(obj) # also dedents the docstring - if obj.__doc__: - obj.__doc__ %= self # insert snippets after dedent + documented = cast(Any, obj) + documented.__doc__ = inspect.getdoc( + documented + ) # also dedents the docstring + if documented.__doc__: + documented.__doc__ %= self # insert snippets after dedent return obj def __setitem__(self, key, value): diff --git a/ultraplot/internals/docstring.pyi b/ultraplot/internals/docstring.pyi new file mode 100644 index 000000000..490eb362b --- /dev/null +++ b/ultraplot/internals/docstring.pyi @@ -0,0 +1,70 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for modifying ultraplot docstrings. +""" +from _typeshed import Incomplete +import inspect +import re +from typing import Any, Callable, TypeVar, cast, overload +from . import ic +_F = TypeVar('_F', bound=Callable[..., Any]) +_T = TypeVar('_T') + +def _obfuscate_kwargs(func: _F) -> _F: + """Mark keyword arguments as compact in generated API documentation.""" + ... + +def _obfuscate_params(func: _F) -> _F: + """Mark all parameters as compact in generated API documentation.""" + ... + +def _obfuscate_signature(func: _F, dummy: Callable[..., Any]) -> _F: + """Mark a misleading or incomplete signature as compact in generated docs. + +The callable's actual signature remains available to Python and language +servers; Sphinx reads the marker below when rendering API headings.""" + ... + +def _concatenate_inherited(func: _F, prepend_summary: bool=False) -> _F: + """Concatenate docstrings from a matplotlib axes method with a ultraplot +axes method and mark its generated-documentation signature as compact.""" + ... + +class _SnippetManager(dict): + """A simple database for handling documentation snippets.""" + _lazy_modules = {'axes': 'ultraplot.axes.base', 'cartesian': 'ultraplot.axes.cartesian', 'polar': 'ultraplot.axes.polar', 'geo': 'ultraplot.axes.geo', 'plot': 'ultraplot.axes.plot', 'figure': 'ultraplot.figure', 'gridspec': 'ultraplot.gridspec', 'legend': 'ultraplot.legend', 'ticker': 'ultraplot.ticker', 'proj': 'ultraplot.proj', 'colors': 'ultraplot.colors', 'utils': 'ultraplot.utils', 'config': 'ultraplot.config', 'demos': 'ultraplot.demos', 'rc': 'ultraplot.axes.base'} + + def __missing__(self, key: Incomplete) -> Incomplete: + """Attempt to import modules that populate missing snippet keys.""" + ... + + @overload + def __call__(self, obj: str) -> str: + """Add snippets to the string or object using ``%(name)s`` substitution. Here +``%(name)s`` is used rather than ``.format`` to support invalid identifiers.""" + ... + + @overload + def __call__(self, obj: _T) -> _T: + """Add snippets to the string or object using ``%(name)s`` substitution. Here +``%(name)s`` is used rather than ``.format`` to support invalid identifiers.""" + ... + + def __setitem__(self, key: Incomplete, value: Incomplete) -> None: + """Populate input strings with other snippets and strip newlines. Developers +should take care to import modules in the correct order.""" + ... +_snippet_manager = _SnippetManager() +_units_docstring = ... + +def _aliases_note(*names: Incomplete) -> str: + """Render a compact ``Aliases: ...`` note for a style parameter. The canonical +name leads the numpydoc field; the common documented synonyms go here so the +parameter reads cleanly instead of opening with a pile of alias names.""" + ... +_line_docstring = ... +_patch_docstring = ... +_pcolor_collection_docstring = ... +_contour_collection_docstring = ... +_text_docstring = ... diff --git a/ultraplot/internals/fonts.pyi b/ultraplot/internals/fonts.pyi new file mode 100644 index 000000000..11c3564e2 --- /dev/null +++ b/ultraplot/internals/fonts.pyi @@ -0,0 +1,74 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Overrides related to math fonts. +""" +from _typeshed import Incomplete +import matplotlib as mpl +from matplotlib.font_manager import findfont, ttfFontProperty +from matplotlib.mathtext import MathTextParser +from . import warnings +try: + from matplotlib._mathtext import BakomaFonts, UnicodeFonts +except ImportError: + from matplotlib.mathtext import UnicodeFonts + BakomaFonts = None +WARN_MATHPARSER = True +WARN_BAKOMA = True +_CM_SYMBOLS = frozenset(('\\sum', '\\prod', '\\coprod', '\\int', '\\oint', '\\bigcup', '\\bigcap', '\\bigvee', '\\bigwedge', '\\biguplus', '\\bigoplus', '\\bigotimes', '\\bigodot')) + +def _is_cm_mathtext_enabled() -> bool: + ... + +def _clear_math_parse_cache() -> None: + ... + +class _UnicodeFonts(UnicodeFonts): + """A simple [UnicodeFonts](https://matplotlib.org/stable/api/_as_gen/matplotlib._mathtext.UnicodeFonts.html) subclass that +interprets ``rc['mathtext.default'] != 'regular'`` in the presence of +``rc['mathtext.fontset'] == 'custom'`` as possibly modifying the active font. + +Works by permitting the ``rc['mathtext.rm']``, ``rc['mathtext.it']``, +etc. settings to have the dummy value ``'regular'`` instead of a valid family +name, e.g. ``rc['mathtext.it'] == 'regular:italic'`` (permitted through an +override of the [validate_font_properties](https://matplotlib.org/stable/api/_as_gen/matplotlib.rcsetup.validate_font_properties.html) validator). +When this dummy value is detected then the font properties passed to +[TrueTypeFont](https://matplotlib.org/stable/api/_as_gen/matplotlib._mathtext.TrueTypeFont.html) are taken by replacing ``'regular'`` +in the "math" fontset with the active font name.""" + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +default_font_prop : `~.font_manager.FontProperties` + The default non-math font, or the base font for Unicode (generic) + font rendering. +load_glyph_flags : `.ft2font.LoadFlags` + Flags passed to the glyph loader (e.g. ``FT_Load_Glyph`` and + ``FT_Load_Char`` for FreeType-based fonts).""" + ... + + def _init_computer_modern_fonts(self, *args: Incomplete, **kwargs: Incomplete) -> None: + ... + + def _collect_replacements(self) -> tuple[dict, dict]: + ... + + def _replace_fonts(self, regular: dict) -> None: + ... + + def _uses_cm_symbol(self, sym: str) -> bool: + ... + + def _get_glyph(self, fontname: str, font_class: str, sym: str) -> Incomplete: + ... + + def get_sized_alternatives_for_symbol(self, fontname: str, sym: str) -> Incomplete: + """Override if your font provides multiple sizes of the same +symbol. Should return a list of symbols matching *sym* in +various sizes. The expression renderer will select the most +appropriate size for a given situation from this list.""" + ... +try: + mapping = MathTextParser._font_type_mapping +except (KeyError, AttributeError): + WARN_MATHPARSER = False diff --git a/ultraplot/internals/guides.pyi b/ultraplot/internals/guides.pyi new file mode 100644 index 000000000..6125dd80e --- /dev/null +++ b/ultraplot/internals/guides.pyi @@ -0,0 +1,51 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilties related to legends and colorbars. +""" +from _typeshed import Incomplete +import matplotlib.artist as martist +import matplotlib.colorbar as mcolorbar +import matplotlib.legend as mlegend +import matplotlib.ticker as mticker +import numpy as np +from . import ic +from . import warnings +REMOVE_AFTER_FLUSH = ('pad', 'space', 'width', 'length', 'shrink', 'align', 'queue') +GUIDE_ALIASES = (('title', 'label'), ('locator', 'ticks'), ('format', 'formatter', 'ticklabels')) + +def _add_guide_kw(name: Incomplete, kwargs: Incomplete, **opts: Incomplete) -> None: + """Add to the `colorbar_kw` or `legend_kw` dict if there are no conflicts.""" + ... + +def _cache_guide_kw(obj: Incomplete, name: Incomplete, kwargs: Incomplete) -> None: + """Cache settings on the object from the input keyword arguments.""" + ... + +def _flush_guide_kw(obj: Incomplete, name: Incomplete, kwargs: Incomplete) -> Incomplete: + """Flux settings cached on the object into the keyword arguments.""" + ... + +def _update_kw(kwargs: Incomplete, overwrite: Incomplete=False, **opts: Incomplete) -> None: + """Add the keyword arguments to the dictionary if not already present.""" + ... + +def _iter_children(*args: Incomplete) -> Incomplete: + """Iterate through `_children` of `HPacker`, `VPacker`, and `DrawingArea`. +This is used to update legend handle properties.""" + ... + +def _iter_iterables(*args: Incomplete) -> Incomplete: + """Iterate over arbitrary nested lists of iterables. Used for deciphering legend input. +Things can get complicated with e.g. bar colunns plus negative-positive colors.""" + ... + +def _update_ticks(self, manual_only: Incomplete=False) -> None: + """Refined colorbar tick updater without subclassing.""" + ... + +class _InsetColorbar(martist.Artist): + """Legend-like class for managing inset colorbars.""" + +class _CenteredLegend(martist.Artist): + """Legend-like class for managing centered-row legends.""" diff --git a/ultraplot/internals/inputs.py b/ultraplot/internals/inputs.py index e3dd461b6..16d1bf686 100644 --- a/ultraplot/internals/inputs.py +++ b/ultraplot/internals/inputs.py @@ -5,6 +5,7 @@ import functools import sys +from typing import Any, Callable, TypeVar, cast import numpy as np import numpy.ma as ma @@ -21,6 +22,8 @@ except ModuleNotFoundError: Triangulation = object +_F = TypeVar("_F", bound=Callable[..., Any]) + # Constants BASEMAP_FUNCS = ( # default latlon=True @@ -289,13 +292,15 @@ def _parse_triangulation_inputs(*args, **kwargs): return triangulation, z, args[1:], kwargs -def _parse_triangulation_with_preprocess(*keys, keywords=None, allow_extra=True): +def _parse_triangulation_with_preprocess( + *keys, keywords=None, allow_extra=True +) -> Callable[[_F], _F]: """ Combines _parse_triangulation with _preprocess_or_redirect for backwards compatibility. """ - def _decorator(func): - def triangulation_wrapper(self, *args, **kwargs): + def _decorator(func: _F) -> _F: + def triangulation_wrapper(self, *args, **kwargs) -> Any: triangulation, z, remaining_args, updated_kwargs = ( _parse_triangulation_inputs(*args, **kwargs) ) @@ -318,14 +323,14 @@ def _tri_cartopy_default(args, kwargs): # Finally make sure all other metadata is correct functools.update_wrapper(final_wrapper, func) - return final_wrapper + return cast(_F, final_wrapper) return _decorator def _preprocess_or_redirect( *keys, keywords=None, allow_extra=True, cartopy_default_transform=True -): +) -> Callable[[_F], _F]: """ Redirect internal plotting calls to native matplotlib methods. Also convert keyword args to positional and pass arguments through 'data' dictionary. @@ -336,12 +341,12 @@ def _preprocess_or_redirect( if isinstance(keywords, str): keywords = (keywords,) - def _decorator(func): + def _decorator(func: _F) -> _F: name = func.__name__ from . import _kwargs_to_args @functools.wraps(func) - def _preprocess_or_redirect(self, *args, **kwargs): + def _preprocess_or_redirect(self, *args, **kwargs) -> Any: if getattr(self, "_internal_call", None): # Redirect internal matplotlib call to native function from ..axes import PlotAxes @@ -404,7 +409,7 @@ def _preprocess_or_redirect(self, *args, **kwargs): # Call main function return func(self, *args, **kwargs) # call unbound method - return _preprocess_or_redirect + return cast(_F, _preprocess_or_redirect) return _decorator diff --git a/ultraplot/internals/inputs.pyi b/ultraplot/internals/inputs.pyi new file mode 100644 index 000000000..c8b3e26e6 --- /dev/null +++ b/ultraplot/internals/inputs.pyi @@ -0,0 +1,194 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for processing input data passed to plotting commands. +""" +from _typeshed import Incomplete +import functools +import sys +from typing import Any, Callable, TypeVar, cast +import numpy as np +import numpy.ma as ma +from . import ic +from . import _not_none, warnings +try: + from cartopy.crs import PlateCarree +except ModuleNotFoundError: + PlateCarree = object +try: + from matplotlib.tri import Triangulation +except ModuleNotFoundError: + Triangulation = object +_F = TypeVar('_F', bound=Callable[..., Any]) +BASEMAP_FUNCS = ('barbs', 'contour', 'contourf', 'hexbin', 'imshow', 'pcolor', 'pcolormesh', 'plot', 'quiver', 'scatter', 'streamplot', 'step') +CARTOPY_FUNCS = ('barbs', 'contour', 'contourf', 'fill', 'fill_between', 'fill_betweenx', 'imshow', 'pcolor', 'pcolormesh', 'plot', 'quiver', 'scatter', 'streamplot', 'step', 'tricontour', 'tricontourf', 'tripcolor') + +def _load_objects() -> None: + """Load array-like objects.""" + ... + +def _is_numeric(data: Incomplete) -> Incomplete: + """Test whether input is numeric array rather than datetime or strings.""" + ... + +def _is_categorical(data: Incomplete) -> Incomplete: + """Test whether input is array of strings.""" + ... + +def _is_descending(data: Incomplete) -> bool: + """Test whether the input data is descending. This is used for auto axis reversal.""" + ... + +def _to_duck_array(data: Incomplete, strip_units: Incomplete=False) -> Incomplete: + """Convert arbitrary input to duck array. Preserve array containers with metadata.""" + ... + +def _to_numpy_array(data: Incomplete, strip_units: Incomplete=False) -> Incomplete: + """Convert arbitrary input to numpy array. Preserve masked arrays and unit arrays.""" + ... + +def _to_masked_array(data: Incomplete, *, copy: Incomplete=False) -> Incomplete: + """Convert numpy array to masked array with consideration for datetimes and quantities.""" + ... + +def _to_edges(x: Incomplete, y: Incomplete, z: Incomplete) -> Incomplete: + """Enforce that coordinates are edges. Convert from centers if possible.""" + ... + +def _to_centers(x: Incomplete, y: Incomplete, z: Incomplete) -> Incomplete: + """Enforce that coordinates are centers. Convert from edges if possible.""" + ... + +def _from_data(data: Incomplete, *args: Incomplete) -> Incomplete: + """Try to convert positional `key` arguments to `data[key]`. If argument is string +it could be a valid positional argument like `fmt` so do not raise error.""" + ... + +def _parse_triangulation_inputs(*args: Incomplete, **kwargs: Incomplete) -> tuple[Triangulation, Any, tuple[Any, ...], dict[str, Any]]: + """Parse inputs using Matplotlib's `get_from_args_and_kwargs` method. +Returns a Triangulation object, z values, and updated args/kwargs.""" + ... + +def _parse_triangulation_with_preprocess(*keys: Incomplete, keywords: Incomplete=None, allow_extra: Incomplete=True) -> Callable[[_F], _F]: + """Combines _parse_triangulation with _preprocess_or_redirect for backwards compatibility.""" + ... + +def _preprocess_or_redirect(*keys: Incomplete, keywords: Incomplete=None, allow_extra: Incomplete=True, cartopy_default_transform: Incomplete=True) -> Callable[[_F], _F]: + """Redirect internal plotting calls to native matplotlib methods. Also convert +keyword args to positional and pass arguments through 'data' dictionary.""" + ... + +def _dist_finite(distribution: Incomplete, weights: Incomplete=None) -> Incomplete: + """Return the finite subset of the distribution together with the matching +subset of the weights. Used to sanitize input for `_dist_kde`.""" + ... + +def _dist_kde(distribution: Incomplete, *, coords: Incomplete=None, points: Incomplete=None, margin: Incomplete=0.0, bw_method: Incomplete=None, weights: Incomplete=None) -> Incomplete: + """Return the coordinates and gaussian kernel density estimate of the input +distribution. This is the single entry point for the kernel density +estimates drawn by [hist](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.hist) and +[ridgeline](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.axes.PlotAxes.html#ultraplot.axes.PlotAxes.ridgeline). + +Parameters +---------- +distribution : array-like + The sample. Flattened to 1D and stripped of non-finite values. +coords : array-like, optional + The coordinates to evaluate the estimate on. If ``None`` an evenly + spaced grid is built from the data range (see `points` and `margin`). +points : int, default: [kde.points](https://ultraplot.readthedocs.io/en/stable/search.html?q=kde.points) + The number of evenly spaced evaluation coordinates. Larger values give + smoother curves at the cost of speed. Ignored if `coords` was passed. +margin : float, default: 0 + The fraction of the data range used to pad either side of the + evaluation grid. Ignored if `coords` was passed. +bw_method : str, float, or callable, optional + The bandwidth selector passed to [scipy.stats.gaussian_kde](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html). Can be + ``'scott'``, ``'silverman'``, a scalar, or a callable. +weights : array-like, optional + The per-sample weights passed to [scipy.stats.gaussian_kde](https://docs.scipy.org/doc/scipy/reference/generated/scipy.stats.gaussian_kde.html). + +Returns +------- +coords : ndarray + The evaluation coordinates. +density : ndarray + The probability density evaluated on `coords`. Integrates to ``1``.""" + ... + +def _dist_clean(distribution: Incomplete) -> Incomplete: + """Clean the distribution data for processing by `boxplot` or `violinplot`. +Handles np.ndarrays where the ndarray is a list of lists of variable sizes.""" + ... + +def _dist_reduce(data: Incomplete, *, mean: Incomplete=None, means: Incomplete=None, median: Incomplete=None, medians: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Reduce statistical distributions to means and medians. Tack on a +distribution keyword argument for processing down the line.""" + ... + +def _dist_range(data: Incomplete, distribution: Incomplete, *, errdata: Incomplete=None, absolute: Incomplete=False, label: Incomplete=False, stds: Incomplete=None, pctiles: Incomplete=None, stds_default: Incomplete=None, pctiles_default: Incomplete=None) -> Incomplete: + """Return a plottable characteristic range for the statistical distribution +relative to the input coordinate (generally a mean or median).""" + ... + +def _safe_mask(mask: Incomplete, *args: Incomplete) -> Incomplete: + """Safely apply the mask to the input arrays, accounting for existing masked +or invalid values. Values matching ``False`` are set to `np.nan`.""" + ... + +def _safe_range(data: Incomplete, lo: Incomplete=0, hi: Incomplete=100) -> Incomplete: + """Safely return the minimum and maximum (default) or percentile range accounting +for masked values. Use min and max functions when possible for speed. Return +``None`` if we fail to get a valid range.""" + ... + +def _meta_coords(*args: Incomplete, which: Incomplete='x', **kwargs: Incomplete) -> Incomplete: + """Return the index arrays associated with string coordinates and +keyword arguments updated with index locators and formatters.""" + ... + +def _meta_labels(data: Incomplete, axis: Incomplete=0, always: Incomplete=True) -> Incomplete: + """Return the array-like "labels" along axis `axis`. If `always` is ``False`` +we return ``None`` for simple ndarray input.""" + ... + +def _meta_title(data: Incomplete, include_units: Incomplete=True) -> str | None: + """Return the "title" of an array-like object with metadata. +Include units in the title if `include_units` is ``True``.""" + ... + +def _meta_units(data: Incomplete) -> Incomplete: + """Get the unit string from the [xarray.DataArray](https://docs.xarray.dev/en/stable/generated/xarray.DataArray.html) attributes or the +[pint.Quantity](https://pint.readthedocs.io/en/stable/search.html?q=pint.Quantity). Format the latter with [unitformat](https://ultraplot.readthedocs.io/en/stable/search.html?q=unitformat).""" + ... + +def _geo_basemap_1d(x: Incomplete, *ys: Incomplete, xmin: Incomplete=-180, xmax: Incomplete=180) -> Incomplete: + """Fix basemap geographic 1D data arrays.""" + ... + +def _geo_basemap_2d(x: Incomplete, y: Incomplete, *zs: Incomplete, xmin: Incomplete=-180, xmax: Incomplete=180, globe: Incomplete=False) -> Incomplete: + """Fix basemap geographic 2D data arrays.""" + ... + +def _geo_cartopy_1d(x: Incomplete, *ys: Incomplete) -> Incomplete: + """Fix cartopy geographic 1D data arrays.""" + ... + +def _geo_cartopy_2d(x: Incomplete, y: Incomplete, *zs: Incomplete, globe: Incomplete=False) -> Incomplete: + """Fix cartopy geographic 2D data arrays.""" + ... + +def _geo_clip(*ys: Incomplete) -> Incomplete: + """Ensure latitudes fall within ``-90`` to ``90``. Important if we +add graticule edges with `edges`.""" + ... + +def _geo_inbounds(x: Incomplete, y: Incomplete, xmin: Incomplete=-180, xmax: Incomplete=180) -> Incomplete: + """Fix conflicts with map coordinates by rolling the data to fall between the +minimum and maximum longitudes and masking out-of-bounds data points.""" + ... + +def _geo_globe(x: Incomplete, y: Incomplete, z: Incomplete, xmin: Incomplete=-180, modulo: Incomplete=False) -> Incomplete: + """Ensure global coverage by fixing gaps over poles and across +longitude seams. Increases the size of the arrays.""" + ... diff --git a/ultraplot/internals/kwargs.py b/ultraplot/internals/kwargs.py index 82396b837..7b98eb04b 100644 --- a/ultraplot/internals/kwargs.py +++ b/ultraplot/internals/kwargs.py @@ -10,9 +10,12 @@ import functools import inspect +from typing import Any, Callable, TypeVar, cast from . import warnings +_F = TypeVar("_F", bound=Callable[..., Any]) + __all__ = [ "_not_none", "_alias_kwargs", @@ -52,7 +55,7 @@ def _not_none(*args, default=None, **kwargs): return first -def _alias_kwargs(**aliases): +def _alias_kwargs(**aliases) -> Callable[[_F], _F]: """ Fold keyword-argument aliases into their canonical names before a call. @@ -71,7 +74,7 @@ def _alias_kwargs(**aliases): # so the first non-``None`` one wins, exactly like `_not_none`. lookup = {syn: canon for canon, syns in aliases.items() for syn in syns} - def decorator(func): + def decorator(func: _F) -> _F: @functools.wraps(func) def wrapper(*args, **kwargs): for syn, canon in lookup.items(): @@ -91,7 +94,7 @@ def wrapper(*args, **kwargs): ) return func(*args, **kwargs) - return wrapper + return cast(_F, wrapper) return decorator diff --git a/ultraplot/internals/kwargs.pyi b/ultraplot/internals/kwargs.pyi new file mode 100644 index 000000000..08cc9e62b --- /dev/null +++ b/ultraplot/internals/kwargs.pyi @@ -0,0 +1,68 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Keyword-argument and alias resolution utilities. + +These helpers centralize how ultraplot resolves keyword aliases, folds synonym +keywords into canonical names, and pops parameters/properties out of ``**kwargs``. +They live in their own module (rather than the ``internals`` grab-bag) because +they form a single cohesive concern and are imported throughout the package. +""" +from _typeshed import Incomplete +import functools +import inspect +from typing import Any, Callable, TypeVar, cast +from . import warnings +_F = TypeVar('_F', bound=Callable[..., Any]) +__all__ = ['_not_none', '_alias_kwargs', '_alias_maps', '_get_aliases', '_kwargs_to_args', '_pop_kwargs', '_pop_params', '_pop_props'] + +def _not_none(*args: Incomplete, default: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Return the first non-``None`` value. This is used with keyword arg aliases and +for setting default values. Use `kwargs` to issue warnings when multiple passed.""" + ... + +def _alias_kwargs(**aliases: Incomplete) -> Callable[[_F], _F]: + """Fold keyword-argument aliases into their canonical names before a call. + +Each keyword maps a canonical parameter name to a tuple of accepted synonyms, +e.g. ``@_alias_kwargs(figwidth=("width",), refnum=("ref",))``. A synonym passed +by the caller is renamed to its canonical name. Passing a canonical together +with a synonym (or two synonyms) warns and keeps the canonical / first value, +matching the precedence and warning of `_not_none`. This replaces the repetitive +``x = _not_none(x=x, y=y)`` boilerplate at the top of aliased functions. + +This handles keyword aliases only: a canonical argument passed *positionally* +is not deduplicated against its synonyms, and a synonym must not shadow a +different real parameter of the wrapped function.""" + ... +_alias_maps = {'rgba': {'red': ('r',), 'green': ('g',), 'blue': ('b',), 'alpha': ('a',)}, 'hsla': {'hue': ('h',), 'saturation': ('s', 'c', 'chroma'), 'luminance': ('l',), 'alpha': ('a',)}, 'patch': {'alpha': ('a', 'alphas', 'fa', 'facealpha', 'facealphas', 'fillalpha', 'fillalphas'), 'color': ('c', 'colors'), 'edgecolor': ('ec', 'edgecolors'), 'facecolor': ('fc', 'facecolors', 'fillcolor', 'fillcolors'), 'hatch': ('h', 'hatching'), 'linestyle': ('ls', 'linestyles'), 'linewidth': ('lw', 'linewidths', 'ew', 'edgewidth', 'edgewidths'), 'zorder': ('z', 'zorders')}, 'line': {'alpha': ('a', 'alphas'), 'color': ('c', 'colors'), 'dashes': ('d', 'dash'), 'drawstyle': ('ds', 'drawstyles'), 'fillstyle': ('fs', 'fillstyles', 'mfs', 'markerfillstyle', 'markerfillstyles'), 'linestyle': ('ls', 'linestyles'), 'linewidth': ('lw', 'linewidths'), 'marker': ('m', 'markers'), 'markersize': ('s', 'ms', 'markersizes'), 'markeredgewidth': ('ew', 'edgewidth', 'edgewidths', 'mew', 'markeredgewidths'), 'markeredgecolor': ('ec', 'edgecolor', 'edgecolors', 'mec', 'markeredgecolors'), 'markerfacecolor': ('fc', 'facecolor', 'facecolors', 'fillcolor', 'fillcolors', 'mc', 'markercolor', 'markercolors', 'mfc', 'markerfacecolors'), 'zorder': ('z', 'zorders')}, 'collection': {'alpha': ('a', 'alphas'), 'colors': ('c', 'color'), 'edgecolors': ('ec', 'edgecolor', 'mec', 'markeredgecolor', 'markeredgecolors'), 'facecolors': ('fc', 'facecolor', 'fillcolor', 'fillcolors', 'mc', 'markercolor', 'markercolors', 'mfc', 'markerfacecolor', 'markerfacecolors'), 'linestyles': ('ls', 'linestyle'), 'linewidths': ('lw', 'linewidth', 'ew', 'edgewidth', 'edgewidths', 'mew', 'markeredgewidth', 'markeredgewidths'), 'marker': ('m', 'markers'), 'sizes': ('s', 'ms', 'markersize', 'markersizes'), 'zorder': ('z', 'zorders')}, 'text': {'color': ('c', 'fontcolor'), 'fontfamily': ('family', 'name', 'fontname'), 'fontsize': ('size',), 'fontstretch': ('stretch',), 'fontstyle': ('style',), 'fontvariant': ('variant',), 'fontweight': ('weight',), 'fontproperties': ('fp', 'font', 'font_properties'), 'zorder': ('z', 'zorders')}} +_INTERNAL_POP_PARAMS = frozenset({'default_cmap', 'default_discrete', 'inbounds', 'plot_contours', 'plot_lines', 'skip_autolev', 'to_centers'}) + +def _signature_cached(func: Incomplete) -> Incomplete: + """Cache inspect.signature lookups for hot utility paths.""" + ... + +def _get_signature(func: Incomplete) -> Incomplete: + """Return a signature, normalizing bound methods to their underlying function.""" + ... + +def _get_aliases(category: Incomplete, *keys: Incomplete) -> Incomplete: + """Get all available aliases.""" + ... + +def _kwargs_to_args(options: Incomplete, *args: Incomplete, allow_extra: Incomplete=False, **kwargs: Incomplete) -> Incomplete: + """Translate keyword arguments to positional arguments. Permit omitted +arguments so that plotting functions can infer values.""" + ... + +def _pop_kwargs(kwargs: Incomplete, *keys: Incomplete, **aliases: Incomplete) -> Incomplete: + """Pop the input properties and return them in a new dictionary.""" + ... + +def _pop_params(kwargs: Incomplete, *funcs: Incomplete, ignore_internal: Incomplete=False) -> Incomplete: + """Pop parameters of the input functions or methods.""" + ... + +def _pop_props(input: Incomplete, *categories: Incomplete, prefix: Incomplete=None, ignore: Incomplete=None, skip: Incomplete=None) -> Incomplete: + """Pop the registered properties and return them in a new dictionary.""" + ... diff --git a/ultraplot/internals/labels.pyi b/ultraplot/internals/labels.pyi new file mode 100644 index 000000000..6024e4713 --- /dev/null +++ b/ultraplot/internals/labels.pyi @@ -0,0 +1,30 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities related to matplotlib text labels. +""" +from _typeshed import Incomplete +import matplotlib.patheffects as mpatheffects +import matplotlib.text as mtext +from matplotlib.font_manager import FontProperties +from ..config import rc +from . import ic +LABEL_PSEUDO_PROPS = frozenset({'border', 'bordercolor', 'borderinvert', 'borderwidth', 'borderstyle', 'bbox', 'bboxcolor', 'bboxstyle', 'bboxalpha', 'bboxpad'}) + +def _split_label_props(kwargs: Incomplete) -> Incomplete: + """Split a kwargs dict into (label_props, text_kwargs) so the latter can be +passed to `mtext.Text(...)` and the former applied via `_update_label`.""" + ... + +def merge_font_properties(dest_fp: FontProperties, src_fp: FontProperties) -> FontProperties: + ... + +def _transfer_label(src: mtext.Text, dest: mtext.Text) -> None: + """Transfer the input text object properties and content to the destination +text object. Then clear the input object text.""" + ... + +def _update_label(text: Incomplete, props: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Add a monkey patch for ``Text.update`` with pseudo "border" and "bbox" +properties without wrapping the entire class. This facillitates inset titles.""" + ... diff --git a/ultraplot/internals/rcsetup.pyi b/ultraplot/internals/rcsetup.pyi new file mode 100644 index 000000000..b867076a4 --- /dev/null +++ b/ultraplot/internals/rcsetup.pyi @@ -0,0 +1,220 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for global configuration. +""" +from _typeshed import Incomplete +import functools +import re +import sys +from collections.abc import MutableMapping +from numbers import Integral, Real +import matplotlib as mpl +import matplotlib.rcsetup as msetup +import numpy as np +from cycler import Cycler +from matplotlib import RcParams +from matplotlib import rcParamsDefault as _rc_matplotlib_native +from matplotlib.colors import Colormap +from matplotlib.font_manager import font_scalings +if hasattr(mpl, '_fontconfig_pattern'): + from matplotlib._fontconfig_pattern import parse_fontconfig_pattern +else: + from matplotlib.fontconfig_pattern import parse_fontconfig_pattern +from . import ic, warnings +from .versions import _version_mpl +REGEX_NAMED_COLOR = re.compile('\\A[a-zA-Z0-9:_ -]*\\Z') +VALIDATE_REGISTERED_CMAPS = False +VALIDATE_REGISTERED_COLORS = False +BLACK = 'black' +CYCLE = 'colorblind' +CMAPCYC = 'twilight' +CMAPDIV = 'BuRd' +CMAPSEQ = 'Fire' +CMAPCAT = 'colorblind10' +DIVERGING = 'div' +FRAMEALPHA = 0.8 +FONTNAME = 'sans-serif' +FONTSIZE = 9.0 +GRIDALPHA = 0.1 +GRIDBELOW = 'line' +GRIDPAD = 3.0 +GRIDRATIO = 0.5 +GRIDSTYLE = '-' +LABELPAD = 4.0 +LARGESIZE = 'med-large' +LINEWIDTH = 0.6 +MARGIN = 0.05 +MATHTEXT = False +SMALLSIZE = 'medium' +TICKDIR = 'out' +TICKLEN = 4.0 +TICKLENRATIO = 0.5 +TICKMINOR = True +TICKPAD = 2.0 +TICKWIDTHRATIO = 0.8 +TITLEPAD = 5.0 +WHITE = 'white' +ZLINES = 2 +ZPATCHES = 1 +LEGEND_LOCS = {'fill': 'fill', 'inset': 'best', 'i': 'best', 0: 'best', 1: 'upper right', 2: 'upper left', 3: 'lower left', 4: 'lower right', 5: 'center left', 6: 'center right', 7: 'lower center', 8: 'upper center', 9: 'center', 'l': 'left', 'r': 'right', 'b': 'bottom', 't': 'top', 'c': 'center', 'ur': 'upper right', 'ul': 'upper left', 'll': 'lower left', 'lr': 'lower right', 'cr': 'center right', 'cl': 'center left', 'uc': 'upper center', 'lc': 'lower center', 'ol': 'outer left', 'or': 'outer right'} +TEXT_LOCS = ... +COLORBAR_LOCS = ... +PANEL_LOCS = ... +ALIGN_LOCS = ... +EM_KEYS = ('legend.borderpad', 'legend.labelspacing', 'legend.handlelength', 'legend.handleheight', 'legend.handletextpad', 'legend.borderaxespad', 'legend.columnspacing') +PT_KEYS = ('font.size', 'xtick.major.size', 'xtick.minor.size', 'ytick.major.size', 'ytick.minor.size', 'xtick.major.pad', 'xtick.minor.pad', 'ytick.major.pad', 'ytick.minor.pad', 'xtick.major.width', 'xtick.minor.width', 'ytick.major.width', 'ytick.minor.width', 'axes.labelpad', 'axes.titlepad', 'axes.linewidth', 'grid.linewidth', 'patch.linewidth', 'hatch.linewidth', 'lines.linewidth', 'contour.linewidth') +FONT_KEYS = set() + +def _get_default_param(key: Incomplete) -> Incomplete: + """Get the default parameter from one of three places. This is used for +the :rc: role when compiling docs and when saving ultraplotrc files.""" + ... + +def _validate_abc(value: Incomplete) -> Incomplete: + """Validate a-b-c setting.""" + ... + +def _validate_belongs(*options: Incomplete) -> Incomplete: + """Return a validator ensuring the item belongs in the list.""" + ... +_CFTIME_RESOLUTIONS = ('SECONDLY', 'MINUTELY', 'HOURLY', 'DAILY', 'MONTHLY', 'YEARLY') + +def _validate_cftime_resolution_format(units: dict) -> dict: + ... + +def _validate_cftime_resolution(unit: str) -> str: + ... + +def _validate_cmap(subtype: Incomplete, cycle: Incomplete=False) -> Incomplete: + """Validate the colormap or cycle. Possibly skip name registration check +and assign the colormap name rather than a colormap instance.""" + ... + +def _validate_color(value: Incomplete, alternative: Incomplete=None) -> Incomplete: + """Validate the color. Possibly skip name registration check.""" + ... + +def _validate_bool_or_iterable(value: Incomplete) -> Incomplete: + ... + +def _validate_bool_or_string(value: Incomplete) -> Incomplete: + ... + +def _validate_fontprops(s: Incomplete) -> Incomplete: + """Parse font property with support for ``'regular'`` placeholder.""" + ... + +def _validate_fontsize(value: Incomplete) -> Incomplete: + """Validate font size with new scalings and permitting other units.""" + ... + +def _validate_labels(labels: Incomplete, lon: Incomplete=True) -> Incomplete: + """Convert labels argument to length-4 boolean array.""" + ... + +def _validate_or_none(validator: Incomplete) -> Incomplete: + """Allow none otherwise pass to the input validator.""" + ... + +def _validate_float_or_iterable(value: Incomplete) -> Incomplete: + ... + +def _validate_string_or_iterable(value: Incomplete) -> Incomplete: + ... + +def _validate_rotation(value: Incomplete) -> Incomplete: + """Valid rotation arguments.""" + ... + +def _validate_units(dest: Incomplete) -> Incomplete: + """Validate the input using the units function.""" + ... + +def _validate_float_or_auto(value: Incomplete) -> Incomplete: + ... + +def _validate_tuple_int_2(value: Incomplete) -> Incomplete: + ... + +def _validate_tuple_float_2(value: Incomplete) -> Incomplete: + ... + +def _rst_table() -> Incomplete: + """Return the setting names and descriptions in an RST-style table.""" + ... + +def _to_string(value: Incomplete) -> Incomplete: + """Translate setting to a string suitable for saving.""" + ... + +def _yaml_table(rcdict: Incomplete, comment: Incomplete=True, description: Incomplete=False) -> Incomplete: + """Return the settings as a nicely tabulated YAML-style table.""" + ... + +class _RcParams(MutableMapping, dict): + """A simple dictionary with locked inputs and validated assignments.""" + + def __init__(self, source: Incomplete, validate: Incomplete) -> None: + ... + + def __repr__(self) -> Incomplete: + ... + + def __str__(self) -> Incomplete: + ... + + def __len__(self) -> Incomplete: + ... + + def __iter__(self) -> Incomplete: + ... + + def __getitem__(self, key: Incomplete) -> Incomplete: + ... + + def __setitem__(self, key: Incomplete, value: Incomplete) -> Incomplete: + ... + + @staticmethod + def _check_key(key: Incomplete, value: Incomplete=None) -> Incomplete: + ... + + def copy(self) -> Incomplete: + ... +_validate_pt = _validate_units('pt') +_validate_em = _validate_units('em') +_validate_in = _validate_units('in') +_validate_bool = msetup.validate_bool +_validate_int = msetup.validate_int +_validate_float = msetup.validate_float +_validate_string = msetup.validate_string +_validate_fontname = msetup.validate_stringlist +_validate_fontweight = getattr(msetup, 'validate_fontweight', _validate_string) +_validate_boxstyle = _validate_belongs('square', 'circle', 'round', 'round4', 'sawtooth', 'roundtooth') +_validate_joinstyle = _validate_belongs('miter', 'round', 'bevel') +if hasattr(msetup, '_validate_linestyle'): + _validate_linestyle = msetup._validate_linestyle +else: + _validate_linestyle = _validate_belongs('-', ':', '--', '-.', 'solid', 'dashed', 'dashdot', 'dotted', 'none', ' ', '') + +def _validator_accepts(validator: Incomplete, value: Incomplete) -> Incomplete: + ... +_validate = RcParams.validate +_rc_matplotlib_default = {'axes.axisbelow': GRIDBELOW, 'axes.formatter.use_mathtext': MATHTEXT, 'axes.grid': True, 'axes.grid.which': 'major', 'axes.edgecolor': BLACK, 'axes.labelcolor': BLACK, 'axes.labelpad': LABELPAD, 'axes.labelsize': SMALLSIZE, 'axes.labelweight': 'normal', 'axes.linewidth': LINEWIDTH, 'axes.titlepad': TITLEPAD, 'axes.titlesize': LARGESIZE, 'axes.titleweight': 'normal', 'axes.xmargin': MARGIN, 'axes.ymargin': MARGIN, 'errorbar.capsize': 3.0, 'figure.autolayout': False, 'figure.figsize': (4.0, 4.0), 'figure.dpi': 100, 'figure.facecolor': '#f4f4f4', 'figure.titlesize': LARGESIZE, 'figure.titleweight': 'bold', 'font.serif': ['TeX Gyre Schola', 'TeX Gyre Bonum', 'TeX Gyre Termes', 'TeX Gyre Pagella', 'DejaVu Serif', 'Bitstream Vera Serif', 'Computer Modern Roman', 'Bookman', 'Century Schoolbook L', 'Charter', 'ITC Bookman', 'New Century Schoolbook', 'Nimbus Roman No9 L', 'Noto Serif', 'Palatino', 'Source Serif Pro', 'Times New Roman', 'Times', 'Utopia', 'serif'], 'font.sans-serif': ['TeX Gyre Heros', 'DejaVu Sans', 'Bitstream Vera Sans', 'Computer Modern Sans Serif', 'Arial', 'Avenir', 'Fira Math', 'Fira Sans', 'Frutiger', 'Geneva', 'Gill Sans', 'Helvetica', 'Lucid', 'Lucida Grande', 'Myriad Pro', 'Noto Sans', 'Roboto', 'Source Sans Pro', 'Tahoma', 'Trebuchet MS', 'Ubuntu', 'Univers', 'Verdana', 'sans-serif'], 'font.cursive': ['TeX Gyre Chorus', 'Apple Chancery', 'Felipa', 'Sand', 'Script MT', 'Textile', 'Zapf Chancery', 'cursive'], 'font.fantasy': ['TeX Gyre Adventor', 'Avant Garde', 'Charcoal', 'Chicago', 'Comic Sans MS', 'Futura', 'Humor Sans', 'Impact', 'Optima', 'Western', 'xkcd', 'fantasy'], 'font.monospace': ['TeX Gyre Cursor', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', 'Computer Modern Typewriter', 'Andale Mono', 'Courier New', 'Courier', 'Fixed', 'Nimbus Mono L', 'Terminal', 'monospace'], 'font.family': FONTNAME, 'font.size': FONTSIZE, 'grid.alpha': GRIDALPHA, 'grid.color': BLACK, 'grid.linestyle': GRIDSTYLE, 'grid.linewidth': LINEWIDTH, 'hatch.color': BLACK, 'hatch.linewidth': LINEWIDTH, 'image.cmap': CMAPSEQ, 'image.interpolation': 'none', 'lines.linestyle': '-', 'lines.linewidth': 1.5, 'lines.markersize': 6.0, 'legend.borderaxespad': 0, 'legend.borderpad': 0.5, 'legend.columnspacing': 1.5, 'legend.edgecolor': BLACK, 'legend.facecolor': WHITE, 'legend.fancybox': False, 'legend.fontsize': SMALLSIZE, 'legend.framealpha': FRAMEALPHA, 'legend.handleheight': 1.0, 'legend.handlelength': 2.0, 'legend.handletextpad': 0.5, 'mathtext.default': 'it', 'mathtext.fontset': 'custom', 'mathtext.bf': 'regular:bold', 'mathtext.cal': 'cursive', 'mathtext.it': 'regular:italic', 'mathtext.rm': 'regular', 'mathtext.sf': 'regular', 'mathtext.tt': 'monospace', 'patch.linewidth': LINEWIDTH, 'savefig.bbox': None, 'savefig.directory': '', 'savefig.dpi': 1000, 'savefig.facecolor': WHITE, 'savefig.format': 'pdf', 'savefig.transparent': False, 'xtick.color': BLACK, 'xtick.direction': TICKDIR, 'xtick.labelsize': SMALLSIZE, 'xtick.major.pad': TICKPAD, 'xtick.major.size': TICKLEN, 'xtick.major.width': LINEWIDTH, 'xtick.minor.pad': TICKPAD, 'xtick.minor.size': TICKLEN * TICKLENRATIO, 'xtick.minor.width': LINEWIDTH * TICKWIDTHRATIO, 'xtick.minor.visible': TICKMINOR, 'ytick.color': BLACK, 'ytick.direction': TICKDIR, 'ytick.labelsize': SMALLSIZE, 'ytick.major.pad': TICKPAD, 'ytick.major.size': TICKLEN, 'ytick.major.width': LINEWIDTH, 'ytick.minor.pad': TICKPAD, 'ytick.minor.size': TICKLEN * TICKLENRATIO, 'ytick.minor.width': LINEWIDTH * TICKWIDTHRATIO, 'ytick.minor.visible': TICKMINOR} +_addendum_rotation = " Must be 'vertical', 'horizontal', or a float indicating degrees." +_addendum_em = ' Interpreted by `~ultraplot.utils.units`. Numeric units are em-widths.' +_addendum_in = ' Interpreted by `~ultraplot.utils.units`. Numeric units are inches.' +_addendum_pt = ' Interpreted by `~ultraplot.utils.units`. Numeric units are points.' +_addendum_font = ' Must be a :ref:`relative font size ` or unit string interpreted by `~ultraplot.utils.units`. Numeric units are points.' +_rc_ultraplot_table = {'navigation.preview': (True, _validate_bool, 'Whether to simplify dense artists and ticks while interactively panning or rotating. Disable for exact rendering during navigation.'), 'curved_quiver.arrowsize': (1.0, _validate_float, 'Default size scaling for arrows in curved quiver plots.'), 'curved_quiver.arrowstyle': ('-|>', _validate_string, 'Default arrow style for curved quiver plots.'), 'curved_quiver.scale': (1.0, _validate_float, 'Default scale factor for curved quiver plots.'), 'curved_quiver.grains': (15, _validate_int, 'Default number of grains (segments) for curved quiver arrows.'), 'curved_quiver.density': (10, _validate_int, 'Default density of arrows for curved quiver plots.'), 'curved_quiver.arrows_at_end': (True, _validate_bool, 'Whether to draw arrows at the end of curved quiver lines by default.'), 'external.shrink': (0.9, _validate_float, 'Default shrink factor for external axes containers.'), 'sankey.nodepad': (0.02, _validate_float, 'Vertical padding between nodes in layered sankey diagrams.'), 'sankey.nodewidth': (0.03, _validate_float, 'Node width for layered sankey diagrams (axes-relative units).'), 'sankey.margin': (0.05, _validate_float, 'Margin around layered sankey diagrams (axes-relative units).'), 'sankey.flow.alpha': (0.75, _validate_float, 'Flow transparency for layered sankey diagrams.'), 'sankey.flow.curvature': (0.5, _validate_float, 'Flow curvature for layered sankey diagrams.'), 'sankey.node.facecolor': ('0.75', _validate_color, 'Default node facecolor for layered sankey diagrams.'), 'ribbon.xmargin': (0.12, _validate_float, 'Horizontal margin around ribbon diagrams (axes-relative units).'), 'ribbon.ymargin': (0.08, _validate_float, 'Vertical margin around ribbon diagrams (axes-relative units).'), 'ribbon.rowheightratio': (2.2, _validate_float, 'Height scale factor controlling ribbon row occupancy.'), 'ribbon.nodewidth': (0.018, _validate_float, 'Node width for ribbon diagrams (axes-relative units).'), 'ribbon.flow.curvature': (0.45, _validate_float, 'Flow curvature for ribbon diagrams.'), 'ribbon.flow.alpha': (0.58, _validate_float, 'Flow transparency for ribbon diagrams.'), 'ribbon.topic_labels': (True, _validate_bool, 'Whether to draw topic labels on the right side of ribbon diagrams.'), 'ribbon.topic_label_offset': (0.028, _validate_float, 'Offset for right-side ribbon topic labels.'), 'ribbon.topic_label_size': (7.4, _validate_float, 'Font size for ribbon topic labels.'), 'ribbon.topic_label_box': (True, _validate_bool, 'Whether to draw backing boxes behind ribbon topic labels.'), 'style': (None, _validate_or_none(_validate_string), "The default matplotlib `stylesheet `__ name. If ``None``, a custom ultraplot style is used. If ``'default'``, the default matplotlib style is used."), 'abc': (False, _validate_abc, "If ``False`` then a-b-c labels are disabled. If ``True`` the default label style `a` is used. If string this indicates the style and must contain the character `a` or ``A``, for example ``'a.'`` or ``'(A)'``."), 'abc.border': (True, _validate_bool, 'Whether to draw a white border around a-b-c labels when :rcraw:`abc.loc` is inside the axes.'), 'abc.borderwidth': (1.5, _validate_pt, 'Width of the white border around a-b-c labels.'), 'text.borderstyle': ('bevel', _validate_joinstyle, "Join style for text border strokes. Must be one of ``'miter'``, ``'round'``, or ``'bevel'``."), 'text.align': (False, _validate_bool, 'Whether text and annotations avoid overlapping each other and the data by default. Set to ``True`` to opt every label into the solver used by `~ultraplot.axes.Axes.auto_align_text`.'), 'text.align.pad': (2.0, _validate_pt, 'Padding in points kept around auto-aligned text.'), 'text.align.maxiter': (60, _validate_int, 'Maximum number of relaxation iterations used to auto-align text.'), 'text.align.arrows': (False, _validate_bool, 'Whether auto-aligned text draws a connector back to the point it labels.'), 'text.curved.upright': (True, _validate_bool, 'Whether curved text is flipped to remain upright by default.'), 'text.curved.ellipsis': (False, _validate_bool, 'Whether to show ellipses when curved text exceeds path length.'), 'text.curved.avoid_overlap': (True, _validate_bool, 'Whether curved text hides overlapping glyphs by default.'), 'text.curved.overlap_tol': (0.1, _validate_float, 'Overlap threshold used when hiding curved-text glyphs.'), 'text.curved.curvature_pad': (2.0, _validate_float, 'Extra curved-text glyph spacing per radian of local curvature.'), 'text.curved.min_advance': (1.0, _validate_float, 'Minimum extra curved-text glyph spacing in pixels.'), 'abc.bbox': (False, _validate_bool, 'Whether to draw semi-transparent bounding boxes around a-b-c labels when :rcraw:`abc.loc` is inside the axes.'), 'abc.bboxcolor': (WHITE, _validate_color, 'a-b-c label bounding box color.'), 'abc.bboxstyle': ('square', _validate_boxstyle, 'a-b-c label bounding box style.'), 'abc.bboxalpha': (0.5, _validate_float, 'a-b-c label bounding box opacity.'), 'abc.bboxpad': (None, _validate_or_none(_validate_pt), 'Padding for the a-b-c label bounding box. By default this is scaled to make the box flush against the subplot edge.' + _addendum_pt), 'abc.color': (BLACK, _validate_color, 'a-b-c label color.'), 'abc.loc': ('left', _validate_belongs(*TEXT_LOCS), 'a-b-c label position. For options see the :ref:`location table `.'), 'abc.size': (LARGESIZE, _validate_fontsize, 'a-b-c label font size.' + _addendum_font), 'abc.titlepad': (LABELPAD, _validate_pt, 'Padding separating the title and a-b-c label when in the same location.' + _addendum_pt), 'abc.weight': ('bold', _validate_fontweight, 'a-b-c label font weight.'), 'autoformat': (True, _validate_bool, 'Whether to automatically apply labels from `pandas.Series`, `pandas.DataFrame`, and `xarray.DataArray` objects passed to plotting functions. See also :rcraw:`unitformat`.'), 'axes.alpha': (None, _validate_or_none(_validate_float), 'Opacity of the background axes patch.'), 'axes.inbounds': (True, _validate_bool, 'Whether to exclude out-of-bounds data when determining the default *y* (*x*) axis limits and the *x* (*y*) axis limits have been locked.'), 'axes.margin': (MARGIN, _validate_float, 'The fractional *x* and *y* axis margins when limits are unset.'), 'axes.sticky_edges': (True, _validate_bool, 'Whether artists added by plotting commands like `plot`, `plotx`, `vlines`, `hlines`, `fill_between`, and `fill_betweenx` are given "sticky" edges, i.e. whether the default axis limits are the artist bounds with no padding. See also `Axes.use_sticky_edges`.'), 'bar.bar_labels': (False, _validate_bool, 'Add value of the bars to the bar labels'), 'borders': (False, _validate_bool, 'Toggles country border lines on and off.'), 'borders.alpha': (None, _validate_or_none(_validate_float), 'Opacity for country border lines.'), 'borders.color': (BLACK, _validate_color, 'Line color for country border lines.'), 'borders.linewidth': (LINEWIDTH, _validate_pt, 'Line width for country border lines.'), 'borders.zorder': (ZLINES, _validate_float, 'Z-order for country border lines.'), 'borders.rasterized': (False, _validate_bool, 'Toggles rasterization on or off for border feature in GeoAxes.'), 'bottomlabel.color': (BLACK, _validate_color, 'Font color for column labels on the bottom of the figure.'), 'bottomlabel.pad': (TITLEPAD, _validate_pt, 'Padding between axes content and column labels on the bottom of the figure.' + _addendum_pt), 'bottomlabel.sharedpad': (2 * TITLEPAD, _validate_pt, 'Padding between column labels and a shared x label on the bottom of the figure.' + _addendum_pt), 'bottomlabel.rotation': ('horizontal', _validate_rotation, 'Rotation for column labels at the bottom of the figure.' + _addendum_rotation), 'bottomlabel.size': (LARGESIZE, _validate_fontsize, 'Font size for column labels on the bottom of the figure.' + _addendum_font), 'bottomlabel.weight': ('bold', _validate_fontweight, 'Font weight for column labels on the bottom of the figure.'), 'cftime.time_unit': ('days since 2000-01-01', _validate_string, 'Time unit for non-Gregorian calendars.'), 'cftime.resolution': ('DAILY', _validate_cftime_resolution, 'Default time resolution for non-Gregorian calendars.'), 'cftime.time_resolution_format': ({'SECONDLY': '%S', 'MINUTELY': '%M', 'HOURLY': '%H', 'DAILY': '%d', 'MONTHLY': '%m', 'YEARLY': '%Y'}, _validate_cftime_resolution_format, 'Dict used for formatting non-Gregorian calendars.'), 'cftime.max_display_ticks': (7, _validate_int, 'Number of ticks to display for cftime units.'), 'coast': (False, _validate_bool, 'Toggles coastline lines on and off.'), 'coast.alpha': (None, _validate_or_none(_validate_float), 'Opacity for coast lines'), 'coast.color': (BLACK, _validate_color, 'Line color for coast lines.'), 'coast.linewidth': (LINEWIDTH, _validate_pt, 'Line width for coast lines.'), 'coast.zorder': (ZLINES, _validate_float, 'Z-order for coast lines.'), 'coast.rasterized': (False, _validate_bool, 'Toggles the rasterization of the coastlines feature for GeoAxes.'), 'colorbar.center_levels': (False, _validate_bool, 'Center the ticks in the center of each segment.'), 'colorbar.edgecolor': (BLACK, _validate_color, 'Color for the inset colorbar frame edge.'), 'colorbar.extend': (1.3, _validate_em, 'Length of rectangular or triangular "extensions" for panel colorbars.' + _addendum_em), 'colorbar.outline': (True, _validate_bool, 'Whether to draw a frame around the colorbar.'), 'colorbar.labelrotation': ('auto', _validate_float_or_auto, 'Rotation of colorbar labels.'), 'colorbar.fancybox': (False, _validate_bool, 'Whether to use a "fancy" round bounding box for inset colorbar frames.'), 'colorbar.framealpha': (FRAMEALPHA, _validate_float, 'Opacity for inset colorbar frames.'), 'colorbar.facecolor': (WHITE, _validate_color, 'Color for the inset colorbar frame.'), 'colorbar.frameon': (True, _validate_bool, 'Whether to draw a frame behind inset colorbars.'), 'colorbar.grid': (False, _validate_bool, 'Whether to draw borders between each level of the colorbar.'), 'colorbar.insetextend': (0.9, _validate_em, 'Length of rectangular or triangular "extensions" for inset colorbars.' + _addendum_em), 'colorbar.insetlength': (8, _validate_em, 'Length of inset colorbars.' + _addendum_em), 'colorbar.insetpad': (0.7, _validate_em, 'Padding between axes edge and inset colorbars.' + _addendum_em), 'colorbar.insetwidth': (1.2, _validate_em, 'Width of inset colorbars.' + _addendum_em), 'colorbar.length': (1, _validate_em, 'Length of outer colorbars.'), 'colorbar.loc': ('right', _validate_belongs(*COLORBAR_LOCS), 'Inset colorbar location. For options see the :ref:`location table `.'), 'colorbar.width': (0.2, _validate_in, 'Width of outer colorbars.' + _addendum_in), 'colorbar.rasterized': (False, _validate_bool, 'Whether to use rasterization for colorbar solids.'), 'colorbar.shadow': (False, _validate_bool, 'Whether to add a shadow underneath inset colorbar frames.'), 'legend.cat.line': (False, _validate_bool, 'Default line/marker mode for `Axes.catlegend`.'), 'legend.cat.marker': ('o', _validate_string, 'Default marker for `Axes.catlegend` entries.'), 'legend.cat.linestyle': ('-', _validate_linestyle, 'Default line style for `Axes.catlegend` entries.'), 'legend.cat.linewidth': (2.0, _validate_float, 'Default line width for `Axes.catlegend` entries.'), 'legend.cat.markersize': (6.0, _validate_float, 'Default marker size for `Axes.catlegend` entries.'), 'legend.cat.alpha': (None, _validate_or_none(_validate_float), 'Default alpha for `Axes.catlegend` entries.'), 'legend.cat.markeredgecolor': (None, _validate_or_none(_validate_color), 'Default marker edge color for `Axes.catlegend` entries.'), 'legend.cat.markeredgewidth': (None, _validate_or_none(_validate_float), 'Default marker edge width for `Axes.catlegend` entries.'), 'legend.size.color': ('0.35', _validate_color, 'Default marker color for `Axes.sizelegend` entries.'), 'legend.size.marker': ('o', _validate_string, 'Default marker for `Axes.sizelegend` entries.'), 'legend.size.area': (True, _validate_bool, 'Whether `Axes.sizelegend` interprets levels as marker area by default.'), 'legend.size.scale': (1.0, _validate_float, 'Default marker size scale factor for `Axes.sizelegend` entries.'), 'legend.size.minsize': (3.0, _validate_float, 'Default minimum marker size for `Axes.sizelegend` entries.'), 'legend.size.format': (None, _validate_or_none(_validate_string), 'Default label format string for `Axes.sizelegend` entries.'), 'legend.size.alpha': (None, _validate_or_none(_validate_float), 'Default alpha for `Axes.sizelegend` entries.'), 'legend.size.markeredgecolor': (None, _validate_or_none(_validate_color), 'Default marker edge color for `Axes.sizelegend` entries.'), 'legend.size.markeredgewidth': (None, _validate_or_none(_validate_float), 'Default marker edge width for `Axes.sizelegend` entries.'), 'legend.num.n': (5, _validate_int, 'Default number of sampled levels for `Axes.numlegend`.'), 'legend.num.cmap': ('viridis', _validate_cmap('continuous'), 'Default colormap for `Axes.numlegend` entries.'), 'legend.num.edgecolor': ('none', _validate_or_none(_validate_color), 'Default edge color for `Axes.numlegend` patch entries.'), 'legend.num.linewidth': (0.0, _validate_float, 'Default edge width for `Axes.numlegend` patch entries.'), 'legend.num.alpha': (None, _validate_or_none(_validate_float), 'Default alpha for `Axes.numlegend` entries.'), 'legend.num.format': (None, _validate_or_none(_validate_string), 'Default label format string for `Axes.numlegend` entries.'), 'legend.geo.facecolor': ('none', _validate_or_none(_validate_color), 'Default face color for `Axes.geolegend` entries.'), 'legend.geo.edgecolor': ('0.25', _validate_or_none(_validate_color), 'Default edge color for `Axes.geolegend` entries.'), 'legend.geo.linewidth': (1.0, _validate_float, 'Default edge width for `Axes.geolegend` entries.'), 'legend.geo.alpha': (None, _validate_or_none(_validate_float), 'Default alpha for `Axes.geolegend` entries.'), 'legend.geo.fill': (None, _validate_or_none(_validate_bool), 'Default fill mode for `Axes.geolegend` entries.'), 'legend.geo.country_reso': ('110m', _validate_belongs('10m', '50m', '110m'), 'Default Natural Earth resolution used for country shorthand geometry entries in `Axes.geolegend`.'), 'legend.geo.country_territories': (False, _validate_bool, 'Whether country shorthand entries in `Axes.geolegend` include far-away territories instead of pruning to the local footprint.'), 'legend.geo.country_proj': (None, _validate_or_none(_validate_string), 'Optional projection name for country shorthand entries in `Axes.geolegend`. Can be overridden per call with a cartopy CRS or callable.'), 'legend.geo.handlesize': (1.0, _validate_float, 'Scale factor applied to both legend handle length and height for `Axes.geolegend` when explicit handle dimensions are not provided.'), 'cycle': (CYCLE, _validate_cmap('discrete', cycle=True), 'Name of the color cycle assigned to :rcraw:`axes.prop_cycle`.'), 'cmap': (CMAPSEQ, _validate_cmap('continuous'), 'Alias for :rcraw:`cmap.sequential` and :rcraw:`image.cmap`.'), 'cmap.autodiverging': (True, _validate_bool, 'Whether to automatically apply a diverging colormap and normalizer based on the data.'), 'cmap.qualitative': (CMAPCAT, _validate_cmap('discrete'), 'Default colormap for qualitative datasets.'), 'cmap.cyclic': (CMAPCYC, _validate_cmap('continuous'), 'Default colormap for cyclic datasets.'), 'cmap.discrete': (None, _validate_or_none(_validate_bool), 'If ``True``, `~ultraplot.colors.DiscreteNorm` is used for every colormap plot. If ``False``, it is never used. If ``None``, it is used for all plot types except `imshow`, `matshow`, `spy`, `hexbin`, and `hist2d`.'), 'cmap.diverging': (CMAPDIV, _validate_cmap('continuous'), 'Default colormap for diverging datasets.'), 'cmap.inbounds': (True, _validate_bool, 'If ``True`` and the *x* and *y* axis limits are fixed, only in-bounds data is considered when determining the default colormap `vmin` and `vmax`.'), 'cmap.levels': (11, _validate_int, 'Default number of `~ultraplot.colors.DiscreteNorm` levels for plotting commands that use colormaps.'), 'cmap.listedthresh': (64, _validate_int, 'Native `~matplotlib.colors.ListedColormap`\\ s with more colors than this are converted to :class:`~ultraplot.colors.ContinuousColormap` rather than :class:`~ultraplot.colors.DiscreteColormap`. This helps translate continuous colormaps from external projects.'), 'cmap.lut': (256, _validate_int, 'Number of colors in the colormap lookup table. Alias for :rcraw:`image.lut`.'), 'cmap.robust': (False, _validate_bool, 'If ``True``, the default colormap `vmin` and `vmax` are chosen using the 2nd to 98th percentiles rather than the minimum and maximum.'), 'cmap.sequential': (CMAPSEQ, _validate_cmap('continuous'), 'Default colormap for sequential datasets. Alias for :rcraw:`image.cmap`.'), 'edgefix': (True, _validate_bool, 'Whether to fix issues with "white lines" appearing between patches in saved vector graphics and with vector graphic backends. Applies to colorbar levels and bar, area, pcolor, and contour plots.'), 'font.name': (FONTNAME, _validate_fontname, 'Alias for :rcraw:`font.family`.'), 'font.small': (SMALLSIZE, _validate_fontsize, 'Alias for :rcraw:`font.smallsize`.'), 'font.smallsize': (SMALLSIZE, _validate_fontsize, "Meta setting that changes the label-like sizes ``axes.labelsize``, ``legend.fontsize``, ``tick.labelsize``, and ``grid.labelsize``. Default is ``'medium'`` (equivalent to :rcraw:`font.size`)." + _addendum_font), 'font.large': (LARGESIZE, _validate_fontsize, 'Alias for :rcraw:`font.largesize`.'), 'font.largesize': (LARGESIZE, _validate_fontsize, "Meta setting that changes the title-like sizes ``abc.size``, ``title.size``, ``suptitle.size``, ``leftlabel.size``, ``rightlabel.size``, etc. Default is ``'med-large'`` (i.e. 1.1 times :rcraw:`font.size`)." + _addendum_font), 'formatter.timerotation': ('vertical', _validate_rotation, 'Rotation for *x* axis datetime tick labels.' + _addendum_rotation), 'formatter.zerotrim': (True, _validate_bool, 'Whether to trim trailing decimal zeros on tick labels.'), 'formatter.log': (False, _validate_bool, 'Whether to use log formatting (e.g., $10^{4}$) for logarithmically scaled axis tick labels.'), 'formatter.limits': ([-5, 6], _validate['axes.formatter.limits'], 'Alias for :rcraw:`axes.formatter.limits`.'), 'formatter.min_exponent': (0, _validate['axes.formatter.min_exponent'], 'Alias for :rcraw:`axes.formatter.min_exponent`.'), 'formatter.offset_threshold': (4, _validate['axes.formatter.offset_threshold'], 'Alias for :rcraw:`axes.formatter.offset_threshold`.'), 'formatter.use_locale': (False, _validate_bool, 'Alias for :rcraw:`axes.formatter.use_locale`.'), 'formatter.use_mathtext': (MATHTEXT, _validate_bool, 'Alias for :rcraw:`axes.formatter.use_mathtext`.'), 'formatter.use_offset': (True, _validate_bool, 'Alias for :rcraw:`axes.formatter.useOffset`.'), 'mathtext.cm_symbols': (False, _validate_bool, 'Whether to render ``\\mathcal`` and big operator symbols (``\\sum``, ``\\int``, ``\\bigcup``, etc.) with Computer Modern while preserving the active font for ordinary letters and numbers. Unlike ``mathtext.fontset: cm`` this does not affect the rest of the math text.'), 'geo.backend': ('cartopy', _validate_belongs('cartopy', 'basemap'), "The backend used for `~ultraplot.axes.GeoAxes`. Must be either 'cartopy' or 'basemap'. .. deprecated:: 3.0.0 The 'basemap' backend is deprecated and may be removed in a future release. Please use 'cartopy' instead."), 'geo.extent': ('globe', _validate_belongs('globe', 'auto'), "If ``'globe'``, the extent of cartopy `~ultraplot.axes.GeoAxes` is always global. If ``'auto'``, the extent is automatically adjusted based on plotted content. Default is ``'globe'``."), 'geo.round': (True, _validate_bool, "If ``True`` (the default), polar `~ultraplot.axes.GeoAxes` like ``'npstere'`` and ``'spstere'`` are bounded with circles rather than squares."), 'geo.choropleth.country_reso': ('110m', _validate_belongs('10m', '50m', '110m'), 'Default Natural Earth resolution used by `GeoAxes.choropleth` when country identifiers are resolved to polygons.'), 'geo.choropleth.country_territories': (False, _validate_bool, 'Whether `GeoAxes.choropleth` keeps distant territories when resolving country identifiers into Natural Earth geometries.'), 'geo.choropleth.zorder': (None, _validate_or_none(_validate_float), 'Default z-order for `GeoAxes.choropleth`. When ``None``, the choropleth is drawn just above the land feature.'), 'graph.draw_nodes': (True, _validate_bool_or_iterable, 'If ``True`` draws the nodes for all the nodes, otherwise only the nodes that are in the iterable.'), 'graph.draw_edges': (True, _validate_bool_or_iterable, 'If ``True`` draws the edges for all the edges, otherwise only the edges that are in the iterable.'), 'graph.draw_labels': (False, _validate_bool_or_iterable, 'If ``True`` draws the labels for all the nodes, otherwise only the nodes that are in the iterable.'), 'graph.draw_grid': (False, _validate_bool, 'If ``True`` draws the grid for all the edges, otherwise only the edges that are in the iterable.'), 'graph.aspect': ('equal', _validate_belongs('equal', 'auto'), 'The aspect ratio of the graph.'), 'graph.facecolor': ('none', _validate_color, 'The facecolor of the graph.'), 'graph.draw_spines': (False, _validate_bool_or_iterable, 'If ``True`` draws the spines for all the edges, otherwise only the edges that are in the iterable.'), 'graph.rescale': (True, _validate_bool, 'If ``True`` rescales the graph to fit the data.'), 'grid': (True, _validate_bool, 'Toggle major gridlines on and off.'), 'grid.below': (GRIDBELOW, _validate_belongs(False, 'line', True), "Alias for :rcraw:`axes.axisbelow`. If ``True``, draw gridlines below everything. If ``True``, draw them above everything. If ``'line'``, draw them above patches but below lines and markers."), 'grid.checkoverlap': (True, _validate_bool, 'Whether to have cartopy automatically check for and remove overlapping `~ultraplot.axes.GeoAxes` gridline labels.'), 'grid.dmslabels': (True, _validate_bool, 'Whether to use degrees-minutes-seconds rather than decimals for cartopy `~ultraplot.axes.GeoAxes` gridlines.'), 'grid.geolabels': (True, _validate_bool, "Whether to include the ``'geo'`` spine in cartopy >= 0.20 when otherwise toggling left, right, bottom, or top `~ultraplot.axes.GeoAxes` gridline labels."), 'grid.inlinelabels': (False, _validate_bool, 'Whether to add inline labels for cartopy `~ultraplot.axes.GeoAxes` gridlines.'), 'grid.labels': (False, _validate_bool, 'Whether to add outer labels for `~ultraplot.axes.GeoAxes` gridlines.'), 'grid.labelcolor': (BLACK, _validate_color, 'Font color for `~ultraplot.axes.GeoAxes` gridline labels.'), 'grid.labelpad': (GRIDPAD, _validate_pt, 'Padding between the map boundary and cartopy `~ultraplot.axes.GeoAxes` gridline labels.' + _addendum_pt), 'grid.labelsize': (SMALLSIZE, _validate_fontsize, 'Font size for `~ultraplot.axes.GeoAxes` gridline labels.' + _addendum_font), 'grid.labelweight': ('normal', _validate_fontweight, 'Font weight for `~ultraplot.axes.GeoAxes` gridline labels.'), 'grid.nsteps': (250, _validate_int, 'Number of points used to draw cartopy `~ultraplot.axes.GeoAxes` gridlines.'), 'grid.pad': (GRIDPAD, _validate_pt, 'Alias for :rcraw:`grid.labelpad`.'), 'grid.rotatelabels': (False, _validate_bool, 'Whether to rotate cartopy `~ultraplot.axes.GeoAxes` gridline labels.'), 'grid.style': ('-', _validate_linestyle, 'Major gridline style. Alias for :rcraw:`grid.linestyle`.'), 'grid.width': (LINEWIDTH, _validate_pt, 'Major gridline width. Alias for :rcraw:`grid.linewidth`.'), 'grid.widthratio': (GRIDRATIO, _validate_float, 'Ratio of minor gridline width to major gridline width.'), 'gridminor': (False, _validate_bool, 'Toggle minor gridlines on and off.'), 'gridminor.alpha': (GRIDALPHA, _validate_float, 'Minor gridline opacity.'), 'gridminor.color': (BLACK, _validate_color, 'Minor gridline color.'), 'gridminor.linestyle': (GRIDSTYLE, _validate_linestyle, 'Minor gridline style.'), 'gridminor.linewidth': (GRIDRATIO * LINEWIDTH, _validate_pt, 'Minor gridline width.'), 'gridminor.style': (GRIDSTYLE, _validate_linestyle, 'Minor gridline style. Alias for :rcraw:`gridminor.linestyle`.'), 'gridminor.width': (GRIDRATIO * LINEWIDTH, _validate_pt, 'Minor gridline width. Alias for :rcraw:`gridminor.linewidth`.'), 'inlineformat': ('retina', _validate_belongs('svg', 'pdf', 'retina', 'png', 'jpeg'), "The inline backend figure format. Valid formats include ``'svg'``, ``'pdf'``, ``'retina'``, ``'png'``, and ``jpeg``."), 'innerborders': (False, _validate_bool, 'Toggles internal political border lines (e.g. states and provinces) on and off.'), 'innerborders.alpha': (None, _validate_or_none(_validate_float), 'Opacity for internal political border lines'), 'innerborders.color': (BLACK, _validate_color, 'Line color for internal political border lines.'), 'innerborders.linewidth': (LINEWIDTH, _validate_pt, 'Line width for internal political border lines.'), 'innerborders.zorder': (ZLINES, _validate_float, 'Z-order for internal political border lines.'), 'kde.points': (200, _validate_int, 'Number of evenly spaced coordinates used to evaluate kernel density estimates. Larger values give smoother curves at the cost of speed.'), 'label.color': (BLACK, _validate_color, 'Alias for :rcraw:`axes.labelcolor`.'), 'label.pad': (LABELPAD, _validate_pt, 'Alias for :rcraw:`axes.labelpad`.' + _addendum_pt), 'label.size': (SMALLSIZE, _validate_fontsize, 'Alias for :rcraw:`axes.labelsize`.' + _addendum_font), 'label.weight': ('normal', _validate_fontweight, 'Alias for :rcraw:`axes.labelweight`.'), 'lakes': (False, _validate_bool, 'Toggles lake patches on and off.'), 'lakes.alpha': (None, _validate_or_none(_validate_float), 'Opacity for lake patches'), 'lakes.color': (WHITE, _validate_color, 'Face color for lake patches.'), 'lakes.zorder': (ZPATCHES, _validate_float, 'Z-order for lake patches.'), 'lakes.rasterized': (False, _validate_bool, 'Toggles rasterization on or off for lake feature'), 'land': (False, _validate_bool, 'Toggles land patches on and off.'), 'land.alpha': (None, _validate_or_none(_validate_float), 'Opacity for land patches'), 'land.color': (BLACK, _validate_color, 'Face color for land patches.'), 'land.zorder': (ZPATCHES, _validate_float, 'Z-order for land patches.'), 'land.rasterized': (False, _validate_bool, 'Toggles the rasterization of the land feature.'), 'leftlabel.color': (BLACK, _validate_color, 'Font color for row labels on the left-hand side.'), 'leftlabel.pad': (TITLEPAD, _validate_pt, 'Padding between axes content and row labels on the left-hand side.' + _addendum_pt), 'leftlabel.sharedpad': (2 * TITLEPAD, _validate_pt, 'Padding between row labels and a shared y label on the left-hand side.' + _addendum_pt), 'leftlabel.rotation': ('vertical', _validate_rotation, 'Rotation for row labels on the left-hand side.' + _addendum_rotation), 'leftlabel.size': (LARGESIZE, _validate_fontsize, 'Font size for row labels on the left-hand side.' + _addendum_font), 'lollipop.markersize': (36, _validate_float, 'Size of lollipops in the lollipop plot.'), 'lollipop.stemcolor': (BLACK, _validate_color, 'Color of lollipop lines.'), 'lollipop.stemwidth': (LINEWIDTH, _validate_pt, 'Width of the stem'), 'lollipop.stemlinestyle': ('-', _validate_linestyle, 'Line style of lollipop lines.'), 'leftlabel.weight': ('bold', _validate_fontweight, 'Font weight for row labels on the left-hand side.'), 'margin': (MARGIN, _validate_float, 'The fractional *x* and *y* axis data margins when limits are unset. Alias for :rcraw:`axes.margin`.'), 'meta.edgecolor': (BLACK, _validate_color, 'Color of axis spines, tick marks, tick labels, and labels.'), 'meta.color': (BLACK, _validate_color, 'Color of axis spines, tick marks, tick labels, and labels. Alias for :rcraw:`meta.edgecolor`.'), 'meta.linewidth': (LINEWIDTH, _validate_pt, 'Thickness of axis spines and major tick lines.'), 'meta.width': (LINEWIDTH, _validate_pt, 'Thickness of axis spines and major tick lines. Alias for :rcraw:`meta.linewidth`.'), 'negcolor': ('blue7', _validate_color, 'Color for negative bars and shaded areas when using ``negpos=True``. See also :rcraw:`poscolor`.'), 'poscolor': ('red7', _validate_color, 'Color for positive bars and shaded areas when using ``negpos=True``. See also :rcraw:`negcolor`.'), 'ocean': (False, _validate_bool, 'Toggles ocean patches on and off.'), 'ocean.alpha': (None, _validate_or_none(_validate_float), 'Opacity for ocean patches'), 'ocean.color': (WHITE, _validate_color, 'Face color for ocean patches.'), 'ocean.zorder': (ZPATCHES, _validate_float, 'Z-order for ocean patches.'), 'ocean.rasterized': (False, _validate_bool, 'Turns rasterization on or off for the oceans feature for GeoAxes.'), 'reso': ('lo', _validate_belongs('lo', 'med', 'hi', 'x-hi', 'xx-hi'), "Resolution for `~ultraplot.axes.GeoAxes` geographic features. Must be one of ``'lo'``, ``'med'``, ``'hi'``, ``'x-hi'``, or ``'xx-hi'``."), 'rightlabel.color': (BLACK, _validate_color, 'Font color for row labels on the right-hand side.'), 'rightlabel.pad': (TITLEPAD, _validate_pt, 'Padding between axes content and row labels on the right-hand side.' + _addendum_pt), 'rightlabel.sharedpad': (2 * TITLEPAD, _validate_pt, 'Padding between row labels and a shared y label on the right-hand side.' + _addendum_pt), 'rightlabel.rotation': ('vertical', _validate_rotation, 'Rotation for row labels on the right-hand side.' + _addendum_rotation), 'rightlabel.size': (LARGESIZE, _validate_fontsize, 'Font size for row labels on the right-hand side.' + _addendum_font), 'rightlabel.weight': ('bold', _validate_fontweight, 'Font weight for row labels on the right-hand side.'), 'rivers': (False, _validate_bool, 'Toggles river lines on and off.'), 'rivers.alpha': (None, _validate_or_none(_validate_float), 'Opacity for river lines.'), 'rivers.color': (BLACK, _validate_color, 'Line color for river lines.'), 'rivers.linewidth': (LINEWIDTH, _validate_pt, 'Line width for river lines.'), 'rivers.zorder': (ZLINES, _validate_float, 'Z-order for river lines.'), 'rivers.rasterized': (False, _validate_bool, 'Toggles rasterization on or off for rivers feature for GeoAxes.'), 'chord.start': (0.0, _validate_float, 'Start angle for chord diagrams.'), 'chord.end': (360.0, _validate_float, 'End angle for chord diagrams.'), 'chord.space': (0.0, _validate_float_or_iterable, 'Inter-sector spacing for chord diagrams.'), 'chord.endspace': (True, _validate_bool, 'Whether to add an ending space gap for chord diagrams.'), 'chord.r_lim': ((97.0, 100.0), _validate_tuple_float_2, 'Radial limits for chord diagrams.'), 'chord.ticks_interval': (None, _validate_or_none(_validate_int), 'Tick interval for chord diagrams.'), 'chord.order': (None, _validate_or_none(_validate_string_or_iterable), 'Ordering of sectors for chord diagrams.'), 'radar.r_lim': ((0.0, 100.0), _validate_tuple_float_2, 'Radial limits for radar charts.'), 'radar.vmin': (0.0, _validate_float, 'Minimum value for radar charts.'), 'radar.vmax': (100.0, _validate_float, 'Maximum value for radar charts.'), 'radar.fill': (True, _validate_bool, 'Whether to fill radar chart polygons.'), 'radar.marker_size': (0, _validate_int, 'Marker size for radar charts.'), 'radar.bg_color': ('#eeeeee80', _validate_or_none(_validate_color), 'Background color for radar charts.'), 'radar.circular': (False, _validate_bool, 'Whether to use circular radar charts.'), 'radar.show_grid_label': (True, _validate_bool, 'Whether to show grid labels on radar charts.'), 'radar.grid_interval_ratio': (0.2, _validate_or_none(_validate_float), 'Grid interval ratio for radar charts.'), 'phylogeny.start': (0.0, _validate_float, 'Start angle for phylogeny plots.'), 'phylogeny.end': (360.0, _validate_float, 'End angle for phylogeny plots.'), 'phylogeny.r_lim': ((50.0, 100.0), _validate_tuple_float_2, 'Radial limits for phylogeny plots.'), 'phylogeny.format': ('newick', _validate_string, 'Input format for phylogeny plots.'), 'phylogeny.outer': (True, _validate_bool, 'Whether to place phylogeny leaves on the outer edge.'), 'phylogeny.align_leaf_label': (True, _validate_bool, 'Whether to align phylogeny leaf labels.'), 'phylogeny.ignore_branch_length': (False, _validate_bool, 'Whether to ignore branch lengths in phylogeny plots.'), 'phylogeny.leaf_label_size': (None, _validate_or_none(_validate_float), 'Leaf label font size for phylogeny plots.'), 'phylogeny.leaf_label_rmargin': (2.0, _validate_float, 'Radial margin for phylogeny leaf labels.'), 'phylogeny.reverse': (False, _validate_bool, 'Whether to reverse phylogeny orientation.'), 'phylogeny.ladderize': (False, _validate_bool, 'Whether to ladderize phylogeny branches.'), 'sankey.align': ('center', _validate_belongs('center', 'left', 'right', 'justify'), 'Horizontal alignment of nodes.'), 'sankey.connect': ((0, 0), _validate_tuple_int_2, 'Connection path for Sankey diagram.'), 'sankey.flow_labels': (False, _validate_bool, 'Whether to draw flow labels.'), 'sankey.flow_label_pos': (0.5, _validate_float, 'Position of flow labels along the flow.'), 'sankey.flow_sort': (True, _validate_bool, 'Whether to sort flows.'), 'sankey.node_labels': (True, _validate_bool, 'Whether to draw node labels.'), 'sankey.node_label_offset': (0.01, _validate_float, 'Offset for node labels.'), 'sankey.node_label_outside': ('auto', _validate_bool_or_string, 'Position of node labels relative to the node.'), 'sankey.other_label': ('Other', _validate_string, "Label for 'other' category in Sankey diagram."), 'sankey.pathlabel': ('', _validate_string, 'Label for the patch.'), 'sankey.pathlengths': (0.25, _validate_float, 'Path lengths for Sankey diagram.'), 'sankey.rotation': (0.0, _validate_float, 'Rotation of the Sankey diagram.'), 'sankey.trunklength': (1.0, _validate_float, 'Trunk length for Sankey diagram.'), 'subplots.align': (False, _validate_bool, 'Whether to align axis labels during draw. See `aligning labels `__.'), 'subplots.equalspace': (False, _validate_bool, 'Whether to make the tight layout algorithm assign the same space for every row and the same space for every column.'), 'subplots.groupspace': (True, _validate_bool, 'Whether to make the tight layout algorithm consider space between only adjacent subplot "groups" rather than every subplot in the row or column.'), 'subplots.innerpad': (1, _validate_em, 'Padding between adjacent subplots.' + _addendum_em), 'subplots.outerpad': (0.5, _validate_em, 'Padding around figure edge.' + _addendum_em), 'subplots.panelpad': (0.5, _validate_em, 'Padding between subplots and panels, and between stacked panels.' + _addendum_em), 'subplots.panelwidth': (0.5, _validate_in, 'Width of side panels.' + _addendum_in), 'subplots.refwidth': (2.5, _validate_in, 'Default width of the reference subplot.' + _addendum_in), 'subplots.share': ('auto', _validate_belongs(0, 1, 2, 3, 4, False, 'labels', 'limits', True, 'all', 'auto'), "The axis sharing level, one of ``0``, ``1``, ``2``, or ``3``, or the more intuitive aliases ``False``, ``'labels'``, ``'limits'``, ``True``, or ``'auto'``. See `~ultraplot.figure.Figure` for details."), 'subplots.span': (True, _validate_bool, 'Toggles spanning axis labels. See `~ultraplot.ui.subplots` for details.'), 'subplots.tight': (True, _validate_bool, 'Whether to auto-adjust the subplot spaces and figure margins.'), 'subplots.pixelsnap': (False, _validate_bool, 'Whether to snap subplot bounds to the renderer pixel grid during draw.'), 'suptitle.color': (BLACK, _validate_color, 'Figure title color.'), 'suptitle.pad': (TITLEPAD, _validate_pt, 'Padding between axes content and the figure super title.' + _addendum_pt), 'suptitle.size': (LARGESIZE, _validate_fontsize, 'Figure title font size.' + _addendum_font), 'suptitle.weight': ('bold', _validate_fontweight, 'Figure title font weight.'), 'tick.color': (BLACK, _validate_color, 'Major and minor tick color.'), 'tick.dir': (TICKDIR, _validate_belongs('in', 'out', 'inout'), "Major and minor tick direction. Must be one of ``'out'``, ``'in'``, or ``'inout'``."), 'tick.labelcolor': (BLACK, _validate_color, 'Axis tick label color.'), 'tick.labelpad': (TICKPAD, _validate_pt, 'Padding between ticks and tick labels.' + _addendum_pt), 'tick.labelsize': (SMALLSIZE, _validate_fontsize, 'Axis tick label font size.' + _addendum_font), 'tick.labelweight': ('normal', _validate_fontweight, 'Axis tick label font weight.'), 'tick.len': (TICKLEN, _validate_pt, 'Length of major ticks in points.'), 'tick.lenratio': (TICKLENRATIO, _validate_float, 'Ratio of minor tickline length to major tickline length.'), 'tick.linewidth': (LINEWIDTH, _validate_pt, 'Major tickline width.'), 'tick.minor': (TICKMINOR, _validate_bool, 'Toggles minor ticks on and off.'), 'tick.pad': (TICKPAD, _validate_pt, 'Alias for :rcraw:`tick.labelpad`.'), 'tick.width': (LINEWIDTH, _validate_pt, 'Major tickline width. Alias for :rcraw:`tick.linewidth`.'), 'tick.widthratio': (TICKWIDTHRATIO, _validate_float, 'Ratio of minor tickline width to major tickline width.'), 'title.above': (True, _validate_belongs(False, True, 'panels'), "Whether to move outer titles and a-b-c labels above panels, colorbars, or legends that are above the axes. If the string 'panels' then text is only redirected above axes panels. Otherwise should be boolean."), 'title.border': (True, _validate_bool, 'Whether to draw a white border around titles when :rcraw:`title.loc` is inside the axes.'), 'title.borderwidth': (1.5, _validate_pt, 'Width of the border around titles.'), 'title.bbox': (False, _validate_bool, 'Whether to draw semi-transparent bounding boxes around titles when :rcraw:`title.loc` is inside the axes.'), 'title.bboxcolor': (WHITE, _validate_color, 'Axes title bounding box color.'), 'title.bboxstyle': ('square', _validate_boxstyle, 'Axes title bounding box style.'), 'title.bboxalpha': (0.5, _validate_float, 'Axes title bounding box opacity.'), 'title.bboxpad': (None, _validate_or_none(_validate_pt), 'Padding for the title bounding box. By default this is scaled to make the box flush against the axes edge.' + _addendum_pt), 'title.color': (BLACK, _validate_color, 'Axes title color. Alias for :rcraw:`axes.titlecolor`.'), 'title.loc': ('center', _validate_belongs(*TEXT_LOCS), 'Title position. For options see the :ref:`location table `.'), 'title.pad': (TITLEPAD, _validate_pt, 'Padding between the axes edge and the inner and outer titles and a-b-c labels. Alias for :rcraw:`axes.titlepad`.' + _addendum_pt), 'title.size': (LARGESIZE, _validate_fontsize, 'Axes title font size. Alias for :rcraw:`axes.titlesize`.' + _addendum_font), 'title.weight': ('normal', _validate_fontweight, 'Axes title font weight. Alias for :rcraw:`axes.titleweight`.'), 'toplabel.color': (BLACK, _validate_color, 'Font color for column labels on the top of the figure.'), 'toplabel.pad': (TITLEPAD, _validate_pt, 'Padding between axes content and column labels on the top of the figure.' + _addendum_pt), 'toplabel.sharedpad': (2 * TITLEPAD, _validate_pt, 'Padding between column labels and a shared x label on the top of the figure.' + _addendum_pt), 'toplabel.rotation': ('horizontal', _validate_rotation, 'Rotation for column labels at the top of the figure.' + _addendum_rotation), 'toplabel.size': (LARGESIZE, _validate_fontsize, 'Font size for column labels on the top of the figure.' + _addendum_font), 'toplabel.weight': ('bold', _validate_fontweight, 'Font weight for column labels on the top of the figure.'), 'unitformat': ('L', _validate_string, 'The format string used to format `pint.Quantity` default unit labels using ``format(units, unitformat)``. See also :rcraw:`autoformat`.'), 'ultraplot.check_for_latest_version': (False, _validate_bool, 'Whether to check for the latest version of UltraPlot on PyPI when importing'), 'ultraplot.eager_import': (False, _validate_bool, 'Whether to import the full public API during setup instead of lazily.')} +_rc_children = {'font.smallsize': ('tick.labelsize', 'xtick.labelsize', 'ytick.labelsize', 'axes.labelsize', 'legend.fontsize', 'grid.labelsize'), 'font.largesize': ('abc.size', 'figure.titlesize', 'suptitle.size', 'axes.titlesize', 'title.size', 'leftlabel.size', 'toplabel.size', 'rightlabel.size', 'bottomlabel.size'), 'meta.color': ('axes.edgecolor', 'axes.labelcolor', 'legend.edgecolor', 'colorbar.edgecolor', 'tick.labelcolor', 'hatch.color', 'xtick.color', 'ytick.color'), 'meta.width': ('axes.linewidth', 'tick.width', 'tick.linewidth', 'xtick.major.width', 'ytick.major.width', 'grid.width', 'grid.linewidth'), 'axes.margin': ('axes.xmargin', 'axes.ymargin'), 'grid.color': ('gridminor.color', 'grid.labelcolor'), 'grid.alpha': ('gridminor.alpha',), 'grid.linewidth': ('gridminor.linewidth',), 'grid.linestyle': ('gridminor.linestyle',), 'tick.color': ('xtick.color', 'ytick.color'), 'tick.dir': ('xtick.direction', 'ytick.direction'), 'tick.len': ('xtick.major.size', 'ytick.major.size'), 'tick.minor': ('xtick.minor.visible', 'ytick.minor.visible'), 'tick.pad': ('xtick.major.pad', 'xtick.minor.pad', 'ytick.major.pad', 'ytick.minor.pad'), 'tick.width': ('xtick.major.width', 'ytick.major.width'), 'tick.labelsize': ('xtick.labelsize', 'ytick.labelsize')} +_rc_synonyms = (('cmap', 'image.cmap', 'cmap.sequential'), ('cmap.lut', 'image.lut'), ('font.name', 'font.family'), ('font.small', 'font.smallsize'), ('font.large', 'font.largesize'), ('formatter.limits', 'axes.formatter.limits'), ('formatter.use_locale', 'axes.formatter.use_locale'), ('formatter.use_mathtext', 'axes.formatter.use_mathtext'), ('formatter.min_exponent', 'axes.formatter.min_exponent'), ('formatter.use_offset', 'axes.formatter.useoffset'), ('formatter.offset_threshold', 'axes.formatter.offset_threshold'), ('grid.below', 'axes.axisbelow'), ('grid.labelpad', 'grid.pad'), ('grid.linewidth', 'grid.width'), ('grid.linestyle', 'grid.style'), ('gridminor.linewidth', 'gridminor.width'), ('gridminor.linestyle', 'gridminor.style'), ('label.color', 'axes.labelcolor'), ('label.pad', 'axes.labelpad'), ('label.size', 'axes.labelsize'), ('label.weight', 'axes.labelweight'), ('margin', 'axes.margin'), ('meta.width', 'meta.linewidth'), ('meta.color', 'meta.edgecolor'), ('tick.labelpad', 'tick.pad'), ('tick.labelsize', 'grid.labelsize'), ('tick.labelcolor', 'grid.labelcolor'), ('tick.labelweight', 'grid.labelweight'), ('tick.linewidth', 'tick.width'), ('title.pad', 'axes.titlepad'), ('title.size', 'axes.titlesize'), ('title.weight', 'axes.titleweight')) +_rc_removed = {'rgbcycle': ('', '0.6.0'), 'geogrid.latmax': ('Please use ax.format(latmax=N) instead.', '0.6.0'), 'geogrid.latstep': ('Please use ax.format(latlines=N) instead.', '0.6.0'), 'geogrid.lonstep': ('Please use ax.format(lonlines=N) instead.', '0.6.0'), 'gridminor.latstep': ('Please use ax.format(latminorlines=N) instead.', '0.6.0'), 'gridminor.lonstep': ('Please use ax.format(lonminorlines=N) instead.', '0.6.0')} +_rc_renamed = {'abc.format': ('abc', '0.5.0'), 'align': ('subplots.align', '0.6.0'), 'axes.facealpha': ('axes.alpha', '0.6.0'), 'geoaxes.edgecolor': ('axes.edgecolor', '0.6.0'), 'geoaxes.facealpha': ('axes.alpha', '0.6.0'), 'geoaxes.facecolor': ('axes.facecolor', '0.6.0'), 'geoaxes.linewidth': ('axes.linewidth', '0.6.0'), 'geogrid.alpha': ('grid.alpha', '0.6.0'), 'geogrid.color': ('grid.color', '0.6.0'), 'geogrid.labels': ('grid.labels', '0.6.0'), 'geogrid.labelpad': ('grid.pad', '0.6.0'), 'geogrid.labelsize': ('grid.labelsize', '0.6.0'), 'geogrid.linestyle': ('grid.linestyle', '0.6.0'), 'geogrid.linewidth': ('grid.linewidth', '0.6.0'), 'share': ('subplots.share', '0.6.0'), 'small': ('font.smallsize', '0.6.0'), 'large': ('font.largesize', '0.6.0'), 'span': ('subplots.span', '0.6.0'), 'tight': ('subplots.tight', '0.6.0'), 'axes.formatter.timerotation': ('formatter.timerotation', '0.6.0'), 'axes.formatter.zerotrim': ('formatter.zerotrim', '0.6.0'), 'abovetop': ('title.above', '0.7.0'), 'subplots.pad': ('subplots.outerpad', '0.7.0'), 'subplots.axpad': ('subplots.innerpad', '0.7.0'), 'subplots.axwidth': ('subplots.refwidth', '0.7.0'), 'text.labelsize': ('font.smallsize', '0.8.0'), 'text.titlesize': ('font.largesize', '0.8.0'), 'alpha': ('axes.alpha', '0.8.0'), 'facecolor': ('axes.facecolor', '0.8.0'), 'edgecolor': ('meta.color', '0.8.0'), 'color': ('meta.color', '0.8.0'), 'linewidth': ('meta.width', '0.8.0'), 'lut': ('cmap.lut', '0.8.0'), 'image.levels': ('cmap.levels', '0.8.0'), 'image.inbounds': ('cmap.inbounds', '0.8.0'), 'image.discrete': ('cmap.discrete', '0.8.0'), 'image.edgefix': ('edgefix', '0.8.0'), 'tick.ratio': ('tick.widthratio', '0.8.0'), 'grid.ratio': ('grid.widthratio', '0.8.0'), 'abc.style': ('abc', '0.8.0'), 'grid.loninline': ('grid.inlinelabels', '0.8.0'), 'grid.latinline': ('grid.inlinelabels', '0.8.0'), 'cmap.edgefix': ('edgefix', '0.9.0'), 'basemap': ('geo.backend', '0.10.0'), 'inlinefmt': ('inlineformat', '0.10.0'), 'cartopy.circular': ('geo.round', '0.10.0'), 'cartopy.autoextent': ('geo.extent', '0.10.0'), 'colorbar.rasterize': ('colorbar.rasterized', '0.10.0')} +_rc_ultraplot_default = ... +_rc_ultraplot_validate = ... +_rc_ultraplot_default = _RcParams(_rc_ultraplot_default, _rc_ultraplot_validate) +_rc_matplotlib_default = RcParams(_rc_matplotlib_default) +_rc_categories = ... +_rc_nodots = ... diff --git a/ultraplot/internals/versions.pyi b/ultraplot/internals/versions.pyi new file mode 100644 index 000000000..3d96f6cb5 --- /dev/null +++ b/ultraplot/internals/versions.pyi @@ -0,0 +1,47 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for handling dependencies and version changes. +""" +from _typeshed import Incomplete +from . import ic +from . import warnings + +class _version(list): + """Casual parser for ``major.minor`` style version strings. We do not want to +add a 'packaging' dependency and only care about major and minor tags.""" + + def __str__(self) -> str: + ... + + def __repr__(self) -> str: + ... + + def __init__(self, version: Incomplete) -> None: + ... + + def __eq__(self, other: Incomplete) -> bool: + ... + + def __ne__(self, other: Incomplete) -> bool: + ... + + def __gt__(self, other: Incomplete) -> bool: + ... + + def __lt__(self, other: Incomplete) -> bool: + ... + + def __ge__(self, other: Incomplete) -> bool: + ... + + def __le__(self, other: Incomplete) -> bool: + ... +import matplotlib +_version_mpl = _version(matplotlib.__version__) +try: + import cartopy +except ImportError: + _version_cartopy = _version('0.0.0') +else: + _version_cartopy = _version(cartopy.__version__) diff --git a/ultraplot/internals/warnings.py b/ultraplot/internals/warnings.py index 80e32fdeb..63deb111a 100644 --- a/ultraplot/internals/warnings.py +++ b/ultraplot/internals/warnings.py @@ -7,9 +7,12 @@ import re import sys import warnings +from typing import Any, Callable, TypeVar, cast from . import ic # noqa: F401 +_F = TypeVar("_F", bound=Callable[..., Any]) + # Internal modules omitted from warning message REGEX_INTERNAL = re.compile(r"\A(matplotlib|mpl_toolkits|ultraplot)\.") @@ -92,14 +95,14 @@ def _deprecated_function(*args, new_obj=new_obj, message=message, **kwargs): return tuple(objs) -def _rename_kwargs(version, **kwargs_rename): +def _rename_kwargs(version, **kwargs_rename) -> Callable[[_F], _F]: """ Emit a basic deprecation warning after removing or renaming keyword argument(s). Each key should be an old keyword, and each argument should be the new keyword or *instructions* for what to use instead. """ - def _decorator(func_orig): + def _decorator(func_orig: _F) -> _F: @functools.wraps(func_orig) def _deprecate_kwargs_wrapper(*args, **kwargs): for key_old, key_new in kwargs_rename.items(): @@ -118,6 +121,6 @@ def _deprecate_kwargs_wrapper(*args, **kwargs): ) return func_orig(*args, **kwargs) - return _deprecate_kwargs_wrapper + return cast(_F, _deprecate_kwargs_wrapper) return _decorator diff --git a/ultraplot/internals/warnings.pyi b/ultraplot/internals/warnings.pyi new file mode 100644 index 000000000..973f6102d --- /dev/null +++ b/ultraplot/internals/warnings.pyi @@ -0,0 +1,38 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Utilities for internal warnings and deprecations. +""" +from _typeshed import Incomplete +import functools +import re +import sys +import warnings +from typing import Any, Callable, TypeVar, cast +from . import ic +_F = TypeVar('_F', bound=Callable[..., Any]) +REGEX_INTERNAL = re.compile('\\A(matplotlib|mpl_toolkits|ultraplot)\\.') +UltraPlotWarning = type('UltraPlotWarning', (UserWarning,), {}) +catch_warnings = warnings.catch_warnings +simplefilter = warnings.simplefilter + +def next_release() -> str: + """message indicating the next major release.""" + ... + +def _warn_ultraplot(message: Incomplete) -> None: + """Emit a `UltraPlotWarning` and show the stack level outside of matplotlib and +ultraplot. This is adapted from matplotlib's warning system.""" + ... + +def _rename_objs(version: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Emit a basic deprecation warning after renaming function(s), method(s), or +class(es). Each key should be an old name, and each argument should be the new +object to point to. Do not document the deprecated object(s) to discourage use.""" + ... + +def _rename_kwargs(version: Incomplete, **kwargs_rename: Incomplete) -> Callable[[_F], _F]: + """Emit a basic deprecation warning after removing or renaming keyword argument(s). +Each key should be an old keyword, and each argument should be the new keyword +or *instructions* for what to use instead.""" + ... diff --git a/ultraplot/legend.pyi b/ultraplot/legend.pyi new file mode 100644 index 000000000..f2e034b91 --- /dev/null +++ b/ultraplot/legend.pyi @@ -0,0 +1,614 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +from _typeshed import Incomplete +from collections.abc import Mapping +from dataclasses import dataclass +from functools import lru_cache +from typing import Any, Iterable, Optional, Tuple, Union +import matplotlib.patches as mpatches +import matplotlib.path as mpath +import matplotlib.text as mtext +import numpy as np +from matplotlib import cm as mcm +from matplotlib import colors as mcolors +from matplotlib.colors import is_color_like as _mpl_is_color_like +from matplotlib import lines as mlines +from matplotlib import legend as mlegend +from matplotlib import legend_handler as mhandler +from matplotlib.markers import MarkerStyle +from .config import rc +from .internals import _not_none, _pop_props, docstring, guides, inputs, rcsetup +from .utils import _fontsize_to_pt, units +try: + from typing import override +except ImportError: + from typing_extensions import override +try: + import cartopy.crs as ccrs + from cartopy.io import shapereader as cshapereader + from cartopy.mpl.feature_artist import FeatureArtist as _CartopyFeatureArtist + from cartopy.mpl.path import shapely_to_path as _cartopy_shapely_to_path +except Exception: + ccrs = None + cshapereader = None + _CartopyFeatureArtist = None + _cartopy_shapely_to_path = None +try: + from shapely.geometry.base import BaseGeometry as _ShapelyBaseGeometry + from shapely.ops import unary_union as _shapely_unary_union +except Exception: + _ShapelyBaseGeometry = None + _shapely_unary_union = None +__all__ = ['Legend', 'LegendEntry', 'GeometryEntry'] + +def _wedge_legend_patch(legend: Incomplete, orig_handle: Incomplete, xdescent: Incomplete, ydescent: Incomplete, width: Incomplete, height: Incomplete, fontsize: Incomplete) -> Incomplete: + """Draw wedge-shaped legend keys for pie wedge handles.""" + ... + +class LegendEntry(mlines.Line2D): + """Convenience artist for custom legend entries. + +This is a lightweight wrapper around [matplotlib.lines.Line2D](https://matplotlib.org/stable/api/_as_gen/matplotlib.lines.Line2D.html) that +initializes with empty data so it can be passed directly to +`Axes.legend()` or `Figure.legend()` handles.""" + + def __init__(self, label: Incomplete=None, *, color: Incomplete=None, line: Incomplete=True, marker: Incomplete=None, linestyle: Incomplete='-', linewidth: Incomplete=2, markersize: Incomplete=6, markerfacecolor: Incomplete=None, markeredgecolor: Incomplete=None, markeredgewidth: Incomplete=None, alpha: Incomplete=None, marker_capstyle: Incomplete=None, marker_joinstyle: Incomplete=None, marker_transform: Incomplete=None, **kwargs: Incomplete) -> None: + """Create a `.Line2D` instance with *x* and *y* data in sequences of *xdata*, *ydata*. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.legend.LegendEntry.html)""" + ... + + @classmethod + def line(cls, label: Incomplete=None, **kwargs: Incomplete) -> Incomplete: + """Build a line-style legend entry.""" + ... + + @classmethod + def marker(cls, label: Incomplete=None, marker: Incomplete='o', **kwargs: Incomplete) -> Incomplete: + """Build a marker-style legend entry.""" + ... + +class _Line2DLegendHandler(mhandler.HandlerLine2D): + """Match single-point marker plots by hiding the legend connector line.""" + + def create_artists(self, legend: Incomplete, orig_handle: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Return the legend artists generated. + +Parameters +---------- +legend : [Legend](https://matplotlib.org/stable/api/_as_gen/matplotlib.legend.Legend.html) + The legend for which these legend artists are being created. +orig_handle : [Artist](https://matplotlib.org/stable/api/_as_gen/matplotlib.artist.Artist.html) or similar + The object for which these legend artists are being created. +xdescent, ydescent, width, height : int + The rectangle (*xdescent*, *ydescent*, *width*, *height*) that the + legend artists being created should fit within. +fontsize : int + The fontsize in pixels. The legend artists being created should + be scaled according to the given fontsize. +trans : [Transform](https://matplotlib.org/stable/api/_as_gen/matplotlib.transforms.Transform.html) + The transform that is applied to the legend artists being created. + Typically from unit coordinates in the handler box to screen + coordinates.""" + ... +_GEOMETRY_SHAPE_PATHS = {'circle': mpath.Path.unit_circle(), 'square': mpath.Path.unit_rectangle(), 'triangle': mpath.Path.unit_regular_polygon(3), 'diamond': mpath.Path.unit_regular_polygon(4), 'pentagon': mpath.Path.unit_regular_polygon(5), 'hexagon': mpath.Path.unit_regular_polygon(6), 'star': mpath.Path.unit_regular_star(5), 'rectangle': mpath.Path([[0, 0], [2, 0], [2, 1], [0, 1], [0, 0]], closed=True, readonly=True), 'line': mpath.Path([[0, 0], [1, 0]], readonly=True)} +_GEOMETRY_SHAPE_ALIASES = {'box': 'square', 'rect': 'rectangle', 'rec': 'rectangle', 'tri': 'triangle', 'pent': 'pentagon', 'hex': 'hexagon'} +_DEFAULT_GEO_JOINSTYLE = 'bevel' + +def _normalize_shape_name(value: str) -> str: + """Normalize geometry shape shorthand names.""" + ... + +def _normalize_country_resolution(resolution: str) -> str: + """Normalize Natural Earth shorthand resolution.""" + ... + +def _country_geometry_for_legend(geometry: Any, *, include_far: bool=False) -> Any: + """Reduce multi-part country geometry for readability while preserving local islands. + +This avoids tiny legend glyphs for countries with distant overseas territories +(e.g., Netherlands in Natural Earth datasets), but tries to keep nearby islands.""" + ... + +def _resolve_country_projection(country_proj: Any) -> Any: + """Resolve shorthand strings to cartopy projections for country legend geometries.""" + ... + +def _project_geometry_for_legend(geometry: Any, country_proj: Any) -> Any: + """Project geometry for legend rendering when requested.""" + ... + +def _resolve_country_geometry(code: str, resolution: str='110m', include_far: bool=False) -> Incomplete: + """Resolve a country shorthand code (e.g., ``AU`` or ``AUS``) to a geometry.""" + ... + +def _geometry_to_path(geometry: Any, *, country_reso: str='110m', country_territories: bool=False, country_proj: Any=None) -> mpath.Path: + """Convert geometry/path shorthand input to a matplotlib path.""" + ... + +def _fit_path_to_handlebox(path: mpath.Path, *, xdescent: float, ydescent: float, width: float, height: float, pad: float=0.08, preserve_aspect: bool=True) -> mpath.Path: + """Normalize an arbitrary path into the legend-handle box.""" + ... + +def _feature_geometry_path(handle: Any) -> Optional[mpath.Path]: + """Extract the first geometry path from a cartopy feature artist.""" + ... + +def _first_scalar(value: Any, default: Any=None) -> Any: + """Return first scalar from lists/arrays used by collection-style artists.""" + ... + +def _patch_joinstyle(value: Any, default: str=_DEFAULT_GEO_JOINSTYLE) -> str: + """Resolve patch joinstyle from artist methods/kwargs with a sensible default.""" + ... + +def _patch_color(orig_handle: Any, prop: str, default: Any=None) -> Any: + """Resolve a patch color, preferring the artist's original color spec. + +Collection-like artists often report post-alpha RGBA arrays from +`get_facecolor()` / `get_edgecolor()`. If we then also copy `alpha`, the +legend proxy ends up visually double-dimmed. Prefer the original color +attributes when available so patch proxies can apply alpha once.""" + ... +_PATCH_STYLE_PROP_SPECS = {'facecolor': {'default': 'none', 'transform': None}, 'edgecolor': {'default': 'none', 'transform': None}, 'linewidth': {'default': 0.0, 'transform': _first_scalar}, 'linestyle': {'default': None, 'transform': _first_scalar}, 'hatch': {'default': None, 'transform': None}, 'hatch_linewidth': {'default': None, 'transform': None}, 'fill': {'default': None, 'transform': None}, 'alpha': {'default': None, 'transform': None}, 'capstyle': {'default': None, 'transform': None}} + +def _copy_patch_style(legend_handle: mpatches.Patch, orig_handle: Any, *, joinstyle_default: str=_DEFAULT_GEO_JOINSTYLE) -> None: + """Copy common patch-style properties from source artist to legend proxy. + +Matplotlib does not provide a reliable generic style-transfer API for +cross-family artists here. In particular, `Artist.update_from()` is not +safe for `Collection -> Patch` copies like `FeatureArtist -> PathPatch`, +and `properties()` still leaves us to normalize collection-valued fields. +So this helper intentionally copies the shared patch-style surface only.""" + ... + +def _feature_legend_patch(legend: Incomplete, orig_handle: Incomplete, xdescent: Incomplete, ydescent: Incomplete, width: Incomplete, height: Incomplete, fontsize: Incomplete) -> Incomplete: + """Draw a normalized geometry path for cartopy feature artists.""" + ... + +def _shapely_geometry_patch(legend: Incomplete, orig_handle: Incomplete, xdescent: Incomplete, ydescent: Incomplete, width: Incomplete, height: Incomplete, fontsize: Incomplete) -> Incomplete: + """Draw shapely geometry handles in legend boxes.""" + ... + +def _geometry_entry_patch(legend: Incomplete, orig_handle: Incomplete, xdescent: Incomplete, ydescent: Incomplete, width: Incomplete, height: Incomplete, fontsize: Incomplete) -> Incomplete: + """Draw a geometry entry path inside the legend-handle box.""" + ... + +class _FeatureArtistLegendHandler(mhandler.HandlerPatch): + """Legend handler for cartopy FeatureArtist instances.""" + + def __init__(self) -> None: + """Parameters +---------- +patch_func : callable, optional + The function that creates the legend key artist. + *patch_func* should have the signature:: + + def patch_func(legend=legend, orig_handle=orig_handle, + xdescent=xdescent, ydescent=ydescent, + width=width, height=height, fontsize=fontsize) + + Subsequently, the created artist will have its ``update_prop`` + method called and the appropriate transform will be applied. + +**kwargs + Keyword arguments forwarded to `.HandlerBase`.""" + ... + + def update_prop(self, legend_handle: Incomplete, orig_handle: Incomplete, legend: Incomplete) -> Incomplete: + ... + +class _ShapelyGeometryLegendHandler(mhandler.HandlerPatch): + """Legend handler for raw shapely geometries.""" + + def __init__(self) -> None: + """Parameters +---------- +patch_func : callable, optional + The function that creates the legend key artist. + *patch_func* should have the signature:: + + def patch_func(legend=legend, orig_handle=orig_handle, + xdescent=xdescent, ydescent=ydescent, + width=width, height=height, fontsize=fontsize) + + Subsequently, the created artist will have its ``update_prop`` + method called and the appropriate transform will be applied. + +**kwargs + Keyword arguments forwarded to `.HandlerBase`.""" + ... + + def update_prop(self, legend_handle: Incomplete, orig_handle: Incomplete, legend: Incomplete) -> Incomplete: + ... + +class _GeometryEntryLegendHandler(mhandler.HandlerPatch): + """Legend handler for `GeometryEntry` custom handles.""" + + def __init__(self) -> None: + """Parameters +---------- +patch_func : callable, optional + The function that creates the legend key artist. + *patch_func* should have the signature:: + + def patch_func(legend=legend, orig_handle=orig_handle, + xdescent=xdescent, ydescent=ydescent, + width=width, height=height, fontsize=fontsize) + + Subsequently, the created artist will have its ``update_prop`` + method called and the appropriate transform will be applied. + +**kwargs + Keyword arguments forwarded to `.HandlerBase`.""" + ... + + def update_prop(self, legend_handle: Incomplete, orig_handle: Incomplete, legend: Incomplete) -> Incomplete: + ... + +class GeometryEntry(mpatches.PathPatch): + """Convenience geometry legend entry. + +Parameters +---------- +geometry + Geometry shorthand (e.g. ``'triangle'`` or ``'country:AU'``), + shapely geometry, or [matplotlib.path.Path](https://matplotlib.org/stable/api/_as_gen/matplotlib.path.Path.html).""" + + def __init__(self, geometry: Any='square', *, country_reso: str='110m', country_territories: bool=False, country_proj: Any=None, label: Optional[str]=None, facecolor: Any='none', edgecolor: Any='0.25', linewidth: float=1.0, joinstyle: str=_DEFAULT_GEO_JOINSTYLE, alpha: Optional[float]=None, fill: Optional[bool]=None, **kwargs: Any) -> None: + """*path* is a `.Path` object. + +Valid keyword arguments are: + +Properties: + agg_filter: a filter function, which takes a (m, n, 3) float array and a dpi value, and returns a (m, n, 3) array and two offsets from the bottom left corner of the image + alpha: unknown + animated: bool + antialiased or aa: bool or None + capstyle: `.CapStyle` or {'butt', 'projecting', 'round'} + clip_box: [BboxBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.transforms.BboxBase.html) or None + clip_on: bool + clip_path: Patch or (Path, Transform) or None + color: [color](https://matplotlib.org/stable/search.html?q=color) + edgecolor or ec: [color](https://matplotlib.org/stable/search.html?q=color) or None + facecolor or fc: [color](https://matplotlib.org/stable/search.html?q=color) or None + figure: [Figure](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.Figure.html) or [SubFigure](https://matplotlib.org/stable/api/_as_gen/matplotlib.figure.SubFigure.html) + fill: bool + gid: str + hatch: {'/', '\\\\', '|', '-', '+', 'x', 'o', 'O', '.', '*'} + hatch_linewidth: unknown + in_layout: bool + joinstyle: `.JoinStyle` or {'miter', 'round', 'bevel'} + label: object + linestyle or ls: {'-', '--', '-.', ':', '', (offset, on-off-seq), ...} + linewidth or lw: float or None + mouseover: bool + path_effects: list of `.AbstractPathEffect` + picker: None or bool or float or callable + rasterized: bool + sketch_params: (scale: float, length: float, randomness: float) + snap: bool or None + transform: [Transform](https://matplotlib.org/stable/api/_as_gen/matplotlib.transforms.Transform.html) + url: str + visible: bool + zorder: float""" + ... + +def _geometry_default_label(geometry: Any, index: int) -> str: + """Derive default labels for geo legend entries.""" + ... + +def _geo_legend_entries(entries: Iterable[Any] | dict[Any, Any], labels: Optional[Iterable[Any]]=None, *, country_reso: str='110m', country_territories: bool=False, country_proj: Any=None, patch_kw: dict=None) -> Incomplete: + """Build geometry semantic legend handles and labels. + +Notes +----- +`entries` may be: +- mapping of ``label -> geometry`` +- sequence of ``(label, geometry)`` or ``(label, geometry, options)`` tuples + where ``options`` is either a projection spec or a dict of per-entry + `GeometryEntry` keyword overrides (e.g., `country_proj`, `country_reso`) +- sequence of geometries with explicit `labels`""" + ... +_COLOR_KEYS = {'color', 'facecolor', 'edgecolor', 'markerfacecolor', 'markeredgecolor', 'markerfacecoloralt'} + +def _is_color_like(value: Incomplete) -> Incomplete: + """Determine whether a value can be interpreted as a single color. + +A tuple or list of 3 or 4 numbers in ``[0, 1]`` is treated as one RGB(A) +color rather than a per-entry style sequence — matching matplotlib's +color parser and giving tuple/list symmetric behavior. Other lists fall +through to per-entry resolution by ``_style_lookup``.""" + ... +_LINE_ALIAS_MAP = {'c': 'color', 'm': 'marker', 'ms': 'markersize', 'markersizes': 'markersize', 'ls': 'linestyle', 'lw': 'linewidth', 'mec': 'markeredgecolor', 'mew': 'markeredgewidth', 'mfc': 'markerfacecolor', 'mfcalt': 'markerfacecoloralt', 'aa': 'antialiased', 'fs': 'fillstyle'} +_PATCH_ALIAS_MAP = {'c': 'color', 'fc': 'facecolor', 'ec': 'edgecolor', 'ls': 'linestyle', 'lw': 'linewidth', 'aa': 'antialiased'} + +def _style_lookup(style: Incomplete, key: Incomplete, index: Incomplete, default: Incomplete=None, *, prop: Incomplete=None) -> Incomplete: + """Resolve a style value from scalar, mapping, or sequence inputs. + +Parameters +---------- +style : the style value (scalar, list, dict) +key : dict key when `style` is a mapping (typically a label) +index : list index when `style` is a sequence +default : fallback value +prop : optional attribute name; if it belongs to _COLOR_KEYS, + the function treats color-like sequences as single colors.""" + ... + +def _format_label(value: Incomplete, fmt: Incomplete) -> Incomplete: + """Format legend labels from values.""" + ... + +def _default_cycle_colors() -> Incomplete: + """Return default color cycle entries.""" + ... +_ENTRY_STYLE_FROM_COLLECTION = {'colors': 'color', 'edgecolors': 'markeredgecolor', 'facecolors': 'markerfacecolor', 'linestyles': 'linestyle', 'linewidths': 'markeredgewidth'} +_ENTRY_AREA_SIZE_KEYS = ('s', 'size', 'sizes') +_ENTRY_DIAMETER_SIZE_KEYS = ('markersize', 'ms', 'markersizes') +_ENTRY_MARKERSIZE_KEYS = (*_ENTRY_AREA_SIZE_KEYS, *_ENTRY_DIAMETER_SIZE_KEYS) + +def _pop_aliases(kwargs: dict[str, Any], alias_map: dict[str, str]) -> dict[str, Any]: + """Pop short aliases (``c``, ``ls``, …) from ``kwargs`` mapped to full names.""" + ... + +def _pop_plurals(kwargs: dict[str, Any], plural_map: dict[str, str]) -> dict[str, Any]: + """Pop collection-style plurals (``colors``, ``linewidths``, …).""" + ... + +def _area_to_markersize(value: Any) -> Any: + """Convert area-style marker sizes to Line2D marker diameters.""" + ... + +def _pop_marker_size(kwargs: dict[str, Any]) -> Any: + """Pop marker-size aliases and return Line2D marker diameters. + +Semantic legend helpers accept scatter-style ``s`` / ``size`` / ``sizes`` +inputs as marker areas, but render handles with ``Line2D`` where +``markersize`` / ``ms`` are diameters.""" + ... + +def _pop_line2d_setters(kwargs: dict[str, Any]) -> dict[str, Any]: + """Pop remaining kwargs that correspond to ``Line2D`` setters. + +Catches properties that ``_pop_props(..., "line")`` does not know about +(e.g. ``fillstyle``, ``solid_capstyle``) so they survive into the +``LegendEntry`` constructor instead of leaking through to ``Axes.legend``, +where matplotlib rejects them. + +``label``/``labels`` look like Line2D setters but are intentionally not +consumed here — the semantic-legend validator (covered by +``test_semantic_legend_rejects_label{,s}_kwarg``) needs them to surface +as ``TypeError`` from the public ``legend()`` call.""" + ... + +def _pop_entry_props(kwargs: dict[str, Any]) -> dict[str, Any]: + """Extract ``LegendEntry`` style properties from ``kwargs``. + +Resolution order (highest → lowest priority): + +1. Full-name properties recognised by ``_pop_props(kwargs, "line")``. +2. Collection-style plurals (``colors`` → ``color``, …). +3. Marker-size aliases. ``s`` / ``size`` / ``sizes`` are scatter-style + areas converted to diameters; ``markersize`` / ``ms`` are diameters. +4. Short aliases (``c`` → ``color``, ``ls`` → ``linestyle``, …). +5. Any other valid ``Line2D`` setter still in ``kwargs``. + +Advanced ``MarkerStyle`` properties (``marker_capstyle``/``_joinstyle``/ +``_transform``) are pulled out first so ``_pop_props`` does not consume +them, and merged back at the end with full priority.""" + ... +_NUM_STYLE_FROM_COLLECTION = {'colors': 'facecolor', 'facecolors': 'facecolor', 'edgecolors': 'edgecolor', 'linestyles': 'linestyle', 'linewidths': 'linewidth'} + +def _pop_num_props(kwargs: dict[str, Any]) -> dict[str, Any]: + """Extract patch-style properties (and collection-plural / short aliases) for +numeric semantic legend entries (``numlegend`` / ``geolegend``).""" + ... + +def _resolve_style_values(styles: dict[str, Any], label: Any, index: int) -> dict[str, Any]: + """Resolve scalar, mapping, or sequence style values for one legend entry.""" + ... + +def _cat_legend_entries(categories: Incomplete, *, color: Incomplete=None, marker: Incomplete='o', line: Incomplete=False, linestyle: Incomplete='-', linewidth: Incomplete=2.0, markersize: Incomplete=6.0, alpha: Incomplete=None, markeredgecolor: Incomplete=None, markeredgewidth: Incomplete=None, markerfacecolor: Incomplete=None, **entry_kwargs: Incomplete) -> Incomplete: + """Build categorical semantic legend handles and labels.""" + ... + +def _entry_legend_entries(entries: Iterable[Any] | Mapping[Any, Any], *, line: bool, marker: Incomplete, color: Incomplete, linestyle: Incomplete, linewidth: Incomplete, markersize: Incomplete, alpha: Incomplete, markeredgecolor: Incomplete, markeredgewidth: Incomplete, markerfacecolor: Incomplete, styles: dict[str, Any]) -> Incomplete: + """Build generic semantic legend handles/labels from mixed entry specifications.""" + ... + +def _size_legend_entries(levels: Iterable[float], *, label_values: Incomplete=None, labels: Incomplete=None, color: Incomplete='0.35', marker: Incomplete='o', area: Incomplete=True, scale: Incomplete=1.0, minsize: Incomplete=3.0, fmt: Incomplete=None, alpha: Incomplete=None, markeredgecolor: Incomplete=None, markeredgewidth: Incomplete=None, markerfacecolor: Incomplete=None, **entry_kwargs: Incomplete) -> Incomplete: + """Build size semantic legend handles and labels.""" + ... + +def _scale_size_legend_values(values: Incomplete, *, source: Incomplete=None, vmin: Incomplete=None, vmax: Incomplete=None, smin: Incomplete=None, smax: Incomplete=None, area_size: Incomplete=True, absolute_size: Incomplete=None) -> Incomplete: + """Transform semantic size values with the same rules used by scatter().""" + ... + +def _infer_size_legend_scale(axes: Incomplete, values: Incomplete) -> Incomplete: + """Infer scatter-style size scaling from the latest compatible scatter artist.""" + ... + +def _num_legend_entries(levels: Incomplete=None, *, vmin: Incomplete=None, vmax: Incomplete=None, n: int=5, cmap: Incomplete='viridis', norm: Incomplete=None, fmt: Incomplete=None, edgecolor: Incomplete='none', linewidth: Incomplete=0.0, linestyle: Incomplete=None, alpha: Incomplete=None, facecolor: Incomplete=None, **entry_kwargs: Incomplete) -> Incomplete: + """Build numeric-color semantic legend handles and labels.""" + ... +ALIGN_OPTS = {None: {'center': 'center', 'left': 'center left', 'right': 'center right', 'top': 'upper center', 'bottom': 'lower center'}, 'left': {'center': 'center right', 'left': 'center right', 'right': 'center right', 'top': 'upper right', 'bottom': 'lower right'}, 'right': {'center': 'center left', 'left': 'center left', 'right': 'center left', 'top': 'upper left', 'bottom': 'lower left'}, 'top': {'center': 'lower center', 'left': 'lower left', 'right': 'lower right', 'top': 'lower center', 'bottom': 'lower center'}, 'bottom': {'center': 'upper center', 'left': 'upper left', 'right': 'upper right', 'top': 'upper center', 'bottom': 'upper center'}} +LegendKw = dict[str, Any] +LegendHandles = Any +LegendLabels = Any + +@dataclass(frozen=True) +class _LegendInputs: + handles: LegendHandles + labels: LegendLabels + loc: Any + align: Any + width: Any + pad: Any + space: Any + frameon: bool + ncol: Any + order: str + label: Any + title: Any + fontsize: float + fontweight: Any + fontcolor: Any + titlefontsize: float + titlefontweight: Any + titlefontcolor: Any + handle_kw: Any + handler_map: Any + span: Optional[Union[int, Tuple[int, int]]] + row: Optional[int] + col: Optional[int] + rows: Optional[Union[int, Tuple[int, int]]] + cols: Optional[Union[int, Tuple[int, int]]] + kwargs: dict[str, Any] + +class Legend(mlegend.Legend): + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `parent`: The artist that contains the legend. +- `handles`: A list of Artists (lines, patches) to be added to the legend. +- `labels`: A list of labels to show next to the artists. +- `loc`: The location of the legend. +- `bbox_to_anchor`: Box that is used to position the legend in conjunction with *loc*. +- `ncols`: The number of columns that the legend has. +- `prop`: The font properties of the legend. +- `fontsize`: The font size of the legend. +- `labelcolor`: The color of the text in the legend. +- `numpoints`: The number of marker points in the legend when creating a legend entry for a `.Line2D` (line). +- `scatterpoints`: The number of marker points in the legend when creating a legend entry for a `.PathCollection` (scatter plot). +- `scatteryoffsets`: The vertical offset (relative to the font size) for the markers created for a scatter plot legend entry. +- `markerscale`: The relative size of legend markers compared to the originally drawn ones. +- `markerfirst`: If *True*, legend marker is placed to the left of the legend label. +- `reverse`: If *True*, the legend labels are displayed in reverse order from the input. +- `frameon`: Whether the legend should be drawn on a patch (frame). +- `fancybox`: Whether round edges should be enabled around the `.FancyBboxPatch` which makes up the legend's background. +- `shadow`: Whether to draw a shadow behind the legend. +- `framealpha`: The alpha transparency of the legend's background. +- `facecolor`: The legend's background color. +- `edgecolor`: The legend's background patch edge color. +- `mode`: If *mode* is set to ``"expand"`` the legend will be horizontally expanded to fill the Axes area (or *bbox_to_anchor* if defines the legend's size). +- `bbox_transform`: The transform for the bounding box (*bbox_to_anchor*). +- `title`: The legend's title. +- `title_fontproperties`: The font properties of the legend's title. +- `title_fontsize`: The font size of the legend's title. +- `alignment`: The alignment of the legend title and the box of entries. +- `borderpad`: The fractional whitespace inside the legend border, in font-size units. +- `labelspacing`: The vertical space between the legend entries, in font-size units. +- `handlelength`: The length of the legend handles, in font-size units. +- `handleheight`: The height of the legend handles, in font-size units. +- `handletextpad`: The pad between the legend handle and text, in font-size units. +- `borderaxespad`: The pad between the Axes and legend border, in font-size units. +- `columnspacing`: The spacing between columns, in font-size units. +- `handler_map`: The custom dictionary mapping instances or types to a legend handler. +- `draggable`: Whether the legend can be dragged with the mouse. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.legend.Legend.html)""" + ... + + @classmethod + def get_default_handler_map(cls) -> Incomplete: + """Extend matplotlib defaults with a wedge handler for pie legends.""" + ... + + @override + def set_loc(self, loc: Incomplete=None) -> Incomplete: + """Set the location of the legend. + +Parameters +---------- +- `loc`: The location of the legend. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.legend.Legend.html#ultraplot.legend.Legend.set_loc)""" + ... + + def remove(self) -> None: + """Remove the legend and sync Ultraplot guide tracking state. + +Matplotlib's base ``Legend.remove`` leaves Ultraplot's internal +``_legend_dict`` and ``legend_`` pointers untouched. When callers +remove a legend (e.g., ``sns.move_legend``), stale entries can keep +showing old legends alongside newly added ones. Keep both systems in +sync before delegating to Matplotlib's removal logic.""" + ... + +def _normalize_em_kwargs(kwargs: dict[str, Any], *, fontsize: float) -> dict[str, Any]: + """Convert legend-related em unit kwargs to absolute values in points.""" + ... +_semantic_style_arg_docstring = ... +_semantic_style_kwargs_docstring = ... +_semantic_num_style_kwargs_docstring = ... +_semantic_handle_kw_docstring = ... + +class UltraLegend: + """Centralized legend builder for axes.""" + + def __init__(self, axes: Incomplete) -> None: + ... + + @staticmethod + def _validate_semantic_kwargs(method: str, kwargs: dict[str, Any]) -> None: + """Prevent ambiguous legend kwargs for semantic legend helpers.""" + ... + + def entrylegend(self, entries: Iterable[Any] | Mapping[Any, Any], *, line: Optional[bool]=None, marker: Incomplete=None, color: Incomplete=None, handle_kw: Optional[dict[str, Any]]=None, add: bool=True, **kwargs: Any) -> Incomplete: + """Build generic semantic legend entries and optionally draw a legend. +Public docs live on `Axes.entrylegend`.""" + ... + + def catlegend(self, categories: Iterable[Any], *, color: Incomplete=None, marker: Incomplete=None, line: Optional[bool]=None, handle_kw: Optional[dict[str, Any]]=None, add: bool=True, **kwargs: Any) -> Incomplete: + """Build categorical legend entries and optionally draw a legend. +Public docs live on `Axes.catlegend`.""" + ... + + def sizelegend(self, levels: Iterable[float], *, labels: Incomplete=None, color: Incomplete=None, marker: Incomplete=None, area: Optional[bool]=None, values: Incomplete=None, vmin: Optional[float]=None, vmax: Optional[float]=None, smin: Optional[float]=None, smax: Optional[float]=None, area_size: Optional[bool]=None, absolute_size: Optional[bool]=None, scale: Optional[float]=None, minsize: Optional[float]=None, fmt: Incomplete=None, handle_kw: Optional[dict[str, Any]]=None, add: bool=True, **kwargs: Any) -> Incomplete: + """Build size legend entries and optionally draw a legend. +Public docs live on `Axes.sizelegend`.""" + ... + + def numlegend(self, levels: Incomplete=None, *, vmin: Incomplete=None, vmax: Incomplete=None, n: Optional[int]=None, cmap: Incomplete=None, norm: Incomplete=None, fmt: Incomplete=None, facecolor: Incomplete=None, edgecolor: Incomplete=None, linewidth: Optional[float]=None, linestyle: Incomplete=None, alpha: Incomplete=None, handle_kw: Optional[dict[str, Any]]=None, add: bool=True, **kwargs: Any) -> Incomplete: + """Build numeric-color legend entries and optionally draw a legend. +Public docs live on `Axes.numlegend`.""" + ... + + def geolegend(self, entries: Iterable[Any] | dict[Any, Any], labels: Optional[Iterable[Any]]=None, *, country_reso: Optional[str]=None, country_territories: Optional[bool]=None, country_proj: Any=None, handlesize: Optional[float]=None, facecolor: Any=None, edgecolor: Any=None, linewidth: Optional[float]=None, alpha: Optional[float]=None, fill: Optional[bool]=None, handle_kw: Optional[dict[str, Any]]=None, add: bool=True, **kwargs: Any) -> Incomplete: + """Build geometry legend entries and optionally draw a legend. +Public docs live on `Axes.geolegend`.""" + ... + + @staticmethod + def _align_map() -> dict[Optional[str], dict[str, str]]: + """Mapping between panel side + align and matplotlib legend loc strings.""" + ... + + def _resolve_inputs(self, handles: Incomplete=None, labels: Incomplete=None, *, loc: Incomplete=None, align: Incomplete=None, width: Incomplete=None, pad: Incomplete=None, space: Incomplete=None, frame: Incomplete=None, frameon: Incomplete=None, ncol: Incomplete=None, ncols: Incomplete=None, alphabetize: Incomplete=False, center: Incomplete=None, order: Incomplete=None, label: Incomplete=None, title: Incomplete=None, fontsize: Incomplete=None, fontweight: Incomplete=None, fontcolor: Incomplete=None, titlefontsize: Incomplete=None, titlefontweight: Incomplete=None, titlefontcolor: Incomplete=None, handle_kw: Incomplete=None, handler_map: Incomplete=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, **kwargs: Any) -> Incomplete: + """Normalize inputs, apply rc defaults, and convert units.""" + ... + + def _resolve_axes_layout(self, inputs: _LegendInputs) -> Incomplete: + """Determine the legend axes and layout-related kwargs.""" + ... + + def _resolve_style_kwargs(self, *, lax: Incomplete, fontcolor: Incomplete, fontweight: Incomplete, handle_kw: Incomplete, kwargs: Incomplete) -> Incomplete: + """Parse frame settings and build per-element style kwargs.""" + ... + + def _build_legends(self, *, lax: Incomplete, inputs: _LegendInputs, center: Incomplete, alphabetize: Incomplete, kw_frame: Incomplete, kwargs: Incomplete) -> Incomplete: + ... + + def _apply_handle_styles(self, objs: Incomplete, *, kw_text: Incomplete, kw_handle: Incomplete) -> Incomplete: + """Apply per-handle styling overrides to legend artists.""" + ... + + def _finalize(self, objs: Incomplete, *, loc: Incomplete, align: Incomplete) -> Incomplete: + """Register legend for guide tracking and return the public object.""" + ... + + def add(self, handles: Incomplete=None, labels: Incomplete=None, *, loc: Incomplete=None, align: Incomplete=None, width: Incomplete=None, pad: Incomplete=None, space: Incomplete=None, frame: Incomplete=None, frameon: Incomplete=None, ncol: Incomplete=None, ncols: Incomplete=None, alphabetize: Incomplete=False, center: Incomplete=None, order: Incomplete=None, label: Incomplete=None, title: Incomplete=None, fontsize: Incomplete=None, fontweight: Incomplete=None, fontcolor: Incomplete=None, titlefontsize: Incomplete=None, titlefontweight: Incomplete=None, titlefontcolor: Incomplete=None, handle_kw: Incomplete=None, handler_map: Incomplete=None, span: Optional[Union[int, Tuple[int, int]]]=None, row: Optional[int]=None, col: Optional[int]=None, rows: Optional[Union[int, Tuple[int, int]]]=None, cols: Optional[Union[int, Tuple[int, int]]]=None, **kwargs: Incomplete) -> Incomplete: + """The driver function for adding axes legends.""" + ... diff --git a/ultraplot/proj.pyi b/ultraplot/proj.pyi new file mode 100644 index 000000000..6f83b4d9c --- /dev/null +++ b/ultraplot/proj.pyi @@ -0,0 +1,201 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Additional cartopy projection classes. +""" +from _typeshed import Incomplete +import warnings +from .internals import ic +from .internals import docstring +try: + from cartopy.crs import AzimuthalEquidistant, Gnomonic, LambertAzimuthalEqualArea, NorthPolarStereo, SouthPolarStereo, _WarpedRectangularProjection +except ModuleNotFoundError: + AzimuthalEquidistant = Gnomonic = LambertAzimuthalEqualArea = object + _WarpedRectangularProjection = NorthPolarStereo = SouthPolarStereo = object +__all__ = ['Aitoff', 'Hammer', 'KavrayskiyVII', 'WinkelTripel', 'NorthPolarAzimuthalEquidistant', 'SouthPolarAzimuthalEquidistant', 'NorthPolarGnomonic', 'SouthPolarGnomonic', 'NorthPolarLambertAzimuthalEqualArea', 'SouthPolarLambertAzimuthalEqualArea'] +_reso_docstring = ... +_init_docstring = ... + +class Aitoff(_WarpedRectangularProjection): + """The [Aitoff](https://en.wikipedia.org/wiki/Aitoff_projection) projection.""" + name = 'aitoff' + + def __init__(self, central_longitude: Incomplete=0, globe: Incomplete=None, false_easting: Incomplete=None, false_northing: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + + @property + def threshold(self) -> float: + """The projection resolution.""" + ... + +class Hammer(_WarpedRectangularProjection): + """The [Hammer](https://en.wikipedia.org/wiki/Hammer_projection) projection.""" + name = 'hammer' + + def __init__(self, central_longitude: Incomplete=0, globe: Incomplete=None, false_easting: Incomplete=None, false_northing: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + + @property + def threshold(self) -> float: + """The projection resolution.""" + ... + +class KavrayskiyVII(_WarpedRectangularProjection): + """The [Kavrayskiy VII](https://en.wikipedia.org/wiki/Kavrayskiy_VII_projection) projection.""" + name = 'kavrayskiyVII' + + def __init__(self, central_longitude: Incomplete=0, globe: Incomplete=None, false_easting: Incomplete=None, false_northing: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + + @property + def threshold(self) -> float: + """The projection resolution.""" + ... + +class WinkelTripel(_WarpedRectangularProjection): + """The [Winkel tripel (Winkel III)](https://en.wikipedia.org/wiki/Winkel_tripel_projection) projection.""" + name = 'winkeltripel' + + def __init__(self, central_longitude: Incomplete=0, globe: Incomplete=None, false_easting: Incomplete=None, false_northing: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + + @property + def threshold(self) -> float: + """The projection resolution.""" + ... + +class NorthPolarAzimuthalEquidistant(AzimuthalEquidistant): + """Analogous to `~cartopy.crs.NorthPolarStereo`.""" + + def __init__(self, central_longitude: Incomplete=0.0, globe: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + +class SouthPolarAzimuthalEquidistant(AzimuthalEquidistant): + """Analogous to `~cartopy.crs.SouthPolarStereo`.""" + + def __init__(self, central_longitude: Incomplete=0.0, globe: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + +class NorthPolarLambertAzimuthalEqualArea(LambertAzimuthalEqualArea): + """Analogous to `~cartopy.crs.NorthPolarStereo`.""" + + def __init__(self, central_longitude: Incomplete=0.0, globe: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + +class SouthPolarLambertAzimuthalEqualArea(LambertAzimuthalEqualArea): + """Analogous to `~cartopy.crs.SouthPolarStereo`.""" + + def __init__(self, central_longitude: Incomplete=0.0, globe: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + +class NorthPolarGnomonic(Gnomonic): + """Analogous to `~cartopy.crs.NorthPolarStereo`.""" + + def __init__(self, central_longitude: Incomplete=0.0, globe: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... + +class SouthPolarGnomonic(Gnomonic): + """Analogous to `~cartopy.crs.SouthPolarStereo`.""" + + def __init__(self, central_longitude: Incomplete=0.0, globe: Incomplete=None) -> None: + """Parameters +---------- +central_longitude : float, default: 0 + The central meridian longitude in degrees. +false_easting: float, default: 0 + X offset from planar origin in metres. +false_northing: float, default: 0 + Y offset from planar origin in metres. +globe : `~cartopy.crs.Globe`, optional + If omitted, a default globe is created.""" + ... diff --git a/ultraplot/py.typed b/ultraplot/py.typed new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/ultraplot/py.typed @@ -0,0 +1 @@ + diff --git a/ultraplot/scale.pyi b/ultraplot/scale.pyi new file mode 100644 index 000000000..4969c78c4 --- /dev/null +++ b/ultraplot/scale.pyi @@ -0,0 +1,874 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Various axis [ScaleBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.ScaleBase.html) classes. +""" +from _typeshed import Incomplete +import copy +import matplotlib.scale as mscale +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +import numpy as np +import numpy.ma as ma +from . import ticker as pticker +from .internals import _not_none, _version_mpl, ic, warnings +__all__ = ['CutoffScale', 'ExpScale', 'FuncScale', 'InverseScale', 'LinearScale', 'LogitScale', 'LogScale', 'MercatorLatitudeScale', 'PowerScale', 'SineLatitudeScale', 'SymmetricalLogScale'] + +def _parse_logscale_args(*keys: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Parse arguments for `LogScale` and `SymmetricalLogScale` that +inexplicably require `x` and `y` suffixes by default. Also +change the default `linthresh` to ``1``.""" + ... + +class _Scale(object): + """Mix-in class that standardizes the behavior of +[set_default_locators_and_formatters](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.ScaleBase.set_default_locators_and_formatters.html) +and [get_transform](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.ScaleBase.get_transform.html). Also overrides +`__init__` so you no longer have to instantiate scales with an +[Axis](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.Axis.html) instance.""" + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + ... + + def set_default_locators_and_formatters(self, axis: Incomplete, only_if_default: Incomplete=False) -> Incomplete: + """Apply all locators and formatters defined as attributes on +initialization and define defaults for all scales. + +Parameters +---------- +axis : [Axis](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.Axis.html) + The axis. +only_if_default : bool, optional + Whether to refrain from updating the locators and formatters if the + axis is currently using non-default versions. Useful if we want to + avoid overwriting user customization when the scale is changed.""" + ... + + def get_transform(self) -> Incomplete: + """Return the scale transform.""" + ... + +class LinearScale(_Scale, mscale.LinearScale): + """As with [LinearScale](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.LinearScale.html) but with +[AutoFormatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ticker.AutoFormatter.html) as the default major formatter.""" + name = 'linear' + + def __init__(self, **kwargs: Incomplete) -> None: + """See also +-------- +ultraplot.constructor.Scale""" + ... + +class LogitScale(_Scale, mscale.LogitScale): + """As with [LogitScale](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.LogitScale.html) but with [AutoFormatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ticker.AutoFormatter.html) +as the default major formatter.""" + name = 'logit' + + def __init__(self, **kwargs: Incomplete) -> None: + """Parameters +---------- +nonpos : {'mask', 'clip'} + Values outside of (0, 1) can be masked as invalid, or clipped to a + number very close to 0 or 1. + +See also +-------- +ultraplot.constructor.Scale""" + ... + +class LogScale(_Scale, mscale.LogScale): + """As with [LogScale](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.LogScale.html) but with [AutoFormatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ticker.AutoFormatter.html) +as the default major formatter. `x` and `y` versions of each keyword +argument are no longer required.""" + name = 'log' + + def __init__(self, **kwargs: Incomplete) -> None: + """Parameters +---------- +base : float, default: 10 + The base of the logarithm. +nonpos : {'mask', 'clip'}, optional + Non-positive values in *x* or *y* can be masked as + invalid, or clipped to a very small positive number. +subs : sequence of int, default: ``[1 2 3 4 5 6 7 8 9]`` + Default *minor* tick locations are on these multiples of each power + of the base. For example, ``subs=(1, 2, 5)`` draws ticks on 1, 2, + 5, 10, 20, 50, 100, 200, 500, etc. +basex, basey, nonposx, nonposy, subsx, subsy + Aliases for the above keywords. These used to be conditional + on the *name* of the axis. + +See also +-------- +ultraplot.constructor.Scale""" + ... + +class SymmetricalLogScale(_Scale, mscale.SymmetricalLogScale): + """As with [SymmetricalLogScale](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.SymmetricalLogScale.html) but with +[AutoFormatter](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ticker.AutoFormatter.html) as the default major formatter. +`x` and `y` versions of each keyword argument are no longer +required.""" + name = 'symlog' + + def __init__(self, **kwargs: Incomplete) -> None: + """Parameters +---------- +base : float, default: 10 + The base of the logarithm. +linthresh : float, default: 1 + Defines the range ``(-linthresh, linthresh)``, within which the plot + is linear. This avoids having the plot go to infinity around zero. +linscale : float, default: 1 + This allows the linear range ``(-linthresh, linthresh)`` to be + stretched relative to the logarithmic range. Its value is the + number of decades to use for each half of the linear range. For + example, when `linscale` is ``1`` (the default), the space used + for the positive and negative halves of the linear range will be + equal to one decade in the logarithmic range. +subs : sequence of int, default: ``[1 2 3 4 5 6 7 8 9]`` + Default *minor* tick locations are on these multiples of each power + of the base. For example, ``subs=(1, 2, 5)`` draws ticks on 1, 2, + 5, 10, 20, 50, 100, 200, 500, etc. +basex, basey, linthreshx, linthreshy, linscalex, linscaley, subsx, subsy + Aliases for the above keywords. These keywords used to be + conditional on the name of the axis. + +See also +-------- +ultraplot.constructor.Scale""" + ... + +class FuncScale(_Scale, mscale.ScaleBase): + """Axis scale composed of arbitrary forward and inverse transformations.""" + name = 'function' + + def __init__(self, transform: Incomplete=None, invert: Incomplete=False, parent_scale: Incomplete=None, **kwargs: Incomplete) -> None: + """Parameters +---------- +- `transform`: The transform used to translate units from the parent axis to the secondary axis. +- `invert`: If ``True``, the forward and inverse functions are *swapped*. +- `parent_scale`: The axis scale of the "parent" axis. +- `major_locator, minor_locator`: The default major and minor locator. +- `major_formatter, minor_formatter`: The default major and minor formatter. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.scale.FuncScale.html)""" + ... + +class FuncTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + is_separable = True + has_inverse = True + + def __init__(self, forward: Incomplete, inverse: Incomplete) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, values: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class PowerScale(_Scale, mscale.ScaleBase): + """"Power scale" that performs the transformation + +.. math:: + + x^{c}""" + name = 'power' + + def __init__(self, power: Incomplete=1, inverse: Incomplete=False) -> None: + """Parameters +---------- +power : float, optional + The power :math:`c` to which :math:`x` is raised. +inverse : bool, optional + If ``True`` this performs the inverse operation :math:`x^{1/c}`.""" + ... + + def limit_range_for_scale(self, vmin: Incomplete, vmax: Incomplete, minpos: Incomplete) -> Incomplete: + """Return the range *vmin* and *vmax* limited to positive numbers.""" + ... + +class PowerTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + has_inverse = True + is_separable = True + + def __init__(self, power: Incomplete) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class InvertedPowerTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + has_inverse = True + is_separable = True + + def __init__(self, power: Incomplete) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class ExpScale(_Scale, mscale.ScaleBase): + """"Exponential scale" that performs either of two transformations. When +`inverse` is ``False`` (the default), performs the transformation + +.. math:: + + Ca^{bx} + +where the constants :math:`a`, :math:`b`, and :math:`C` are set by the +input (see below). When `inverse` is ``True``, this performs the inverse +transformation + +.. math:: + + (\\log_a(x) - \\log_a(C))/b + +which in appearance is equivalent to `LogScale` since it is just a linear +transformation of the logarithm.""" + name = 'exp' + + def __init__(self, a: Incomplete=np.e, b: Incomplete=1, c: Incomplete=1, inverse: Incomplete=False) -> None: + """Parameters +---------- +a : float, optional + The base of the exponential, i.e. the :math:`a` in :math:`Ca^{bx}`. +b : float, optional + The scale for the exponent, i.e. the :math:`b` in :math:`Ca^{bx}`. +c : float, optional + The coefficient of the exponential, i.e. the :math:`C` in :math:`Ca^{bx}`. +inverse : bool, optional + If ``True``, the "forward" direction performs the inverse operation. + +See also +-------- +ultraplot.constructor.Scale""" + ... + + def limit_range_for_scale(self, vmin: Incomplete, vmax: Incomplete, minpos: Incomplete) -> Incomplete: + """Return the range *vmin* and *vmax* limited to positive numbers.""" + ... + +class ExpTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + has_inverse = True + is_separable = True + + def __init__(self, a: Incomplete, b: Incomplete, c: Incomplete) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class InvertedExpTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + has_inverse = True + is_separable = True + + def __init__(self, a: Incomplete, b: Incomplete, c: Incomplete) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class MercatorLatitudeScale(_Scale, mscale.ScaleBase): + """Axis scale that is linear in the [Mercator projection latitude](http://en.wikipedia.org/wiki/Mercator_projection). Adapted from [this example](https://matplotlib.org/2.0.2/examples/api/custom_scale_example.html). +The scale function is as follows: + +.. math:: + + y = \\ln(\\tan(\\pi x \\,/\\, 180) + \\sec(\\pi x \\,/\\, 180)) + +The inverse scale function is as follows: + +.. math:: + + x = 180\\,\\arctan(\\sinh(y)) \\,/\\, \\pi""" + name = 'mercator' + + def __init__(self, thresh: Incomplete=85.0) -> None: + """Parameters +---------- +thresh : float, optional + Threshold between 0 and 90, used to constrain axis limits + between ``-thresh`` and ``+thresh``. + +See also +-------- +ultraplot.constructor.Scale""" + ... + + def limit_range_for_scale(self, vmin: Incomplete, vmax: Incomplete, minpos: Incomplete) -> Incomplete: + """Return the range *vmin* and *vmax* limited to within +/-90 degrees +(exclusive).""" + ... + +class MercatorLatitudeTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + is_separable = True + has_inverse = True + + def __init__(self, thresh: Incomplete) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class InvertedMercatorLatitudeTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + is_separable = True + has_inverse = True + + def __init__(self, thresh: Incomplete) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class SineLatitudeScale(_Scale, mscale.ScaleBase): + """Axis scale that is linear in the sine transformation of *x*. The axis +limits are constrained to fall between ``-90`` and ``+90`` degrees. +The scale function is as follows: + +.. math:: + + y = \\sin(\\pi x/180) + +The inverse scale function is as follows: + +.. math:: + + x = 180\\arcsin(y)/\\pi""" + name = 'sine' + + def __init__(self) -> None: + """See also +-------- +ultraplot.constructor.Scale""" + ... + + def limit_range_for_scale(self, vmin: Incomplete, vmax: Incomplete, minpos: Incomplete) -> tuple[int, int]: + """Return the range *vmin* and *vmax* limited to within +/-90 degrees +(inclusive).""" + ... + +class SineLatitudeTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + is_separable = True + has_inverse = True + + def __init__(self) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class InvertedSineLatitudeTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + is_separable = True + has_inverse = True + + def __init__(self) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class CutoffScale(_Scale, mscale.ScaleBase): + """Axis scale composed of arbitrary piecewise linear transformations. +The axis can undergo discrete jumps, "accelerations", or "decelerations" +between successive thresholds.""" + name = 'cutoff' + + def __init__(self, *args: Incomplete) -> None: + """Parameters +---------- +*args : thresh_1, scale_1, ..., thresh_N, [scale_N], optional + Sequence of "thresholds" and "scales". If the final scale is + omitted (i.e. you passed an odd number of arguments) it is set + to ``1``. Each ``scale_i`` in the sequence can be interpreted + as follows: + + * If ``scale_i < 1``, the axis is decelerated from ``thresh_i`` to + ``thresh_i+1``. For ``scale_N``, the axis is decelerated + everywhere above ``thresh_N``. + * If ``scale_i > 1``, the axis is accelerated from ``thresh_i`` to + ``thresh_i+1``. For ``scale_N``, the axis is accelerated + everywhere above ``thresh_N``. + * If ``scale_i == numpy.inf``, the axis *discretely jumps* from + ``thresh_i`` to ``thresh_i+1``. The final scale ``scale_N`` + *cannot* be ``numpy.inf``. + +See also +-------- +ultraplot.constructor.Scale + +Example +------- +>>> import ultraplot as uplt +>>> import numpy as np +>>> scale = uplt.CutoffScale(10, 0.5) # move slower above 10 +>>> scale = uplt.CutoffScale(10, 2, 20) # move faster between 10 and 20 +>>> scale = uplt.CutoffScale(10, np.inf, 20) # jump from 10 to 20""" + ... + +class CutoffTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + has_inverse = True + is_separable = True + + def __init__(self, threshs: Incomplete, scales: Incomplete, zero_dists: Incomplete=None) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +class InverseScale(_Scale, mscale.ScaleBase): + """Axis scale that is linear in the *inverse* of *x*. The forward and inverse +scale functions are as follows: + +.. math:: + + y = x^{-1}""" + name = 'inverse' + + def __init__(self) -> None: + """See also +-------- +ultraplot.constructor.Scale""" + ... + + def limit_range_for_scale(self, vmin: Incomplete, vmax: Incomplete, minpos: Incomplete) -> Incomplete: + """Return the range *vmin* and *vmax* limited to positive numbers.""" + ... + +class InverseTransform(mtransforms.Transform): + input_dims = 1 + output_dims = 1 + is_separable = True + has_inverse = True + + def __init__(self) -> None: + """Parameters +---------- +shorthand_name : str + A string representing the "name" of the transform. The name carries + no significance other than to improve the readability of + ``str(transform)`` when DEBUG=True.""" + ... + + def inverted(self) -> Incomplete: + """Return the corresponding inverse transformation. + +It holds ``x == self.inverted().transform(self.transform(x))``. + +The return value of this method should be treated as +temporary. An update to *self* does not cause a corresponding +update to its inverted copy.""" + ... + + def transform_non_affine(self, a: Incomplete) -> Incomplete: + """Apply only the non-affine part of this transformation. + +``transform(values)`` is always equivalent to +``transform_affine(transform_non_affine(values))``. + +In non-affine transformations, this is generally equivalent to +``transform(values)``. In affine transformations, this is +always a no-op. + +Parameters +---------- +values : array + The input values as an array of length `input_dims` or + shape (N, `input_dims`). + +Returns +------- +array + The output values as an array of length `output_dims` or + shape (N, `output_dims`), depending on the input.""" + ... + +def _scale_factory(scale: Incomplete, axis: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + """Generate an axis scale. + +Parameters +---------- +scale : str or [ScaleBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.ScaleBase.html) + The axis scale name or scale instance. +axis : [Axis](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.Axis.html) + The axis instance. +*args, **kwargs + Passed to [ScaleBase](https://matplotlib.org/stable/api/_as_gen/matplotlib.scale.ScaleBase.html) if `scale` is a string.""" + ... diff --git a/ultraplot/tests/test_docstring_helpers.py b/ultraplot/tests/test_docstring_helpers.py index 17d826d49..c83d98a00 100644 --- a/ultraplot/tests/test_docstring_helpers.py +++ b/ultraplot/tests/test_docstring_helpers.py @@ -1,6 +1,16 @@ """Tests for the shared style docstrings in ``ultraplot.internals.docstring``.""" +import inspect + import ultraplot as uplt +from ultraplot.axes import ( + Axes, + CartesianAxes, + GeoAxes, + PolarAxes, + TaylorAxes, +) +from ultraplot.figure import Figure from ultraplot.internals import docstring @@ -51,6 +61,20 @@ def test_method_docstring_fully_substituted() -> None: assert "%(artist" not in doc +def test_public_docstrings_with_snippets_are_fully_substituted() -> None: + """Public methods must not expose internal snippet placeholders.""" + for obj in (uplt.axes.PlotAxes.circos, uplt.Configurator.register_handler): + doc = obj.__doc__ or "" + assert "%(" not in doc + + assert "Create a Circos instance using pyCirclize." in ( + uplt.axes.PlotAxes.circos.__doc__ or "" + ) + assert "Register a callback function to be executed" in ( + uplt.Configurator.register_handler.__doc__ or "" + ) + + def test_geo_format_folds_alias_entries() -> None: # The geo format docstring folded its standalone "Aliases for ..." blocks # into trailing notes on the canonical locator entries. @@ -61,3 +85,65 @@ def test_geo_format_folds_alias_entries() -> None: assert ( "Aliases: ``lonminorlines_kw`` and ``latminorlines_kw``, respectively." in geo ) + + +def test_compact_doc_markers_preserve_runtime_signatures() -> None: + """Documentation presentation must not alter callable introspection.""" + + def keyword_only(*, explicit=None, **kwargs): + return explicit, kwargs + + def positional(first, second=None): + return first, second + + keyword_signature = inspect.signature(keyword_only) + positional_signature = inspect.signature(positional) + assert docstring._obfuscate_kwargs(keyword_only) is keyword_only + assert docstring._obfuscate_params(positional) is positional + assert inspect.signature(keyword_only) == keyword_signature + assert inspect.signature(positional) == positional_signature + assert keyword_only.__ultraplot_doc_signature__ == "(**kwargs)" + assert positional.__ultraplot_doc_signature__ == "(*args, **kwargs)" + + +def test_format_implementation_signatures_remain_visible() -> None: + """Format methods retain their declared signatures for tools and editors.""" + cases = ( + (Axes, "title"), + (CartesianAxes, "xlim"), + (PolarAxes, "r0"), + (GeoAxes, "lonlim"), + (TaylorAxes, "corrlabel"), + ) + for cls, representative_parameter in cases: + signature = inspect.signature(cls.format) + assert signature == cls._format_signatures[cls] + assert representative_parameter in signature.parameters + assert cls.format.__ultraplot_doc_signature__ == "(**kwargs)" + + assert inspect.signature(Figure.format) == Figure._format_signature + assert "suptitle" in inspect.signature(Figure.format).parameters + assert Figure.format.__ultraplot_doc_signature__ == "(**kwargs)" + + figure_signature = inspect.signature(Figure) + assert "refnum" in figure_signature.parameters + assert Figure.__init__.__ultraplot_doc_signature__ == "(**kwargs)" + + +def test_snippet_manager_preserves_callable_signature() -> None: + """Docstring expansion acts as a typed identity decorator.""" + + @docstring._snippet_manager + def documented(value, *, option=None): + """Return the input value.""" + return value, option + + assert str(inspect.signature(documented)) == "(value, *, option=None)" + + +def test_inherited_docstrings_preserve_callable_signature() -> None: + """Matplotlib docstring concatenation only compacts the Sphinx heading.""" + signature = inspect.signature(Axes.legend) + assert "handles" in signature.parameters + assert "labels" in signature.parameters + assert Axes.legend.__ultraplot_doc_signature__ == "(*args, **kwargs)" diff --git a/ultraplot/tests/test_kwargs_helpers.py b/ultraplot/tests/test_kwargs_helpers.py index 853131d78..fd63fa3e1 100644 --- a/ultraplot/tests/test_kwargs_helpers.py +++ b/ultraplot/tests/test_kwargs_helpers.py @@ -1,9 +1,11 @@ """Tests for the keyword-argument / alias helpers in ``ultraplot.internals.kwargs``.""" +import inspect import warnings from ultraplot import internals from ultraplot.internals import kwargs as ikwargs +from ultraplot.internals import warnings as uwarnings def test_kwargs_helpers_reexported_from_package() -> None: @@ -45,6 +47,15 @@ def func(*, refnum=1, figwidth=None, **kwargs): assert func(width=5) == (1, 5, {}) # synonym folded to canonical assert func(ref=2, figwidth=3) == (2, 3, {}) # mix of alias + canonical assert func(other=9) == (1, None, {"other": 9}) # unrelated kwargs pass through + assert str(inspect.signature(func)) == "(*, refnum=1, figwidth=None, **kwargs)" + + +def test_rename_kwargs_preserves_callable_signature() -> None: + @uwarnings._rename_kwargs("0.1.0", old="current") + def func(*, current=None): + return current + + assert str(inspect.signature(func)) == "(*, current=None)" def test_alias_kwargs_none_synonym_defers_to_default() -> None: diff --git a/ultraplot/tests/test_stubs.py b/ultraplot/tests/test_stubs.py new file mode 100644 index 000000000..5c114dac1 --- /dev/null +++ b/ultraplot/tests/test_stubs.py @@ -0,0 +1,230 @@ +import ast +import os +import re +import shutil +import subprocess +import sys +from pathlib import Path + +import pytest + +from ultraplot.internals.docstring import _snippet_manager + +ROOT = Path(__file__).resolve().parents[2] +PACKAGE = ROOT / "ultraplot" +GENERATED_HEADER = "# @generated by tools/generate_stubs.py; do not edit" +PLACEHOLDER_PATTERN = re.compile(r"%\(([^)]+)\)s") + + +def _generated_stubs(): + return sorted( + path + for path in PACKAGE.rglob("*.pyi") + if path.read_text(encoding="utf-8").startswith(GENERATED_HEADER) + ) + + +def _type_checking_imports(path): + """Return the names imported inside a ``TYPE_CHECKING`` guard.""" + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + names = set() + for node in tree.body: + if not isinstance(node, ast.If): + continue + test = node.test + if not (isinstance(test, ast.Name) and test.id == "TYPE_CHECKING") and not ( + isinstance(test, ast.Attribute) and test.attr == "TYPE_CHECKING" + ): + continue + for statement in ast.walk(node): + if isinstance(statement, (ast.Import, ast.ImportFrom)): + names.update(alias.asname or alias.name for alias in statement.names) + return names + + +def _top_level_imports(path): + """Return the names imported at module scope.""" + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + return { + alias.asname or alias.name + for node in tree.body + if isinstance(node, (ast.Import, ast.ImportFrom)) + for alias in node.names + } + + +def test_generated_stubs_are_current(): + pyrefly = shutil.which("pyrefly") + if pyrefly is None: + pytest.skip("stub freshness requires the optional `typing` dependencies") + env = os.environ.copy() + env.setdefault("MPLCONFIGDIR", "/tmp/ultraplot-matplotlib") + result = subprocess.run( + [ + sys.executable, + str(ROOT / "tools" / "generate_stubs.py"), + "--check", + "--pyrefly", + pyrefly, + ], + cwd=ROOT, + env=env, + check=True, + capture_output=True, + text=True, + ) + assert "source modules and their stubs" in result.stdout + assert "all up to date" in result.stdout + + +def test_generated_stub_signatures_are_fully_annotated(): + missing = [] + for path in _generated_stubs(): + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + for node in ast.walk(tree): + if not isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef)): + continue + if node.returns is None: + missing.append(f"{path.relative_to(ROOT)}:{node.lineno}: return") + arguments = ( + *node.args.posonlyargs, + *node.args.args, + *node.args.kwonlyargs, + node.args.vararg, + node.args.kwarg, + ) + for argument in arguments: + if ( + argument is not None + and argument.arg not in {"self", "cls"} + and argument.annotation is None + ): + missing.append( + f"{path.relative_to(ROOT)}:{node.lineno}: {argument.arg}" + ) + assert not missing, "Unannotated generated signatures:\n" + "\n".join(missing) + + +def test_generated_stubs_are_valid_and_docstrings_are_expanded(): + stubs = _generated_stubs() + assert stubs + + unresolved = [] + for path in stubs: + tree = ast.parse(path.read_text(encoding="utf-8"), filename=str(path)) + for node in ast.walk(tree): + if not isinstance( + node, (ast.ClassDef, ast.FunctionDef, ast.AsyncFunctionDef) + ): + continue + doc = ast.get_docstring(node, clean=False) or "" + for key in PLACEHOLDER_PATTERN.findall(doc): + try: + _snippet_manager[key] + except KeyError: + continue + unresolved.append(f"{path.relative_to(ROOT)}:{node.lineno}: {key}") + + assert not unresolved, "Registered docstring placeholders remain:\n" + "\n".join( + unresolved + ) + + +def test_root_stub_exposes_lazy_public_imports(): + source_names = _type_checking_imports(PACKAGE / "__init__.py") + stub_names = _top_level_imports(PACKAGE / "__init__.pyi") + + assert source_names + assert not source_names - stub_names + + +def test_generated_stubs_include_compact_runtime_docstrings(): + plot_stub = PACKAGE / "axes" / "plot.pyi" + plot_tree = ast.parse(plot_stub.read_text(encoding="utf-8")) + plot_doc = "" + for node in ast.walk(plot_tree): + if isinstance(node, ast.FunctionDef) and node.name == "plot": + plot_doc = ast.get_docstring(node) or "" + break + assert "Plot standard lines" in plot_doc + assert "Parameters" in plot_doc + assert "Full API documentation" in plot_doc + assert "Matplotlib documentation" not in plot_doc + assert len(plot_doc) < 8000 + assert "=====================\nultraplot documentation" not in plot_doc + assert ":class:`~pandas.DataFrame`" not in plot_doc + + grid_stub = PACKAGE / "gridspec.pyi" + grid_tree = ast.parse(grid_stub.read_text(encoding="utf-8")) + twiny_doc = "" + for node in ast.walk(grid_tree): + if isinstance(node, ast.FunctionDef) and node.name == "twiny": + twiny_doc = ast.get_docstring(node) or "" + break + assert "for every axes in the grid" in twiny_doc + + +def test_long_hover_docstrings_are_compact_and_linked(): + ui_tree = ast.parse((PACKAGE / "ui.pyi").read_text(encoding="utf-8")) + subplots = next( + node + for node in ui_tree.body + if isinstance(node, ast.FunctionDef) and node.name == "subplots" + ) + doc = ast.get_docstring(subplots) or "" + assert len(doc) < 8000 + assert "%(figure.figure)s" not in doc + assert "- `array`" in doc + assert "- `nrows, ncols`" in doc + assert ( + "[Full API documentation](https://ultraplot.readthedocs.io/en/stable/" + "api/ultraplot.ui.subplots.html)" in doc + ) + assert "Returns\n-------" not in doc + + +def test_plot_stub_exposes_static_signature(): + """The dynamic plot wrapper should retain its useful public call shape.""" + tree = ast.parse((PACKAGE / "axes" / "plot.pyi").read_text(encoding="utf-8")) + plot_axes = next( + node + for node in tree.body + if isinstance(node, ast.ClassDef) and node.name == "PlotAxes" + ) + plot = next( + node + for node in plot_axes.body + if isinstance(node, ast.FunctionDef) and node.name == "plot" + ) + + assert ast.unparse(plot.args.vararg.annotation) == "Any" + assert [argument.arg for argument in plot.args.kwonlyargs] == [ + "scalex", + "scaley", + "data", + ] + assert ast.unparse(plot.args.kwarg.annotation) == "Any" + assert ast.unparse(plot.returns) == "list[Any]" + + +def test_subplot_grid_stub_preserves_axes_indexing_chain(): + """Integer indexing must lead static analyzers from a grid to an axes.""" + grid_stub = PACKAGE / "gridspec.pyi" + tree = ast.parse(grid_stub.read_text(encoding="utf-8")) + grid = next( + node + for node in tree.body + if isinstance(node, ast.ClassDef) and node.name == "SubplotGrid" + ) + assert "paxes.PlotAxes" in {ast.unparse(base) for base in grid.bases} + getitems = [ + node + for node in grid.body + if isinstance(node, ast.FunctionDef) and node.name == "__getitem__" + ] + assert len(getitems) >= 2 + assert any( + ast.unparse(node.args.args[1].annotation) == "int" + and ast.unparse(node.returns) == "paxes.Axes" + for node in getitems + ) diff --git a/ultraplot/text.pyi b/ultraplot/text.pyi new file mode 100644 index 000000000..0b8cc6840 --- /dev/null +++ b/ultraplot/text.pyi @@ -0,0 +1,100 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Text-related artists and helpers. +""" +from _typeshed import Incomplete +from typing import Iterable, Tuple +import matplotlib.text as mtext +import numpy as np +from .internals import labels +__all__ = ['CurvedText'] + +class CurvedText(mtext.Text): + """A text object that follows an arbitrary curve. + +Parameters +---------- +x, y : array-like + Curve coordinates. +text : str + Text to render along the curve. +axes : matplotlib.axes.Axes + Target axes. +upright : bool, default: True + Whether to flip the curve direction to keep text upright. +ellipsis : bool, default: False + Whether to show an ellipsis when the text exceeds curve length. + avoid_overlap : bool, default: True + Whether to hide glyphs that overlap after rotation. +overlap_tol : float, default: 0.1 + Fractional overlap area (0–1) required before hiding a glyph. +curvature_pad : float, default: 2.0 + Extra spacing in pixels per radian of local curvature. +min_advance : float, default: 1.0 + Minimum additional spacing (pixels) enforced between glyph centers. +**kwargs + Passed to [matplotlib.text.Text](https://matplotlib.org/stable/api/_as_gen/matplotlib.text.Text.html) for character styling.""" + + def __init__(self, x: Incomplete, y: Incomplete, text: Incomplete, axes: Incomplete, *, upright: Incomplete=True, ellipsis: Incomplete=False, avoid_overlap: Incomplete=True, overlap_tol: Incomplete=0.1, curvature_pad: Incomplete=2.0, min_advance: Incomplete=1.0, **kwargs: Incomplete) -> None: + """Create a `.Text` instance at *x*, *y* with string *text*. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.text.CurvedText.html)""" + ... + + def _restore_clip_on(self, t: Incomplete) -> None: + """Re-assert clip_on after add_artist/add_text resets it.""" + ... + + def _build_characters(self, text: str) -> None: + ... + + def set_text(self, s: Incomplete) -> None: + """Set the text string *s*. + +It may contain newlines (``\\n``) or math in LaTeX syntax. + +Parameters +---------- +s : object + Any object gets converted to its `str` representation, except for + ``None`` which is converted to an empty string.""" + ... + + def get_text(self) -> str: + """Return the text string.""" + ... + + def set_curve(self, x: Iterable[float], y: Iterable[float]) -> None: + ... + + def get_curve(self) -> Tuple[np.ndarray, np.ndarray]: + ... + + def _apply_label_props(self, props: Incomplete) -> None: + ... + + def set_zorder(self, zorder: Incomplete) -> None: + """Set the zorder for the artist. Artists with lower zorder +values are drawn first. + +Parameters +---------- +level : float""" + ... + + def set_transform(self, transform: Incomplete) -> None: + """Set the artist transform. + +Parameters +---------- +t : [Transform](https://matplotlib.org/stable/api/_as_gen/matplotlib.transforms.Transform.html)""" + ... + + def draw(self, renderer: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> None: + """Overload `Text.draw()` to update character positions and rotations.""" + ... + + def update_positions(self, renderer: Incomplete) -> None: + """Update positions and rotations of the individual text elements.""" + ... diff --git a/ultraplot/textalign.pyi b/ultraplot/textalign.pyi new file mode 100644 index 000000000..e251f30b6 --- /dev/null +++ b/ultraplot/textalign.pyi @@ -0,0 +1,139 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Automatic repositioning of text and annotation boxes so they do not overlap. + +The solver works entirely in display (pixel) space, so it is agnostic to the +transform attached to each label -- data, axes, log-scaled, polar and +geographic labels are all handled the same way. Labels are reset to their +original anchors before every pass, which keeps the result stable across +repeated draws, resizes and dpi changes. +""" +from _typeshed import Incomplete +from typing import Iterable, Optional, Sequence +import matplotlib.collections as mcollections +import matplotlib.lines as mlines +import matplotlib.patches as mpatches +import matplotlib.text as mtext +import matplotlib.transforms as mtransforms +import numpy as np +__all__ = ['align_text'] +_RESTART_LIMIT = 120 + +def _points_to_pixels(fig: Incomplete, value: Incomplete) -> float: + ... + +def _expand_bbox(bbox: Incomplete, padx: float, pady: float) -> Incomplete: + ... + +def _fits(box: Incomplete, sx: Incomplete, sy: Incomplete, bounds: Incomplete) -> bool: + """Whether shifting ``box`` (x0, y0, x1, y1) by half of (sx, sy) keeps it inside +``bounds`` -- half, because a box only takes half of a pairwise push.""" + ... + +def _overlap_shift(b1: Incomplete, b2: Incomplete, bounds: Incomplete=None) -> Incomplete: + """Return the translation ``(sx, sy)`` separating box ``b1`` from ``b2``, or zeros. + +Boxes are ``(x0, y0, x1, y1)``. Both axis-aligned escape routes are considered +and the shallower one wins, because every pixel a label moves is a pixel further +from the thing it describes. If that route would push the label out of +``bounds`` the other one is used instead -- without this, a stack of labels +jammed against the edge of the axes gets shoved straight back into the wall on +every iteration and can never spread out sideways. + +This runs once per colliding pair per iteration, so it deals in plain floats: +building a two-element numpy array here costs more than all the arithmetic.""" + ... + +def _point_shift(box: Incomplete, px: Incomplete, py: Incomplete) -> Incomplete: + """Return the shortest translation ``(sx, sy)`` that moves ``box`` off a point.""" + ... + +def _colliding_pairs(boxes: Incomplete, live: Incomplete) -> Incomplete: + """Indices (i, j), i < j, of every pair of live boxes that currently overlap. + +One vectorised sweep. A k-d tree radius query is asymptotically better and is +genuinely faster at this step in isolation, but it does not pay for itself +here: even at 800 labels this sweep is a low single-digit percentage of the +solve, which is dominated by resolving the collisions it finds. It is not worth +a SciPy dependency to speed up something that is not the bottleneck.""" + ... + +def _count_overlaps(boxes: Incomplete) -> int: + """Number of label pairs that visibly overlap. Takes the raw boxes, without the +padding cushion: the cushion is a solver knob, but the score must be judged on +the boxes the reader actually sees.""" + ... + +def _crowd_seed(anchors: Incomplete, obstacles: Incomplete, sizes: Incomplete) -> np.ndarray: + """Initial offsets that push every label away from its local crowd. + +Relaxing from the original positions is a purely local search, so a dense +cluster can settle into a knot that no amount of further iteration undoes. +Starting from a pre-exploded configuration puts the solver in a different +basin, which is what the restarts are for.""" + ... + +def _artist_points(artist: Incomplete) -> Optional[np.ndarray]: + """Sample the display-space points an artist occupies, or None if unsupported.""" + ... + +def _gather_obstacles(ax: Incomplete, labels: Incomplete, avoid_points: bool) -> Incomplete: + """Collect display-space points (data markers/vertices) that labels avoid.""" + ... + +def _label_bbox(label: Incomplete, renderer: Incomplete, padx: Incomplete, pady: Incomplete) -> Incomplete: + ... + +def _position(label: Incomplete) -> tuple: + """Where the label currently sits, in its own coordinate system.""" + ... + +def _place(label: Incomplete, point: Incomplete) -> None: + """Move a label to ``point`` and record that we are the ones who put it there.""" + ... + +def _reset_label(label: Incomplete) -> np.ndarray: + """Restore a label to its user-specified anchor and return that anchor. + +The anchor is cached in the label's own coordinate system the first time we +see it, so re-running the solver on every draw is idempotent rather than +cumulative. A label that is not where we last left it has been repositioned by +the user since the previous solve, and that new position becomes the anchor -- +otherwise ``set_position`` on an aligned label would appear to do nothing, +with the next draw quietly dragging it back to an anchor the user has +abandoned.""" + ... + +def _text_transform(label: Incomplete, renderer: Incomplete) -> Incomplete: + """Return the transform mapping a label's stored position to display space.""" + ... + +def _move_label(label: Incomplete, delta_display: Incomplete, anchor: Incomplete, transform: Incomplete) -> None: + """Offset a label by ``delta_display`` pixels from its anchor.""" + ... + +def _target_display(label: Incomplete, renderer: Incomplete) -> Incomplete: + """Display-space point the label refers to (the annotated point, or its anchor).""" + ... + +def align_text(ax: Incomplete, labels: Optional[Sequence[mtext.Text]]=None, *, renderer: Incomplete=None, pad: float=2.0, avoid_points: bool=True, avoid: Iterable=(), only_move: str='xy', max_iter: int=60, spring: float=0.05, step: float=0.6, clip: bool=True, arrows: bool | dict=False, min_arrow_dist: float=8.0) -> list: + """Nudge text objects until they no longer overlap each other or the data. + +Parameters +---------- +- `ax`: The axes whose labels are aligned. +- `labels`: The labels to move. +- `pad`: Padding in points added around every label bounding box. +- `avoid_points`: Whether labels also repel the data points of lines and scatter plots. +- `avoid`: Additional artists (a legend, an inset, ...) whose bounding boxes the labels must stay clear of. +- `only_move`: Restrict movement to a single axis. +- `max_iter`: Maximum number of relaxation iterations. +- `spring`: Strength of the pull back towards the original anchor. +- `step`: Damping applied to each iteration's displacement. +- `clip`: Whether to keep labels inside the axes. +- `arrows`: Whether to draw a connector from displaced labels back to their anchor. +- `min_arrow_dist`: Only draw connectors for labels displaced further than this (in points). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.textalign.align_text.html)""" + ... diff --git a/ultraplot/ticker.pyi b/ultraplot/ticker.pyi new file mode 100644 index 000000000..3b804cdb1 --- /dev/null +++ b/ultraplot/ticker.pyi @@ -0,0 +1,638 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Various [Locator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Locator.html) and [Formatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.Formatter.html) classes. +""" +from _typeshed import Incomplete +import locale +import re +from fractions import Fraction +import matplotlib.axis as maxis +import matplotlib.dates as mdates +import matplotlib.ticker as mticker +import matplotlib.transforms as mtransforms +import matplotlib.units as munits +from datetime import datetime, timedelta +import numpy as np +try: + import cftime +except ModuleNotFoundError: + cftime = None +from .config import rc +from .internals import ic +from .internals import _not_none, context, docstring +try: + import cartopy.crs as ccrs + from cartopy.mpl.ticker import LatitudeFormatter, LongitudeFormatter, _PlateCarreeFormatter +except ModuleNotFoundError: + ccrs = None + LatitudeFormatter = LongitudeFormatter = _PlateCarreeFormatter = object +__all__ = ['IndexLocator', 'DiscreteLocator', 'DegreeLocator', 'LongitudeLocator', 'LatitudeLocator', 'AutoFormatter', 'SimpleFormatter', 'IndexFormatter', 'SciFormatter', 'SigFigFormatter', 'FracFormatter', 'CFDatetimeFormatter', 'AutoCFDatetimeFormatter', 'AutoCFDatetimeLocator', 'DegreeFormatter', 'LongitudeFormatter', 'LatitudeFormatter'] +REGEX_ZERO = re.compile('\\A[-−]?0(.0*)?\\Z') +REGEX_MINUS = re.compile('\\A[-−]\\Z') +REGEX_MINUS_ZERO = re.compile('\\A[-−]0(.0*)?\\Z') +_precision_docstring = ... +_zerotrim_docstring = ... +_auto_docstring = ... +_formatter_call = '\nConvert number to a string.\n\nParameters\n----------\nx : float\n The value.\npos : float, optional\n The position.\n' +_dms_docstring = ... + +def _default_precision_zerotrim(precision: Incomplete=None, zerotrim: Incomplete=None) -> Incomplete: + """Return the default zerotrim and precision. Shared by several formatters.""" + ... + +class IndexLocator(mticker.Locator): + """Format numbers by assigning fixed strings to non-negative indices. The ticks +are restricted to the extent of plotted content when content is present.""" + + def __init__(self, base: Incomplete=1, offset: Incomplete=0) -> None: + ... + + def set_params(self, base: Incomplete=None, offset: Incomplete=None) -> None: + """Do nothing, and raise a warning. Any locator class not supporting the +set_params() function will call this.""" + ... + + def __call__(self) -> Incomplete: + """Return the locations of the ticks.""" + ... + + def tick_values(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + """Return the values of the located ticks given **vmin** and **vmax**. + +.. note:: + To get tick locations with the vmin and vmax values defined + automatically for the associated ``axis`` simply call + the Locator instance:: + + >>> print(type(loc)) + + >>> print(loc()) + [1, 2, 3, 4]""" + ... + +class DiscreteLocator(mticker.Locator): + """A tick locator suitable for discretized colorbars. Adds ticks to some +subset of the location list depending on the available space determined from +[get_tick_space](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.Axis.get_tick_space.html). Zero will be used if it appears in the +location list, and step sizes along the location list are restricted to "nice" +intervals by default.""" + default_params = {'nbins': None, 'minor': False, 'steps': np.array([1, 2, 3, 4, 5, 6, 8, 10]), 'min_n_ticks': 2} + + def __init__(self, locs: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +locs : array-like + The tick location list. +nbins : int, optional + Maximum number of ticks to select. By default this is automatically + determined based on the the axis length and tick label font size. +minor : bool, default: False + Whether this is for "minor" ticks. Setting to ``True`` will select more + ticks with an index step that divides the index step used for "major" ticks. +steps : array-like of int, default: ``[1 2 3 4 5 6 8]`` + Valid integer index steps when selecting from the tick list. Must fall + between 1 and 9. Powers of 10 of these step sizes will also be permitted. +min_n_ticks : int, default: 1 + The minimum number of ticks to select. See also `nbins`.""" + ... + + def __call__(self) -> Incomplete: + """Return the locations of the ticks.""" + ... + + def set_params(self, steps: Incomplete=None, nbins: Incomplete=None, minor: Incomplete=None, min_n_ticks: Incomplete=None) -> None: + """Set the parameters for this locator. See `DiscreteLocator` for details.""" + ... + + def tick_values(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + """Return the locations of the ticks.""" + ... + +class DegreeLocator(mticker.MaxNLocator): + """Locate geographic gridlines with degree-minute-second support. +Adapted from cartopy.""" + default_params = mticker.MaxNLocator.default_params.copy() + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +dms : bool, default: False + Locate the ticks on clean degree-minute-second intervals and format the + ticks with minutes and seconds instead of decimals.""" + ... + + def set_params(self, **kwargs: Incomplete) -> None: + """Set parameters for this locator. + +Parameters +---------- +nbins : int or 'auto', optional + see `.MaxNLocator` +steps : array-like, optional + see `.MaxNLocator` +integer : bool, optional + see `.MaxNLocator` +symmetric : bool, optional + see `.MaxNLocator` +prune : {'lower', 'upper', 'both', None}, optional + see `.MaxNLocator` +min_n_ticks : int, optional + see `.MaxNLocator`""" + ... + + def _guess_steps(self, vmin: Incomplete, vmax: Incomplete) -> None: + ... + + def _raw_ticks(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + """Generate a list of tick locations including the range *vmin* to +*vmax*. In some applications, one or both of the end locations +will not be needed, in which case they are trimmed off +elsewhere.""" + ... + + def bin_boundaries(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + ... + +class LongitudeLocator(DegreeLocator): + """Locate longitude gridlines with degree-minute-second support. +Adapted from cartopy.""" + + def __init__(self, lon0: Incomplete=0, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +dms : bool, default: False + Locate the ticks on clean degree-minute-second intervals and format the + ticks with minutes and seconds instead of decimals. + +Parameters +---------- +lon0 : float, default=0 + The central longitude around which the longitude labels are centered. + This parameter adjusts the alignment of the longitude gridlines and + labels, ensuring they are centered relative to the specified value.""" + ... + +class LatitudeLocator(DegreeLocator): + """Locate latitude gridlines with degree-minute-second support. +Adapted from cartopy.""" + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +dms : bool, default: False + Locate the ticks on clean degree-minute-second intervals and format the + ticks with minutes and seconds instead of decimals.""" + ... + + def tick_values(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + """Return the values of the located ticks given **vmin** and **vmax**. + +.. note:: + To get tick locations with the vmin and vmax values defined + automatically for the associated ``axis`` simply call + the Locator instance:: + + >>> print(type(loc)) + + >>> print(loc()) + [1, 2, 3, 4]""" + ... + + def _guess_steps(self, vmin: Incomplete, vmax: Incomplete) -> None: + ... + + def _raw_ticks(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + """Generate a list of tick locations including the range *vmin* to +*vmax*. In some applications, one or both of the end locations +will not be needed, in which case they are trimmed off +elsewhere.""" + ... + +class AutoFormatter(mticker.ScalarFormatter): + """The default formatter used for ultraplot tick labels. +Replaces [ScalarFormatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.ScalarFormatter.html).""" + + def __init__(self, zerotrim: Incomplete=None, tickrange: Incomplete=None, wraprange: Incomplete=None, prefix: Incomplete=None, suffix: Incomplete=None, negpos: Incomplete=None, **kwargs: Incomplete) -> None: + """Parameters +---------- +zerotrim : bool, default: [formatter.zerotrim](https://ultraplot.readthedocs.io/en/stable/search.html?q=formatter.zerotrim) + Whether to trim trailing decimal zeros. +tickrange : 2-tuple of float, optional + Range within which major tick marks are labeled. + All ticks are labeled by default. +wraprange : 2-tuple of float, optional + Range outside of which tick values are wrapped. For example, + ``(-180, 180)`` will format a value of ``200`` as ``-160``. +prefix, suffix : str, optional + Prefix and suffix for all tick strings. The suffix is added before + the optional `negpos` suffix. +negpos : str, optional + Length-2 string indicating the suffix for "negative" and "positive" + numbers, meant to replace the minus sign. + +Other parameters +---------------- +**kwargs + Passed to [matplotlib.ticker.ScalarFormatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.ScalarFormatter.html). + +See also +-------- +ultraplot.constructor.Formatter +ultraplot.ticker.SimpleFormatter + +Note +---- +[matplotlib.ticker.ScalarFormatter](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.ScalarFormatter.html) determines the number of +significant digits based on the axis limits, and therefore may +truncate digits while formatting ticks on highly non-linear axis +scales like [LogScale](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.scale.LogScale.html). `AutoFormatter` corrects +this behavior, making it suitable for arbitrary axis scales. We +therefore use `AutoFormatter` with every axis scale by default.""" + ... + + def __call__(self, x: Incomplete, pos: Incomplete=None) -> Incomplete: + """Convert number to a string. + +Parameters +---------- +x : float + The value. +pos : float, optional + The position.""" + ... + + def get_offset(self) -> str: + """Get the offset but *always* use math text.""" + ... + + @staticmethod + def _add_prefix_suffix(string: Incomplete, prefix: Incomplete=None, suffix: Incomplete=None) -> Incomplete: + """Add prefix and suffix to string.""" + ... + + def _fix_small_number(self, x: Incomplete, string: Incomplete, precision_offset: Incomplete=2) -> Incomplete: + """Fix formatting for non-zero formatted as zero. The `offset` controls the offset +from true floating point precision at which we want to limit string precision.""" + ... + + def _get_decimal_point(self, use_locale: Incomplete=None) -> str: + """Get decimal point symbol for current locale (e.g. in Europe will be comma).""" + ... + + @staticmethod + def _get_default_decimal_point(use_locale: Incomplete=None) -> str: + """Get decimal point symbol for current locale. Called externally.""" + ... + + @staticmethod + def _decimal_place(x: Incomplete) -> int: + """Return the decimal place of the number (e.g., 100 is -2 and 0.01 is 2).""" + ... + + @staticmethod + def _minus_format(string: Incomplete) -> Incomplete: + """Format the minus sign and avoid "negative zero," e.g. ``-0.000``.""" + ... + + @staticmethod + def _neg_pos_format(x: Incomplete, negpos: Incomplete, wraprange: Incomplete=None) -> Incomplete: + """Permit suffixes indicators for "negative" and "positive" numbers.""" + ... + + @staticmethod + def _outside_tick_range(x: Incomplete, tickrange: Incomplete) -> Incomplete: + """Return whether point is outside tick range up to some precision.""" + ... + + @staticmethod + def _trim_trailing_zeros(string: Incomplete, decimal_point: Incomplete='.') -> Incomplete: + """Sanitize tick label strings.""" + ... + + @staticmethod + def _wrap_tick_range(x: Incomplete, wraprange: Incomplete) -> Incomplete: + """Wrap the tick range to within these values.""" + ... + +class SimpleFormatter(mticker.Formatter): + """A general purpose number formatter. This is similar to `AutoFormatter` +but suitable for arbitrary formatting not necessarily associated with +an [Axis](https://matplotlib.org/stable/api/_as_gen/matplotlib.axis.Axis.html) instance.""" + + def __init__(self, precision: Incomplete=None, zerotrim: Incomplete=None, tickrange: Incomplete=None, wraprange: Incomplete=None, prefix: Incomplete=None, suffix: Incomplete=None, negpos: Incomplete=None) -> None: + """Parameters +---------- +precision : int, default: {6, 2} + The maximum number of digits after the decimal point. Default is ``6`` + when `zerotrim` is ``True`` and ``2`` otherwise. +zerotrim : bool, default: [formatter.zerotrim](https://ultraplot.readthedocs.io/en/stable/search.html?q=formatter.zerotrim) + Whether to trim trailing decimal zeros. +tickrange : 2-tuple of float, optional + Range within which major tick marks are labeled. + All ticks are labeled by default. +wraprange : 2-tuple of float, optional + Range outside of which tick values are wrapped. For example, + ``(-180, 180)`` will format a value of ``200`` as ``-160``. +prefix, suffix : str, optional + Prefix and suffix for all tick strings. The suffix is added before + the optional `negpos` suffix. +negpos : str, optional + Length-2 string indicating the suffix for "negative" and "positive" + numbers, meant to replace the minus sign. + +See also +-------- +ultraplot.constructor.Formatter +ultraplot.ticker.AutoFormatter""" + ... + + def __call__(self, x: Incomplete, pos: Incomplete=None) -> Incomplete: + """Convert number to a string. + +Parameters +---------- +x : float + The value. +pos : float, optional + The position.""" + ... + +class IndexFormatter(mticker.Formatter): + """Format numbers by assigning fixed strings to non-negative indices. Generally +paired with `IndexLocator` or [FixedLocator](https://matplotlib.org/stable/api/_as_gen/matplotlib.ticker.FixedLocator.html).""" + + def __init__(self, labels: Incomplete) -> None: + ... + + def __call__(self, x: Incomplete, pos: Incomplete=None) -> Incomplete: + """Return the format for tick value *x* at position pos. +``pos=None`` indicates an unspecified location.""" + ... + +class SciFormatter(mticker.Formatter): + """Format numbers with scientific notation.""" + + def __init__(self, precision: Incomplete=None, zerotrim: Incomplete=None) -> None: + """Parameters +---------- +precision : int, default: {6, 2} + The maximum number of digits after the decimal point. Default is ``6`` + when `zerotrim` is ``True`` and ``2`` otherwise. +zerotrim : bool, default: [formatter.zerotrim](https://ultraplot.readthedocs.io/en/stable/search.html?q=formatter.zerotrim) + Whether to trim trailing decimal zeros. + +See also +-------- +ultraplot.constructor.Formatter +ultraplot.ticker.AutoFormatter""" + ... + + def __call__(self, x: Incomplete, pos: Incomplete=None) -> str: + """Convert number to a string. + +Parameters +---------- +x : float + The value. +pos : float, optional + The position.""" + ... + +class SigFigFormatter(mticker.Formatter): + """Format numbers by retaining the specified number of significant digits.""" + + def __init__(self, sigfig: Incomplete=None, zerotrim: Incomplete=None, base: Incomplete=None) -> None: + """Parameters +---------- +sigfig : float, default: 3 + The number of significant digits. +zerotrim : bool, default: [formatter.zerotrim](https://ultraplot.readthedocs.io/en/stable/search.html?q=formatter.zerotrim) + Whether to trim trailing decimal zeros. +base : float, default: 1 + The base unit for rounding. For example ``SigFigFormatter(2, base=5)`` + rounds to the nearest 5 with up to 2 digits (e.g., 87 --> 85, 8.7 --> 8.5). + +See also +-------- +ultraplot.constructor.Formatter +ultraplot.ticker.AutoFormatter""" + ... + + def __call__(self, x: Incomplete, pos: Incomplete=None) -> Incomplete: + """Convert number to a string. + +Parameters +---------- +x : float + The value. +pos : float, optional + The position.""" + ... + +class FracFormatter(mticker.Formatter): + """Format numbers as integers or integer fractions. Optionally express the +values relative to some constant like [numpy.pi](https://numpy.org/doc/stable/reference/generated/numpy.pi.html).""" + + def __init__(self, symbol: Incomplete='', number: Incomplete=1) -> None: + """Parameters +---------- +symbol : str, default: '' + The constant symbol, e.g. ``r'$\\pi$'``. +number : float, default: 1 + The constant value, e.g. [numpy.pi](https://numpy.org/doc/stable/reference/generated/numpy.pi.html). + +Note +---- +The fractions shown by this formatter are resolved using the builtin +`fractions.Fraction` class and `fractions.Fraction.limit_denominator`. + +See also +-------- +ultraplot.constructor.Formatter +ultraplot.ticker.AutoFormatter""" + ... + + def __call__(self, x: Incomplete, pos: Incomplete=None) -> Incomplete: + """Convert number to a string. + +Parameters +---------- +x : float + The value. +pos : float, optional + The position.""" + ... + +class CFDatetimeFormatter(mticker.Formatter): + """Format dates using `cftime.datetime.strftime` format strings.""" + + def __init__(self, fmt: Incomplete, calendar: Incomplete='standard', units: Incomplete='days since 2000-01-01') -> None: + """Parameters +---------- +fmt : str + The `strftime` format string. +calendar : str, default: 'standard' + The calendar for interpreting numeric tick values. +units : str, default: 'days since 2000-01-01' + The time units for interpreting numeric tick values.""" + ... + + def __call__(self, x: Incomplete, pos: Incomplete=None) -> Incomplete: + """Return the format for tick value *x* at position pos. +``pos=None`` indicates an unspecified location.""" + ... + +class AutoCFDatetimeFormatter(mticker.Formatter): + """Automatic formatter for `cftime.datetime` data.""" + + def __init__(self, locator: Incomplete, calendar: Incomplete, time_units: Incomplete=None) -> None: + ... + + def pick_format(self, resolution: Incomplete) -> Incomplete: + ... + + def __call__(self, x: Incomplete, pos: Incomplete=0) -> Incomplete: + """Return the format for tick value *x* at position pos. +``pos=None`` indicates an unspecified location.""" + ... + +class AutoCFDatetimeLocator(mticker.Locator): + """Determines tick locations when plotting `cftime.datetime` data.""" + if cftime: + real_world_calendars = cftime._cftime._calendars + else: + real_world_calendars = () + + def __init__(self, maxticks: Incomplete=None, calendar: Incomplete='standard', date_unit: Incomplete=None, minticks: Incomplete=3) -> None: + ... + + def set_params(self, maxticks: Incomplete=None, minticks: Incomplete=None, max_display_ticks: Incomplete=None) -> None: + """Set the parameters for the locator.""" + ... + + def compute_resolution(self, num1: Incomplete, num2: Incomplete, date1: Incomplete, date2: Incomplete) -> Incomplete: + """Returns the resolution of the dates. +Also updates self.calendar from date1 for consistency.""" + ... + + def __call__(self) -> Incomplete: + """Return the locations of the ticks.""" + ... + + def tick_values(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + """Return the values of the located ticks given **vmin** and **vmax**. + +.. note:: + To get tick locations with the vmin and vmax values defined + automatically for the associated ``axis`` simply call + the Locator instance:: + + >>> print(type(loc)) + + >>> print(loc()) + [1, 2, 3, 4]""" + ... + + def _safe_num2date(self, value: Incomplete, vmax: Incomplete=None) -> Incomplete: + """Safely converts numeric values to cftime.datetime objects. + +If a single value is provided, it converts and returns a single datetime object. +If both value (vmin) and vmax are provided, it converts and returns a tuple of +datetime objects (lower, upper). + +This helper is used to handle cases where the conversion might fail +due to invalid inputs or calendar-specific constraints. If the conversion +fails, it returns None or a tuple of Nones.""" + ... + + def _safe_create_datetime(self, year: Incomplete, month: Incomplete=1, day: Incomplete=1, hour: Incomplete=0, minute: Incomplete=0, second: Incomplete=0) -> Incomplete: + """Safely creates a cftime.datetime object with the given date and time components. + +This helper is used to handle cases where creating a datetime object might fail +due to invalid inputs (e.g., invalid dates in specific calendars). If the creation +fails, it returns None.""" + ... + + def _safe_daily_locator(self, vmin: Incomplete, vmax: Incomplete) -> Incomplete: + """Safely generates daily tick values using MaxNLocator. + +This helper is used to handle cases where the locator might fail +due to invalid input ranges or other issues. If the locator fails, +it returns None.""" + ... + +class _CartopyFormatter(object): + """Mixin class for cartopy formatters.""" + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + ... + + def __call__(self, value: Incomplete, pos: Incomplete=None) -> Incomplete: + ... + +class DegreeFormatter(_CartopyFormatter, _PlateCarreeFormatter): + """Formatter for longitude and latitude gridline labels. +Adapted from cartopy.""" + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +dms : bool, default: False + Locate the ticks on clean degree-minute-second intervals and format the + ticks with minutes and seconds instead of decimals.""" + ... + + def _apply_transform(self, value: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + ... + + def _hemisphere(self, value: Incomplete, *args: Incomplete, **kwargs: Incomplete) -> Incomplete: + ... + +class LongitudeFormatter(_CartopyFormatter, LongitudeFormatter): + """Format longitude gridline labels. Adapted from +`cartopy.mpl.ticker.LongitudeFormatter` with support for +proper centering based on lon0.""" + + def __init__(self, lon0: Incomplete=0, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +lon0 : float, optional + Central longitude value to use for centering the map. + Labels will be adjusted relative to this value. +Parameters +---------- +dms : bool, default: False + Locate the ticks on clean degree-minute-second intervals and format the + ticks with minutes and seconds instead of decimals.""" + ... + +class LatitudeFormatter(_CartopyFormatter, LatitudeFormatter): + """Format latitude gridline labels. Adapted from +`cartopy.mpl.ticker.LatitudeFormatter`.""" + + def __init__(self, *args: Incomplete, **kwargs: Incomplete) -> None: + """Parameters +---------- +dms : bool, default: False + Locate the ticks on clean degree-minute-second intervals and format the + ticks with minutes and seconds instead of decimals.""" + ... + +class CFTimeConverter(mdates.DateConverter): + """Converter for cftime.datetime data.""" + + @staticmethod + def axisinfo(unit: Incomplete, axis: Incomplete) -> Incomplete: + """Returns the [AxisInfo](https://matplotlib.org/stable/api/_as_gen/matplotlib.units.AxisInfo.html) for *unit*.""" + ... + + @classmethod + def default_units(cls, x: Incomplete, axis: Incomplete) -> Incomplete: + """Computes some units for the given data point.""" + ... + + @classmethod + def convert(cls, value: Incomplete, unit: Incomplete, axis: Incomplete) -> Incomplete: + """Converts value with `cftime.date2num`.""" + ... diff --git a/ultraplot/ui.py b/ultraplot/ui.py index f61b03840..aa773502a 100644 --- a/ultraplot/ui.py +++ b/ultraplot/ui.py @@ -9,6 +9,7 @@ from . import figure as pfigure from . import gridspec as pgridspec from ._subplots import SubplotManager +from .figure import Figure from .internals import ( _not_none, _pop_params, @@ -125,7 +126,7 @@ def isinteractive(): @docstring._snippet_manager -def figure(**kwargs): +def figure(**kwargs) -> Figure: """ Create an empty figure. Subplots can be subsequently added using `~ultraplot.figure.Figure.add_subplot` or `~ultraplot.figure.Figure.subplots`. @@ -153,7 +154,7 @@ def figure(**kwargs): @docstring._snippet_manager -def subplot(**kwargs): +def subplot(**kwargs) -> tuple[Figure, paxes.Axes]: """ Return a figure and a single subplot. This command is analogous to `matplotlib.pyplot.subplot`, @@ -196,7 +197,7 @@ def subplot(**kwargs): @docstring._snippet_manager -def subplots(*args, **kwargs): +def subplots(*args, **kwargs) -> tuple[Figure, pgridspec.SubplotGrid]: """ Return a figure and an arbitrary grid of subplots. This command is analogous to `matplotlib.pyplot.subplots`, diff --git a/ultraplot/ui.pyi b/ultraplot/ui.pyi new file mode 100644 index 000000000..4f662456d --- /dev/null +++ b/ultraplot/ui.pyi @@ -0,0 +1,153 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +The starting point for creating ultraplot figures. +""" +from _typeshed import Incomplete +import matplotlib.pyplot as plt +from . import axes as paxes +from . import figure as pfigure +from . import gridspec as pgridspec +from ._subplots import SubplotManager +from .figure import Figure +from .internals import _not_none, _pop_params, _pop_props, _pop_rc, docstring, ic +__all__ = ['figure', 'subplot', 'subplots', 'show', 'close', 'switch_backend', 'ion', 'ioff', 'isinteractive'] +_pyplot_docstring = ... + +def _parse_figsize(kwargs: Incomplete) -> Incomplete: + """Translate `figsize` into ultraplot-specific `figwidth` and `figheight` keys.""" + ... + +def show(*args: Incomplete, **kwargs: Incomplete) -> None: + """Call [matplotlib.pyplot.show](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.show.html). +This is included so you don't have to import [pyplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.html). + +Parameters +---------- +*args, **kwargs + Passed to [matplotlib.pyplot.show](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.show.html).""" + ... + +def close(*args: Incomplete, **kwargs: Incomplete) -> None: + """Call [matplotlib.pyplot.close](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.close.html). +This is included so you don't have to import [pyplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.html). + +Parameters +---------- +*args, **kwargs + Passed to [matplotlib.pyplot.close](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.close.html).""" + ... + +def switch_backend(*args: Incomplete, **kwargs: Incomplete) -> None: + """Call [matplotlib.pyplot.switch_backend](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.switch_backend.html). +This is included so you don't have to import [pyplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.html). + +Parameters +---------- +*args, **kwargs + Passed to [matplotlib.pyplot.switch_backend](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.switch_backend.html).""" + ... + +def ion() -> Incomplete: + """Call [matplotlib.pyplot.ion](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.ion.html). +This is included so you don't have to import [pyplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.html).""" + ... + +def ioff() -> Incomplete: + """Call [matplotlib.pyplot.ioff](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.ioff.html). +This is included so you don't have to import [pyplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.html).""" + ... + +def isinteractive() -> bool: + """Call [matplotlib.pyplot.isinteractive](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.isinteractive.html). +This is included so you don't have to import [pyplot](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.html).""" + ... + +def figure(**kwargs: Incomplete) -> Figure: + """Create an empty figure. + +Parameters +---------- +- `refnum`: The reference subplot number. +- `refaspect`: The reference subplot aspect ratio. +- `refwidth, refheight`: The width, height of the reference subplot. +- `figwidth, figheight`: The figure width and height. +- `figsize`: Tuple specifying the figure ``(width, height)``. +- `sharex, sharey, share`: The axis sharing "level" for the *x* axis, *y* axis, or both axes. +- `spanx, spany, span`: Whether to use "spanning" axis labels for the *x* axis, *y* axis, or both axes. +- `alignx, aligny, align`: Whether to ["align" axis labels](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/align_labels_demo.html) for the *x* axis, *y* axis, or both axes. +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, or both. +- `tight`: Whether automatic calls to `~Figure.auto_layout` should include [tight layout adjustments](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight). +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. +- `journal`: String corresponding to an academic journal standard used to control the figure width `figwidth` and, if specified, the figure height `figheight`. +- `**kwargs`: Passed to [ultraplot.figure.Figure.format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.format). + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ui.figure.html)""" + ... + +def subplot(**kwargs: Incomplete) -> tuple[Figure, paxes.Axes]: + """Return a figure and a single subplot. + +Parameters +---------- +- `refnum`: The reference subplot number. +- `refaspect`: The reference subplot aspect ratio. +- `refwidth, refheight`: The width, height of the reference subplot. +- `figwidth, figheight`: The figure width and height. +- `figsize`: Tuple specifying the figure ``(width, height)``. +- `sharex, sharey, share`: The axis sharing "level" for the *x* axis, *y* axis, or both axes. +- `spanx, spany, span`: Whether to use "spanning" axis labels for the *x* axis, *y* axis, or both axes. +- `alignx, aligny, align`: Whether to ["align" axis labels](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/align_labels_demo.html) for the *x* axis, *y* axis, or both axes. +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, or both. +- `tight`: Whether automatic calls to `~Figure.auto_layout` should include [tight layout adjustments](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight). +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. +- `journal`: String corresponding to an academic journal standard used to control the figure width `figwidth` and, if specified, the figure height `figheight`. +- `**kwargs`: Passed to [ultraplot.figure.Figure.format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.format) or the projection-specific ``format`` command for the axes. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ui.subplot.html)""" + ... + +def subplots(*args: Incomplete, **kwargs: Incomplete) -> tuple[Figure, pgridspec.SubplotGrid]: + """Return a figure and an arbitrary grid of subplots. + +Parameters +---------- +- `array`: The subplot grid specifier. +- `nrows, ncols`: The number of rows and columns in the subplot grid. +- `order`: Whether subplots are numbered in column-major (``'C'``) or row-major (``'F'``) order. +- `proj, projection`: The map projection specification(s). +- `proj_kw, projection_kw`: Keyword arguments passed to `Basemap` or `Projection` classes on instantiation. +- `backend`: Whether to use `Basemap` or `Projection` for map projections. +- `left, right, top, bottom`: The fixed space between the subplots and the figure edge. +- `wspace, hspace, space`: The fixed space between grid columns, rows, and both, respectively. +- `wratios, hratios`: Passed to [GridSpec](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.gridspec.GridSpec.html), denotes the width and height ratios for the subplot grid. +- `wpad, hpad, pad`: The tight layout padding between columns, rows, and both, respectively. +- `wequal, hequal, equal`: Whether to make the tight layout algorithm apply equal spacing between columns, rows, or both. +- `wgroup, hgroup, group`: Whether to make the tight layout algorithm just consider spaces between adjacent subplots instead of entire columns and rows of subplots. +- `outerpad`: The scalar tight layout padding around the left, right, top, bottom figure edges. +- `innerpad`: The scalar tight layout padding between columns and rows. +- `panelpad`: The scalar tight layout padding between subplots and their panels, colorbars, and legends and between "stacks" of these objects. +- `refnum`: The reference subplot number. +- `refaspect`: The reference subplot aspect ratio. +- `refwidth, refheight`: The width, height of the reference subplot. +- `figwidth, figheight`: The figure width and height. +- `figsize`: Tuple specifying the figure ``(width, height)``. +- `sharex, sharey, share`: The axis sharing "level" for the *x* axis, *y* axis, or both axes. +- `spanx, spany, span`: Whether to use "spanning" axis labels for the *x* axis, *y* axis, or both axes. +- `alignx, aligny, align`: Whether to ["align" axis labels](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/align_labels_demo.html) for the *x* axis, *y* axis, or both axes. +- `tight`: Whether automatic calls to `~Figure.auto_layout` should include [tight layout adjustments](https://ultraplot.readthedocs.io/en/stable/search.html?q=ug_tight). +- `journal`: String corresponding to an academic journal standard used to control the figure width `figwidth` and, if specified, the figure height `figheight`. +- `**kwargs`: Passed to [ultraplot.figure.Figure.format](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.figure.Figure.html#ultraplot.figure.Figure.format) or the projection-specific ``format`` command for each axes. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.ui.subplots.html)""" + ... diff --git a/ultraplot/ultralayout.pyi b/ultraplot/ultralayout.pyi new file mode 100644 index 000000000..293b15e5b --- /dev/null +++ b/ultraplot/ultralayout.pyi @@ -0,0 +1,153 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +UltraLayout: Advanced constraint-based layout system for non-orthogonal subplot arrangements. + +This module provides UltraPlot's constraint-based layout computation for subplot grids +that don't follow simple orthogonal patterns, such as [[1, 1, 2, 2], [0, 3, 3, 0]] +where subplot 3 should be nicely centered between subplots 1 and 2. +""" +from _typeshed import Incomplete +from typing import Dict, List, Optional, Tuple +import numpy as np +try: + from kiwisolver import Solver, Variable + KIWI_AVAILABLE = True +except ImportError: + KIWI_AVAILABLE = False + Variable = None + Solver = None +__all__ = ['ColorbarLayoutSolver', 'UltraLayoutSolver', 'compute_ultra_positions', 'get_grid_positions_ultra', 'is_orthogonal_layout'] + +def is_orthogonal_layout(array: np.ndarray) -> bool: + """Check if a subplot array follows an orthogonal (grid-aligned) layout. + +An orthogonal layout is one where every subplot's edges align with +other subplots' edges, forming a simple grid. + +Parameters +---------- +array : np.ndarray + 2D array of subplot numbers (with 0 for empty cells) + +Returns +------- +bool + True if layout is orthogonal, False otherwise""" + ... + +class UltraLayoutSolver: + """UltraLayout: Constraint-based layout solver using kiwisolver for subplot positioning. + +This solver computes aesthetically pleasing positions for subplots in +non-orthogonal arrangements by using constraint satisfaction, providing +a superior layout experience for complex subplot arrangements.""" + + def __init__(self, array: np.ndarray, figwidth: float=10.0, figheight: float=8.0, wspace: Optional[List[float]]=None, hspace: Optional[List[float]]=None, left: float=0.125, right: float=0.125, top: float=0.125, bottom: float=0.125, wratios: Optional[List[float]]=None, hratios: Optional[List[float]]=None, wpanels: Optional[List[bool]]=None, hpanels: Optional[List[bool]]=None) -> None: + """Initialize the UltraLayout solver. + +Parameters +---------- +array : np.ndarray + 2D array of subplot numbers (with 0 for empty cells) +figwidth, figheight : float + Figure dimensions in inches +wspace, hspace : list of float, optional + Spacing between columns and rows in inches +left, right, top, bottom : float + Margins in inches +wratios, hratios : list of float, optional + Width and height ratios for columns and rows +wpanels, hpanels : list of bool, optional + Flags indicating panel columns or rows with fixed widths/heights.""" + ... + + def _setup_variables(self) -> None: + """Create kiwisolver variables for all grid lines.""" + ... + + def _setup_constraints(self) -> None: + """Set up all constraints for the layout.""" + ... + + def solve(self) -> Dict[int, Tuple[float, float, float, float]]: + """Solve the constraint system and return subplot positions. + +Returns +------- +dict + Dictionary mapping subplot numbers to (left, bottom, width, height) + in figure-relative coordinates [0, 1]""" + ... + +class ColorbarLayoutSolver: + """Constraint-based solver for inset colorbar frame alignment.""" + + def __init__(self, loc: str, cb_width: float, cb_height: float, pad_left: float, pad_right: float, pad_bottom: float, pad_top: float) -> None: + ... + + def _setup_constraints(self) -> None: + ... + + def solve(self) -> Dict[str, Tuple[float, float, float, float]]: + """Solve the constraint system and return inset and frame bounds.""" + ... + +def compute_ultra_positions(array: np.ndarray, figwidth: float=10.0, figheight: float=8.0, wspace: Optional[List[float]]=None, hspace: Optional[List[float]]=None, left: float=0.125, right: float=0.125, top: float=0.125, bottom: float=0.125, wratios: Optional[List[float]]=None, hratios: Optional[List[float]]=None, wpanels: Optional[List[bool]]=None, hpanels: Optional[List[bool]]=None) -> Dict[int, Tuple[float, float, float, float]]: + """Compute subplot positions using UltraLayout for non-orthogonal layouts. + +Parameters +---------- +array : np.ndarray + 2D array of subplot numbers (with 0 for empty cells) +figwidth, figheight : float + Figure dimensions in inches +wspace, hspace : list of float, optional + Spacing between columns and rows in inches +left, right, top, bottom : float + Margins in inches +wratios, hratios : list of float, optional + Width and height ratios for columns and rows +wpanels, hpanels : list of bool, optional + Flags indicating panel columns or rows with fixed widths/heights. + +Returns +------- +dict + Dictionary mapping subplot numbers to (left, bottom, width, height) + in figure-relative coordinates [0, 1] + +Examples +-------- +>>> array = np.array([[1, 1, 2, 2], [0, 3, 3, 0]]) +>>> positions = compute_ultra_positions(array) +>>> positions[3] # Position of subplot 3 +(0.25, 0.125, 0.5, 0.35)""" + ... + +def get_grid_positions_ultra(array: np.ndarray, figwidth: float, figheight: float, wspace: Optional[List[float]]=None, hspace: Optional[List[float]]=None, left: float=0.125, right: float=0.125, top: float=0.125, bottom: float=0.125, wratios: Optional[List[float]]=None, hratios: Optional[List[float]]=None, wpanels: Optional[List[bool]]=None, hpanels: Optional[List[bool]]=None) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: + """Get grid line positions using UltraLayout. + +This returns arrays of grid line positions similar to GridSpec.get_grid_positions(), +but computed using UltraLayout's constraint satisfaction for better handling of non-orthogonal layouts. + +Parameters +---------- +array : np.ndarray + 2D array of subplot numbers +figwidth, figheight : float + Figure dimensions in inches +wspace, hspace : list of float, optional + Spacing between columns and rows in inches +left, right, top, bottom : float + Margins in inches +wratios, hratios : list of float, optional + Width and height ratios for columns and rows +wpanels, hpanels : list of bool, optional + Flags indicating panel columns or rows with fixed widths/heights. + +Returns +------- +bottoms, tops, lefts, rights : np.ndarray + Arrays of grid line positions for each cell""" + ... diff --git a/ultraplot/utils.pyi b/ultraplot/utils.pyi new file mode 100644 index 000000000..8d8b57ce0 --- /dev/null +++ b/ultraplot/utils.pyi @@ -0,0 +1,583 @@ +# @generated by tools/generate_stubs.py; do not edit +# fmt: off +""" +Various tools that may be useful while making plots. +""" +from _typeshed import Incomplete +import functools +import re +from numbers import Integral, Real +from dataclasses import dataclass +from typing import Generator +import matplotlib.colors as mcolors +import matplotlib.font_manager as mfonts +from matplotlib.gridspec import GridSpec +import numpy as np +from matplotlib import rcParams as rc_matplotlib +from .externals import hsluv +from .internals import ic +from .internals import _not_none, docstring, warnings +__all__ = ['arange', 'edges', 'edges2d', 'get_colors', 'set_hue', 'set_saturation', 'set_luminance', 'set_alpha', 'shift_hue', 'scale_saturation', 'scale_luminance', 'to_hex', 'to_rgb', 'to_xyz', 'to_rgba', 'to_xyza', 'units'] +UNIT_REGEX = re.compile('\\A([-+]?[0-9._]+(?:[eE][-+]?[0-9_]+)?)(.*)\\Z') +UNIT_DICT = {'in': 1.0, 'ft': 12.0, 'yd': 36.0, 'm': 39.37, 'dm': 3.937, 'cm': 0.3937, 'mm': 0.03937, 'pc': 1 / 6.0, 'pt': 1 / 72.0, 'ly': 3.725e+17} +_docstring_rgba = '\ncolor : color-spec\n The color. Sanitized with `to_rgba`.\n' +_docstring_to_rgb = "\ncolor : color-spec\n The color. Can be a 3-tuple or 4-tuple of channel values, a hex\n string, a registered color name, a cycle color like ``'C0'``, or\n a 2-tuple colormap coordinate specification like ``('magma', 0.5)``\n (see `~ultraplot.colors.ColorDatabase` for details).\n\n If `space` is ``'rgb'``, this is a tuple of RGB values, and any\n channels are larger than ``2``, the channels are assumed to be\n on the ``0`` to ``255`` scale and are divided by ``255``.\nspace : {'rgb', 'hsv', 'hcl', 'hpl', 'hsl'}, optional\n The colorspace for the input channel values. Ignored unless `color`\n is a tuple of numbers.\ncycle : str, default: :rcraw:`cycle`\n The registered color cycle name used to interpret colors that\n look like ``'C0'``, ``'C1'``, etc.\nclip : bool, default: True\n Whether to clip channel values into the valid ``0`` to ``1`` range.\n Setting this to ``False`` can result in invalid colors.\n" +_docstring_space = "\nspace : {'hcl', 'hpl', 'hsl', 'hsv'}, optional\n The hue-saturation-luminance-like colorspace used to transform the color.\n Default is the strictly perceptually uniform colorspace ``'hcl'``.\n" +_docstring_hex = '\ncolor : str\n An 8-digit HEX string indicating the\n red, green, blue, and alpha channel values.\n' + +def _keep_units(func: Incomplete) -> Incomplete: + """Very simple decorator to strip and re-apply the same units.""" + ... + +def arange(min_: Incomplete, *args: Incomplete) -> Incomplete: + """Identical to [numpy.arange](https://numpy.org/doc/stable/reference/generated/numpy.arange.html) but with inclusive endpoints. For example, +``uplt.arange(2, 4)`` returns the numpy array ``[2, 3, 4]`` instead of +``[2, 3]``. This is useful for generating lists of tick locations or +colormap levels, e.g. ``ax.format(xlocator=uplt.arange(0, 10))`` +or ``ax.pcolor(levels=uplt.arange(0, 10))``. + +Parameters +---------- +*args : float + If three arguments are passed, these are the minimum, maximum, and step + size. If fewer than three arguments are passed, the step size is ``1``. + If one argument is passed, this is the maximum, and the minimum is ``0``. + +Returns +------- +numpy.ndarray + Array of points. + +See also +-------- +numpy.arange +ultraplot.constructor.Locator +ultraplot.axes.CartesianAxes.format +ultraplot.axes.PolarAxes.format +ultraplot.axes.GeoAxes.format +ultraplot.axes.Axes.colorbar +ultraplot.axes.PlotAxes""" + ... + +def edges(z: Incomplete, axis: Incomplete=-1) -> Incomplete: + """Calculate the approximate "edge" values along an axis given "center" values. +The size of the axis is increased by one. This is used internally to calculate +coordinate edges when you supply coordinate centers to pseudocolor commands. + +Parameters +---------- +z : array-like + An array of any shape. +axis : int, optional + The axis along which "edges" are calculated. The size of this + axis will be increased by one. + +Returns +------- +numpy.ndarray + Array of "edge" coordinates. + +See also +-------- +edges2d +ultraplot.axes.PlotAxes.pcolor +ultraplot.axes.PlotAxes.pcolormesh +ultraplot.axes.PlotAxes.pcolorfast""" + ... + +def edges2d(z: Incomplete) -> Incomplete: + """Calculate the approximate "edge" values given a 2D grid of "center" values. +The size of both axes is increased by one. This is used internally to calculate +coordinate edges when you supply coordinate to pseudocolor commands. + +Parameters +---------- +z : array-like + A 2D array. + +Returns +------- +numpy.ndarray + Array of "edge" coordinates. + +See also +-------- +edges +ultraplot.axes.PlotAxes.pcolor +ultraplot.axes.PlotAxes.pcolormesh +ultraplot.axes.PlotAxes.pcolorfast""" + ... + +def get_colors(*args: Incomplete, **kwargs: Incomplete) -> list[str]: + """Get the colors associated with a registered or +on-the-fly color cycle or colormap. + +Parameters +---------- +*args, **kwargs + Passed to [Cycle](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.constructor.Cycle.html). + +Returns +------- +colors : list of str + A list of HEX strings. + +See also +-------- +ultraplot.constructor.Cycle +ultraplot.constructor.Colormap""" + ... + +def _transform_color(func: Incomplete, color: Incomplete, space: Incomplete) -> Incomplete: + """Standardize input for color transformation functions.""" + ... + +def shift_hue(color: Incomplete, shift: Incomplete=0, space: Incomplete='hcl') -> str: + """Shift the hue channel of a color. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +shift : float, optional + The HCL hue channel is offset by this value. +space : {'hcl', 'hpl', 'hsl', 'hsv'}, optional + The hue-saturation-luminance-like colorspace used to transform the color. + Default is the strictly perceptually uniform colorspace ``'hcl'``. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +set_hue +set_saturation +set_luminance +set_alpha +scale_saturation +scale_luminance""" + ... + +def scale_saturation(color: Incomplete, scale: Incomplete=1, space: Incomplete='hcl') -> str: + """Scale the saturation channel of a color. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +scale : float, optional + The HCL saturation channel is multiplied by this value. +space : {'hcl', 'hpl', 'hsl', 'hsv'}, optional + The hue-saturation-luminance-like colorspace used to transform the color. + Default is the strictly perceptually uniform colorspace ``'hcl'``. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +set_hue +set_saturation +set_luminance +set_alpha +shift_hue +scale_luminance""" + ... + +def scale_luminance(color: Incomplete, scale: Incomplete=1, space: Incomplete='hcl') -> str: + """Scale the luminance channel of a color. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +scale : float, optional + The luminance channel is multiplied by this value. +space : {'hcl', 'hpl', 'hsl', 'hsv'}, optional + The hue-saturation-luminance-like colorspace used to transform the color. + Default is the strictly perceptually uniform colorspace ``'hcl'``. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +set_hue +set_saturation +set_luminance +set_alpha +shift_hue +scale_saturation""" + ... + +def set_hue(color: Incomplete, hue: Incomplete, space: Incomplete='hcl') -> str: + """Return a color with a different hue and the same luminance and saturation +as the input color. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +hue : float, optional + The new hue. Should lie between ``0`` and ``360`` degrees. +space : {'hcl', 'hpl', 'hsl', 'hsv'}, optional + The hue-saturation-luminance-like colorspace used to transform the color. + Default is the strictly perceptually uniform colorspace ``'hcl'``. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +set_saturation +set_luminance +set_alpha +shift_hue +scale_saturation +scale_luminance""" + ... + +def set_saturation(color: Incomplete, saturation: Incomplete, space: Incomplete='hcl') -> str: + """Return a color with a different saturation and the same hue and luminance +as the input color. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +saturation : float, optional + The new saturation. Should lie between ``0`` and ``360`` degrees. +space : {'hcl', 'hpl', 'hsl', 'hsv'}, optional + The hue-saturation-luminance-like colorspace used to transform the color. + Default is the strictly perceptually uniform colorspace ``'hcl'``. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +set_hue +set_luminance +set_alpha +shift_hue +scale_saturation +scale_luminance""" + ... + +def set_luminance(color: Incomplete, luminance: Incomplete, space: Incomplete='hcl') -> str: + """Return a color with a different luminance and the same hue and saturation +as the input color. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +luminance : float, optional + The new luminance. Should lie between ``0`` and ``100``. +space : {'hcl', 'hpl', 'hsl', 'hsv'}, optional + The hue-saturation-luminance-like colorspace used to transform the color. + Default is the strictly perceptually uniform colorspace ``'hcl'``. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +set_hue +set_saturation +set_alpha +shift_hue +scale_saturation +scale_luminance""" + ... + +def set_alpha(color: Incomplete, alpha: Incomplete) -> str: + """Return a color with the opacity channel set to the specified value. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +alpha : float, optional + The new opacity. Should be between ``0`` and ``1``. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +set_hue +set_saturation +set_luminance +shift_hue +scale_saturation +scale_luminance""" + ... + +def _translate_cycle_color(color: Incomplete, cycle: Incomplete=None) -> Incomplete: + """Parse the input cycle color.""" + ... + +def to_hex(color: Incomplete, space: Incomplete='rgb', cycle: Incomplete=None, keep_alpha: Incomplete=True) -> str: + """Translate the color from an arbitrary colorspace to a HEX string. +This is a generalization of [matplotlib.colors.to_hex](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.to_hex.html). + +Parameters +---------- +color : color-spec + The color. Can be a 3-tuple or 4-tuple of channel values, a hex + string, a registered color name, a cycle color like ``'C0'``, or + a 2-tuple colormap coordinate specification like ``('magma', 0.5)`` + (see [ColorDatabase](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ColorDatabase.html) for details). + + If `space` is ``'rgb'``, this is a tuple of RGB values, and any + channels are larger than ``2``, the channels are assumed to be + on the ``0`` to ``255`` scale and are divided by ``255``. +space : {'rgb', 'hsv', 'hcl', 'hpl', 'hsl'}, optional + The colorspace for the input channel values. Ignored unless `color` + is a tuple of numbers. +cycle : str, default: [cycle](https://ultraplot.readthedocs.io/en/stable/search.html?q=cycle) + The registered color cycle name used to interpret colors that + look like ``'C0'``, ``'C1'``, etc. +clip : bool, default: True + Whether to clip channel values into the valid ``0`` to ``1`` range. + Setting this to ``False`` can result in invalid colors. +keep_alpha : bool, default: True + Whether to keep the opacity channel. If ``True`` an 8-digit HEX + is returned. Otherwise a 6-digit HEX is returned. + +Returns +------- +color : str + An 8-digit HEX string indicating the + red, green, blue, and alpha channel values. + +See also +-------- +to_rgb +to_rgba +to_xyz +to_xyza""" + ... + +def to_rgb(color: Incomplete, space: Incomplete='rgb', cycle: Incomplete=None) -> Incomplete: + """Translate the color from an arbitrary colorspace to an RGB tuple. This is +a generalization of [matplotlib.colors.to_rgb](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.to_rgb.html) and the inverse of `to_xyz`. + +Parameters +---------- +color : color-spec + The color. Can be a 3-tuple or 4-tuple of channel values, a hex + string, a registered color name, a cycle color like ``'C0'``, or + a 2-tuple colormap coordinate specification like ``('magma', 0.5)`` + (see [ColorDatabase](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ColorDatabase.html) for details). + + If `space` is ``'rgb'``, this is a tuple of RGB values, and any + channels are larger than ``2``, the channels are assumed to be + on the ``0`` to ``255`` scale and are divided by ``255``. +space : {'rgb', 'hsv', 'hcl', 'hpl', 'hsl'}, optional + The colorspace for the input channel values. Ignored unless `color` + is a tuple of numbers. +cycle : str, default: [cycle](https://ultraplot.readthedocs.io/en/stable/search.html?q=cycle) + The registered color cycle name used to interpret colors that + look like ``'C0'``, ``'C1'``, etc. +clip : bool, default: True + Whether to clip channel values into the valid ``0`` to ``1`` range. + Setting this to ``False`` can result in invalid colors. + +Returns +------- +color : 3-tuple + An RGB tuple. + +See also +-------- +to_hex +to_rgba +to_xyz +to_xyza""" + ... + +def to_rgba(color: Incomplete, space: Incomplete='rgb', cycle: Incomplete=None, clip: Incomplete=True) -> Incomplete: + """Translate the color from an arbitrary colorspace to an RGBA tuple. This is +a generalization of [matplotlib.colors.to_rgba](https://matplotlib.org/stable/api/_as_gen/matplotlib.colors.to_rgba.html) and the inverse of `to_xyz`. + +Parameters +---------- +color : color-spec + The color. Can be a 3-tuple or 4-tuple of channel values, a hex + string, a registered color name, a cycle color like ``'C0'``, or + a 2-tuple colormap coordinate specification like ``('magma', 0.5)`` + (see [ColorDatabase](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.colors.ColorDatabase.html) for details). + + If `space` is ``'rgb'``, this is a tuple of RGB values, and any + channels are larger than ``2``, the channels are assumed to be + on the ``0`` to ``255`` scale and are divided by ``255``. +space : {'rgb', 'hsv', 'hcl', 'hpl', 'hsl'}, optional + The colorspace for the input channel values. Ignored unless `color` + is a tuple of numbers. +cycle : str, default: [cycle](https://ultraplot.readthedocs.io/en/stable/search.html?q=cycle) + The registered color cycle name used to interpret colors that + look like ``'C0'``, ``'C1'``, etc. +clip : bool, default: True + Whether to clip channel values into the valid ``0`` to ``1`` range. + Setting this to ``False`` can result in invalid colors. + +Returns +------- +color : 4-tuple + An RGBA tuple. + +See also +-------- +to_hex +to_rgb +to_xyz +to_xyza""" + ... + +def to_xyz(color: Incomplete, space: Incomplete='hcl') -> Incomplete: + """Translate color in *any* format to a tuple of channel values in *any* +colorspace. This is the inverse of `to_rgb`. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +space : {'hcl', 'hpl', 'hsl', 'hsv', 'rgb'}, optional + The colorspace for the output channel values. + +Returns +------- +color : 3-tuple + Tuple of channel values for the colorspace `space`. + +See also +-------- +to_hex +to_rgb +to_rgba +to_xyza""" + ... + +def to_xyza(color: Incomplete, space: Incomplete='hcl') -> Incomplete: + """Translate color in *any* format to a tuple of channel values in *any* +colorspace. This is the inverse of `to_rgba`. + +Parameters +---------- +color : color-spec + The color. Sanitized with `to_rgba`. +space : {'hcl', 'hpl', 'hsl', 'hsv', 'rgb'}, optional + The colorspace for the output channel values. + +Returns +------- +color : 3-tuple + Tuple of channel values for the colorspace `space`. + +See also +-------- +to_hex +to_rgb +to_rgba +to_xyz""" + ... + +def _fontsize_to_pt(size: Incomplete) -> Incomplete: + """Translate font preset size or unit string to points.""" + ... + +def units(value: Incomplete, numeric: Incomplete=None, dest: Incomplete=None, *, fontsize: Incomplete=None, figure: Incomplete=None, axes: Incomplete=None, width: Incomplete=None) -> Incomplete: + """Convert values between arbitrary physical units. + +Parameters +---------- +- `value`: A size specifier or sequence of size specifiers. +- `numeric`: The units associated with numeric input. +- `dest`: The destination units. +- `fontsize`: The font size in points used for scaling. +- `axes`: The axes to use for scaling units that look like ``'0.1ax'``. +- `figure`: The figure to use for scaling units that look like ``'0.1fig'``. +- `width`: Whether to use the width or height for the axes and figure relative coordinates. + +[Full API documentation](https://ultraplot.readthedocs.io/en/stable/api/ultraplot.utils.units.html)""" + ... + +def _get_subplot_layout(gs: 'GridSpec', all_axes: Incomplete, same_type: Incomplete=True) -> tuple[np.ndarray[int, int], np.ndarray[int, int], dict[type, int]]: + """Helper function to determine the grid layout of axes in a +GridSpec. It returns a grid of axis numbers and a grid of +axis types. This function is used internally to determine +the layout of axes in a GridSpec.""" + ... + +@dataclass +class _Crawler: + """A crawler is used to find edges of axes in a grid layout. +This is useful for determining whether to turn shared labels +on or depending on the position of an axis in the gridspec. +It crawls over the grid in all four cardinal directions and +checks whether it reaches a border of the grid or an axis of +a different type. It was created as adding colorbars will +change the underlying gridspec and therefore we cannot rely +on the original gridspec to determine whether an axis is a +border or not.""" + ax: object + grid: np.ndarray[int, int] + grid_axis_type: np.ndarray[int, int] + target: int + axis_type: int + directions = {'left': (0, -1), 'right': (0, 1), 'top': (-1, 0), 'bottom': (1, 0)} + + def find_edges(self) -> Generator[tuple[str, bool], None, None]: + """Check all cardinal directions. When we find a +border for any starting conditions we break and +consider it a border. This could mean that for some +partial overlaps we consider borders that should +not be borders -- we are conservative in this +regard.""" + ... + + def find_edge_for(self, direction: str, d: tuple[int, int]) -> tuple[str, bool]: + """Setup search for a specific direction.""" + ... + + def is_border(self, pos: tuple[int, int], direction: tuple[int, int]) -> bool: + """Recursively move over the grid by following the direction.""" + ... + + def _check_ranges(self, direction: tuple[int, int], other: int) -> bool: + """Helper function to determined whether a subplot +is enclosed or enclosed another subplot. This is +key to know where a border is, e.g. + +1 2 +1 3 + +Implies that 1 cannot share y with 2 and 3, but 2, and 3 +can share x.""" + ... + +def check_for_update(package_name: str) -> None: + ...