mirror of
https://github.com/clearml/clearml
synced 2025-04-07 22:24:30 +00:00
Fix uploading 3D plots with plt shows 2D plot on task results page
This commit is contained in:
parent
4020c8cd42
commit
efde6e4135
@ -458,6 +458,36 @@ class PatchedMatplotlib:
|
|||||||
process_tick_text(
|
process_tick_text(
|
||||||
list(plotly_renderer.current_mpl_ax.get_yticklabels()), ("yaxis", "yaxis0", "yaxis1"), 1
|
list(plotly_renderer.current_mpl_ax.get_yticklabels()), ("yaxis", "yaxis0", "yaxis1"), 1
|
||||||
)
|
)
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
# check if we have a 3d plot
|
||||||
|
if (
|
||||||
|
"zaxis" in plotly_renderer.plotly_fig.get("layout", {})
|
||||||
|
or "zaxis0" in plotly_renderer.plotly_fig.get("layout", {})
|
||||||
|
or "zaxis1" in plotly_renderer.plotly_fig.get("layout", {})
|
||||||
|
or len(plotly_renderer.plotly_fig.get("data", [{}])[0].get("z", [])) > 0
|
||||||
|
):
|
||||||
|
process_tick_text(
|
||||||
|
list(plotly_renderer.current_mpl_ax.get_zticklabels()),
|
||||||
|
("zaxis", "zaxis0", "zaxis1"),
|
||||||
|
2,
|
||||||
|
)
|
||||||
|
|
||||||
|
# rotate the X axis -90 degrees such that it matches matplotlib
|
||||||
|
plotly_renderer.plotly_fig.setdefault("layout", {}).setdefault("scene", {}).setdefault(
|
||||||
|
"camera", {}
|
||||||
|
).setdefault("eye", {}).setdefault("x", -1)
|
||||||
|
|
||||||
|
# reverse the X and Y axes such that they match matplotlib
|
||||||
|
plotly_renderer.plotly_fig.setdefault("layout", {}).setdefault("scene", {}).setdefault(
|
||||||
|
"xaxis", {}
|
||||||
|
).setdefault("autorange", "reversed")
|
||||||
|
|
||||||
|
plotly_renderer.plotly_fig.setdefault("layout", {}).setdefault("scene", {}).setdefault(
|
||||||
|
"yaxis", {}
|
||||||
|
).setdefault("autorange", "reversed")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
# try to bring back legend
|
# try to bring back legend
|
||||||
# noinspection PyBroadException
|
# noinspection PyBroadException
|
||||||
|
@ -133,8 +133,8 @@ class Exporter(object):
|
|||||||
self.draw_line(ax, line)
|
self.draw_line(ax, line)
|
||||||
for text in ax.texts:
|
for text in ax.texts:
|
||||||
self.draw_text(ax, text)
|
self.draw_text(ax, text)
|
||||||
for (text, ttp) in zip([ax.xaxis.label, ax.yaxis.label, ax.title],
|
for (text, ttp) in zip([ax.xaxis.label, ax.yaxis.label, ax.zaxis.label, ax.title],
|
||||||
["xlabel", "ylabel", "title"]):
|
["xlabel", "ylabel", "zlabel", "title"]):
|
||||||
if(hasattr(text, "get_text") and text.get_text()):
|
if(hasattr(text, "get_text") and text.get_text()):
|
||||||
self.draw_text(ax, text, force_trans=ax.transAxes,
|
self.draw_text(ax, text, force_trans=ax.transAxes,
|
||||||
text_type=ttp)
|
text_type=ttp)
|
||||||
|
@ -449,7 +449,7 @@ def prep_ticks(ax, index, ax_type, props):
|
|||||||
positional arguments:
|
positional arguments:
|
||||||
ax - the mpl axes instance
|
ax - the mpl axes instance
|
||||||
index - the index of the axis in `props`
|
index - the index of the axis in `props`
|
||||||
ax_type - 'x' or 'y' (for now)
|
ax_type - 'x' or 'y' or 'z'
|
||||||
props - an mplexporter poperties dictionary
|
props - an mplexporter poperties dictionary
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@ -458,6 +458,8 @@ def prep_ticks(ax, index, ax_type, props):
|
|||||||
axis = ax.get_xaxis()
|
axis = ax.get_xaxis()
|
||||||
elif ax_type == "y":
|
elif ax_type == "y":
|
||||||
axis = ax.get_yaxis()
|
axis = ax.get_yaxis()
|
||||||
|
elif ax_type == "z":
|
||||||
|
axis = ax.get_zaxis()
|
||||||
else:
|
else:
|
||||||
return dict() # whoops!
|
return dict() # whoops!
|
||||||
|
|
||||||
@ -491,6 +493,9 @@ def prep_ticks(ax, index, ax_type, props):
|
|||||||
elif ax_type == "y" and "ylim" in props:
|
elif ax_type == "y" and "ylim" in props:
|
||||||
axis_dict["range"] = [props["ylim"][0], props["ylim"][1]]
|
axis_dict["range"] = [props["ylim"][0], props["ylim"][1]]
|
||||||
axis_dict["custom_range"] = True
|
axis_dict["custom_range"] = True
|
||||||
|
elif ax_type == "z" and "zlim" in props:
|
||||||
|
axis_dict["range"] = [props["zlim"][0], props["zlim"][1]]
|
||||||
|
axis_dict["custom_range"] = True
|
||||||
elif scale == "log":
|
elif scale == "log":
|
||||||
try:
|
try:
|
||||||
axis_dict["tick0"] = props["axes"][index]["tickvalues"][0]
|
axis_dict["tick0"] = props["axes"][index]["tickvalues"][0]
|
||||||
@ -515,6 +520,12 @@ def prep_ticks(ax, index, ax_type, props):
|
|||||||
math.log10(props["ylim"][1]),
|
math.log10(props["ylim"][1]),
|
||||||
]
|
]
|
||||||
axis_dict["custom_range"] = True
|
axis_dict["custom_range"] = True
|
||||||
|
elif ax_type == "z" and "zlim" in props:
|
||||||
|
axis_dict["range"] = [
|
||||||
|
math.log10(props["zlim"][0]),
|
||||||
|
math.log10(props["zlim"][1]),
|
||||||
|
]
|
||||||
|
axis_dict["custom_range"] = True
|
||||||
else:
|
else:
|
||||||
axis_dict = dict(range=None, type="linear")
|
axis_dict = dict(range=None, type="linear")
|
||||||
warnings.warn(
|
warnings.warn(
|
||||||
@ -561,6 +572,23 @@ def prep_xy_axis(ax, props, x_bounds, y_bounds):
|
|||||||
yaxis.update(prep_ticks(ax, 1, "y", props))
|
yaxis.update(prep_ticks(ax, 1, "y", props))
|
||||||
return xaxis, yaxis
|
return xaxis, yaxis
|
||||||
|
|
||||||
|
def prep_xyz_axis(ax, props, x_bounds, y_bounds):
|
||||||
|
# there is no z_bounds as they can't (at least easily) be extracted from an `Axes3DSubplot` object
|
||||||
|
xaxis, yaxis = prep_xy_axis(ax, props, x_bounds, y_bounds)
|
||||||
|
# noinspection PyBroadException
|
||||||
|
try:
|
||||||
|
zaxis = dict(
|
||||||
|
type=props["axes"][2]["scale"],
|
||||||
|
range=list(props.get("zlim", [])),
|
||||||
|
showgrid=props["axes"][2].get("grid", {}).get("gridOn", False),
|
||||||
|
side=props["axes"][2].get("position"),
|
||||||
|
tickfont=dict(size=props["axes"][2].get("fontsize", {})),
|
||||||
|
)
|
||||||
|
zaxis.update(prep_ticks(ax, 2, "z", props))
|
||||||
|
except Exception:
|
||||||
|
zaxis = {}
|
||||||
|
return xaxis, yaxis, zaxis
|
||||||
|
|
||||||
|
|
||||||
def mpl_dates_to_datestrings(dates, mpl_formatter):
|
def mpl_dates_to_datestrings(dates, mpl_formatter):
|
||||||
"""Convert matplotlib dates to iso-formatted-like time strings.
|
"""Convert matplotlib dates to iso-formatted-like time strings.
|
||||||
|
@ -160,12 +160,16 @@ class PlotlyRenderer(Renderer):
|
|||||||
yaxis = dict(
|
yaxis = dict(
|
||||||
anchor="x{0}".format(self.axis_ct or ''), zeroline=False, ticks="inside"
|
anchor="x{0}".format(self.axis_ct or ''), zeroline=False, ticks="inside"
|
||||||
)
|
)
|
||||||
|
zaxis = dict(
|
||||||
|
anchor="x{0}".format(self.axis_ct or ''), zeroline=False, ticks="inside"
|
||||||
|
)
|
||||||
# update defaults with things set in mpl
|
# update defaults with things set in mpl
|
||||||
mpl_xaxis, mpl_yaxis = mpltools.prep_xy_axis(
|
mpl_xaxis, mpl_yaxis, mpl_zaxis = mpltools.prep_xyz_axis(
|
||||||
ax=ax, props=props, x_bounds=self.mpl_x_bounds, y_bounds=self.mpl_y_bounds
|
ax=ax, props=props, x_bounds=self.mpl_x_bounds, y_bounds=self.mpl_y_bounds
|
||||||
)
|
)
|
||||||
xaxis.update(mpl_xaxis)
|
xaxis.update(mpl_xaxis)
|
||||||
yaxis.update(mpl_yaxis)
|
yaxis.update(mpl_yaxis)
|
||||||
|
zaxis.update(mpl_zaxis)
|
||||||
bottom_spine = mpltools.get_spine_visible(ax, "bottom")
|
bottom_spine = mpltools.get_spine_visible(ax, "bottom")
|
||||||
top_spine = mpltools.get_spine_visible(ax, "top")
|
top_spine = mpltools.get_spine_visible(ax, "top")
|
||||||
left_spine = mpltools.get_spine_visible(ax, "left")
|
left_spine = mpltools.get_spine_visible(ax, "left")
|
||||||
@ -178,6 +182,8 @@ class PlotlyRenderer(Renderer):
|
|||||||
# put axes in our figure
|
# put axes in our figure
|
||||||
self.plotly_fig["layout"]["xaxis{0}".format(self.axis_ct or '')] = xaxis
|
self.plotly_fig["layout"]["xaxis{0}".format(self.axis_ct or '')] = xaxis
|
||||||
self.plotly_fig["layout"]["yaxis{0}".format(self.axis_ct or '')] = yaxis
|
self.plotly_fig["layout"]["yaxis{0}".format(self.axis_ct or '')] = yaxis
|
||||||
|
if mpl_zaxis:
|
||||||
|
self.plotly_fig["layout"]["zaxis{0}".format(self.axis_ct or '')] = zaxis
|
||||||
|
|
||||||
# let all subsequent dates be handled properly if required
|
# let all subsequent dates be handled properly if required
|
||||||
|
|
||||||
@ -398,13 +404,17 @@ class PlotlyRenderer(Renderer):
|
|||||||
if isinstance(props["label"], six.string_types)
|
if isinstance(props["label"], six.string_types)
|
||||||
else props["label"]
|
else props["label"]
|
||||||
),
|
),
|
||||||
x=[xy_pair[0] for xy_pair in props["data"]],
|
x=props["data"][0],
|
||||||
y=[xy_pair[1] for xy_pair in props["data"]],
|
y=props["data"][1],
|
||||||
xaxis="x{0}".format(self.axis_ct),
|
xaxis="x{0}".format(self.axis_ct),
|
||||||
yaxis="y{0}".format(self.axis_ct),
|
yaxis="y{0}".format(self.axis_ct),
|
||||||
line=line,
|
line=line,
|
||||||
marker=marker,
|
marker=marker,
|
||||||
)
|
)
|
||||||
|
if len(props["data"]) >= 3:
|
||||||
|
marked_line["z"] = props["data"][2]
|
||||||
|
marked_line["zaxis"] = "z{0}".format(self.axis_ct)
|
||||||
|
marked_line["type"] = "scatter3d"
|
||||||
if self.x_is_mpl_date:
|
if self.x_is_mpl_date:
|
||||||
formatter = (
|
formatter = (
|
||||||
self.current_mpl_ax.get_xaxis()
|
self.current_mpl_ax.get_xaxis()
|
||||||
|
Loading…
Reference in New Issue
Block a user