Skip to main content

A Matplotlib-based utility module for creating broken axes.

Project description

中文版本

break_axes: Matplotlib Axis Break and Custom Scaling Tool

A Python-based Matplotlib extension module for implementing axis breaks (visual gaps) and multi-interval custom scaling functions, suitable for displaying data with large value ranges or irrelevant intermediate intervals.

Module Overview

Matplotlib natively does not support axis breaks (visual gaps) and flexible multi-interval scaling. This module fills this gap with a series of easy-to-use functions, including:

  • Drawing break markers on axis edges to indicate data gaps
  • Clipping axis spines, lines, and plot elements to hide unwanted intervals
  • Supporting linear/logarithmic custom scaling for multiple data intervals

Installation

  1. Install from PyPI

    pip install break_axes
    
  2. Build the binary distribution package (wheel) locally
    First install the build tool: pip install build, then run:

    python -m build
    

    This generates a .whl binary package in the dist/ directory (faster installation).

  3. Install the package locally (development mode)
    Use this for development and real-time debugging, allowing code changes without reinstalling:

    pip install -e .
    

Core Functions

The functions are usually used are below:

  • scale_axes
  • broken_and_clip_axes
  • remove_minor_ticks

framework.png

However, for more flexible break settings, you may need to read the source code (less than 900 lines, about half of which are docstrings).

Function Name Description
create_scale Used to generate a ScaleBase object for scaled axes
scale_axis A wrapper function for create_scale, used to directly apply scaling
scale_axes Used to apply axis scaling in batches, supporting simultaneous scaling of x-axis and y-axis
offset_data_point Get the vertex coordinates of the break identifier corresponding to the specified break point
get_broken_points Get the vertex coordinates of the marker end points
xy2points Combine input x, y coordinates into data point coordinates
add_broken_line Add break markers at specified positions
add_broken_line_in_axis Add break markers on the axis
get_axis_clip_path Get the clipping path of the specified axis for clipping axis spines
get_axes_clip_path Get the clipping path of the axes for clipping artists within the axes
clip_axes Clip spines and artists
broken_and_clip_axes Wrapper for add_broken_line_in_axis and clip_axes
remove_minor_ticks Remove minor ticks from the given axis
remove_xaxis_minor_ticks Remove minor ticks from the x-axis
remove_yaxis_minor_ticks Remove minor ticks from the y-axis

Dependencies

  • Python 3.8 or higher
  • Matplotlib 3.5.0 or higher
    Installation command: pip install matplotlib

Quick Start

1. Import the Module

import matplotlib.pyplot as plt

from break_axes import __version__, scale_axes, broken_and_clip_axes

plt.rcParams['figure.figsize'] = (3,3)
plt.rcParams['figure.dpi'] = 200
plt.rcParams['axes.linewidth'] = 1.5

print(f"break_axes version: {__version__}")

2. Multiple Axis Breaks

multi_break.png

fig, ax = plt.subplots(figsize=(4.5,3))
ax.set(xlim=(-32,32), ylim=(0,180), xlabel="x (unit)", ylabel="y (unit)")
ax.set_facecolor("#DDFFAA")
ax.grid(ls=':', lw=0.5, color='dimgray')

# scale x-axis and y-axis to reduce the blank space
scale_axes(ax,
           x_interval=[(-28, -2, 0.01), (2, 28, 0.01)],
           y_interval=[(40,100, 0.1), (100, 180, 0.6)],
           mode="linear")


_ = ax.set_xticks([-31,-30,-29,-1,0,1,29,30,31])
_ = ax.set_yticks([0,20, 40, 100, 120, 140,160])

rects = ax.bar([-31,-30,-29,-1,0,1,31,30,29], [20,40,22,132,155,108,5,27,17] )
ax.bar_label(rects)

# Text and Annotation wont be clipped
ax.annotate("This is a very long long string.", xy=(-30, 80), xytext=(-30, 168),
    arrowprops=dict(
        arrowstyle='-|>',
        connectionstyle="arc3,rad=0.1",
        color='k',
        shrinkA=5, shrinkB=5
    )
)

# Add broken line in x-axis and y-axis, clip spines and artists in axes
broken_and_clip_axes(ax, x=[-15,15], y=[70], axes_clip=True, which='lower',
                     gap=5, dx=3, dy=3)

# plt.savefig("break_axes_bar.png", transparent=False)

3. Logarithmic Axes

logscale_break.png

import numpy as np

x = np.logspace(0, 16, 100, base=2)

fig, ax = plt.subplots(figsize=(4,3))
ax.set(xlim=(1, 2<<16), ylim=(1, 2<<16), facecolor="#DDFFAA")
ax.plot(x, x)
ax.set_xticks([ 2<<i for i in range(0,17,3)])
# ax.set_yticks([1, 10, 100, 500, 5000, 10000],
#               [1, 10, 100, 500, 5000, r'$10^4$'])  # type: ignore

ax.annotate("This is a very long long string.",
    xy=(5, 10), xytext=(10, 20000),
    arrowprops=dict(
        arrowstyle='-|>',
        connectionstyle="arc3,rad=0.1",
        color='k',
        shrinkA=5, shrinkB=5
    )
)

ax.grid(ls=':')
ax.set_xlabel("X Label")
ax.set_ylabel("Y Label")
ax.set_title("Broken Axis Example - Log Mode")

