Skip to content

Commit 927631e

Browse files
committed
Merge pull request matplotlib#6431 from efiring/merge_from_v2.x
Merge from v2.x
2 parents 30d4ca5 + 6a9e968 commit 927631e

File tree

16 files changed

+190
-102
lines changed

16 files changed

+190
-102
lines changed

.travis.yml

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -77,16 +77,14 @@ install:
7777
pip install --upgrade wheel
7878
pip install --upgrade setuptools
7979
- |
80-
# Install dependencies
80+
# Install only from travis wheelhouse
8181
if [ -z "$PRE" ]; then
82-
# Install only from travis wheelhouse
83-
wheelhouse_pip_install $NUMPY $PANDAS;
82+
wheelhouse_pip_install python-dateutil $NUMPY $PANDAS pyparsing!=2.1.2 pillow sphinx!=1.3.0;
8483
else
85-
# Fall back to pypi for non suported python versions
86-
pip install $PRE $NUMPY $PANDAS;
84+
pip install $PRE python-dateutil $NUMPY pyparsing!=2.1.2 pillow sphinx!=1.3.0;
8785
fi
8886
# Always install from pypi
89-
pip install $PRE pep8 cycler coveralls coverage python-dateutil pyparsing!=2.0.4
87+
pip install $PRE pep8 cycler coveralls coverage
9088
pip install pillow sphinx!=1.3.0 $MOCK numpydoc ipython colorspacious
9189
# Install nose from a build which has partial
9290
# support for python36 and suport for coverage output suppressing

doc/users/whats_new/rcparams.rst

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
Configuration (rcParams)
22
------------------------
33

4-
+----------------------------+--------------------------------------------------+
5-
| Parameter | Description |
6-
+============================+==================================================+
7-
|`date.autoformatter.year` | foramt string for 'year' scale dates |
8-
+----------------------------+--------------------------------------------------+
9-
|`date.autoformatter.month` | format string for 'month' scale dates |
10-
+----------------------------+--------------------------------------------------+
11-
|`date.autoformatter.day` | format string for 'day' scale dates |
12-
+----------------------------+--------------------------------------------------+
13-
|`date.autoformatter.hour` | format string for 'hour' scale times |
14-
+----------------------------+--------------------------------------------------+
15-
|`date.autoformatter.minute` | format string for 'minute' scale times |
16-
+----------------------------+--------------------------------------------------+
17-
|`date.autoformatter.second` | format string for 'second' scale times |
18-
+----------------------------+--------------------------------------------------+
19-
|`scatter.marker` | default marker for scatter plot |
20-
+----------------------------+--------------------------------------------------+
21-
|`svg.hashsalt` | see note |
22-
+----------------------------+--------------------------------------------------+
4+
+---------------------------------+--------------------------------------------------+
5+
| Parameter | Description |
6+
+=================================+==================================================+
7+
|`date.autoformatter.year` | foramt string for 'year' scale dates |
8+
+---------------------------------+--------------------------------------------------+
9+
|`date.autoformatter.month` | format string for 'month' scale dates |
10+
+---------------------------------+--------------------------------------------------+
11+
|`date.autoformatter.day` | format string for 'day' scale dates |
12+
+---------------------------------+--------------------------------------------------+
13+
|`date.autoformatter.hour` | format string for 'hour' scale times |
14+
+---------------------------------+--------------------------------------------------+
15+
|`date.autoformatter.minute` | format string for 'minute' scale times |
16+
+---------------------------------+--------------------------------------------------+
17+
|`date.autoformatter.second` | format string for 'second' scale times |
18+
+---------------------------------+--------------------------------------------------+
19+
|`date.autoformatter.microsecond` | format string for 'microsecond' scale times |
20+
+---------------------------------+--------------------------------------------------+
21+
|`scatter.marker` | default marker for scatter plot |
22+
+---------------------------------+--------------------------------------------------+
23+
|`svg.hashsalt` | see note |
24+
+---------------------------------+--------------------------------------------------+
2325

