Crosshai cursor or Selector with matplotlib.backends.backend_wxagg

Dear all,

after looking around for a plotting library I found Matplotlib and I tried to create a gray scale image in a wxpython application. Looks good!

Now I have to find a line in the image with mainly vertical orientation. To do this a crosshair cursor would be fine. In Pylab I found a SpanSelector which also looks promising.

Unfortunately I failed in adding a crosshair cursor or a SpanSelector into my wxpython application figure.

Does anyone have an example add hand showing me how to achieve this?
Thanks and
Best regards
Reinhard

This may be more than you asked for…

I have a Toolbar subclass that adds a button to graphically select a subset from the data, its sort of similar to the zoom tool only it doesnt zoom. This is specific to Qt4, but maybe you will find it useful. Toolbar._init_toolbar adds a “Select” action, which is wired so that one corner of a rectangle is defined by the mouse press, the opposite by the mouse release:

class Toolbar(MplToolbar):

def init(self, *args, **kwargs):

pixmap = QtGui.QPixmap()

pixmap.load(‘:/cross.png’)

mplCursors.SELECT_POINT = pixmap

super(Toolbar, self).init(*args, **kwargs)

def _init_toolbar(self):

self.basedir = os.path.join(mpl.rcParams[ ‘datapath’ ],‘images’)

a = self.addAction(self._icon(‘home.svg’), ‘Home’, self.home)

a.setToolTip(‘Reset original view’)

a = self.addAction(self._icon(‘back.svg’), ‘Back’, self.back)

a.setToolTip(‘Back to previous view’)

a = self.addAction(self._icon(‘forward.svg’), ‘Forward’, self.forward)

a.setToolTip(‘Forward to next view’)

self.addSeparator()

a = self.addAction(self._icon(‘move.svg’), ‘Pan’, self.pan)

a.setToolTip(‘Pan axes with left mouse, zoom with right’)

a = self.addAction(self._icon(‘zoom_to_rect.svg’), ‘Zoom’, self.zoom)

a.setToolTip(‘Zoom to rectangle’)

a = self.addAction(QtGui.QIcon(‘:/crosshairs.svg’), ‘Select’,

self.selectPointMode)

a.setToolTip(‘Select the nearest data point’)

self.addSeparator()

a = self.addAction(self._icon(‘subplots.png’), ‘Subplots’,

self.configure_subplots)

a.setToolTip(‘Configure subplots’)

a = self.addAction(self._icon(‘filesave.svg’), ‘Save’,

self.save_figure)

a.setToolTip(‘Save the figure’)

self.buttons = {}

Add the x,y location widget at the right side of the toolbar

The stretch factor is 1 which means any resizing of the toolbar

will resize this label instead of the buttons.

if self.coordinates:

self.locLabel = QtGui.QLabel( “”, self )

self.locLabel.setAlignment(

QtCore.Qt.AlignRight | QtCore.Qt.AlignTop )

self.locLabel.setSizePolicy(

QtGui.QSizePolicy(QtGui.QSizePolicy.Expanding,

QtGui.QSizePolicy.Ignored))

labelAction = self.addWidget(self.locLabel)

labelAction.setVisible(True)

reference holder for subplots_adjust window

self.adj_window = None

def mouse_move(self, event):

#print ‘mouse_move’, event.button

if not event.inaxes or not self._active:

if self._lastCursor != mplCursors.POINTER:

self.set_cursor(mplCursors.POINTER)

self._lastCursor = mplCursors.POINTER

else:

if self._active==‘ZOOM’:

if self._lastCursor != mplCursors.SELECT_REGION:

self.set_cursor(mplCursors.SELECT_REGION)

self._lastCursor = mplCursors.SELECT_REGION

if self._xypress:

x, y = event.x, event.y

lastx, lasty, a, ind, lim, trans = self._xypress[0]

self.draw_rubberband(event, x, y, lastx, lasty)

elif (self._active==‘PAN’ and

self._lastCursor != mplCursors.MOVE):

self.set_cursor(mplCursors.MOVE)

self._lastCursor = mplCursors.MOVE

elif self._active==‘SELECT’:

