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

Skip to content

Commit 7c9e70a

Browse files
committed
Making a number of changes related to "blocking" stuff:
1) Adding to cbook.py a method is_sequence_of_strings that is then used in BlockingInput to test for a tuple-like sequence of event names 2) Modified the use of *fmt* in clabel so that it an also be a dictionary matching contour levels to arbitrary strings. 3) Removing the extraneous np.array or np.asarray commands in ContourLabeler as they were forcing linecontour to array, but linecontour should already be an array. 4) In blocking_input.py replacing all print commands with calls to matplotlib.verbose.report 5) Removing extra cleanup call from BlockingInput as finally is always executed, regardless of exception status. 6) Removing what appears to be a "patch" command screwup - there were two versions of several of the Blocking* classes in blocking_input.py svn path=/trunk/matplotlib/; revision=5786
1 parent 53aafbf commit 7c9e70a

4 files changed

Lines changed: 43 additions & 217 deletions

File tree

lib/matplotlib/blocking_input.py

Lines changed: 15 additions & 203 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@
1919

2020
import time
2121
import numpy as np
22-
import matplotlib.path as path
22+
from matplotlib import path, verbose
23+
from cbook import is_sequence_of_strings
2324

2425
class BlockingInput(object):
2526
"""
@@ -28,7 +29,7 @@ class BlockingInput(object):
2829
"""
2930
def __init__(self, fig, eventslist=()):
3031
self.fig = fig
31-
assert isinstance(eventslist, tuple), "Requires a tuple of event name strings"
32+
assert is_sequence_of_strings(eventslist), "Requires a sequence of event name strings"
3233
self.eventslist = eventslist
3334

3435
def on_event(self, event):
@@ -41,8 +42,7 @@ def on_event(self, event):
4142
# subclasses
4243
self.add_event(event)
4344

44-
if self.verbose:
45-
print "Event %i" % len(self.events)
45+
verbose.report("Event %i" % len(self.events))
4646

4747
# This will extract info from events
4848
self.post_event()
@@ -80,7 +80,7 @@ def pop(self,index=-1):
8080
self.pop_event(index)
8181
pop.__doc__=pop_event.__doc__
8282

83-
def __call__(self, n=1, timeout=30, verbose=False ):
83+
def __call__(self, n=1, timeout=30 ):
8484
"""
8585
Blocking call to retrieve n events
8686
"""
@@ -90,7 +90,6 @@ def __call__(self, n=1, timeout=30, verbose=False ):
9090

9191
self.events = []
9292
self.done = False
93-
self.verbose = verbose
9493
self.callbacks = []
9594

9695
# Ensure that the figure is shown
@@ -112,12 +111,10 @@ def __call__(self, n=1, timeout=30, verbose=False ):
112111
if timeout > 0 and counter > timeout/0.01:
113112
print "Timeout reached";
114113
break;
115-
finally: # Activated on exception like ctrl-c
114+
finally: # Run even on exception like ctrl-c
115+
# Disconnect the callbacks
116116
self.cleanup()
117117

118-
# Disconnect the callbacks
119-
self.cleanup()
120-
121118
# Return the events in this case
122119
return self.events
123120

