Skip to content

Commit

Permalink
Merge pull request #13 from eriknovak/feature/vlines
Browse files Browse the repository at this point in the history
Add tick placement, label and rotation support; make framework attrs consistent
  • Loading branch information
eriknovak committed Nov 21, 2023
2 parents d4f598d + 458cceb commit ad1c625
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 198 deletions.
43 changes: 35 additions & 8 deletions datachart/schema/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@
"plot.line.alpha": Union[float, None],
"plot.line.drawstyle": Union[LineDrawStyle, None],
"plot.line.zorder": Union[int, float, None],
"plot.xticks.label.rotate": Union[int, float, None],
"plot.yticks.label.rotate": Union[int, float, None],
},
)

Expand All @@ -128,6 +130,8 @@
"plot.bar.edge.width": Union[int, float, None],
"plot.bar.edge.color": Union[str, None],
"plot.bar.error.color": Union[str, None],
"plot.xticks.label.rotate": Union[int, float, None],
"plot.yticks.label.rotate": Union[int, float, None],
},
)

Expand All @@ -143,6 +147,8 @@
"plot.hist.align": Union[str, None],
"plot.hist.edge.width": Union[int, float, None],
"plot.hist.edge.color": Union[str, None],
"plot.xticks.label.rotate": Union[int, float, None],
"plot.yticks.label.rotate": Union[int, float, None],
},
)

Expand Down Expand Up @@ -198,10 +204,10 @@ class ChartCommonAttrs(TypedDict):
max_cols: Union[int, None]
aspect_ratio: Union[str, None]
figsize: Union[Tuple[float, float], None]
x_min: Union[int, float, None]
x_max: Union[int, float, None]
y_min: Union[int, float, None]
y_max: Union[int, float, None]
xmin: Union[int, float, None]
xmax: Union[int, float, None]
ymin: Union[int, float, None]
ymax: Union[int, float, None]
# visibility attributes
show_legend: Union[bool, None]
show_grid: Union[str, None]
Expand All @@ -216,16 +222,16 @@ class ChartCommonAttrs(TypedDict):

class VLineAttrs(TypedDict):
x: Union[int, float]
y_min: Union[int, float, None]
y_max: Union[int, float, None]
ymin: Union[int, float, None]
ymax: Union[int, float, None]
style: Union[VLineConfigAttrs, None]
label: Union[str, None]


class HLineAttrs(TypedDict):
y: Union[int, float]
x_min: Union[int, float, None]
x_max: Union[int, float, None]
xmin: Union[int, float, None]
xmax: Union[int, float, None]
style: Union[HLineConfigAttrs, None]
label: Union[str, None]

Expand All @@ -252,6 +258,13 @@ class LineDataAttrs(TypedDict):
xlabel: Union[str, None]
ylabel: Union[str, None]

xticks: Union[int, float, None]
xticklabels: Union[List[str], None]
xtickrotate: Union[int, None]
yticks: Union[int, float, None]
yticklabels: Union[List[str], None]
ytickrotate: Union[int, None]

vlines: Union[VLineAttrs, List[VLineAttrs]]
hlines: Union[HLineAttrs, List[HLineAttrs]]

Expand Down Expand Up @@ -284,6 +297,13 @@ class BarDataAttrs(TypedDict):
xlabel: Union[str, None]
ylabel: Union[str, None]

xticks: Union[int, float, None]
xticklabels: Union[List[str], None]
xtickrotate: Union[int, None]
yticks: Union[int, float, None]
yticklabels: Union[List[str], None]
ytickrotate: Union[int, None]

vlines: Union[VLineAttrs, List[VLineAttrs]]
hlines: Union[HLineAttrs, List[HLineAttrs]]

Expand Down Expand Up @@ -312,6 +332,13 @@ class HistDataAttrs(TypedDict):
xlabel: Union[str, None]
ylabel: Union[str, None]

xticks: Union[int, float, None]
xticklabels: Union[List[str], None]
xtickrotate: Union[int, None]
yticks: Union[int, float, None]
yticklabels: Union[List[str], None]
ytickrotate: Union[int, None]