if self._lastCursor != mplCursors.SELECT_POINT:

QtGui.QApplication.restoreOverrideCursor()

QtGui.QApplication.setOverrideCursor(

QtGui.QCursor(mplCursors.SELECT_POINT))

self._lastCursor = mplCursors.SELECT_POINT

if event.inaxes and event.inaxes.get_navigate():

try: s = event.inaxes.format_coord(event.xdata, event.ydata)

except ValueError: pass

except OverflowError: pass

else:

if len(self.mode):

self.set_message(‘%s : %s’ % (self.mode, s))

else:

self.set_message(s)

else: self.set_message(self.mode)

def selectPointMode(self, *args):

if self._active == ‘SELECT’:

self._active = None

else:

self._active = ‘SELECT’

if self._idPress is not None:

self._idPress = self.canvas.mpl_disconnect(self._idPress)

self.mode = ‘’

if self._idRelease is not None:

self._idRelease = self.canvas.mpl_disconnect(self._idRelease)

self.mode = ‘’

if self._active:

self._idRelease = self.canvas.mpl_connect(

‘button_press_event’, self.selectPoint)

self.mode = ‘pixel select mode’

self.canvas.widgetlock(self)

else:

self.canvas.widgetlock.release(self)

self.set_message(self.mode)

def selectPoint(self, event):

if event.inaxes and event.inaxes.get_navigate():

self.xdatastart=event.xdata

self.ydatastart=event.ydata

self.xstart=event.x

self.ystart=event.y

self._banddraw = self.canvas.mpl_connect(

‘motion_notify_event’,self.drawband)

self._idRelease = self.canvas.mpl_disconnect(self._idRelease)

self._idRelease = self.canvas.mpl_connect(

‘button_release_event’, self.selectSecondPoint)

def selectSecondPoint(self, event):

if event.inaxes and event.inaxes.get_navigate():

self._banddraw=self.canvas.mpl_disconnect(self._banddraw)

self._idRelease = self.canvas.mpl_disconnect(self._idRelease)

self._idRelease = self.canvas.mpl_connect(

‘button_press_event’, self.selectPoint)

self.draw_rubberband(event, 0, 0, 0, 0)

self.emit(

QtCore.SIGNAL(‘pickEvent’),

self.xdatastart,

self.ydatastart,

event.xdata,

event.ydata

)

def drawband(self, event):

self.draw_rubberband(event,self.xstart, self.ystart, event.x, event.y)

The mouse release calls selectSecondPoint, which emits a signal containing the x and y start and end data. That gets routed to the onPick method on my Qt4Canvas instance:

def onPick(self, xstart, ystart, xend, yend):

xstart_i, ystart_i = self.getIndices(xstart, ystart)

xend_i, yend_i = self.getIndices(xend, yend)

if xstart_i > xend_i: xstart_i, xend_i = xend_i, xstart_i

if ystart_i > yend_i: ystart_i, yend_i = yend_i, ystart_i

try:

indices = self.indices[ystart_i:yend_i+1, xstart_i:xend_i+1]

self.emit(QtCore.SIGNAL(‘pickEvent’), indices.flatten())

except TypeError:

pass

which determines the indices of my data that are contained within the region defined by the user:

def getIndices(self, xdata, ydata):

xIndex = locateClosest(xdata, self.xPixelLocs)

yIndex = locateClosest(ydata, self.yPixelLocs)

return xIndex, yIndex

def locateClosest(point, points):

compare = numpy.abs(points-point)

return numpy.nonzero(numpy.ravel(compare==compare.min()))[0]

···

On Tuesday 11 November 2008 09:03:30 am jansohn@…2379… wrote:

Dear all,

after looking around for a plotting library I found Matplotlib and I tried

to create a gray scale image in a wxpython application. Looks good!

Now I have to find a line in the image with mainly vertical orientation. To

do this a crosshair cursor would be fine. In Pylab I found a SpanSelector

which also looks promising.

Unfortunately I failed in adding a crosshair cursor or a SpanSelector into

my wxpython application figure.

Does anyone have an example add hand showing me how to achieve this?