"""
2010-06-30 16:00 IJC: Figuring out how to select a position at a given location.
For an example of how this works:
import clickinput
coords = clickinput.picktest()
print "You finally picked a location, at: ",coords
"""
import matplotlib.pyplot as plt
[docs]def picktest(zoom=10):
"""
Set up a small, simple test and run PICKLOC on it.
"""
setuptest()
out = pickloc(zoom=zoom)
return out
[docs]def setuptest():
"""
Set up a small, simple test with which to test PICKLOC.
"""
import numpy as np
f=plt.figure()
plt.imshow(np.random.randn(100,100),interpolation=None)
plt.plot([23],[66],'*k',ms=15)
plt.draw()
[docs]def pickloc(ax=None, zoom=10, resetaxes=False, titstr="click to select location"):
"""
:INPUTS:
ax : (axes instance)
axes in which to pick a location
zoom : int or 2-tuple
zoom radius for target confirmation in x,y or both
resetaxes : bool
whether to reset axes limits after selection
titstr : str
String to initially display at title of plot.
Press enter/return to exit out, returning -1
:NOTES:
Since I updated Matplotlib the "hit enter to exit"
functionality doesn't work. Need to fix that..
"""
# 2011-04-29 19:26 IJC:
# 2011-09-03 20:59 IJMC: Zoom can now be a tuple; x,y not cast as int.
# 2011-12-22 13:22 IJMC: On enter, exit out with -1
# 2012-08-18 19:53 IJMC: Cleaned up a bit more, added titstr,
# zoom=None works better now.
pickedloc = False
if ax is None:
ax = plt.gca()
axlimits = ax.axis()
if hasattr(zoom, '__iter__') and len(zoom)>1:
xzoom, yzoom = zoom
else:
xzoom = zoom
yzoom = zoom
while not pickedloc:
if titstr is not None:
ax.set_title(titstr)
ax.axis(axlimits)
x = None
while x is None:
selectevent = plt.ginput(n=1,show_clicks=False)
if len(selectevent)>0: # Prevent user from cancelling out.
x,y = selectevent[0]
else:
return -1
#x = x.astype(int)
#y = y.astype(int)
if zoom is None:
confirmevent = selectevent
pickedloc = True
else:
ax.axis([x-xzoom,x+xzoom,y-yzoom,y+yzoom])
ax.set_title("you selected xy=(%i,%i)\nclick again to confirm, or hit Enter/Return at the prompt to try again." %(x,y) )
plt.draw()
confirmevent = plt.ginput(n=1,show_clicks=False)
if len(confirmevent)>0:
pickedloc = True
loc = confirmevent[0]
if resetaxes:
ax.axis(axlimits)
plt.draw()
return loc
[docs]def fitparabola(*args, **kw):
"""Fit a parabola to a data vector.
INPUTS:
Either y, or x,y -- sequences of data
OPTIONS:
zoom : float or 2-sequence
radii for zoom confirmation.
xrange : float
+/- range of x values for data to use in fit
ax : matplotlib "axes" instance
Where to plot: if None, create a new figure
plotfit : bool
Whether to plot fitted data
OUTPUTS:
fit : 3-sequence
Best-fit parameters of parabola (suitable for
:func:`numpy.polyfit`)
REQUIREMENTS:
:module:`numpy`
"""
# 2011-09-03 21:20 IJMC: Created
import numpy as np
# Read options
defaults = dict(zoom=None, xrange=None, ax=None, plotfit=False)
for key in defaults:
if (not kw.has_key(key)):
kw[key] = defaults[key]
zoom = kw['zoom']
xrange = kw['xrange']
ax = kw['ax']
plotfit = kw['plotfit']
# Initialize data:
if len(args)==1:
x = np.array(args[0])
nx = x.size
y = np.arange(nx, dtype=float)
else:
x = np.array(args[0])
y = np.array(args[1])
nx = x.size
# Plot data
if ax is None:
f=plt.figure()
ax = plt.axes()
ax.plot(x, y, '-k')
# Select point:
x0, y0 = pickloc(zoom=zoom)
# Index data and fit:
index = (x > (x0 - xrange)) * (x < (x0 + xrange))
fit = np.polyfit(x[index], y[index], 2)
if plotfit:
ax.plot(x[index], y[index], 'r-')
ax.plot(x[index], np.polyval(fit, x[index]), 'og')
return fit