mirror of
https://github.com/clearml/clearml
synced 2025-05-06 13:54:26 +00:00
Add extra_layout argument for all loggers, setting layout configuration for plotly objects
This commit is contained in:
parent
95105cbe6a
commit
7ad4ec2314
@ -142,7 +142,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:param iter: Iteration number
|
:param iter: Iteration number
|
||||||
:type value: int
|
:type value: int
|
||||||
"""
|
"""
|
||||||
ev = ScalarEvent(metric=self._normalize_name(title), variant=self._normalize_name(series), value=value, iter=iter)
|
ev = ScalarEvent(metric=self._normalize_name(title), variant=self._normalize_name(series), value=value,
|
||||||
|
iter=iter)
|
||||||
self._report(ev)
|
self._report(ev)
|
||||||
|
|
||||||
def report_vector(self, title, series, values, iter):
|
def report_vector(self, title, series, values, iter):
|
||||||
@ -159,7 +160,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
"""
|
"""
|
||||||
if not isinstance(values, Iterable):
|
if not isinstance(values, Iterable):
|
||||||
raise ValueError('values: expected an iterable')
|
raise ValueError('values: expected an iterable')
|
||||||
ev = VectorEvent(metric=self._normalize_name(title), variant=self._normalize_name(series), values=values, iter=iter)
|
ev = VectorEvent(metric=self._normalize_name(title), variant=self._normalize_name(series), values=values,
|
||||||
|
iter=iter)
|
||||||
self._report(ev)
|
self._report(ev)
|
||||||
|
|
||||||
def report_plot(self, title, series, plot, iter):
|
def report_plot(self, title, series, plot, iter):
|
||||||
@ -185,7 +187,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
plot = json.dumps(plot, default=default)
|
plot = json.dumps(plot, default=default)
|
||||||
elif not isinstance(plot, six.string_types):
|
elif not isinstance(plot, six.string_types):
|
||||||
raise ValueError('Plot should be a string or a dict')
|
raise ValueError('Plot should be a string or a dict')
|
||||||
ev = PlotEvent(metric=self._normalize_name(title), variant=self._normalize_name(series), plot_str=plot, iter=iter)
|
ev = PlotEvent(metric=self._normalize_name(title), variant=self._normalize_name(series), plot_str=plot,
|
||||||
|
iter=iter)
|
||||||
self._report(ev)
|
self._report(ev)
|
||||||
|
|
||||||
def report_image(self, title, series, src, iter):
|
def report_image(self, title, series, src, iter):
|
||||||
@ -201,7 +204,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:param iter: Iteration number
|
:param iter: Iteration number
|
||||||
:type value: int
|
:type value: int
|
||||||
"""
|
"""
|
||||||
ev = ImageEventNoUpload(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter, src=src)
|
ev = ImageEventNoUpload(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter,
|
||||||
|
src=src)
|
||||||
self._report(ev)
|
self._report(ev)
|
||||||
|
|
||||||
def report_media(self, title, series, src, iter):
|
def report_media(self, title, series, src, iter):
|
||||||
@ -217,7 +221,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:param iter: Iteration number
|
:param iter: Iteration number
|
||||||
:type value: int
|
:type value: int
|
||||||
"""
|
"""
|
||||||
ev = ImageEventNoUpload(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter, src=src)
|
ev = ImageEventNoUpload(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter,
|
||||||
|
src=src)
|
||||||
self._report(ev)
|
self._report(ev)
|
||||||
|
|
||||||
def report_image_and_upload(self, title, series, iter, path=None, image=None, upload_uri=None,
|
def report_image_and_upload(self, title, series, iter, path=None, image=None, upload_uri=None,
|
||||||
@ -245,7 +250,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
raise ValueError('Upload configuration is required (use setup_upload())')
|
raise ValueError('Upload configuration is required (use setup_upload())')
|
||||||
if len([x for x in (path, image) if x is not None]) != 1:
|
if len([x for x in (path, image) if x is not None]) != 1:
|
||||||
raise ValueError('Expected only one of [filename, image]')
|
raise ValueError('Expected only one of [filename, image]')
|
||||||
kwargs = dict(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter, file_history_size=max_image_history)
|
kwargs = dict(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter,
|
||||||
|
file_history_size=max_image_history)
|
||||||
ev = ImageEvent(image_data=image, upload_uri=upload_uri, local_image_path=path,
|
ev = ImageEvent(image_data=image, upload_uri=upload_uri, local_image_path=path,
|
||||||
delete_after_upload=delete_after_upload, **kwargs)
|
delete_after_upload=delete_after_upload, **kwargs)
|
||||||
self._report(ev)
|
self._report(ev)
|
||||||
@ -284,7 +290,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
self._report(ev)
|
self._report(ev)
|
||||||
|
|
||||||
def report_histogram(self, title, series, histogram, iter, labels=None, xlabels=None,
|
def report_histogram(self, title, series, histogram, iter, labels=None, xlabels=None,
|
||||||
xtitle=None, ytitle=None, comment=None, mode='group'):
|
xtitle=None, ytitle=None, comment=None, mode='group', layout_config=None):
|
||||||
"""
|
"""
|
||||||
Report an histogram bar plot
|
Report an histogram bar plot
|
||||||
:param title: Title (AKA metric)
|
:param title: Title (AKA metric)
|
||||||
@ -306,6 +312,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:type comment: str
|
:type comment: str
|
||||||
:param mode: multiple histograms mode. valid options are: stack / group / relative. Default is 'group'.
|
:param mode: multiple histograms mode. valid options are: stack / group / relative. Default is 'group'.
|
||||||
:type mode: str
|
:type mode: str
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
:type layout_config: dict or None
|
||||||
"""
|
"""
|
||||||
assert mode in ('stack', 'group', 'relative')
|
assert mode in ('stack', 'group', 'relative')
|
||||||
|
|
||||||
@ -319,6 +327,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
xlabels=xlabels,
|
xlabels=xlabels,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
mode=mode,
|
mode=mode,
|
||||||
|
layout_config=layout_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.report_plot(
|
return self.report_plot(
|
||||||
@ -328,7 +337,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
iter=iter,
|
iter=iter,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_table(self, title, series, table, iteration):
|
def report_table(self, title, series, table, iteration, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Report a table plot.
|
Report a table plot.
|
||||||
|
|
||||||
@ -340,8 +349,10 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:type table: pandas.DataFrame
|
:type table: pandas.DataFrame
|
||||||
:param iteration: Iteration number
|
:param iteration: Iteration number
|
||||||
:type iteration: int
|
:type iteration: int
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
:type layout_config: dict or None
|
||||||
"""
|
"""
|
||||||
table_output = create_plotly_table(table, title, series)
|
table_output = create_plotly_table(table, title, series, layout_config=layout_config)
|
||||||
return self.report_plot(
|
return self.report_plot(
|
||||||
title=self._normalize_name(title),
|
title=self._normalize_name(title),
|
||||||
series=self._normalize_name(series),
|
series=self._normalize_name(series),
|
||||||
@ -349,7 +360,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
iter=iteration,
|
iter=iteration,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_line_plot(self, title, series, iter, xtitle, ytitle, mode='lines', reverse_xaxis=False, comment=None):
|
def report_line_plot(self, title, series, iter, xtitle, ytitle, mode='lines', reverse_xaxis=False,
|
||||||
|
comment=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Report a (possibly multiple) line plot.
|
Report a (possibly multiple) line plot.
|
||||||
|
|
||||||
@ -369,6 +381,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:type reverse_xaxis: bool
|
:type reverse_xaxis: bool
|
||||||
:param comment: comment underneath the title
|
:param comment: comment underneath the title
|
||||||
:type comment: str
|
:type comment: str
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
:type layout_config: dict or None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
plotly_dict = create_line_plot(
|
plotly_dict = create_line_plot(
|
||||||
@ -379,6 +393,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
mode=mode,
|
mode=mode,
|
||||||
reverse_xaxis=reverse_xaxis,
|
reverse_xaxis=reverse_xaxis,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=layout_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.report_plot(
|
return self.report_plot(
|
||||||
@ -389,7 +404,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
)
|
)
|
||||||
|
|
||||||
def report_2d_scatter(self, title, series, data, iter, mode='lines', xtitle=None, ytitle=None, labels=None,
|
def report_2d_scatter(self, title, series, data, iter, mode='lines', xtitle=None, ytitle=None, labels=None,
|
||||||
comment=None):
|
comment=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Report a 2d scatter graph (with lines)
|
Report a 2d scatter graph (with lines)
|
||||||
|
|
||||||
@ -407,6 +422,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:param labels: label (text) per point in the scatter (in the same order)
|
:param labels: label (text) per point in the scatter (in the same order)
|
||||||
:param comment: comment underneath the title
|
:param comment: comment underneath the title
|
||||||
:type comment: str
|
:type comment: str
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
:type layout_config: dict or None
|
||||||
"""
|
"""
|
||||||
plotly_dict = create_2d_scatter_series(
|
plotly_dict = create_2d_scatter_series(
|
||||||
np_row_wise=data,
|
np_row_wise=data,
|
||||||
@ -417,6 +434,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
ytitle=ytitle,
|
ytitle=ytitle,
|
||||||
labels=labels,
|
labels=labels,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=layout_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.report_plot(
|
return self.report_plot(
|
||||||
@ -428,7 +446,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
|
|
||||||
def report_3d_scatter(self, title, series, data, iter, labels=None, mode='lines', color=((217, 217, 217, 0.14),),
|
def report_3d_scatter(self, title, series, data, iter, labels=None, mode='lines', color=((217, 217, 217, 0.14),),
|
||||||
marker_size=5, line_width=0.8, xtitle=None, ytitle=None, ztitle=None, fill=None,
|
marker_size=5, line_width=0.8, xtitle=None, ytitle=None, ztitle=None, fill=None,
|
||||||
comment=None):
|
comment=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Report a 3d scatter graph (with markers)
|
Report a 3d scatter graph (with markers)
|
||||||
|
|
||||||
@ -450,6 +468,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:param ytitle: optional y-axis title
|
:param ytitle: optional y-axis title
|
||||||
:param ztitle: optional z-axis title
|
:param ztitle: optional z-axis title
|
||||||
:param comment: comment underneath the title
|
:param comment: comment underneath the title
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
:type layout_config: dict or None
|
||||||
"""
|
"""
|
||||||
data_series = data if isinstance(data, list) else [data]
|
data_series = data if isinstance(data, list) else [data]
|
||||||
|
|
||||||
@ -469,6 +489,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
yaxis_title=ytitle,
|
yaxis_title=ytitle,
|
||||||
zaxis_title=ztitle,
|
zaxis_title=ztitle,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=layout_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
for i, values in enumerate(data_series):
|
for i, values in enumerate(data_series):
|
||||||
@ -492,7 +513,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
iter=iter,
|
iter=iter,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_value_matrix(self, title, series, data, iter, xtitle=None, ytitle=None, xlabels=None, ylabels=None, comment=None):
|
def report_value_matrix(self, title, series, data, iter, xtitle=None, ytitle=None, xlabels=None, ylabels=None,
|
||||||
|
comment=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Report a heat-map matrix
|
Report a heat-map matrix
|
||||||
|
|
||||||
@ -509,6 +531,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:param xlabels: optional label per column of the matrix
|
:param xlabels: optional label per column of the matrix
|
||||||
:param ylabels: optional label per row of the matrix
|
:param ylabels: optional label per row of the matrix
|
||||||
:param comment: comment underneath the title
|
:param comment: comment underneath the title
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
:type layout_config: dict or None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
plotly_dict = create_value_matrix(
|
plotly_dict = create_value_matrix(
|
||||||
@ -520,6 +544,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
comment=comment,
|
comment=comment,
|
||||||
xtitle=xtitle,
|
xtitle=xtitle,
|
||||||
ytitle=ytitle,
|
ytitle=ytitle,
|
||||||
|
layout_config=layout_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.report_plot(
|
return self.report_plot(
|
||||||
@ -530,7 +555,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
)
|
)
|
||||||
|
|
||||||
def report_value_surface(self, title, series, data, iter, xlabels=None, ylabels=None,
|
def report_value_surface(self, title, series, data, iter, xlabels=None, ylabels=None,
|
||||||
xtitle=None, ytitle=None, ztitle=None, camera=None, comment=None):
|
xtitle=None, ytitle=None, ztitle=None, camera=None, comment=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Report a 3d surface (same data as heat-map matrix, only presented differently)
|
Report a 3d surface (same data as heat-map matrix, only presented differently)
|
||||||
|
|
||||||
@ -549,6 +574,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:param ztitle: optional z-axis title
|
:param ztitle: optional z-axis title
|
||||||
:param camera: X,Y,Z camera position. def: (1,1,1)
|
:param camera: X,Y,Z camera position. def: (1,1,1)
|
||||||
:param comment: comment underneath the title
|
:param comment: comment underneath the title
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
:type layout_config: dict or None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
plotly_dict = create_3d_surface(
|
plotly_dict = create_3d_surface(
|
||||||
@ -562,6 +589,7 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
ztitle=ztitle,
|
ztitle=ztitle,
|
||||||
camera=camera,
|
camera=camera,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=layout_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
return self.report_plot(
|
return self.report_plot(
|
||||||
@ -588,6 +616,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
:type path: str
|
:type path: str
|
||||||
:param matrix: A 3D numpy.ndarray object containing image data (RGB). Required unless filename is provided.
|
:param matrix: A 3D numpy.ndarray object containing image data (RGB). Required unless filename is provided.
|
||||||
:type matrix: str
|
:type matrix: str
|
||||||
|
:param upload_uri: upload image destination (str)
|
||||||
|
:type upload_uri: str
|
||||||
:param max_image_history: maximum number of image to store per metric/variant combination
|
:param max_image_history: maximum number of image to store per metric/variant combination
|
||||||
use negative value for unlimited. default is set in global configuration (default=5)
|
use negative value for unlimited. default is set in global configuration (default=5)
|
||||||
:param delete_after_upload: if True, one the file was uploaded the local copy will be deleted
|
:param delete_after_upload: if True, one the file was uploaded the local copy will be deleted
|
||||||
@ -597,7 +627,8 @@ class Reporter(InterfaceBase, AbstractContextManager, SetupUploadMixin, AsyncMan
|
|||||||
raise ValueError('Upload configuration is required (use setup_upload())')
|
raise ValueError('Upload configuration is required (use setup_upload())')
|
||||||
if len([x for x in (path, matrix) if x is not None]) != 1:
|
if len([x for x in (path, matrix) if x is not None]) != 1:
|
||||||
raise ValueError('Expected only one of [filename, matrix]')
|
raise ValueError('Expected only one of [filename, matrix]')
|
||||||
kwargs = dict(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter, file_history_size=max_image_history)
|
kwargs = dict(metric=self._normalize_name(title), variant=self._normalize_name(series), iter=iter,
|
||||||
|
file_history_size=max_image_history)
|
||||||
ev = UploadEvent(image_data=matrix, upload_uri=upload_uri, local_image_path=path,
|
ev = UploadEvent(image_data=matrix, upload_uri=upload_uri, local_image_path=path,
|
||||||
delete_after_upload=delete_after_upload, **kwargs)
|
delete_after_upload=delete_after_upload, **kwargs)
|
||||||
_, url = ev.get_target_full_upload_uri(upload_uri or self._storage_uri, self._metrics.storage_key_prefix)
|
_, url = ev.get_target_full_upload_uri(upload_uri or self._storage_uri, self._metrics.storage_key_prefix)
|
||||||
|
@ -13,7 +13,6 @@ except ImportError:
|
|||||||
from PIL import Image
|
from PIL import Image
|
||||||
from pathlib2 import Path
|
from pathlib2 import Path
|
||||||
|
|
||||||
from .backend_api.services import tasks
|
|
||||||
from .backend_interface.logger import StdStreamPatch, LogFlusher
|
from .backend_interface.logger import StdStreamPatch, LogFlusher
|
||||||
from .backend_interface.task import Task as _Task
|
from .backend_interface.task import Task as _Task
|
||||||
from .backend_interface.task.development.worker import DevWorker
|
from .backend_interface.task.development.worker import DevWorker
|
||||||
@ -153,7 +152,8 @@ class Logger(object):
|
|||||||
xlabels=None, # type: Optional[List[str]]
|
xlabels=None, # type: Optional[List[str]]
|
||||||
xaxis=None, # type: Optional[str]
|
xaxis=None, # type: Optional[str]
|
||||||
yaxis=None, # type: Optional[str]
|
yaxis=None, # type: Optional[str]
|
||||||
mode=None # type: Optional[str]
|
mode=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, plot a vector as (default stacked) histogram.
|
For explicit reporting, plot a vector as (default stacked) histogram.
|
||||||
@ -180,10 +180,12 @@ class Logger(object):
|
|||||||
:param str xaxis: The x-axis title. (Optional)
|
:param str xaxis: The x-axis title. (Optional)
|
||||||
:param str yaxis: The y-axis title. (Optional)
|
:param str yaxis: The y-axis title. (Optional)
|
||||||
:param str mode: Multiple histograms mode, stack / group / relative. Default is 'group'.
|
:param str mode: Multiple histograms mode, stack / group / relative. Default is 'group'.
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
self._touch_title_series(title, series)
|
self._touch_title_series(title, series)
|
||||||
return self.report_histogram(title, series, values, iteration, labels=labels, xlabels=xlabels,
|
return self.report_histogram(title, series, values, iteration, labels=labels, xlabels=xlabels,
|
||||||
xaxis=xaxis, yaxis=yaxis, mode=mode)
|
xaxis=xaxis, yaxis=yaxis, mode=mode, extra_layout=extra_layout)
|
||||||
|
|
||||||
def report_histogram(
|
def report_histogram(
|
||||||
self,
|
self,
|
||||||
@ -195,7 +197,8 @@ class Logger(object):
|
|||||||
xlabels=None, # type: Optional[List[str]]
|
xlabels=None, # type: Optional[List[str]]
|
||||||
xaxis=None, # type: Optional[str]
|
xaxis=None, # type: Optional[str]
|
||||||
yaxis=None, # type: Optional[str]
|
yaxis=None, # type: Optional[str]
|
||||||
mode=None # type: Optional[str]
|
mode=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, plot a (default grouped) histogram.
|
For explicit reporting, plot a (default grouped) histogram.
|
||||||
@ -207,8 +210,8 @@ class Logger(object):
|
|||||||
.. code-block:: py
|
.. code-block:: py
|
||||||
|
|
||||||
vector_series = np.random.randint(10, size=10).reshape(2,5)
|
vector_series = np.random.randint(10, size=10).reshape(2,5)
|
||||||
logger.report_histogram(title='histogram example', series='histogram series', values=vector_series, iteration=0,
|
logger.report_histogram(title='histogram example', series='histogram series',
|
||||||
labels=['A','B'], xaxis='X axis label', yaxis='Y axis label')
|
values=vector_series, iteration=0, labels=['A','B'], xaxis='X axis label', yaxis='Y axis label')
|
||||||
|
|
||||||
You can view the reported histograms in the **Trains Web-App (UI)**, **RESULTS** tab, **PLOTS** sub-tab.
|
You can view the reported histograms in the **Trains Web-App (UI)**, **RESULTS** tab, **PLOTS** sub-tab.
|
||||||
|
|
||||||
@ -224,6 +227,8 @@ class Logger(object):
|
|||||||
:param str xaxis: The x-axis title. (Optional)
|
:param str xaxis: The x-axis title. (Optional)
|
||||||
:param str yaxis: The y-axis title. (Optional)
|
:param str yaxis: The y-axis title. (Optional)
|
||||||
:param str mode: Multiple histograms mode, stack / group / relative. Default is 'group'.
|
:param str mode: Multiple histograms mode, stack / group / relative. Default is 'group'.
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(values, np.ndarray):
|
if not isinstance(values, np.ndarray):
|
||||||
@ -241,7 +246,8 @@ class Logger(object):
|
|||||||
xlabels=xlabels,
|
xlabels=xlabels,
|
||||||
xtitle=xaxis,
|
xtitle=xaxis,
|
||||||
ytitle=yaxis,
|
ytitle=yaxis,
|
||||||
mode=mode or 'group'
|
mode=mode or 'group',
|
||||||
|
layout_config=extra_layout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_table(
|
def report_table(
|
||||||
@ -251,7 +257,8 @@ class Logger(object):
|
|||||||
iteration, # type: int
|
iteration, # type: int
|
||||||
table_plot=None, # type: Optional[pd.DataFrame]
|
table_plot=None, # type: Optional[pd.DataFrame]
|
||||||
csv=None, # type: Optional[str]
|
csv=None, # type: Optional[str]
|
||||||
url=None # type: Optional[str]
|
url=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit report, report a table plot.
|
For explicit report, report a table plot.
|
||||||
@ -284,6 +291,9 @@ class Logger(object):
|
|||||||
:type csv: str
|
:type csv: str
|
||||||
:param url: A URL to the location of csv file.
|
:param url: A URL to the location of csv file.
|
||||||
:type url: str
|
:type url: str
|
||||||
|
:param extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
|
:type extra_layout: dict
|
||||||
"""
|
"""
|
||||||
mutually_exclusive(
|
mutually_exclusive(
|
||||||
UsageError, _check_none=True,
|
UsageError, _check_none=True,
|
||||||
@ -293,7 +303,8 @@ class Logger(object):
|
|||||||
if url or csv:
|
if url or csv:
|
||||||
if not pd:
|
if not pd:
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
"pandas is required in order to support reporting tables using CSV or a URL, please install the pandas python package"
|
"pandas is required in order to support reporting tables using CSV or a URL, "
|
||||||
|
"please install the pandas python package"
|
||||||
)
|
)
|
||||||
if url:
|
if url:
|
||||||
table = pd.read_csv(url)
|
table = pd.read_csv(url)
|
||||||
@ -313,7 +324,8 @@ class Logger(object):
|
|||||||
title=title,
|
title=title,
|
||||||
series=series,
|
series=series,
|
||||||
table=reporter_table,
|
table=reporter_table,
|
||||||
iteration=iteration
|
iteration=iteration,
|
||||||
|
layout_config=extra_layout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_line_plot(
|
def report_line_plot(
|
||||||
@ -325,7 +337,8 @@ class Logger(object):
|
|||||||
yaxis, # type: str
|
yaxis, # type: str
|
||||||
mode='lines', # type: str
|
mode='lines', # type: str
|
||||||
reverse_xaxis=False, # type: bool
|
reverse_xaxis=False, # type: bool
|
||||||
comment=None # type: Optional[str]
|
comment=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, plot one or more series as lines.
|
For explicit reporting, plot one or more series as lines.
|
||||||
@ -352,6 +365,8 @@ class Logger(object):
|
|||||||
- ``False`` - The x-axis is low to high (not reversed). (Default)
|
- ``False`` - The x-axis is low to high (not reversed). (Default)
|
||||||
|
|
||||||
:param str comment: A comment displayed with the plot, underneath the title.
|
:param str comment: A comment displayed with the plot, underneath the title.
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
series = [self.SeriesInfo(**s) if isinstance(s, dict) else s for s in series]
|
series = [self.SeriesInfo(**s) if isinstance(s, dict) else s for s in series]
|
||||||
@ -368,6 +383,7 @@ class Logger(object):
|
|||||||
mode=mode,
|
mode=mode,
|
||||||
reverse_xaxis=reverse_xaxis,
|
reverse_xaxis=reverse_xaxis,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=extra_layout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_scatter2d(
|
def report_scatter2d(
|
||||||
@ -380,7 +396,8 @@ class Logger(object):
|
|||||||
yaxis=None, # type: Optional[str]
|
yaxis=None, # type: Optional[str]
|
||||||
labels=None, # type: Optional[List[str]]
|
labels=None, # type: Optional[List[str]]
|
||||||
mode='lines', # type: str
|
mode='lines', # type: str
|
||||||
comment=None # type: Optional[str]
|
comment=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, report a 2d scatter plot.
|
For explicit reporting, report a 2d scatter plot.
|
||||||
@ -408,8 +425,7 @@ class Logger(object):
|
|||||||
|
|
||||||
:param str title: The title of the plot.
|
:param str title: The title of the plot.
|
||||||
:param str series: The title of the series.
|
:param str series: The title of the series.
|
||||||
:param scatter: The scatter data.
|
:param list scatter: The scatter data. numpy.ndarray or list of (pairs of x,y) scatter:
|
||||||
:type numpy.ndarray, list of (pairs of x,y) scatter:
|
|
||||||
:param int iteration: The iteration number. To set an initial iteration, for example to continue a previously
|
:param int iteration: The iteration number. To set an initial iteration, for example to continue a previously
|
||||||
:param str xaxis: The x-axis title. (Optional)
|
:param str xaxis: The x-axis title. (Optional)
|
||||||
:param str yaxis: The y-axis title. (Optional)
|
:param str yaxis: The y-axis title. (Optional)
|
||||||
@ -424,6 +440,8 @@ class Logger(object):
|
|||||||
- ``lines+markers``
|
- ``lines+markers``
|
||||||
|
|
||||||
:param str comment: A comment displayed with the plot, underneath the title.
|
:param str comment: A comment displayed with the plot, underneath the title.
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(scatter, np.ndarray):
|
if not isinstance(scatter, np.ndarray):
|
||||||
@ -444,6 +462,7 @@ class Logger(object):
|
|||||||
ytitle=yaxis,
|
ytitle=yaxis,
|
||||||
labels=labels,
|
labels=labels,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=extra_layout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_scatter3d(
|
def report_scatter3d(
|
||||||
@ -458,7 +477,8 @@ class Logger(object):
|
|||||||
labels=None, # type: Optional[List[str]]
|
labels=None, # type: Optional[List[str]]
|
||||||
mode='markers', # type: str
|
mode='markers', # type: str
|
||||||
fill=False, # type: bool
|
fill=False, # type: bool
|
||||||
comment=None # type: Optional[str]
|
comment=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, plot a 3d scatter graph (with markers).
|
For explicit reporting, plot a 3d scatter graph (with markers).
|
||||||
@ -466,7 +486,7 @@ class Logger(object):
|
|||||||
:param str title: The title of the plot.
|
:param str title: The title of the plot.
|
||||||
:param str series: The title of the series.
|
:param str series: The title of the series.
|
||||||
:param Union[numpy.ndarray, list] scatter: The scatter data.
|
:param Union[numpy.ndarray, list] scatter: The scatter data.
|
||||||
:type scatter: list of (pairs of x,y,z), list of series [[(x1,y1,z1)...]], or numpy.ndarray
|
list of (pairs of x,y,z), list of series [[(x1,y1,z1)...]], or numpy.ndarray
|
||||||
:param int iteration: The iteration number.
|
:param int iteration: The iteration number.
|
||||||
:param str xaxis: The x-axis title. (Optional)
|
:param str xaxis: The x-axis title. (Optional)
|
||||||
:param str yaxis: The y-axis title. (Optional)
|
:param str yaxis: The y-axis title. (Optional)
|
||||||
@ -497,6 +517,8 @@ class Logger(object):
|
|||||||
- ``False`` - Do not fill (Default)
|
- ``False`` - Do not fill (Default)
|
||||||
|
|
||||||
:param str comment: A comment displayed with the plot, underneath the title.
|
:param str comment: A comment displayed with the plot, underneath the title.
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
# check if multiple series
|
# check if multiple series
|
||||||
multi_series = (
|
multi_series = (
|
||||||
@ -536,6 +558,7 @@ class Logger(object):
|
|||||||
xtitle=xaxis,
|
xtitle=xaxis,
|
||||||
ytitle=yaxis,
|
ytitle=yaxis,
|
||||||
ztitle=zaxis,
|
ztitle=zaxis,
|
||||||
|
layout_config=extra_layout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_confusion_matrix(
|
def report_confusion_matrix(
|
||||||
@ -548,7 +571,8 @@ class Logger(object):
|
|||||||
yaxis=None, # type: Optional[str]
|
yaxis=None, # type: Optional[str]
|
||||||
xlabels=None, # type: Optional[List[str]]
|
xlabels=None, # type: Optional[List[str]]
|
||||||
ylabels=None, # type: Optional[List[str]]
|
ylabels=None, # type: Optional[List[str]]
|
||||||
comment=None # type: Optional[str]
|
comment=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, plot a heat-map matrix.
|
For explicit reporting, plot a heat-map matrix.
|
||||||
@ -570,6 +594,8 @@ class Logger(object):
|
|||||||
:param list(str) xlabels: Labels for each column of the matrix. (Optional)
|
:param list(str) xlabels: Labels for each column of the matrix. (Optional)
|
||||||
:param list(str) ylabels: Labels for each row of the matrix. (Optional)
|
:param list(str) ylabels: Labels for each row of the matrix. (Optional)
|
||||||
:param str comment: A comment displayed with the plot, underneath the title.
|
:param str comment: A comment displayed with the plot, underneath the title.
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(matrix, np.ndarray):
|
if not isinstance(matrix, np.ndarray):
|
||||||
@ -588,6 +614,7 @@ class Logger(object):
|
|||||||
xlabels=xlabels,
|
xlabels=xlabels,
|
||||||
ylabels=ylabels,
|
ylabels=ylabels,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=extra_layout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_matrix(
|
def report_matrix(
|
||||||
@ -599,7 +626,8 @@ class Logger(object):
|
|||||||
xaxis=None, # type: Optional[str]
|
xaxis=None, # type: Optional[str]
|
||||||
yaxis=None, # type: Optional[str]
|
yaxis=None, # type: Optional[str]
|
||||||
xlabels=None, # type: Optional[List[str]]
|
xlabels=None, # type: Optional[List[str]]
|
||||||
ylabels=None # type: Optional[List[str]]
|
ylabels=None, # type: Optional[List[str]]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, plot a confusion matrix.
|
For explicit reporting, plot a confusion matrix.
|
||||||
@ -615,10 +643,13 @@ class Logger(object):
|
|||||||
:param str yaxis: The y-axis title. (Optional)
|
:param str yaxis: The y-axis title. (Optional)
|
||||||
:param list(str) xlabels: Labels for each column of the matrix. (Optional)
|
:param list(str) xlabels: Labels for each column of the matrix. (Optional)
|
||||||
:param list(str) ylabels: Labels for each row of the matrix. (Optional)
|
:param list(str) ylabels: Labels for each row of the matrix. (Optional)
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
self._touch_title_series(title, series)
|
self._touch_title_series(title, series)
|
||||||
return self.report_confusion_matrix(title, series, matrix, iteration,
|
return self.report_confusion_matrix(title, series, matrix, iteration,
|
||||||
xaxis=xaxis, yaxis=yaxis, xlabels=xlabels, ylabels=ylabels)
|
xaxis=xaxis, yaxis=yaxis, xlabels=xlabels, ylabels=ylabels,
|
||||||
|
extra_layout=extra_layout)
|
||||||
|
|
||||||
def report_surface(
|
def report_surface(
|
||||||
self,
|
self,
|
||||||
@ -632,7 +663,8 @@ class Logger(object):
|
|||||||
xlabels=None, # type: Optional[List[str]]
|
xlabels=None, # type: Optional[List[str]]
|
||||||
ylabels=None, # type: Optional[List[str]]
|
ylabels=None, # type: Optional[List[str]]
|
||||||
camera=None, # type: Optional[Sequence[float]]
|
camera=None, # type: Optional[Sequence[float]]
|
||||||
comment=None # type: Optional[str]
|
comment=None, # type: Optional[str]
|
||||||
|
extra_layout=None, # type: Optional[dict]
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
For explicit reporting, report a 3d surface plot.
|
For explicit reporting, report a 3d surface plot.
|
||||||
@ -658,6 +690,8 @@ class Logger(object):
|
|||||||
:param list(str) ylabels: Labels for each row of the matrix. (Optional)
|
:param list(str) ylabels: Labels for each row of the matrix. (Optional)
|
||||||
:param list(float) camera: X,Y,Z coordinates indicating the camera position. The default value is ``(1,1,1)``.
|
:param list(float) camera: X,Y,Z coordinates indicating the camera position. The default value is ``(1,1,1)``.
|
||||||
:param str comment: A comment displayed with the plot, underneath the title.
|
:param str comment: A comment displayed with the plot, underneath the title.
|
||||||
|
:param dict extra_layout: optional dictionary for layout configuration, passed directly to plotly
|
||||||
|
example: extra_layout={'xaxis': {'type': 'date', 'range': ['2020-01-01', '2020-01-31']}}
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if not isinstance(matrix, np.ndarray):
|
if not isinstance(matrix, np.ndarray):
|
||||||
@ -678,6 +712,7 @@ class Logger(object):
|
|||||||
ztitle=zaxis,
|
ztitle=zaxis,
|
||||||
camera=camera,
|
camera=camera,
|
||||||
comment=comment,
|
comment=comment,
|
||||||
|
layout_config=extra_layout,
|
||||||
)
|
)
|
||||||
|
|
||||||
def report_image(
|
def report_image(
|
||||||
@ -805,7 +840,8 @@ class Logger(object):
|
|||||||
describing the task ID, title, series and iteration.
|
describing the task ID, title, series and iteration.
|
||||||
|
|
||||||
.. note::
|
.. note::
|
||||||
:paramref:`~.Logger.report_image.local_path`, :paramref:`~.Logger.report_image.url`, :paramref:`~.Logger.report_image.image` and :paramref:`~.Logger.report_image.matrix`
|
:paramref:`~.Logger.report_image.local_path`, :paramref:`~.Logger.report_image.url`,
|
||||||
|
:paramref:`~.Logger.report_image.image` and :paramref:`~.Logger.report_image.matrix`
|
||||||
are mutually exclusive, and at least one must be provided.
|
are mutually exclusive, and at least one must be provided.
|
||||||
|
|
||||||
:param str title: Title (AKA metric)
|
:param str title: Title (AKA metric)
|
||||||
|
@ -109,3 +109,15 @@ class NestedBlobsDict(BlobsDict):
|
|||||||
|
|
||||||
def keys(self):
|
def keys(self):
|
||||||
return self._keys(self, '')
|
return self._keys(self, '')
|
||||||
|
|
||||||
|
|
||||||
|
def merge_dicts(dict1, dict2):
|
||||||
|
""" Recursively merges dict2 into dict1 """
|
||||||
|
if not isinstance(dict1, dict) or not isinstance(dict2, dict):
|
||||||
|
return dict2
|
||||||
|
for k in dict2:
|
||||||
|
if k in dict1:
|
||||||
|
dict1[k] = merge_dicts(dict1[k], dict2[k])
|
||||||
|
else:
|
||||||
|
dict1[k] = dict2[k]
|
||||||
|
return dict1
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
from ..errors import UsageError
|
from ..errors import UsageError
|
||||||
|
from ..utilities.dicts import merge_dicts
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
@ -10,7 +11,7 @@ from attr import attrs, attrib
|
|||||||
|
|
||||||
|
|
||||||
def create_2d_histogram_plot(np_row_wise, labels, title=None, xtitle=None, ytitle=None, series=None, xlabels=None,
|
def create_2d_histogram_plot(np_row_wise, labels, title=None, xtitle=None, ytitle=None, series=None, xlabels=None,
|
||||||
comment=None, mode='group'):
|
comment=None, mode='group', layout_config=None):
|
||||||
"""
|
"""
|
||||||
Create a 2D Plotly histogram chart from a 2D numpy array
|
Create a 2D Plotly histogram chart from a 2D numpy array
|
||||||
:param np_row_wise: 2D numpy data array
|
:param np_row_wise: 2D numpy data array
|
||||||
@ -20,12 +21,15 @@ def create_2d_histogram_plot(np_row_wise, labels, title=None, xtitle=None, ytitl
|
|||||||
:param ytitle: Y-Series title
|
:param ytitle: Y-Series title
|
||||||
:param comment: comment underneath the title
|
:param comment: comment underneath the title
|
||||||
:param mode: multiple histograms mode. valid options are: stack / group / relative. Default is 'group'.
|
:param mode: multiple histograms mode. valid options are: stack / group / relative. Default is 'group'.
|
||||||
|
:param layout_config: optional extra layout configuration
|
||||||
:return: Plotly chart dict
|
:return: Plotly chart dict
|
||||||
"""
|
"""
|
||||||
assert mode in ('stack', 'group', 'relative')
|
assert mode in ('stack', 'group', 'relative')
|
||||||
|
|
||||||
np_row_wise = np.atleast_2d(np_row_wise)
|
np_row_wise = np.atleast_2d(np_row_wise)
|
||||||
assert len(np_row_wise.shape) == 2, "Expected a 2D numpy array"
|
assert len(np_row_wise.shape) == 2, "Expected a 2D numpy array"
|
||||||
|
use_series = bool(labels)
|
||||||
|
|
||||||
# using labels without xlabels leads to original behavior
|
# using labels without xlabels leads to original behavior
|
||||||
if labels is not None and xlabels is None:
|
if labels is not None and xlabels is None:
|
||||||
assert len(labels) == np_row_wise.shape[0], "Please provide a label for each data row"
|
assert len(labels) == np_row_wise.shape[0], "Please provide a label for each data row"
|
||||||
@ -41,7 +45,9 @@ def create_2d_histogram_plot(np_row_wise, labels, title=None, xtitle=None, ytitl
|
|||||||
|
|
||||||
data = [_np_row_to_plotly_data_item(np_row=np_row_wise[i, :], label=labels[i] if labels else None, xlabels=xlabels)
|
data = [_np_row_to_plotly_data_item(np_row=np_row_wise[i, :], label=labels[i] if labels else None, xlabels=xlabels)
|
||||||
for i in range(np_row_wise.shape[0])]
|
for i in range(np_row_wise.shape[0])]
|
||||||
return _plotly_hist_dict(title=title, xtitle=xtitle, ytitle=ytitle, mode=mode, data=data, comment=comment)
|
return _plotly_hist_dict(title=series if use_series else title,
|
||||||
|
xtitle=xtitle, ytitle=ytitle, mode=mode, data=data, comment=comment,
|
||||||
|
layout_config=layout_config)
|
||||||
|
|
||||||
|
|
||||||
def _to_np_array(value):
|
def _to_np_array(value):
|
||||||
@ -73,7 +79,8 @@ class SeriesInfo(object):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def create_line_plot(title, series, xtitle, ytitle, mode='lines', reverse_xaxis=False, comment=None, MAX_SIZE=None):
|
def create_line_plot(title, series, xtitle, ytitle, mode='lines', reverse_xaxis=False,
|
||||||
|
comment=None, MAX_SIZE=None, layout_config=None):
|
||||||
plotly_obj = _plotly_scatter_layout_dict(
|
plotly_obj = _plotly_scatter_layout_dict(
|
||||||
title=title if not comment else (title + '<br><sup>' + comment + '</sup>'),
|
title=title if not comment else (title + '<br><sup>' + comment + '</sup>'),
|
||||||
xaxis_title=xtitle,
|
xaxis_title=xtitle,
|
||||||
@ -119,11 +126,14 @@ def create_line_plot(title, series, xtitle, ytitle, mode='lines', reverse_xaxis=
|
|||||||
"type": "scatter",
|
"type": "scatter",
|
||||||
} for s in series)
|
} for s in series)
|
||||||
|
|
||||||
|
if layout_config:
|
||||||
|
plotly_obj["layout"] = merge_dicts(plotly_obj["layout"], layout_config)
|
||||||
|
|
||||||
return plotly_obj
|
return plotly_obj
|
||||||
|
|
||||||
|
|
||||||
def create_2d_scatter_series(np_row_wise, title="Scatter", series_name="Series", xtitle="x", ytitle="y", mode="lines",
|
def create_2d_scatter_series(np_row_wise, title="Scatter", series_name="Series", xtitle="x", ytitle="y", mode="lines",
|
||||||
labels=None, comment=None):
|
labels=None, comment=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Create a 2D scatter Plotly graph from a 2 column numpy array
|
Create a 2D scatter Plotly graph from a 2 column numpy array
|
||||||
:param np_row_wise: 2 column numpy data array [(x0,y0), (x1,y1) ...]
|
:param np_row_wise: 2 column numpy data array [(x0,y0), (x1,y1) ...]
|
||||||
@ -134,6 +144,7 @@ def create_2d_scatter_series(np_row_wise, title="Scatter", series_name="Series",
|
|||||||
:param mode: scatter type mode ('lines' / 'markers' / 'lines+markers')
|
:param mode: scatter type mode ('lines' / 'markers' / 'lines+markers')
|
||||||
:param labels: label (text) per point on the scatter graph
|
:param labels: label (text) per point on the scatter graph
|
||||||
:param comment: comment underneath the title
|
:param comment: comment underneath the title
|
||||||
|
:param layout_config: optional dictionary for layout configuration, passed directly to plotly
|
||||||
:return: Plotly chart dict
|
:return: Plotly chart dict
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -154,12 +165,12 @@ def create_2d_scatter_series(np_row_wise, title="Scatter", series_name="Series",
|
|||||||
series = SeriesInfo(name=series_name, data=np_row_wise, labels=labels)
|
series = SeriesInfo(name=series_name, data=np_row_wise, labels=labels)
|
||||||
|
|
||||||
return create_line_plot(title=title, series=[series], xtitle=xtitle, ytitle=ytitle, mode=mode,
|
return create_line_plot(title=title, series=[series], xtitle=xtitle, ytitle=ytitle, mode=mode,
|
||||||
comment=comment, MAX_SIZE=100000)
|
comment=comment, MAX_SIZE=100000, layout_config=layout_config)
|
||||||
|
|
||||||
|
|
||||||
def create_3d_scatter_series(np_row_wise, title="Scatter", series_name="Series", xtitle="x", ytitle="y", ztitle="z",
|
def create_3d_scatter_series(np_row_wise, title="Scatter", series_name="Series", xtitle="x", ytitle="y", ztitle="z",
|
||||||
mode="lines", color=((217, 217, 217, 0.14),), marker_size=5, line_width=0.8,
|
mode="lines", color=((217, 217, 217, 0.14),), marker_size=5, line_width=0.8,
|
||||||
labels=None, fill_axis=-1, plotly_obj=None):
|
labels=None, fill_axis=-1, plotly_obj=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Create a 3D scatter Plotly graph from a 3 column numpy array
|
Create a 3D scatter Plotly graph from a 3 column numpy array
|
||||||
:param np_row_wise: 3 column numpy data array [(x0,y0,z0), (x1,y1,z1) ...]
|
:param np_row_wise: 3 column numpy data array [(x0,y0,z0), (x1,y1,z1) ...]
|
||||||
@ -170,6 +181,7 @@ def create_3d_scatter_series(np_row_wise, title="Scatter", series_name="Series",
|
|||||||
:param ztitle: Z-axis title
|
:param ztitle: Z-axis title
|
||||||
:param labels: label (text) per point on the scatter graph
|
:param labels: label (text) per point on the scatter graph
|
||||||
:param fill_axis: fill area under the curve
|
:param fill_axis: fill area under the curve
|
||||||
|
:param layout_config: additional layout configuration
|
||||||
:return: Plotly chart dict
|
:return: Plotly chart dict
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
@ -198,11 +210,15 @@ def create_3d_scatter_series(np_row_wise, title="Scatter", series_name="Series",
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
plotly_obj["data"].append(this_scatter_data)
|
plotly_obj["data"].append(this_scatter_data)
|
||||||
|
|
||||||
|
if layout_config:
|
||||||
|
plotly_obj["layout"] = merge_dicts(plotly_obj["layout"], layout_config)
|
||||||
|
|
||||||
return plotly_obj
|
return plotly_obj
|
||||||
|
|
||||||
|
|
||||||
def create_value_matrix(np_value_matrix, title="Heatmap Matrix", xlabels=None, ylabels=None, xtitle="X", ytitle="Y",
|
def create_value_matrix(np_value_matrix, title="Heatmap Matrix", xlabels=None, ylabels=None, xtitle="X", ytitle="Y",
|
||||||
custom_colors=True, series=None, comment=None):
|
custom_colors=True, series=None, comment=None, layout_config=None):
|
||||||
conf_matrix_plot = {
|
conf_matrix_plot = {
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
@ -231,12 +247,15 @@ def create_value_matrix(np_value_matrix, title="Heatmap Matrix", xlabels=None, y
|
|||||||
conf_matrix_plot["data"][0].update({"colorscale": scale})
|
conf_matrix_plot["data"][0].update({"colorscale": scale})
|
||||||
conf_matrix_plot["data"][0].update({"colorbar": bar})
|
conf_matrix_plot["data"][0].update({"colorbar": bar})
|
||||||
|
|
||||||
|
if layout_config:
|
||||||
|
conf_matrix_plot["layout"] = merge_dicts(conf_matrix_plot["layout"], layout_config)
|
||||||
|
|
||||||
return conf_matrix_plot
|
return conf_matrix_plot
|
||||||
|
|
||||||
|
|
||||||
def create_3d_surface(np_value_matrix, title="3D Surface", xlabels=None, ylabels=None, xtitle="X", ytitle="Y",
|
def create_3d_surface(np_value_matrix, title="3D Surface", xlabels=None, ylabels=None, xtitle="X", ytitle="Y",
|
||||||
ztitle="Z", custom_colors=True, series=None, camera=None, comment=None):
|
ztitle="Z", custom_colors=True, series=None, camera=None, comment=None, layout_config=None):
|
||||||
conf_matrix_plot = {
|
surface_plot = {
|
||||||
"data": [
|
"data": [
|
||||||
{
|
{
|
||||||
"z": np_value_matrix.tolist(),
|
"z": np_value_matrix.tolist(),
|
||||||
@ -278,17 +297,20 @@ def create_3d_surface(np_value_matrix, title="3D Surface", xlabels=None, ylabels
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if camera:
|
if camera:
|
||||||
conf_matrix_plot['layout']['scene']['camera'] = {"eye": {"x": camera[0], "y": camera[1], "z": camera[2]}}
|
surface_plot['layout']['scene']['camera'] = {"eye": {"x": camera[0], "y": camera[1], "z": camera[2]}}
|
||||||
|
|
||||||
if custom_colors:
|
if custom_colors:
|
||||||
scale, bar = _get_z_colorbar_data()
|
scale, bar = _get_z_colorbar_data()
|
||||||
conf_matrix_plot["data"][0].update({"colorscale": scale})
|
surface_plot["data"][0].update({"colorscale": scale})
|
||||||
conf_matrix_plot["data"][0].update({"colorbar": bar})
|
surface_plot["data"][0].update({"colorbar": bar})
|
||||||
|
|
||||||
return conf_matrix_plot
|
if layout_config:
|
||||||
|
surface_plot["layout"] = merge_dicts(surface_plot["layout"], layout_config)
|
||||||
|
|
||||||
|
return surface_plot
|
||||||
|
|
||||||
|
|
||||||
def create_image_plot(image_src, title, width=640, height=480, series=None, comment=None):
|
def create_image_plot(image_src, title, width=640, height=480, series=None, comment=None, layout_config=None):
|
||||||
image_plot = {
|
image_plot = {
|
||||||
"data": [],
|
"data": [],
|
||||||
"layout": {
|
"layout": {
|
||||||
@ -315,6 +337,10 @@ def create_image_plot(image_src, title, width=640, height=480, series=None, comm
|
|||||||
"name": series,
|
"name": series,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if layout_config:
|
||||||
|
image_plot["layout"] = merge_dicts(image_plot["layout"], layout_config)
|
||||||
|
|
||||||
return image_plot
|
return image_plot
|
||||||
|
|
||||||
|
|
||||||
@ -339,7 +365,7 @@ def _get_z_colorbar_data(z_data=None, values=None, colors=None):
|
|||||||
return colorscale, colorbar
|
return colorscale, colorbar
|
||||||
|
|
||||||
|
|
||||||
def _plotly_hist_dict(title, xtitle, ytitle, mode='group', data=None, comment=None):
|
def _plotly_hist_dict(title, xtitle, ytitle, mode='group', data=None, comment=None, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Create a basic Plotly chart dictionary
|
Create a basic Plotly chart dictionary
|
||||||
:param title: Chart title
|
:param title: Chart title
|
||||||
@ -348,11 +374,12 @@ def _plotly_hist_dict(title, xtitle, ytitle, mode='group', data=None, comment=No
|
|||||||
:param mode: multiple histograms mode. optionals stack / group / relative. Default is 'group'.
|
:param mode: multiple histograms mode. optionals stack / group / relative. Default is 'group'.
|
||||||
:param data: Data items
|
:param data: Data items
|
||||||
:type data: list
|
:type data: list
|
||||||
|
:param layout_config: dict
|
||||||
:return: Plotly chart dict
|
:return: Plotly chart dict
|
||||||
"""
|
"""
|
||||||
assert mode in ('stack', 'group', 'relative')
|
assert mode in ('stack', 'group', 'relative')
|
||||||
|
|
||||||
return {
|
plotly_object = {
|
||||||
"data": data or [],
|
"data": data or [],
|
||||||
"layout": {
|
"layout": {
|
||||||
"title": title if not comment else (title + '<br><sup>' + comment + '</sup>'),
|
"title": title if not comment else (title + '<br><sup>' + comment + '</sup>'),
|
||||||
@ -367,6 +394,10 @@ def _plotly_hist_dict(title, xtitle, ytitle, mode='group', data=None, comment=No
|
|||||||
"bargroupgap": 0
|
"bargroupgap": 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if layout_config:
|
||||||
|
plotly_object["layout"] = merge_dicts(plotly_object["layout"], layout_config)
|
||||||
|
|
||||||
|
return plotly_object
|
||||||
|
|
||||||
|
|
||||||
def _np_row_to_plotly_data_item(np_row, label, xlabels=None):
|
def _np_row_to_plotly_data_item(np_row, label, xlabels=None):
|
||||||
@ -413,8 +444,8 @@ def _plotly_scatter_layout_dict(title="Scatter", xaxis_title="X", yaxis_title="Y
|
|||||||
|
|
||||||
|
|
||||||
def plotly_scatter3d_layout_dict(title="Scatter", xaxis_title="X", yaxis_title="Y", zaxis_title="Z",
|
def plotly_scatter3d_layout_dict(title="Scatter", xaxis_title="X", yaxis_title="Y", zaxis_title="Z",
|
||||||
series=None, show_legend=True, comment=None):
|
series=None, show_legend=True, comment=None, layout_config=None):
|
||||||
return {
|
plotly_object = {
|
||||||
"data": [],
|
"data": [],
|
||||||
"layout": {
|
"layout": {
|
||||||
"showlegend": show_legend,
|
"showlegend": show_legend,
|
||||||
@ -428,8 +459,13 @@ def plotly_scatter3d_layout_dict(title="Scatter", xaxis_title="X", yaxis_title="
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if layout_config:
|
||||||
|
plotly_object["layout"] = merge_dicts(plotly_object["layout"], layout_config)
|
||||||
|
|
||||||
def create_plotly_table(table_plot, title, series):
|
return plotly_object
|
||||||
|
|
||||||
|
|
||||||
|
def create_plotly_table(table_plot, title, series, layout_config=None):
|
||||||
"""
|
"""
|
||||||
Create a basic Plotly table json style to be sent
|
Create a basic Plotly table json style to be sent
|
||||||
|
|
||||||
@ -439,6 +475,7 @@ def create_plotly_table(table_plot, title, series):
|
|||||||
:type title: str
|
:type title: str
|
||||||
:param series: Series (AKA variant)
|
:param series: Series (AKA variant)
|
||||||
:type series: str
|
:type series: str
|
||||||
|
:param layout_config: additional configuration layout
|
||||||
"""
|
"""
|
||||||
if not pd:
|
if not pd:
|
||||||
raise UsageError(
|
raise UsageError(
|
||||||
@ -474,4 +511,7 @@ def create_plotly_table(table_plot, title, series):
|
|||||||
"name": series,
|
"name": series,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if layout_config:
|
||||||
|
ret["layout"] = merge_dicts(ret["layout"], layout_config)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
Loading…
Reference in New Issue
Block a user