Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 5883c66

Browse files
committed
clabel can be called with approximate postions of labels
1 parent 396a644 commit 5883c66

4 files changed

Lines changed: 95 additions & 49 deletions

File tree

examples/pylab_examples/contour_demo.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@
3535
plt.title('Simplest default with labels')
3636

3737

38+
# contour labels can be placed manually by providing list of positions
39+
# (in data coordinate). See ginput_manual_clabel.py for interactive
40+
# placement.
41+
plt.figure()
42+
CS = plt.contour(X, Y, Z)
43+
manual_locations = [(-1, -1.4), (-0.62, -0.7), (-2, 0.5), (1.7, 1.2), (2.0, 1.4), (2.4, 1.7)]
44+
plt.clabel(CS, inline=1, fontsize=10, manual=manual_locations)
45+
plt.title('labels at selected locations')
46+
47+
3848
# You can force all the contours to be the same color.
3949
plt.figure()
4050
CS = plt.contour(X, Y, Z, 6,

examples/pylab_examples/contour_label_demo.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,11 @@ def __repr__(self):
5050
CS.levels = [nf(val) for val in CS.levels ]
5151

5252
# Label levels with specially formatted floats
53-
plt.clabel(CS, CS.levels, inline=True, fmt='%r %%', fontsize=10)
53+
if plt.rcParams["text.usetex"]:
54+
fmt = r'%r \%%'
55+
else:
56+
fmt = '%r %%'
57+
plt.clabel(CS, CS.levels, inline=True, fmt=fmt, fontsize=10)
5458

5559
##################################################
5660
# Label contours with arbitrary strings using a

lib/matplotlib/blocking_input.py

Lines changed: 5 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
"""
1919

2020
from __future__ import print_function
21-
from matplotlib import path, verbose
21+
from matplotlib import verbose
2222
from matplotlib.cbook import is_sequence_of_strings
2323
import matplotlib.lines as mlines
2424

@@ -306,52 +306,10 @@ def button1(self,event):
306306
"""
307307

308308
# Shorthand
309-
cs = self.cs
310-
311-
if event.inaxes == cs.ax:
312-
conmin,segmin,imin,xmin,ymin = cs.find_nearest_contour(
313-
event.x, event.y, cs.labelIndiceList)[:5]
314-
315-
# Get index of nearest level in subset of levels used for labeling
316-
lmin = cs.labelIndiceList.index(conmin)
317-
318-
# Coordinates of contour
319-
paths = cs.collections[conmin].get_paths()
320-
lc = paths[segmin].vertices
321-
322-
# In pixel/screen space
323-
slc = cs.ax.transData.transform(lc)
324-
325-
# Get label width for rotating labels and breaking contours
326-
lw = cs.get_label_width(cs.labelLevelList[lmin],
327-
cs.labelFmt, cs.labelFontSizeList[lmin])
328-
329-
"""
330-
# requires python 2.5
331-
# Figure out label rotation.
332-
rotation,nlc = cs.calc_label_rot_and_inline(
333-
slc, imin, lw, lc if self.inline else [],
334-
self.inline_spacing )
335-
"""
336-
# Figure out label rotation.
337-
if self.inline: lcarg = lc
338-
else: lcarg = None
339-
rotation,nlc = cs.calc_label_rot_and_inline(
340-
slc, imin, lw, lcarg,
341-
self.inline_spacing )
342-
343-
cs.add_label(xmin,ymin,rotation,cs.labelLevelList[lmin],
344-
cs.labelCValueList[lmin])
345-
346-
if self.inline:
347-
# Remove old, not looping over paths so we can do this up front
348-
paths.pop(segmin)
349-
350-
# Add paths if not empty or single point
351-
for n in nlc:
352-
if len(n)>1:
353-
paths.append( path.Path(n) )
354-
309+
if event.inaxes == self.cs.ax:
310+
self.cs.add_label_near(event.x, event.y, self.inline,
311+
inline_spacing=self.inline_spacing,
312+
transform=False)
355313
self.fig.canvas.draw()
356314
else: # Remove event if not valid
357315
BlockingInput.pop(self)

lib/matplotlib/contour.py

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ def clabel(self, *args, **kwargs):
110110
placement, delete or backspace act like the third mouse button,
111111
and any other key will select a label location).
112112
113+
*manual* can be an iterable object of x,y tuples. Contour labels
114+
will be created as if mouse is clicked at each x,y positions.
115+
113116
*rightside_up*:
114117
if *True* (default), label rotations will always be plus
115118
or minus 90 degrees from level.
@@ -197,7 +200,12 @@ def clabel(self, *args, **kwargs):
197200
#self.labelCValues = [] # same
198201
self.labelXYs = []
199202