@@ -196,9 +193,9 @@ def add_click(self,event):
196193
This add the coordinates of an event to the list of clicks
197194
"""
198195
self.clicks.append((event.xdata,event.ydata))
199-
if self.verbose:
200-
print "input %i: %f,%f" % (len(self.clicks),
201-
event.xdata, event.ydata)
196+
197+
verbose.report("input %i: %f,%f" %
198+
(len(self.clicks),event.xdata, event.ydata))
202199

203200
# If desired plot up click
204201
if self.show_clicks:
@@ -238,15 +235,15 @@ def cleanup(self):
238235
# Call base class to remove callbacks
239236
BlockingInput.cleanup(self)
240237

241-
def __call__(self, n=1, timeout=30, verbose=False, show_clicks=True):
238+
def __call__(self, n=1, timeout=30, show_clicks=True):
242239
"""
243240
Blocking call to retrieve n coordinate pairs through mouse
244241
clicks.
245242
"""
246243
self.show_clicks = show_clicks
247244
self.clicks = []
248245
self.marks = []
249-
BlockingInput.__call__(self,n=n,timeout=timeout,verbose=verbose)
246+
BlockingInput.__call__(self,n=n,timeout=timeout)
250247

251248
return self.clicks
252249

@@ -324,7 +321,7 @@ def button3(self,event):
324321

325322
def __call__(self,inline,n=-1,timeout=-1):
326323
self.inline=inline
327-
BlockingMouseInput.__call__(self,n=n,timeout=timeout,verbose=False,
324+
BlockingMouseInput.__call__(self,n=n,timeout=timeout,
328325
show_clicks=False)
329326

330327
class BlockingKeyMouseInput(BlockingInput):
@@ -343,198 +340,13 @@ def post_event(self):
343340

344341
self.keyormouse = self.events[-1].name == 'key_press_event'
345342

346-
def __call__(self, timeout=30, verbose=False):
347-
"""
348-
Blocking call to retrieve a single mouse or key click
349-
Returns True if key click, False if mouse, or None if timeout
350-
"""
351-
self.keyormouse = None
352-
BlockingInput.__call__(self,n=1,timeout=timeout,verbose=verbose)
353-
354-
return self.keyormouse
355-
356-
"""
357-
This provides several classes used for interaction with figure windows:
358-
359-
:class:`BlockingInput`
360-
creates a callable object to retrieve events in a blocking way for interactive sessions
361-
362-
:class:`BlockingKeyMouseInput`
363-
creates a callable object to retrieve key or mouse clicks in a blocking way for interactive sessions.
364-
Note: Subclass of BlockingInput. Used by waitforbuttonpress
365-
366-
:class:`BlockingMouseInput`
367-
creates a callable object to retrieve mouse clicks in a blocking way for interactive sessions.
368-
Note: Subclass of BlockingInput. Used by ginput
369-
"""
370-
371-
import time
372-
373-
class BlockingInput(object):
374-
"""
375-
Class that creates a callable object to retrieve events in a
376-
blocking way.
377-
"""
378-
def __init__(self, fig, eventslist=()):
379-
self.fig = fig
380-
assert isinstance(eventslist, tuple), \
381-
"Requires a tuple of event name strings"
382-
self.eventslist = eventslist
383-
384-
def on_event(self, event):
385-
"""
386-
Event handler that will be passed to the current figure to
387-
retrieve events.
388-
"""
389-
self.events.append(event)
390-
391-
if self.verbose:
392-
print "Event %i" % len(self.events)
393-
394-
# This will extract info from events
395-
self.post_event()
396-
397-
if len(self.events) >= self.n and self.n > 0:
398-
self.done = True
399-
400-
def post_event(self):
401-
"""For baseclass, do nothing but collect events"""
402-
pass
403-
404-
def cleanup(self):
405-
"""Remove callbacks"""
406-
for cb in self.callbacks:
407-
self.fig.canvas.mpl_disconnect(cb)
408-
409-
self.callbacks=[]
410-
411-
def __call__(self, n=1, timeout=30, verbose=False ):
412-
"""
413-
Blocking call to retrieve n events
414-
"""
415-
416-
assert isinstance(n, int), "Requires an integer argument"
417-
self.n = n
418-
419-
self.events = []
420-
self.done = False
421-
self.verbose = verbose
422-
self.callbacks = []
423-
424-
# Ensure that the figure is shown
425-
self.fig.show()
426-
427-
# connect the events to the on_event function call
428-
for n in self.eventslist:
429-
self.callbacks.append( self.fig.canvas.mpl_connect(n, self.on_event) )
430-
431-
try:
432-
# wait for n clicks
433-
counter = 0
434-
while not self.done:
435-
self.fig.canvas.flush_events()
436-
time.sleep(0.01)
437-
438-
# check for a timeout
439-
counter += 1
440-
if timeout > 0 and counter > timeout/0.01:
441-
print "Timeout reached";
442-
break;
443-
finally: # Activated on exception like ctrl-c
444-
self.cleanup()
445-
446-
# Disconnect the callbacks
447-
self.cleanup()
448-
449-
# Return the events in this case
450-
return self.events
451-
452-
class BlockingMouseInput(BlockingInput):
453-
"""
454-
Class that creates a callable object to retrieve mouse clicks in a
455-
blocking way.
456-
"""
457-
def __init__(self, fig):
458-
BlockingInput.__init__(self, fig=fig, eventslist=('button_press_event',) )
459-
460-
def post_event(self):
461-
"""
462-
This will be called to process events
463-
"""
464-
assert len(self.events)>0, "No events yet"
465-
466-
event = self.events[-1]
467-
468-
if event.button == 3:
469-
# If it's a right click, pop the last coordinates.
470-
if len(self.clicks) > 0:
471-
self.clicks.pop()
472-
del self.events[-2:] # Remove button=3 event and previous event
473-
474-
if self.show_clicks:
475-
mark = self.marks.pop()
476-
mark.remove()
477-
self.fig.canvas.draw()
478-
elif event.button == 2 and self.n < 0:
479-
# If it's a middle click, and we are in infinite mode, finish
480-
self.done = True
481-
elif event.inaxes:
482-
# If it's a valid click, append the coordinates to the list
483-
self.clicks.append((event.xdata, event.ydata))
484-
if self.verbose:
485-
print "input %i: %f,%f" % (len(self.clicks),
486-
event.xdata, event.ydata)
487-
if self.show_clicks:
488-
self.marks.extend(
489-
event.inaxes.plot([event.xdata,], [event.ydata,], 'r+') )
490-
self.fig.canvas.draw()
491-
492-
def cleanup(self):
493-
# clean the figure
494-
if self.show_clicks:
495-
for mark in self.marks:
496-
mark.remove()
497-
self.marks = []
498-
self.fig.canvas.draw()
499-
500-
# Call base class to remove callbacks
501-
BlockingInput.cleanup(self)
502-
503-
def __call__(self, n=1, timeout=30, verbose=False, show_clicks=True):
504-
"""
505-
Blocking call to retrieve n coordinate pairs through mouse
506-
clicks.
507-
"""
508-
self.show_clicks = show_clicks
509-
self.clicks = []
510-
self.marks = []
511-
BlockingInput.__call__(self,n=n,timeout=timeout,verbose=verbose)
512-
513-
return self.clicks
514-
515-
class BlockingKeyMouseInput(BlockingInput):
516-
"""
517-
Class that creates a callable object to retrieve a single mouse or
518-
keyboard click
519-
"""
520-
def __init__(self, fig):
521-
BlockingInput.__init__(self, fig=fig, eventslist=('button_press_event','key_press_event') )
522-
523-
def post_event(self):
524-
"""
525-
Determines if it is a key event
526-
"""
527-
assert len(self.events)>0, "No events yet"
528-
529-
self.keyormouse = self.events[-1].name == 'key_press_event'
530-
531-
def __call__(self, timeout=30, verbose=False):
343+
def __call__(self, timeout=30):
532344
"""
533345
Blocking call to retrieve a single mouse or key click
534346
Returns True if key click, False if mouse, or None if timeout
535347
"""
536348
self.keyormouse = None
537-
BlockingInput.__call__(self,n=1,timeout=timeout,verbose=verbose)
349+
BlockingInput.__call__(self,n=1,timeout=timeout)
538350

539351
return self.keyormouse
540352

lib/matplotlib/cbook.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,15 @@ def is_string_like(obj):
270270
except (TypeError, ValueError): return 0
271271
return 1
272272

273+
def is_sequence_of_strings(obj):
274+
"""
275+
Returns true if *obj* is iterable and contains strings
276+
"""
277+
if not iterable(obj): return False
278+
for o in obj:
279+
if not is_string_like(o): return False
280+
return True
281+
273282
def is_writable_file_like(obj):
274283
'return true if *obj* looks like a file object with a *write* method'
275284
return hasattr(obj, 'write') and callable(obj.write)

lib/matplotlib/contour.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ def clabel(self, *args, **kwargs):
7171
7272
*fmt*:
7373
a format string for the label. Default is '%1.3f'
74+
Alternatively, this can be a dictionary matching contour
75+
levels with arbitrary strings to use for each contour level
76+
(i.e., fmt[level]=string)
7477
7578
*manual*:
7679
if *True*, contour labels will be placed manually using
@@ -158,10 +161,10 @@ def print_label(self, linecontour,labelwidth):
158161
if lcsize > 10 * labelwidth:
159162
return 1
160163

161-
xmax = np.amax(np.array(linecontour)[:,0])
162-
xmin = np.amin(np.array(linecontour)[:,0])
163-
ymax = np.amax(np.array(linecontour)[:,1])
164-
ymin = np.amin(np.array(linecontour)[:,1])
164+
xmax = np.amax(linecontour[:,0])
165+
xmin = np.amin(linecontour[:,0])
166+
ymax = np.amax(linecontour[:,1])
167+
ymin = np.amin(linecontour[:,1])
165168

166169
lw = labelwidth
167170
if (xmax - xmin) > 1.2* lw or (ymax - ymin) > 1.2 * lw:
@@ -210,7 +213,7 @@ def get_label_width(self, lev, fmt, fsize):
210213
if cbook.is_string_like(lev):
211214
lw = (len(lev)) * fsize
212215
else:
213-
lw = (len(fmt%lev)) * fsize
216+
lw = (len(self.get_text(lev,fmt))) * fsize
214217

215218
return lw
216219

@@ -227,8 +230,10 @@ def get_text(self, lev, fmt):
227230
if cbook.is_string_like(lev):
228231
return lev
229232
else:
230-
return fmt%lev
231-
233+
if isinstance(fmt,dict):
234+
return fmt[lev]
235+
else:
236+
return fmt%lev
232237

233238
def break_linecontour(self, linecontour, rot, labelwidth, ind):
234239
"break a contour in two contours at the location of the label"
@@ -243,8 +248,8 @@ def break_linecontour(self, linecontour, rot, labelwidth, ind):
243248

244249
slc = trans.transform(linecontour)
245250
x,y = slc[ind]
246-
xx= np.asarray(slc)[:,0].copy()
247-
yy=np.asarray(slc)[:,1].copy()
251+
xx=slc[:,0].copy()
252+
yy=slc[:,1].copy()
248253

249254
#indices which are under the label
250255
inds, = np.nonzero(((xx < x+xlabel) & (xx > x-xlabel)) &
@@ -325,8 +330,8 @@ def locate_label(self, linecontour, labelwidth):
325330
else:
326331
ysize = labelwidth
327332

328-
XX = np.resize(np.asarray(linecontour)[:,0],(xsize, ysize))
329-
YY = np.resize(np.asarray(linecontour)[:,1],(xsize, ysize))
333+
XX = np.resize(linecontour[:,0],(xsize, ysize))
334+
YY = np.resize(linecontour[:,1],(xsize, ysize))
330335
#I might have fouled up the following:
331336
yfirst = YY[:,0].reshape(xsize, 1)
332337
ylast = YY[:,-1].reshape(xsize, 1)

0 commit comments

Comments
 (0)