When creating custom RenderPlan objects that are added to different sides of a plot (e.g., using .add_left(), .add_top(), etc.), you often need to adjust the drawing logic (like orientation or axis inversion) based on where the plan is placed.
To implement side-aware drawing, it is recommended to inherit from StatsBase instead of the base RenderPlan. You can then use the following attributes to query the placement:
.side: Returns the current side (e.g., 'left', 'top')..is_body: Boolean indicating if the plan is in the main area, top, or bottom..is_flank: Boolean indicating if the plan is on the left or right side.
Example logic for adjusting orientation and axis inversion:
from marsilea.plotter.base import StatsBase
class Lollipop(StatsBase):
def __init__(self, data):
self.set_data(data)
def render_ax(self, spec):
ax = spec.ax
data = spec.data
lim = len(data)
locs = np.arange(lim) + 0.5
# Adjust orientation based on whether it's the main body or a side flank
orientation = "vertical" if self.is_body else "horizontal"
ax.stem(locs, data, basefmt="none", orientation=orientation)
ax.set_axis_off()
if self.is_body:
ax.set_xlim(0, lim)
if self.side == "left":
ax.invert_xaxis()
if self.is_flank:
ax.set_ylim(lim, 0)