Visdom: Feature Request: support datetime fot tics

Created on 24 Mar 2017  路  6Comments  路  Source: fossasia/visdom

Most helpful comment

Interesting @Florian-Roessler, thanks for sharing!

I think it may be useful to add a function viz.matplot(mplfig) to the Python client that takes as input Matplotlib figure mplfig, converts it to a Plotly figure (hacking the margins if necessary), and sends it to the server as you describe.

(Note that power users can directly use _send() if they want to hack their own visualizations.)

All 6 comments

I ran into the same issue and my solution so far has been the following:

The example here does not include datetime for ticks but it hopefully is obvious how this would work with a matplotlib figure generated with datetime ticks.

I generated the graph I wanted using matplotlib and then used plotly tools to convert it into a plotly graph:

import matplotlib.pyplot as plt
import plotly.tools as tls

mpl_fig = plt.figure()
x = np.linspace(np.pi, 3*np.pi, 1000)
sinx = np.sin(x)
ax = mpl_fig.add_subplot(111)
ax.plot(x, sinx)
ax.set_title('A Sine Curve')
ax.set_ylabel('test')
plt.tight_layout()
plotly_fig = tls.mpl_to_plotly(mpl_fig)

The only issue with this is that the mpl_to_plotly() will set layout defaults which results in the plot pane not fitting the graph dimensions.

bad_layout

To overcome this I checked the layout that is send by a viz.line() plot and overwrote the standard "layout" generated by mpl_to_plotly by a custom version.

plotly_fig["layout"] = {u'showlegend': ['simulation'],
                                u'yaxis': {u'title': 'sin(x)'},
                                u'margin': {u'r': 60, u'b': 60, u'l': 60, u't': 60},
                                u'xaxis': {u'title': 'Time'},
                                u'title': "%s for %s" % (name, operator_name[op])}

This results in better treatment of image scaling in the plot panes of visdom.

good_layout

For all of this to work I also just added a custom function into __init__.py to allow me sending a plot to the server which I realise needs to be improved but I share it for the sake of the example here.

def mpl_converted(self, converted, win=None, env=None, opts=None, update=None):
        return self._send({
            'data': converted["data"],
            'win': win,
            'eid': env,
            'layout': converted["layout"]
        })

Any suggestions welcome, happy to contribute to the project with a PR (after comments and improvements) if that is wanted.

Interesting @Florian-Roessler, thanks for sharing!

I think it may be useful to add a function viz.matplot(mplfig) to the Python client that takes as input Matplotlib figure mplfig, converts it to a Plotly figure (hacking the margins if necessary), and sends it to the server as you describe.

(Note that power users can directly use _send() if they want to hack their own visualizations.)

Note also that as @lvdmaaten mentioned, you can use _send directly with the usual Plotly API.

Specifically, for date/time xaxis, see https://plot.ly/python/time-series/ ('Time Series Plot with Custom Date Range'):

import datetime

def to_unix_time(dt):
    epoch =  datetime.datetime.utcfromtimestamp(0)
    return (dt - epoch).total_seconds() * 1000

x = [datetime.datetime(year=2013, month=10, day=04),
    datetime.datetime(year=2013, month=11, day=05),
    datetime.datetime(year=2013, month=12, day=06)]
data = [dict(
            x=x,
            y=[1, 3, 6])]

layout = dict(xaxis = dict(
                   range = [to_unix_time(datetime.datetime(2013, 10, 17)),
                            to_unix_time(datetime.datetime(2013, 11, 20))]
    ))

Note that you don't need to use go.Scatter and go.Layout (you can use dicts instead).
Once you have your Plotly data and layout, you can just do:

self._send({
        'data': data,
         'win': win,
         'eid': env,
         'layout': layout
 })

@ajabri, can you rewrite the code above as a self-contained example? I get that "datetime is not JSON serializable". If I simplify the data to get past that, I get u'' as the retuned window and nothing is being plot. I presume that self should be a visdom.Visdom(), right?

I think it may be useful to add a function viz.matplot(mplfig) to the Python client that takes as input Matplotlib figure mplfig, converts it to a Plotly figure (hacking the margins if necessary), and sends it to the server as you describe.

I second that, it would be extremely useful, especially for already existing visualizations in Matplotlib that I would like to port to Visdom.

Hi @psmaragdis

Sorry for replying so late! Here's a self-contained, bug-free example:

import datetime
import visdom

def to_unix_time(dt):
    epoch =  datetime.datetime.utcfromtimestamp(0)
    return (dt - epoch).total_seconds() * 1000

x = [datetime.datetime(year=2013, month=10, day=04),
    datetime.datetime(year=2013, month=11, day=05),
    datetime.datetime(year=2013, month=12, day=06)]

data = [dict(
            x=[str(xx) for xx in x],
            y=[1, 3, 6],
            type='plot')]

layout = dict(xaxis = dict(
   range = [to_unix_time(datetime.datetime(2013, 10, 17)),
            to_unix_time(datetime.datetime(2013, 11, 20))]
))

visdom.Visdom()._send({
    'data': data,
    'opts': {},
    'layout': layout
})
Was this page helpful?
0 / 5 - 0 ratings

Related issues

SanderGielisse picture SanderGielisse  路  5Comments

amartya18x picture amartya18x  路  6Comments

rdevon picture rdevon  路  5Comments

shubhamjain0594 picture shubhamjain0594  路  3Comments

dizcza picture dizcza  路  7Comments