-
Notifications
You must be signed in to change notification settings - Fork 18
Fix SubplotGrid indexing and enhance legend placement with 'ref' argument #461
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
d055bcf to
438a952
Compare
…lacement inference
72f6072 to
ab996e1
Compare
5643ff6 to
a1f0e66
Compare
…intelligent placement, and robust checks
8491a20 to
c1f5a09
Compare
…intelligent placement, and robust checks
|
I've had some simple tests, very brilliant work. Now the logic is very simple and very clear. It already satisfied for pretty much everything. Bringing up those weird edge cases is kind of like looking for faults, unless you're really into making it perfect and still care about that stuff. |
|
Failing image is shape difference fyi |
Any cases we should be aware of? |
Example 1 # %% test ultraplot legend
import ultraplot as pplt
fig, axs = pplt.subplots(ncols=4, nrows=4, share='all', width='10cm')
axs.format(yticklabels=[], xticklabels=[])
cycle = pplt.Cycle("default", N=16)
for n, ax in enumerate(axs):
ax.text(.5, .5, f'ax:{n}\ncols:{n%4+1}', transform=ax.transAxes, ha='center',va='center')
ax.scatter(.5, .25, transform=ax.transAxes, color=cycle.get_next()['color'], label=f"ax{n}")
fig.legend(ax=axs[1, 1:], loc="b", ref=axs[2,:-1])
fig.legend(ax=axs[[3,5,8,12]], loc="b", ref=axs[0,1:-1])
fig.legend(ax=axs[-2:], loc='l', ref=axs[1:3, 3], ncols=1)Example 2 # %% test ultraplot legend
import ultraplot as pplt
fig, axs = pplt.subplots(ncols=4, nrows=4, share='all', width='10cm')
axs.format(yticklabels=[], xticklabels=[])
cycle = pplt.Cycle("default", N=16)
for n, ax in enumerate(axs):
ax.text(.5, .5, f'ax:{n}\ncols:{n%4+1}', transform=ax.transAxes, ha='center',va='center')
ax.scatter(.5, .25, transform=ax.transAxes, color=cycle.get_next()['color'], label=f"ax{n}")
fig.legend(ax=axs[-2:], loc='l', ref=axs[1:3, 3], ncols=1)
fig.legend(ax=axs[1, 1:], loc="b", ref=axs[2,:-1])
fig.legend(ax=axs[[3,5,8,12]], loc="b", ref=axs[0,1:-1])The only difference is the last line moves two lines up. It not something I need, just play around for fun. |
|
I see. The legend does take up space to prevent overlap. For outside legends it is more a feature than a bug. |
|
And there's also overlaps between legend and axs when space of axs is small. Take |
Closes #459, #460
This PR addresses issues with
SubplotGridindexing and significantly enhances the flexibility and intuitiveness of legend placement.1. SubplotGrid 1D List/Array Indexing
SubplotGrid(returned bysubplots) now supports 1D list or numpy array indexing (e.g.,axs[[0, 5]]). This returns a newSubplotGridcontaining only the selected axes, whereas previously it was misinterpreted as 2D indexing or raised errors.2. Decoupled Legend Placement (
refargument)refkeyword argument tofig.legend(andfig.colorbar).ax: Specifies the content source (handles/labels).ref: Specifies the location anchor.fig.legend(ax=axs[1, :], ref=axs[0, :], loc='bottom')to place a legend using data from the second row below the first row.ref(oraxifrefis missing) is a list of axes (e.g.,axs[[0, 1]]) and no explicit span (rows/cols) is provided, UltraPlot now automatically infers the span based on the legend location. For example,fig.legend(ax=axs[[0, 1]], loc='bottom')will create a single legend spanning the width of both axes.refgroup (e.g., forloc='right', it anchors to the rightmost axis in the group; forloc='bottom', the bottommost).Documentation & Tests
docs/colorbars_legends.py.ultraplot/tests/test_gridspec.py(slicing) andultraplot/tests/test_legend.py(ref argument, span inference).API Changes
refargument is optional, and standardfig.legendusage remains compatible.