2426
Added ``svg.hashsalt`` key to rcParams
2527
```````````````````````````````````````

lib/matplotlib/animation.py

Lines changed: 56 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,11 @@
3636
import abc
3737
import contextlib
3838
import tempfile
39+
import warnings
3940
from matplotlib.cbook import iterable, is_string_like
4041
from matplotlib.compat import subprocess
4142
from matplotlib import verbose
42-
from matplotlib import rcParams, rcParamsDefault
43+
from matplotlib import rcParams, rcParamsDefault, rc_context
4344

4445
# Process creation flag for subprocess to prevent it raising a terminal
4546
# window. See for example:
@@ -192,6 +193,11 @@ class MovieWriter(AbstractMovieWriter):
192193
frame_format: string
193194
The format used in writing frame data, defaults to 'rgba'
194195
'''
196+
197+
# Specifies whether the size of all frames need to be identical
198+
# i.e. whether we can use savefig.bbox = 'tight'
199+
frame_size_can_vary = False
200+
195201
def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,
196202
metadata=None):
197203
'''
@@ -210,8 +216,8 @@ def __init__(self, fps=5, codec=None, bitrate=None, extra_args=None,
210216
automatically by the underlying utility.
211217
extra_args: list of strings or None
212218
A list of extra string arguments to be passed to the underlying
213-
movie utiltiy. The default is None, which passes the additional
214-
argurments in the 'animation.extra_args' rcParam.
219+
movie utility. The default is None, which passes the additional
220+
arguments in the 'animation.extra_args' rcParam.
215221
metadata: dict of string:string or None
216222
A dictionary of keys and values for metadata to include in the
217223
output file. Some keys that may be of use include:
@@ -355,6 +361,11 @@ def isAvailable(cls):
355361

356362
class FileMovieWriter(MovieWriter):
357363
'`MovieWriter` subclass that handles writing to a file.'
364+
365+
# In general, if frames are writen to files on disk, it's not important
366+
# that they all be identically sized
367+
frame_size_can_vary = True
368+
358369
def __init__(self, *args, **kwargs):
359370
MovieWriter.__init__(self, *args, **kwargs)
360371
self.frame_format = rcParams['animation.frame_format']
@@ -491,15 +502,15 @@ class FFMpegBase(object):
491502

492503
@property
493504
def output_args(self):
494-
# The %dk adds 'k' as a suffix so that ffmpeg treats our bitrate as in
495-
# kbps
496505
args = ['-vcodec', self.codec]
497506
# For h264, the default format is yuv444p, which is not compatible
498507
# with quicktime (and others). Specifying yuv420p fixes playback on
499508
# iOS,as well as HTML5 video in firefox and safari (on both Win and
500509
# OSX). Also fixes internet explorer. This is as of 2015/10/29.
501510
if self.codec == 'h264' and '-pix_fmt' not in self.extra_args:
502511
args.extend(['-pix_fmt', 'yuv420p'])
512+
# The %dk adds 'k' as a suffix so that ffmpeg treats our bitrate as in
513+
# kbps
503514
if self.bitrate > 0:
504515
args.extend(['-b', '%dk' % self.bitrate])
505516
if self.extra_args:
@@ -794,8 +805,8 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
794805
`animation.bitrate`.
795806
796807
*extra_args* is a list of extra string arguments to be passed to the
797-
underlying movie utiltiy. The default is None, which passes the
798-
additional argurments in the 'animation.extra_args' rcParam.
808+
underlying movie utility. The default is None, which passes the
809+
additional arguments in the 'animation.extra_args' rcParam.
799810
800811
*metadata* is a dictionary of keys and values for metadata to include
801812
in the output file. Some keys that may be of use include:
@@ -815,29 +826,6 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
815826
if savefig_kwargs is None:
816827
savefig_kwargs = {}
817828

818-
# FIXME: Using 'bbox_inches' doesn't currently work with
819-
# writers that pipe the data to the command because this
820-
# requires a fixed frame size (see Ryan May's reply in this
821-
# thread: [1]). Thus we drop the 'bbox_inches' argument if it
822-
# exists in savefig_kwargs.
823-
#
824-
# [1] (http://matplotlib.1069221.n5.nabble.com/
825-
# Animation-class-let-save-accept-kwargs-which-
826-
# are-passed-on-to-savefig-td39627.html)
827-
#
828-
if 'bbox_inches' in savefig_kwargs:
829-
if not (writer in ['ffmpeg_file', 'mencoder_file'] or
830-
isinstance(writer,
831-
(FFMpegFileWriter, MencoderFileWriter))):
832-
print("Warning: discarding the 'bbox_inches' argument in "
833-
"'savefig_kwargs' as it is only currently supported "
834-
"with the writers 'ffmpeg_file' and 'mencoder_file' "
835-
"(writer used: "
836-
"'{0}').".format(
837-
writer if isinstance(writer, six.string_types)
838-
else writer.__class__.__name__))
839-
savefig_kwargs.pop('bbox_inches')
840-
841829
# Need to disconnect the first draw callback, since we'll be doing
842830
# draws. Otherwise, we'll end up starting the animation.
843831
if self._first_draw_id is not None:
@@ -881,7 +869,6 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
881869
extra_args=extra_args,
882870
metadata=metadata)
883871
else:
884-
import warnings
885872
warnings.warn("MovieWriter %s unavailable" % writer)
886873

887874
try:
@@ -895,22 +882,48 @@ def save(self, filename, writer=None, fps=None, dpi=None, codec=None,
895882

896883
verbose.report('Animation.save using %s' % type(writer),
897884
level='helpful')
885+
886+
# FIXME: Using 'bbox_inches' doesn't currently work with
887+
# writers that pipe the data to the command because this
888+
# requires a fixed frame size (see Ryan May's reply in this
889+
# thread: [1]). Thus we drop the 'bbox_inches' argument if it
890+
# exists in savefig_kwargs.
891+
#
892+
# [1] (http://matplotlib.1069221.n5.nabble.com/
893+
# Animation-class-let-save-accept-kwargs-which-
894+
# are-passed-on-to-savefig-td39627.html)
895+
#
896+
if 'bbox_inches' in savefig_kwargs and not writer.frame_size_can_vary:
897+
warnings.warn("Warning: discarding the 'bbox_inches' argument in "
898+
"'savefig_kwargs' as it not supported by "
899+
"{0}).".format(writer.__class__.__name__))
900+
savefig_kwargs.pop('bbox_inches')
901+
898902
# Create a new sequence of frames for saved data. This is different
899903
# from new_frame_seq() to give the ability to save 'live' generated
900904
# frame information to be saved later.
901905
# TODO: Right now, after closing the figure, saving a movie won't work
902906
# since GUI widgets are gone. Either need to remove extra code to
903-
# allow for this non-existant use case or find a way to make it work.
904-
with writer.saving(self._fig, filename, dpi):
905-
for anim in all_anim:
906-
# Clear the initial frame
907-
anim._init_draw()
908-
for data in zip(*[a.new_saved_frame_seq()
909-
for a in all_anim]):
910-
for anim, d in zip(all_anim, data):
911-
# TODO: Need to see if turning off blit is really necessary
912-
anim._draw_next_frame(d, blit=False)
913-
writer.grab_frame(**savefig_kwargs)
907+
# allow for this non-existent use case or find a way to make it work.
908+
with rc_context():
909+
# See above about bbox_inches savefig kwarg
910+
if (not writer.frame_size_can_vary and
911+
rcParams['savefig.bbox'] == 'tight'):
912+
verbose.report("Disabling savefig.bbox = 'tight', as it is "
913+
"not supported by "
914+
"{0}.".format(writer.__class__.__name__),
915+
level='helpful')
916+
rcParams['savefig.bbox'] = None
917+
with writer.saving(self._fig, filename, dpi):
918+
for anim in all_anim:
919+
# Clear the initial frame
920+
anim._init_draw()
921+
for data in zip(*[a.new_saved_frame_seq()
922+
for a in all_anim]):
923+
for anim, d in zip(all_anim, data):
924+
# TODO: See if turning off blit is really necessary
925+
anim._draw_next_frame(d, blit=False)
926+
writer.grab_frame(**savefig_kwargs)
914927

915928
# Reconnect signal for first draw if necessary
916929
if reconnect_first_draw:
@@ -1038,7 +1051,7 @@ def to_html5_video(self):
10381051
directly into the HTML5 video tag. This respects the rc parameters
10391052
for the writer as well as the bitrate. This also makes use of the
10401053
``interval`` to control the speed, and uses the ``repeat``
1041-
paramter to decide whether to loop.
1054+
parameter to decide whether to loop.
10421055
'''
10431056
VIDEO_TAG = r'''<video {size} {options}>
10441057
<source type="video/mp4" src="data:video/mp4;base64,{video}">

lib/matplotlib/axes/_base.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,8 @@ def __init__(self, fig, rect,
576576
self.tick_params(top=rcParams['xtick.top'],
577577
bottom=rcParams['xtick.bottom'],
578578
left=rcParams['ytick.left'],
579-
right=rcParams['ytick.right'])
579+
right=rcParams['ytick.right'],
580+
which='both')
580581

581582
def __setstate__(self, state):
582583
self.__dict__ = state

lib/matplotlib/backends/backend_qt5.py

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -751,13 +751,17 @@ def __init__(self, targetfig, parent):
751751

752752
self.defaults = {}
753753
for attr in ('left', 'bottom', 'right', 'top', 'wspace', 'hspace', ):
754-
self.defaults[attr] = getattr(self.targetfig.subplotpars, attr)
754+
val = getattr(self.targetfig.subplotpars, attr)
755+
self.defaults[attr] = val
755756
slider = getattr(self, 'slider' + attr)
757+
txt = getattr(self, attr + 'value')
756758
slider.setMinimum(0)
757759
slider.setMaximum(1000)
758760
slider.setSingleStep(5)
761+
# do this before hooking up the callbacks
762+
slider.setSliderPosition(int(val * 1000))
763+
txt.setText("%.2f" % val)
759764
slider.valueChanged.connect(getattr(self, 'func' + attr))
760-
761765
self._setSliderPositions()
762766

763767
def _setSliderPositions(self):
@@ -772,7 +776,7 @@ def funcleft(self, val):
772776
self.targetfig.subplots_adjust(left=val)
773777
self.leftvalue.setText("%.2f" % val)
774778
if self.drawon:
775-
self.targetfig.canvas.draw()
779+
self.targetfig.canvas.draw_idle()
776780

777781
def funcright(self, val):
778782
if val == self.sliderleft.value():
@@ -781,7 +785,7 @@ def funcright(self, val):
781785
self.targetfig.subplots_adjust(right=val)
782786
self.rightvalue.setText("%.2f" % val)
783787
if self.drawon:
784-
self.targetfig.canvas.draw()
788+
self.targetfig.canvas.draw_idle()
785789

786790
def funcbottom(self, val):
787791
if val == self.slidertop.value():
@@ -790,7 +794,7 @@ def funcbottom(self, val):
790794
self.targetfig.subplots_adjust(bottom=val)
791795
self.bottomvalue.setText("%.2f" % val)
792796
if self.drawon:
793-
self.targetfig.canvas.draw()
797+
self.targetfig.canvas.draw_idle()
794798

795799
def functop(self, val):
796800
if val == self.sliderbottom.value():
@@ -799,31 +803,31 @@ def functop(self, val):
799803
self.targetfig.subplots_adjust(top=val)
800804
self.topvalue.setText("%.2f" % val)
801805
if self.drawon:
802-
self.targetfig.canvas.draw()
806+
self.targetfig.canvas.draw_idle()
803807

804808
def funcwspace(self, val):
805809
val /= 1000.
806810
self.targetfig.subplots_adjust(wspace=val)
807811
self.wspacevalue.setText("%.2f" % val)
808812
if self.drawon:
809-
self.targetfig.canvas.draw()
813+
self.targetfig.canvas.draw_idle()
810814

811815
def funchspace(self, val):
812816
val /= 1000.
813817
self.targetfig.subplots_adjust(hspace=val)
814818
self.hspacevalue.setText("%.2f" % val)
815819
if self.drawon:
816-
self.targetfig.canvas.draw()
820+
self.targetfig.canvas.draw_idle()
817821

818822
def functight(self):
819823
self.targetfig.tight_layout()
820824
self._setSliderPositions()
821-
self.targetfig.canvas.draw()
825+
self.targetfig.canvas.draw_idle()
822826

823827
def reset(self):
824828
self.targetfig.subplots_adjust(**self.defaults)
825829
self._setSliderPositions()
826-
self.targetfig.canvas.draw()
830+
self.targetfig.canvas.draw_idle()
827831

828832

829833
def error_msg_qt(msg, parent=None):

lib/matplotlib/cbook.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1452,8 +1452,8 @@ def issubclass_safe(x, klass):
14521452
return False
14531453

14541454

1455-
def safe_masked_invalid(x):
1456-
x = np.asanyarray(x)
1455+
def safe_masked_invalid(x, copy=False):
1456+
x = np.array(x, subok=True, copy=copy)
14571457
try:
14581458
xm = np.ma.masked_invalid(x, copy=False)
14591459
xm.shrink_mask()

lib/matplotlib/contour.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,7 +1133,7 @@ def changed(self):
11331133
# add label colors
11341134
cm.ScalarMappable.changed(self)
11351135

1136-
def _autolev(self, z, N):
1136+
def _autolev(self, N):
11371137
"""
11381138
Select contour levels to span the data.
11391139
@@ -1169,12 +1169,12 @@ def _contour_level_args(self, z, args):
11691169
self._auto = False
11701170
if self.levels is None:
11711171
if len(args) == 0:
1172-
lev = self._autolev(z, 7)
1172+
lev = self._autolev(7)
11731173
else:
11741174
level_arg = args[0]
11751175
try:
11761176
if type(level_arg) == int:
1177-
lev = self._autolev(z, level_arg)
1177+
lev = self._autolev(level_arg)
11781178
else:
11791179
lev = np.asarray(level_arg).astype(np.float64)
11801180
except:
@@ -1547,12 +1547,12 @@ def _contour_args(self, args, kwargs):
15471547
raise TypeError("Too many arguments to %s; see help(%s)" %
15481548
(fn, fn))
15491549
z = ma.masked_invalid(z, copy=False)
1550-
self.zmax = ma.maximum(z)
1551-
self.zmin = ma.minimum(z)
1550+
self.zmax = float(z.max())
1551+
self.zmin = float(z.min())
15521552
if self.logscale and self.zmin <= 0:
15531553
z = ma.masked_where(z <= 0, z)
15541554
warnings.warn('Log scale: values of z <= 0 have been masked')
1555-
self.zmin = z.min()
1555+
self.zmin = float(z.min())
15561556
self._contour_level_args(z, args)
15571557
return (x, y, z)
15581558

0 commit comments

Comments
 (0)