-
Notifications
You must be signed in to change notification settings - Fork 18
Description
I like what you have done in PR #418. But there's a little more I'd like to discuss if you don't mind. Please excuse me if I'm mistaken.
I've been exploring the ax/row(s)/col(s)/span arguments of legend. These arguments are useful when someone wants the legend placed based on specific axes rather than the whole figure. However, when using this feature, two questions naturally arise: which axes' elements to include and where to position the legend. This leads to some confusion. I don't have definite answers, but I'd like to highlight this for your consideration.
Take the following code (without the fig.legend part) as an example, and let's assume loc="bottom throughout the discussion.
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}")
# Now the fig.legend() part.-
fig.legend(ax=axs[4:6], loc='b', span=(1,2))works as expected:axs[4:6]→ includes elements fromaxs[4]andaxs[5].span=(1,2)→ merges them into a single legend and places it below columns 1 and 2, i.e., belowaxs[4]andaxs[5].
-
fig.legend(ax=axs[4:6], loc="bottom", span=(3,4))works, though seems odd but makes sense with complex layout. It includes elements fromaxs[4]andaxs[5]but places the legend below columns 3 and 4, i.e., belowaxs[6]andaxs[7]. What about other rows? Sinceaxandcolscan be disrelevant, then how to put legend under 1st row, i.e., belowaxs[2]andaxs[3]
Currently, ax accepts a zero‑based slice but not an array. [4:7] is valid, while [4,5] is not. Meanwhile, span/cols accept a one‑based tuple but not a slice or array. In the example above, for the second row, cols=(1,3) essentially corresponds to axs[4:7].
If ax controls which elements are included, it should accept a scalar, slice, or list. And if span=(1,3) means “from column 1 to column 3,” that makes sense. But why does axs start at 0 while cols start at 1?
Trying fig.legend(ax=axs[0,3,6], loc='bottom', span=(3,4)) # or axs[[0,3,6]] results in only axs[3] being included, which doesn't seem right.