brokenaxes

repository·master·Indexed 20 days ago

https://github.com/bendichter/brokenaxes

A Python library for matplotlib that enables the creation of plots with breaks in the x or y axes. It allows for the visualization of data spanning discontinuous ranges without compressing gaps. Key features include support for logarithmic scales via xscale and yscale arguments, integration with matplotlib.gridspec.GridSpec for complex subplot layouts, and support for datetime objects in axis limits.

Tokens
2.9K
Snippets
10
Records
11
Agent score
69%

What's inside brokenaxes

  1. How brokenaxes works and how to customize it

    master

    The brokenaxes object is a high-level abstraction that manages several smaller matplotlib Axes objects.

    • bax.axs: A list containing the individual Axes objects created for each range defined in xlims and ylims. To perform advanced customizations (like specific date formatting), iterate over this list and modify the axes directly.
    • bax.big_ax: A large, invisible Axes object that spans the entire region occupied by the broken axes. This is used to render labels (like set_xlabel) that should span the whole plot rather than a single segment.
    • bax.diag_handles: A list of the diagonal lines used to indicate breaks. You can remove or manipulate these manually if needed.
  2. Use brokenaxes with Matplotlib subplots via GridSpec

    master

    To use brokenaxes within a Matplotlib figure containing multiple subplots, you must use matplotlib.gridspec.GridSpec. Instead of passing a standard axes object, you pass a GridSpec slot to the subplot_spec parameter of the brokenaxes constructor. This allows you to define broken axes for specific regions of a grid layout.

    from brokenaxes import brokenaxes
    from matplotlib.gridspec import GridSpec
    import numpy as np
    
    # Create a GridSpec with 2 rows and 1 column
    sps1, sps2 = GridSpec(2, 1)
    
    # Initialize brokenaxes using the first GridSpec slot
    bax1 = brokenaxes(xlims=((.1, .3), (.7, .8)), subplot_spec=sps1)
    x = np.linspace(0, 1, 100)
    bax1.plot(x, np.sin(x*30), ls=':', color='m')
    
    # Initialize brokenaxes using the second GridSpec slot
    bax2 = brokenaxes(xlims=((0, 2.5), (3, 6)), subplot_spec=sps2)
    x_data = np.random.poisson(3, 1000)
    bax2.hist(x_data, histtype='bar')
  3. Use logarithmic scales with brokenaxes

    master

    When using brokenaxes with logarithmic scales, the library cannot automatically compute the correct 1:1 layout. You must explicitly specify the scale type using the xscale and/or yscale arguments in the brokenaxes constructor. This ensures the axes are adapted correctly for logarithmic data.

    Commonly used arguments for this purpose are:

    • xscale='log'
    • yscale='log'
    import matplotlib.pyplot as plt
    from brokenaxes import brokenaxes
    import numpy as np
    
    fig = plt.figure(figsize=(5,5))
    bax = brokenaxes(xlims=((1, 500), (600, 10000)),
    	     ylims=((1, 500), (600, 10000)),
    		 hspace=.15, xscale='log', yscale='log')
    
    x = np.logspace(0.0, 4, 100)
    bax.loglog(x, x, label='$y=x=10^{0}$ to $10^{4}$')
    
    bax.legend(loc='best')
    bax.grid(axis='both', which='major', ls='-')
    bax.grid(axis='both', which='minor', ls='--', alpha=0.4)
    bax.set_xlabel('x')
    bax.set_ylabel('y')
    plt.show()
  4. Use brokenaxes with subplots via GridSpec

    master

    To use brokenaxes within a subplot layout, you must use Matplotlib's GridSpec to define the subplot specifications. Instead of passing a standard axes object, you pass a GridSpec slice to the subplot_spec parameter of the brokenaxes constructor.

    This allows you to integrate broken axes into complex multi-plot layouts where standard Matplotlib subplots might not suffice for displaying discontinuous data ranges.

    from brokenaxes import brokenaxes
    from matplotlib.gridspec import GridSpec
    import numpy as np
    
    # Create a GridSpec layout (e.g., 2 rows, 1 column)
    sps1, sps2 = GridSpec(2, 1)
    
    # Initialize brokenaxes using the GridSpec slice for the first subplot
    bax1 = brokenaxes(xlims=((.1, .3), (.7, .8)), subplot_spec=sps1)
    
    # Initialize brokenaxes using the GridSpec slice for the second subplot
    bax2 = brokenaxes(xlims=((0, 2.5), (3, 6)), subplot_spec=sps2)
  5. Create brokenaxes subplots using GridSpec

    master

    You can integrate brokenaxes into a larger matplotlib layout by passing a matplotlib.gridspec.GridSpec subplot specification to the subplot_spec argument in the brokenaxes constructor.

    from brokenaxes import brokenaxes
    from matplotlib.gridspec import GridSpec
    import numpy as np
    
    sps1, sps2 = GridSpec(2,1)
    
    bax = brokenaxes(xlims=((.1, .3), (.7, .8)), subplot_spec=sps1)
    x = np.linspace(0, 1, 100)
    bax.plot(x, np.sin(x*30), ls=':', color='m')
    
    x = np.random.poisson(3, 1000)
    bax = brokenaxes(xlims=((0, 2.5), (3, 6)), subplot_spec=sps2)
    bax.hist(x, histtype='bar')
  6. Use log scales with brokenaxes

    master

    To use logarithmic scales on broken axes, pass xscale='log' and/or yscale='log' to the brokenaxes constructor. This allows you to define discontinuous ranges within a log-scale context.

    import matplotlib.pyplot as plt
    from brokenaxes import brokenaxes
    import numpy as np
    
    fig = plt.figure(figsize=(5, 5))
    bax = brokenaxes(
        xlims=((1, 500), (600, 10000)),
        ylims=((1, 500), (600, 10000)),
        hspace=.15,
        xscale='log',
        yscale='log',
    )
    
    x = np.logspace(0.0, 4, 100)
    bax.loglog(x, x, label='$y=x=10^{0}$ to $10^{4}$')
    
    bax.legend(loc='best')
    bax.grid(axis='both', which='major', ls='-')
    bax.grid(axis='both', which='minor', ls='--', alpha=0.4)
    bax.set_xlabel('x')
    bax.set_ylabel('y')
    plt.show()
  7. Basic usage of brokenaxes

    master

    To create a plot with broken axes, use the brokenaxes class from the brokenaxes package. You define the broken regions by providing lists of tuples to the xlims and ylims arguments. This allows you to specify which ranges of the x and y axes should be visible. The hspace parameter can be used to control the spacing between the broken axes.

    Common methods available on a brokenaxes instance include .plot(), .legend(), .set_xlabel(), and .set_ylabel(), which behave similarly to standard Matplotlib axes.

    import matplotlib.pyplot as plt
    from brokenaxes import brokenaxes
    import numpy as np
    
    fig = plt.figure(figsize=(5,2))
    # Define visible x-ranges as ((start, end), (start, end), ...) 
    # and visible y-ranges similarly
    bax = brokenaxes(xlims=((0, .1), (.4, .7)), ylims=((-1, .7), (.79, 1)), hspace=.05)
    
    x = np.linspace(0, 1, 100)
    bax.plot(x, np.sin(10 * x), label='sin')
    bax.plot(x, np.cos(10 * x), label='cos')
    bax.legend(loc=3)
    bax.set_xlabel('time')
    bax.set_ylabel('value')
  8. Use datetime objects for axis limits

    master

    The xlims and ylims parameters support datetime.datetime objects. When using datetimes, you may need to manually manage the diagonal break handles and format the axis ticks using matplotlib.dates on the individual axes objects stored in bax.axs.

    import matplotlib.pyplot as plt
    from brokenaxes import brokenaxes
    import numpy as np
    import datetime
    
    fig = plt.figure(figsize=(5, 5))
    xx = [datetime.datetime(2020, 1, x) for x in range(1, 20)]
    
    yy = np.arange(1, 20)
    
    bax = brokenaxes(
        xlims=(
            (
                datetime.datetime(2020, 1, 1),
                datetime.datetime(2020, 1, 3),
            ),
            (
                datetime.datetime(2020, 1, 6),
                datetime.datetime(2020, 1, 20),
            )
        )
    )
    
    bax.plot(xx, yy)
    
    fig.autofmt_xdate()
    [x.remove() for x in bax.diag_handles]
    bax.draw_diags()
    
    import matplotlib.dates as mdates
    for ax in bax.axs:
        ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%b-%d'))
  9. Add text annotations to brokenaxes

    master

    You can add text to a brokenaxes object using the .text(x, y, s) method. The coordinates are relative to the entire broken axes region.

    import matplotlib.pyplot as plt
    from brokenaxes import brokenaxes
    
    fig = plt.figure(figsize=(5, 5))
    bax = brokenaxes(
        xlims=((0, 0.1), (0.4, 0.7)), ylims=((-1, 0.7), (0.79, 1))
    )
    bax.text(0.5, 0.5, "hello")