12
12
13
13
from . mplexporter import Renderer
14
14
from . import mpltools
15
- from plotly .graph_objs import *
16
-
15
+ import plotly .graph_objs as go
17
16
18
17
19
18
# Warning format
20
- def warning_on_one_line (message , category , filename , lineno , file = None , line = None ):
21
- return '%s:%s: %s:\n \n %s\n \n ' % (filename , lineno , category .__name__ , message )
19
+ def warning_on_one_line (msg , category , filename , lineno , file = None , line = None ):
20
+ return '%s:%s: %s:\n \n %s\n \n ' % (filename , lineno , category .__name__ , msg )
22
21
warnings .formatwarning = warning_on_one_line
23
22
23
+
24
24
class PlotlyRenderer (Renderer ):
25
25
"""A renderer class inheriting from base for rendering mpl plots in plotly.
26
26
@@ -48,7 +48,7 @@ def __init__(self):
48
48
All class attributes are listed here in the __init__ method.
49
49
50
50
"""
51
- self .plotly_fig = Figure (data = Data (), layout = Layout () )
51
+ self .plotly_fig = go . Figure ()
52
52
self .mpl_fig = None
53
53
self .current_mpl_ax = None
54
54
self .bar_containers = None
@@ -76,17 +76,19 @@ def open_figure(self, fig, props):
76
76
"""
77
77
self .msg += "Opening figure\n "
78
78
self .mpl_fig = fig
79
- self .plotly_fig ['layout' ] = Layout (
80
- width = int (props ['figwidth' ]* props ['dpi' ]),
81
- height = int (props ['figheight' ]* props ['dpi' ]),
79
+ self .plotly_fig ['layout' ] = go . Layout (
80
+ width = int (props ['figwidth' ] * props ['dpi' ]),
81
+ height = int (props ['figheight' ] * props ['dpi' ]),
82
82
autosize = False ,
83
83
hovermode = 'closest' )
84
84
self .mpl_x_bounds , self .mpl_y_bounds = mpltools .get_axes_bounds (fig )
85
- margin = Margin (
86
- l = int (self .mpl_x_bounds [0 ]* self .plotly_fig ['layout' ]['width' ]),
87
- r = int ((1 - self .mpl_x_bounds [1 ])* self .plotly_fig ['layout' ]['width' ]),
88
- t = int ((1 - self .mpl_y_bounds [1 ])* self .plotly_fig ['layout' ]['height' ]),
89
- b = int (self .mpl_y_bounds [0 ]* self .plotly_fig ['layout' ]['height' ]),
85
+ margin = go .Margin (
86
+ l = int (self .mpl_x_bounds [0 ] * self .plotly_fig ['layout' ]['width' ]),
87
+ r = int (
88
+ (1 - self .mpl_x_bounds [1 ]) * self .plotly_fig ['layout' ]['width' ]),
89
+ t = int ((1 - self .mpl_y_bounds [1 ]) * self .plotly_fig ['layout' ][
90
+ 'height' ]),
91
+ b = int (self .mpl_y_bounds [0 ] * self .plotly_fig ['layout' ]['height' ]),
90
92
pad = 0 )
91
93
self .plotly_fig ['layout' ]['margin' ] = margin
92
94
@@ -145,19 +147,20 @@ def open_axes(self, ax, props):
145
147
self .current_bars = []
146
148
self .axis_ct += 1
147
149
# set defaults in axes
148
- xaxis = XAxis (
150
+ xaxis = go . XAxis (
149
151
anchor = 'y{0}' .format (self .axis_ct ),
150
152
zeroline = False ,
151
153
ticks = 'inside' )
152
- yaxis = YAxis (
154
+ yaxis = go . YAxis (
153
155
anchor = 'x{0}' .format (self .axis_ct ),
154
156
zeroline = False ,
155
157
ticks = 'inside' )
156
158
# update defaults with things set in mpl
157
- mpl_xaxis , mpl_yaxis = mpltools .prep_xy_axis (ax = ax ,
158
- props = props ,
159
- x_bounds = self .mpl_x_bounds ,
160
- y_bounds = self .mpl_y_bounds )
159
+ mpl_xaxis , mpl_yaxis = mpltools .prep_xy_axis (
160
+ ax = ax ,
161
+ props = props ,
162
+ x_bounds = self .mpl_x_bounds ,
163
+ y_bounds = self .mpl_y_bounds )
161
164
xaxis .update (mpl_xaxis )
162
165
yaxis .update (mpl_yaxis )
163
166
bottom_spine = mpltools .get_spine_visible (ax , 'bottom' )
@@ -169,7 +172,6 @@ def open_axes(self, ax, props):
169
172
xaxis ['showline' ] = bottom_spine
170
173
yaxis ['showline' ] = top_spine
171
174
172
-
173
175
# put axes in our figure
174
176
self .plotly_fig ['layout' ]['xaxis{0}' .format (self .axis_ct )] = xaxis
175
177
self .plotly_fig ['layout' ]['yaxis{0}' .format (self .axis_ct )] = yaxis
@@ -216,15 +218,15 @@ def draw_bar(self, coll):
216
218
widths = [bar_props ['x1' ] - bar_props ['x0' ] for bar_props in trace ]
217
219
heights = [bar_props ['y1' ] - bar_props ['y0' ] for bar_props in trace ]
218
220
vertical = abs (
219
- sum (widths [0 ]- widths [iii ] for iii in range (len (widths )))
221
+ sum (widths [0 ] - widths [iii ] for iii in range (len (widths )))
220
222
) < tol
221
223
horizontal = abs (
222
- sum (heights [0 ]- heights [iii ] for iii in range (len (heights )))
224
+ sum (heights [0 ] - heights [iii ] for iii in range (len (heights )))
223
225
) < tol
224
226
if vertical and horizontal :
225
227
# Check for monotonic x. Can't both be true!
226
228
x_zeros = [bar_props ['x0' ] for bar_props in trace ]
227
- if all ((x_zeros [iii + 1 ] > x_zeros [iii ]
229
+ if all ((x_zeros [iii + 1 ] > x_zeros [iii ]
228
230
for iii in range (len (x_zeros [:- 1 ])))):
229
231
orientation = 'v'
230
232
else :
@@ -242,9 +244,9 @@ def draw_bar(self, coll):
242
244
# check if we're stacked or not...
243
245
for old , new in zip (old_heights , new_heights ):
244
246
if abs (old - new ) > tol :
245
- self .plotly_fig ['layout' ]['barmode' ]= 'stack'
246
- self .plotly_fig ['layout' ]['hovermode' ]= 'x'
247
- x = [bar ['x0' ]+ (bar ['x1' ]- bar ['x0' ])/ 2 for bar in trace ]
247
+ self .plotly_fig ['layout' ]['barmode' ] = 'stack'
248
+ self .plotly_fig ['layout' ]['hovermode' ] = 'x'
249
+ x = [bar ['x0' ] + (bar ['x1' ] - bar ['x0' ]) / 2 for bar in trace ]
248
250
y = [bar ['y1' ] for bar in trace ]
249
251
bar_gap = mpltools .get_bar_gap ([bar ['x0' ] for bar in trace ],
250
252
[bar ['x1' ] for bar in trace ])
@@ -257,21 +259,22 @@ def draw_bar(self, coll):
257
259
# check if we're stacked or not...
258
260
for old , new in zip (old_rights , new_rights ):
259
261
if abs (old - new ) > tol :
260
- self .plotly_fig ['layout' ]['barmode' ]= 'stack'
261
- self .plotly_fig ['layout' ]['hovermode' ]= 'y'
262
+ self .plotly_fig ['layout' ]['barmode' ] = 'stack'
263
+ self .plotly_fig ['layout' ]['hovermode' ] = 'y'
262
264
x = [bar ['x1' ] for bar in trace ]
263
- y = [bar ['y0' ]+ (bar ['y1' ]- bar ['y0' ])/ 2 for bar in trace ]
265
+ y = [bar ['y0' ] + (bar ['y1' ] - bar ['y0' ]) / 2 for bar in trace ]
264
266
bar_gap = mpltools .get_bar_gap ([bar ['y0' ] for bar in trace ],
265
267
[bar ['y1' ] for bar in trace ])
266
- bar = Bar (orientation = orientation ,
267
- x = x ,
268
- y = y ,
269
- xaxis = 'x{0}' .format (self .axis_ct ),
270
- yaxis = 'y{0}' .format (self .axis_ct ),
271
- opacity = trace [0 ]['alpha' ], # TODO: get all alphas if array?
272
- marker = Marker (
273
- color = trace [0 ]['facecolor' ], # TODO: get all
274
- line = Line (width = trace [0 ]['edgewidth' ]))) # TODO: get all
268
+ bar = go .Bar (
269
+ orientation = orientation ,
270
+ x = x ,
271
+ y = y ,
272
+ xaxis = 'x{0}' .format (self .axis_ct ),
273
+ yaxis = 'y{0}' .format (self .axis_ct ),
274
+ opacity = trace [0 ]['alpha' ], # TODO: get all alphas if array?
275
+ marker = go .Marker (
276
+ color = trace [0 ]['facecolor' ], # TODO: get all
277
+ line = go .Line (width = trace [0 ]['edgewidth' ]))) # TODO ditto
275
278
if len (bar ['x' ]) > 1 :
276
279
self .msg += " Heck yeah, I drew that bar chart\n "
277
280
self .plotly_fig ['data' ] += bar ,
@@ -282,7 +285,6 @@ def draw_bar(self, coll):
282
285
warnings .warn ('found box chart data with length <= 1, '
283
286
'assuming data redundancy, not plotting.' )
284
287
285
-
286
288
def draw_marked_line (self , ** props ):
287
289
"""Create a data dict for a line obj.
288
290
@@ -328,32 +330,33 @@ def draw_marked_line(self, **props):
328
330
self .msg += "... with just markers\n "
329
331
mode = "markers"
330
332
if props ['linestyle' ]:
331
- line = Line (
333
+ line = go . Line (
332
334
opacity = props ['linestyle' ]['alpha' ],
333
335
color = props ['linestyle' ]['color' ],
334
336
width = props ['linestyle' ]['linewidth' ],
335
337
dash = mpltools .convert_dash (props ['linestyle' ]['dasharray' ])
336
338
)
337
339
if props ['markerstyle' ]:
338
- marker = Marker (
340
+ marker = go . Marker (
339
341
opacity = props ['markerstyle' ]['alpha' ],
340
342
color = props ['markerstyle' ]['facecolor' ],
341
343
symbol = mpltools .convert_symbol (props ['markerstyle' ]['marker' ]),
342
344
size = props ['markerstyle' ]['markersize' ],
343
- line = Line (
345
+ line = go . Line (
344
346
color = props ['markerstyle' ]['edgecolor' ],
345
347
width = props ['markerstyle' ]['edgewidth' ]
346
348
)
347
349
)
348
350
if props ['coordinates' ] == 'data' :
349
- marked_line = Scatter (mode = mode ,
350
- name = props ['label' ],
351
- x = [xy_pair [0 ] for xy_pair in props ['data' ]],
352
- y = [xy_pair [1 ] for xy_pair in props ['data' ]],
353
- xaxis = 'x{0}' .format (self .axis_ct ),
354
- yaxis = 'y{0}' .format (self .axis_ct ),
355
- line = line ,
356
- marker = marker )
351
+ marked_line = go .Scatter (
352
+ mode = mode ,
353
+ name = props ['label' ],
354
+ x = [xy_pair [0 ] for xy_pair in props ['data' ]],
355
+ y = [xy_pair [1 ] for xy_pair in props ['data' ]],
356
+ xaxis = 'x{0}' .format (self .axis_ct ),
357
+ yaxis = 'y{0}' .format (self .axis_ct ),
358
+ line = line ,
359
+ marker = marker )
357
360
self .plotly_fig ['data' ] += marked_line ,
358
361
self .msg += " Heck yeah, I drew that line\n "
359
362
else :
@@ -459,7 +462,6 @@ def draw_path(self, **props):
459
462
warnings .warn ("I found a path object that I don't think is part "
460
463
"of a bar chart. Ignoring." )
461
464
462
-
463
465
def draw_text (self , ** props ):
464
466
"""Create an annotation dict for a text obj.
465
467
@@ -491,18 +493,19 @@ def draw_text(self, **props):
491
493
"""
492
494
self .msg += " Attempting to draw an mpl text object\n "
493
495
if not mpltools .check_corners (props ['mplobj' ], self .mpl_fig ):
494
- warnings .warn ("Looks like the annotation(s) you are trying \n "
495
- "to draw lies/lay outside the given figure size.\n \n "
496
- "Therefore, the resulting Plotly figure may not be \n "
497
- "large enough to view the full text. To adjust \n "
498
- "the size of the figure, use the 'width' and \n "
499
- "'height' keys in the Layout object. Alternatively,\n "
500
- "use the Margin object to adjust the figure's margins." )
496
+ warnings .warn (
497
+ "Looks like the annotation(s) you are trying \n "
498
+ "to draw lies/lay outside the given figure size.\n \n "
499
+ "Therefore, the resulting Plotly figure may not be \n "
500
+ "large enough to view the full text. To adjust \n "
501
+ "the size of the figure, use the 'width' and \n "
502
+ "'height' keys in the Layout object. Alternatively,\n "
503
+ "use the Margin object to adjust the figure's margins." )
501
504
align = props ['mplobj' ]._multialignment
502
505
if not align :
503
- align = props ['style' ]['halign' ] # mpl default
506
+ align = props ['style' ]['halign' ] # mpl default
504
507
if 'annotations' not in self .plotly_fig ['layout' ]:
505
- self .plotly_fig ['layout' ]['annotations' ] = Annotations ()
508
+ self .plotly_fig ['layout' ]['annotations' ] = go . Annotations ()
506
509
if props ['text_type' ] == 'xlabel' :
507
510
self .msg += " Text object is an xlabel\n "
508
511
self .draw_xlabel (** props )
@@ -519,8 +522,9 @@ def draw_text(self, **props):
519
522
"coordinates\n "
520
523
x_px , y_px = props ['mplobj' ].get_transform ().transform (
521
524
props ['position' ])
522
- x , y = mpltools .display_to_paper (x_px , y_px ,
523
- self .plotly_fig ['layout' ])
525
+ x , y = mpltools .display_to_paper (
526
+ x_px , y_px , self .plotly_fig ['layout' ]
527
+ )
524
528
xref = 'paper'
525
529
yref = 'paper'
526
530
xanchor = props ['style' ]['halign' ] # no difference here!
@@ -547,7 +551,7 @@ def draw_text(self, **props):
547
551
yref = 'paper'
548
552
xanchor = props ['style' ]['halign' ] # no difference here!
549
553
yanchor = mpltools .convert_va (props ['style' ]['valign' ])
550
- annotation = Annotation (
554
+ annotation = go . Annotation (
551
555
text = props ['text' ],
552
556
opacity = props ['style' ]['alpha' ],
553
557
x = x ,
@@ -558,7 +562,7 @@ def draw_text(self, **props):
558
562
xanchor = xanchor ,
559
563
yanchor = yanchor ,
560
564
showarrow = False , # change this later?
561
- font = Font (
565
+ font = go . Font (
562
566
color = props ['style' ]['color' ],
563
567
size = props ['style' ]['fontsize' ]
564
568
)
@@ -600,10 +604,11 @@ def draw_title(self, **props):
600
604
'position' ])
601
605
x , y = mpltools .display_to_paper (x_px , y_px ,
602
606
self .plotly_fig ['layout' ])
603
- annotation = Annotation (
607
+ annotation = go . Annotation (
604
608
text = props ['text' ],
605
- font = Font (color = props ['style' ]['color' ],
606
- size = props ['style' ]['fontsize' ]
609
+ font = go .Font (
610
+ color = props ['style' ]['color' ],
611
+ size = props ['style' ]['fontsize' ]
607
612
),
608
613
xref = 'paper' ,
609
614
yref = 'paper' ,
@@ -618,8 +623,9 @@ def draw_title(self, **props):
618
623
self .msg += " Only one subplot found, adding as a " \
619
624
"plotly title\n "
620
625
self .plotly_fig ['layout' ]['title' ] = props ['text' ]
621
- titlefont = Font (size = props ['style' ]['fontsize' ],
622
- color = props ['style' ]['color' ]
626
+ titlefont = go .Font (
627
+ size = props ['style' ]['fontsize' ],
628
+ color = props ['style' ]['color' ]
623
629
)
624
630
self .plotly_fig ['layout' ]['titlefont' ] = titlefont
625
631
@@ -649,8 +655,9 @@ def draw_xlabel(self, **props):
649
655
self .msg += " Adding xlabel\n "
650
656
axis_key = 'xaxis{0}' .format (self .axis_ct )
651
657
self .plotly_fig ['layout' ][axis_key ]['title' ] = props ['text' ]
652
- titlefont = Font (size = props ['style' ]['fontsize' ],
653
- color = props ['style' ]['color' ])
658
+ titlefont = go .Font (
659
+ size = props ['style' ]['fontsize' ],
660
+ color = props ['style' ]['color' ])
654
661
self .plotly_fig ['layout' ][axis_key ]['titlefont' ] = titlefont
655
662
656
663
def draw_ylabel (self , ** props ):
@@ -679,8 +686,9 @@ def draw_ylabel(self, **props):
679
686
self .msg += " Adding ylabel\n "
680
687
axis_key = 'yaxis{0}' .format (self .axis_ct )
681
688
self .plotly_fig ['layout' ][axis_key ]['title' ] = props ['text' ]
682
- titlefont = Font (size = props ['style' ]['fontsize' ],
683
- color = props ['style' ]['color' ])
689
+ titlefont = go .Font (
690
+ size = props ['style' ]['fontsize' ],
691
+ color = props ['style' ]['color' ])
684
692
self .plotly_fig ['layout' ][axis_key ]['titlefont' ] = titlefont
685
693
686
694
def resize (self ):
0 commit comments