200-
if self.labelManual:
203+
if cbook.iterable(self.labelManual):
204+
for x,y in self.labelManual:
205+
self.add_label_near(x, y, inline,
206+
inline_spacing)
207+
208+
elif self.labelManual:
201209
print('Select label locations manually using first mouse button.')
202210
print('End manual selection with second mouse button.')
203211
if not inline:
@@ -532,6 +540,72 @@ def add_label_clabeltext(self,x,y,rotation,lev,cvalue):
532540
self._add_label(t, x, y, lev, cvalue)
533541

534542

543+
def add_label_near(self, x, y, inline=True, inline_spacing=5,
544+
transform=None):
545+
"""
546+
Add a label near the point (x, y) of the given transform.
547+
If transform is None, data transform is used. If transform is
548+
False, IdentityTransform is used.
549+
550+
*inline*:
551+
controls whether the underlying contour is removed or
552+
not. Default is *True*.
553+
554+
*inline_spacing*:
555+
space in pixels to leave on each side of label when
556+
placing inline. Defaults to 5. This spacing will be
557+
exact for labels at locations where the contour is
558+
straight, less so for labels on curved contours.
559+
"""
560+
561+
if transform is None:
562+
transform = self.ax.transData
563+
564+
if transform:
565+
x,y = transform.transform_point((x, y))
566+
567+
conmin,segmin,imin,xmin,ymin = self.find_nearest_contour(
568+
x, y, self.labelIndiceList)[:5]
569+
570+
# Get index of nearest level in subset of levels used for labeling
571+
lmin = self.labelIndiceList.index(conmin)
572+
573+
# Coordinates of contour
574+
paths = self.collections[conmin].get_paths()
575+
lc = paths[segmin].vertices
576+
577+
# In pixel/screen space
578+
slc = self.ax.transData.transform(lc)
579+
580+
# Get label width for rotating labels and breaking contours
581+
lw = self.get_label_width(self.labelLevelList[lmin],
582+
self.labelFmt, self.labelFontSizeList[lmin])
583+
584+
"""
585+
# requires python 2.5
586+
# Figure out label rotation.
587+
rotation,nlc = cs.calc_label_rot_and_inline(
588+
slc, imin, lw, lc if self.inline else [],
589+
self.inline_spacing )
590+
"""
591+
# Figure out label rotation.
592+
if inline: lcarg = lc
593+
else: lcarg = None
594+
rotation,nlc = self.calc_label_rot_and_inline(
595+
slc, imin, lw, lcarg,
596+
inline_spacing )
597+
598+
self.add_label(xmin,ymin,rotation,self.labelLevelList[lmin],
599+
self.labelCValueList[lmin])
600+
601+
if inline:
602+
# Remove old, not looping over paths so we can do this up front
603+
paths.pop(segmin)
604+
605+
# Add paths if not empty or single point
606+
for n in nlc:
607+
if len(n)>1:
608+
paths.append( mpath.Path(n) )
535609

536610
def pop_label(self,index=-1):
537611
'''Defaults to removing last label, but any index can be supplied'''

0 commit comments

Comments
 (0)