vlines: Union[VLineAttrs, List[VLineAttrs]]
hlines: Union[HLineAttrs, List[HLineAttrs]]

Expand Down
61 changes: 34 additions & 27 deletions datachart/utils/attrs.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,34 +443,41 @@ def configure_axis_ticks_position(ax: plt.Axes, chart: dict):
"""

tick_attrs = [
("xticks", "xticklabels", "xaxis"),
("yticks", "yticklabels", "yaxis"),
("xticks", "xticklabels", "xtickrotate", "xaxis"),
("yticks", "yticklabels", "ytickrotate", "yaxis"),
]
for attrs in tick_attrs:
ticks = chart.get(attrs[0], None)
ticklabels = chart.get(attrs[1], None)
func = ax.set_xticks if attrs[2] == "xaxis" else ax.set_yticks

if ticks is None and ticklabels is not None:
warnings.warn(
f"The attribute `{attrs[0]}` is not specified but `{attrs[1]}` is. "
+ f"Please provide the `{attrs[0]}` values."
)
continue
elif ticks is not None:
if ticklabels is None:
# draw only the ticks
func(ticks)
elif len(ticks) != len(ticklabels):
labels = chart.get(attrs[1], None)
rotation = chart.get(attrs[2], 0)

dticks = getattr(ax, attrs[3]).get_ticklocs()
dlabels = getattr(ax, attrs[3]).get_ticklabels()
set_ticks = getattr(ax, attrs[3]).set_ticks

if ticks is None and labels is None:
set_ticks(dticks, labels=dlabels, rotation=rotation)
elif ticks is None and labels is not None:
if len(dticks) == len(labels):
set_ticks(dticks, labels=labels, rotation=rotation)
else:
warnings.warn(
f"The values of `{attrs[0]}` and `{attrs[1]}` are of different lengths. "
+ f"Please provide the same number of values. Ignoring `{attrs[1]}` values..."
)
# draw only the ticks
func(ticks)
else:
# draw both the ticks and the labels
func(ticks, labels=ticklabels)
set_ticks(dticks, labels=dlabels, rotation=rotation)
elif ticks is not None and labels is None:
set_ticks(ticks, labels=ticks, rotation=rotation)
elif ticks is not None and len(ticks) != len(labels):
warnings.warn(
f"The values of `{attrs[0]}` and `{attrs[1]}` are of different lengths. "
+ f"Please provide the same number of values. Ignoring `{attrs[1]}` values..."
)
# draw only the ticks
set_ticks(ticks, labels=ticks, rotation=rotation)
else:
# draw both the ticks and the labels
set_ticks(ticks, labels=labels, rotation=rotation)


def configure_axis_limits(ax: plt.Axes, settings: dict):
Expand All @@ -485,16 +492,16 @@ def configure_axis_limits(ax: plt.Axes, settings: dict):
The settings.
"""

if settings["x_min"] is not None or settings["x_max"] is not None:
if settings["xmin"] is not None or settings["xmax"] is not None:
xmin, xmax = ax.get_xlim()
xmin = settings["x_min"] if settings["x_min"] is not None else xmin
xmax = settings["x_max"] if settings["x_max"] is not None else xmax
xmin = settings["xmin"] if settings["xmin"] is not None else xmin
xmax = settings["xmax"] if settings["xmax"] is not None else xmax
ax.set_xlim(xmin=xmin, xmax=xmax)

if settings["y_min"] is not None or settings["y_max"] is not None:
if settings["ymin"] is not None or settings["ymax"] is not None:
ymin, ymax = ax.get_ylim()
ymin = settings["y_min"] if settings["y_min"] is not None else ymin
ymax = settings["y_max"] if settings["y_max"] is not None else ymax
ymin = settings["ymin"] if settings["ymin"] is not None else ymin
ymax = settings["ymax"] if settings["ymax"] is not None else ymax
ax.set_ylim(ymin=ymin, ymax=ymax)


Expand Down
Loading

0 comments on commit ad1c625

Please sign in to comment.