scale_axes(ax,
    x_interval=[(3, 6, 0.5)],
    y_interval=[(9, 12, 0.5)],
    mode='log', base_x=2, base_y=2)
broken_and_clip_axes(ax, x=[23], y=[1450],
    axes_clip=True, which='lower', gap=5, dx=3, dy=3)

plt.show()

4. Remove Minor Ticks

Minor Ticks in scaled interval maybe too dense because of the small scale factor, use remove_minor_ticks to remove minor ticks in the given axis.

import matplotlib.pyplot as plt
import numpy as np

from break_axes import broken_and_clip_axes, scale_axes
from break_axes.break_axes import remove_yaxis_minor_ticks

plt.rcParams["ytick.minor.visible"] = True
plt.rcParams["xtick.minor.visible"] = True
plt.rcParams["xtick.top"] = True
plt.rcParams["ytick.right"] = True


x = np.linspace(0, np.pi, 25)
y1 = 0.15 * np.sin(x) + 0.97
y2 = -0.06 * np.sin(x)

fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(6, 2.4), sharey=True)
for ax in (ax1, ax2):
    ax.set_xlim(-0.1, np.pi + 0.1)
    ax.plot(x, y1, marker="o", mew=1, mec="dimgray")
    ax.plot(x, y2, marker="s", mew=1, mec="dimgray")

    ax.set_yticks([-0.05, 0, 0.95, 1, 1.05, 1.1])
    scale_axes(ax, y_interval=[(0.02, 0.95, 0.05)])

    ax.set_yticks([-0.05, 0, 0.95, 1, 1.05, 1.1])

    broken_and_clip_axes(ax, y=[0.5])

# must be put below set_yticks or set_xticks
remove_yaxis_minor_ticks(ax2, intervals=[(0.02, 0.95)])

plt.show()

remove_ticks_in_scaled_interval.png

5. Set Broken Lines Property

schematic_diagram.png

broken_lines_property.png

import numpy as np

x = np.logspace(-2, 4, 150)

fig, ax = plt.subplots(figsize=(4,3))
ax.set(xlim=(1,10000), ylim=(1,10000), facecolor="#DDFFAA")
ax.plot(x, x)
ax.set_xticks([0.01, 0.1, 1, 10, 100, 500, 5000, 10000])
ax.set_yticks([0.01, 0.1, 1, 10, 100, 500, 5000, 10000])

ax.annotate("This is a very long long string.",
    xy=(5, 10), xytext=(10, 5000),
    arrowprops=dict(
        arrowstyle='-|>',
        connectionstyle="arc3,rad=0.1",
        color='k',
        shrinkA=5, shrinkB=5
    )
)

ax.grid(ls=':')
ax.set_xlabel("X Label")
ax.set_ylabel("Y Label")
ax.set_title("Set Broken Lines Propertye", pad=10)

scale_axes(ax,
    x_interval=[(2, 3, 0.5)],
    y_interval=[(-1, 0, 0.5)],
    mode='log')
broken_lines = broken_and_clip_axes(ax, x=[300], y=[0.3],
    axes_clip=True, which='both', gap=6, dx=4, dy=4)

bottom_left, bottom_right = broken_lines["bottom"][0]
bottom_left.set(color='r', linewidth=1)
bottom_right.set(color='g', linewidth=1)

left_bottom, left_top = broken_lines["left"][0]
left_bottom.set(color='r', linewidth=2.5)
left_top.set(color='g', linewidth=2.5)

plt.show()

6. Not Clip Line

heatcapacity_of_ice_and_water.png

Code to see the example: heat_capacity_of_ice_and_water.ipynb

Notes

  1. Fix axis ranges first: Before calling the break/clip functions, you must fix the axis ranges using ax.set_xlim() or ax.set_ylim() — this is crucial to ensure accurate calculation of break positions.
  2. Interval rules: When using scale_axes, intervals must be non-overlapping and in order (e.g., [(0,2,2), (5,10,1)] is valid, [(5,10,1), (0,2,2)] is invalid).
  3. Clipping exclusions: Text elements (such as labels, tick values) and the axis background (ax.patch) will not be clipped to avoid affecting readability. Users can also use get_axes_clip_path to obtain the axis clipping path and manually add artists that need to be clipped with reference to the clip_axes function.

Version and Author

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

break_axes-0.5.0.tar.gz (16.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

break_axes-0.5.0-py3-none-any.whl (13.1 kB view details)

Uploaded Python 3

File details

Details for the file break_axes-0.5.0.tar.gz.

File metadata

  • Download URL: break_axes-0.5.0.tar.gz
  • Upload date:
  • Size: 16.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for break_axes-0.5.0.tar.gz
Algorithm Hash digest
SHA256 6adfd2a8a412bc6ac121e2ddff06b13841d88d251a8b6b3a3afb1b3440dc862f
MD5 6cac7e0e005126a063871434c8d7387f
BLAKE2b-256 a2e91452f8cc18eaa6f46de4959252c84bd8588926670572d58b80d060b3f001

See more details on using hashes here.

File details

Details for the file break_axes-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: break_axes-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 13.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.3

File hashes

Hashes for break_axes-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8343ee762ac87da739a0c5231a25b4dd9117314e1dbbd8dbf25be4931f42e049
MD5 5031491038986c0047c281f090f30523
BLAKE2b-256 416d2f2982e35646fd1e18849cfb42a9c61b1584229456508a574efe483c40a4

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page