Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fcfcee3

Browse filesBrowse files
committed
Log/linear 'scale' for axes work now. If log, base must == 10.
If base != 10 for the LogTransform object from matplotlib, we convert the 'scale' back to linear, autorange the axis, issue a warning, and plot the data on a linear scale.
1 parent 800265b commit fcfcee3
Copy full SHA for fcfcee3

File tree

Expand file treeCollapse file tree

2 files changed

+99
-10
lines changed
Filter options
Expand file treeCollapse file tree

2 files changed

+99
-10
lines changed

‎plotly/matplotlylib/mpltools.py

Copy file name to clipboardExpand all lines: plotly/matplotlylib/mpltools.py
+88Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
66
"""
77

8+
import math
9+
import warnings
810

911
def check_bar_match(old_bar, new_bar):
1012
"""Check if two bars belong in the same collection (bar chart).
@@ -259,6 +261,92 @@ def make_bar(**props):
259261
}
260262

261263

264+
def prep_x_ticks(ax, props):
265+
axis = dict()
266+
scale = props['axes'][0]['scale']
267+
if scale == 'linear':
268+
try:
269+
axis['tick0'] = props['axes'][0]['tickvalues'][0]
270+
axis['dtick'] = props['axes'][0]['tickvalues'][1] - \
271+
props['axes'][0]['tickvalues'][0]
272+
axis['autotick'] = False
273+
except (IndexError, TypeError):
274+
axis = dict(nticks=props['axes'][0]['nticks'])
275+
return axis
276+
elif scale == 'log':
277+
try:
278+
axis['tick0'] = props['axes'][0]['tickvalues'][0]
279+
axis['dtick'] = props['axes'][0]['tickvalues'][1] - \
280+
props['axes'][0]['tickvalues'][0]
281+
axis['autotick'] = False
282+
except (IndexError, TypeError):
283+
axis = dict(nticks=props['axes'][0]['nticks'])
284+
base = ax.get_xaxis().get_transform().base
285+
if base == 10:
286+
axis['range'] = [math.log10(props['xlim'][0]),
287+
math.log10(props['xlim'][1])]
288+
else:
289+
axis = dict(range=None, type='linear')
290+
warnings.warn("Converted non-base10 x-axis log scale to 'linear'")
291+
return axis
292+
else:
293+
return dict()
294+
295+
296+
def prep_y_ticks(ax, props):
297+
axis = dict()
298+
scale = props['axes'][1]['scale']
299+
if scale == 'linear':
300+
try:
301+
axis['tick0'] = props['axes'][1]['tickvalues'][0]
302+
axis['dtick'] = props['axes'][1]['tickvalues'][1] - \
303+
props['axes'][1]['tickvalues'][0]
304+
axis['autotick'] = False
305+
except (IndexError, TypeError):
306+
axis = dict(nticks=props['axes'][1]['nticks'])
307+
return axis
308+
elif scale == 'log':
309+
try:
310+
axis['tick0'] = props['axes'][1]['tickvalues'][0]
311+
axis['dtick'] = props['axes'][1]['tickvalues'][1] - \
312+
props['axes'][1]['tickvalues'][0]
313+
axis['autotick'] = False
314+
except (IndexError, TypeError):
315+
axis = dict(nticks=props['axes'][1]['nticks'])
316+
base = ax.get_yaxis().get_transform().base
317+
if base == 10:
318+
axis['range'] = [math.log10(props['ylim'][0]),
319+
math.log10(props['ylim'][1])]
320+
else:
321+
axis = dict(range=None, type='linear')
322+
warnings.warn("Converted non-base10 y-axis log scale to 'linear'")
323+
return axis
324+
else:
325+
return dict()
326+
327+
328+
def prep_xy_axis(ax, props, x_bounds, y_bounds):
329+
xaxis = dict(
330+
type=props['axes'][0]['scale'],
331+
range=props['xlim'],
332+
showgrid=props['axes'][0]['grid']['gridOn'],
333+
domain=convert_x_domain(props['bounds'], x_bounds),
334+
side=props['axes'][0]['position'],
335+
tickfont=dict(size=props['axes'][0]['fontsize'])
336+
)
337+
xaxis.update(prep_x_ticks(ax, props))
338+
yaxis = dict(
339+
type=props['axes'][1]['scale'],
340+
range=props['ylim'],
341+
showgrid=props['axes'][1]['grid']['gridOn'],
342+
domain=convert_y_domain(props['bounds'], y_bounds),
343+
side=props['axes'][1]['position'],
344+
tickfont=dict(size=props['axes'][1]['fontsize'])
345+
)
346+
yaxis.update(prep_y_ticks(ax, props))
347+
return xaxis, yaxis
348+
349+
262350
DASH_MAP = {
263351
'10,0': 'solid',
264352
'6,6': 'dash',

‎plotly/matplotlylib/renderer.py

Copy file name to clipboardExpand all lines: plotly/matplotlylib/renderer.py
+11-10Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -129,26 +129,27 @@ def open_axes(self, ax, props):
129129
"""
130130
self.msg += " Opening axes\n"
131131
self.axis_ct += 1
132+
# set defaults in axes
132133
xaxis = XAxis(
133-
range=props['xlim'],
134-
showgrid=props['axes'][1]['grid']['gridOn'],
135-
domain=mpltools.convert_x_domain(props['bounds'],
136-
self.mpl_x_bounds),
137134
anchor='y{}'.format(self.axis_ct),
138135
zeroline=False,
139136
showline=True,
140-
mirror=True,
137+
mirror='ticks',
141138
ticks='inside')
142139
yaxis = YAxis(
143-
range=props['ylim'],
144-
showgrid=props['axes'][0]['grid']['gridOn'],
145-
domain=mpltools.convert_y_domain(props['bounds'],
146-
self.mpl_y_bounds),
147140
anchor='x{}'.format(self.axis_ct),
148141
zeroline=False,
149142
showline=True,
150-
mirror=True,
143+
mirror='ticks',
151144
ticks='inside')
145+
# update defaults with things set in mpl
146+
mpl_xaxis, mpl_yaxis = mpltools.prep_xy_axis(ax=ax,
147+
props=props,
148+
x_bounds=self.mpl_x_bounds,
149+
y_bounds=self.mpl_y_bounds)
150+
xaxis.update(mpl_xaxis)
151+
yaxis.update(mpl_yaxis)
152+
# put axes in our figure
152153
self.plotly_fig['layout']['xaxis{}'.format(self.axis_ct)] = xaxis
153154
self.plotly_fig['layout']['yaxis{}'.format(self.axis_ct)] = yaxis
154155

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.