4 @brief Base classes for iinteractive plotting using PyPlot
10 (C) 2011 by the GRASS Development Team
12 This program is free software under the GNU General Public License
13 (>=v2). Read the file COPYING that comes with GRASS for details.
15 @author Michael Barton, Arizona State University
22 import wx.lib.plot
as plot
28 from icons.icon
import MetaIcon
34 'draw' : MetaIcon(img =
'show',
35 label = _(
'Draw/re-draw plot')),
36 'transect' : MetaIcon(img =
'layer-raster-profile',
37 label = _(
'Draw transect in map display window to profile')),
38 'options' : MetaIcon(img =
'settings',
39 label = _(
'Plot options')),
40 'statistics' : MetaIcon(img =
'check',
41 label = _(
'Plot statistics')),
42 'save' : MetaIcon(img =
'save',
43 label = _(
'Save profile data to CSV file')),
44 'quit' : BaseIcons[
'quit'].SetLabel(_(
'Quit plot tool')),
48 """!Abstract PyPlot display frame class"""
49 def __init__(self, parent = None, id = wx.ID_ANY, size = wx.Size(700, 400),
50 style = wx.DEFAULT_FRAME_STYLE, rasterList = [], **kwargs):
52 wx.Frame.__init__(self, parent, id, size = size, style = style, **kwargs)
63 'long-dash' : wx.LONG_DASH,
64 'short-dash' : wx.SHORT_DASH,
65 'dot-dash' : wx.DOT_DASH }
73 self.SetIcon(wx.Icon(os.path.join(ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
78 self.
statusbar = self.CreateStatusBar(number = 2, style = 0)
79 self.statusbar.SetStatusWidths([-2, -1])
94 self.client.canvas.Bind(wx.EVT_MOTION, self.
OnMotion)
107 self.CentreOnScreen()
112 def _createColorDict(self):
113 """!Create color dictionary to return wx.Colour tuples
114 for assigning colors to images in imagery groups"""
117 for clr
in grass.named_colors.iterkeys():
118 if clr ==
'white' or clr ==
'black':
continue
119 r = grass.named_colors[clr][0] * 255
120 g = grass.named_colors[clr][1] * 255
121 b = grass.named_colors[clr][2] * 255
125 """!Initialize options for entire plot
131 self.
properties[
'font'][
'prop'] = UserSettings.Get(group = self.
plottype, key =
'font')
132 self.
properties[
'font'][
'wxfont'] = wx.Font(11, wx.FONTFAMILY_SWISS,
134 wx.FONTWEIGHT_NORMAL)
138 colstr = str(self.
properties[
'raster'][
'pcolor'])
139 self.
properties[
'raster'][
'pcolor'] = tuple(int(colval)
for colval
in colstr.strip(
'()').
split(
','))
144 colstr = str(self.
properties[
'marker'][
'color'])
145 self.
properties[
'marker'][
'color'] = tuple(int(colval)
for colval
in colstr.strip(
'()').
split(
','))
149 colstr = str(self.
properties[
'grid'][
'color'])
150 self.
properties[
'grid'][
'color'] = tuple(int(colval)
for colval
in colstr.strip(
'()').
split(
','))
153 self.
properties[
'x-axis'][
'prop'] = UserSettings.Get(group = self.
plottype, key =
'x-axis')
157 self.
properties[
'y-axis'][
'prop'] = UserSettings.Get(group = self.
plottype, key =
'y-axis')
164 self.client.SetShowScrollbars(
True)
167 self.client.setLogScale((
False,
False))
169 self.client.SetXSpec(self.
properties[
'x-axis'][
'prop'][
'type'])
171 self.client.SetXSpec(
'auto')
174 self.client.SetYSpec(self.
properties[
'y-axis'][
'prop'][
'type'])
176 self.client.SetYSpec(
'auto')
179 """!Initialize or update raster dictionary for plotting
187 idx = rasterList.index(r)
190 ret = grass.raster_info(r)
198 rdict[r][
'units'] =
''
199 if ret[
'units']
not in (
'(none)',
'"none"',
'',
None):
200 rdict[r][
'units'] = ret[
'units']
202 rdict[r][
'plegend'] = r.split(
'@')[0]
203 rdict[r][
'datalist'] = []
204 rdict[r][
'pline'] =
None
205 rdict[r][
'datatype'] = ret[
'datatype']
210 if self.
properties[
'raster'][
'pwidth'] !=
None:
211 rdict[r][
'pwidth'] = self.
properties[
'raster'][
'pwidth']
213 rdict[r][
'pwidth'] = 1
215 if self.
properties[
'raster'][
'pstyle'] !=
None and \
217 rdict[r][
'pstyle'] = self.
properties[
'raster'][
'pstyle']
219 rdict[r][
'pstyle'] =
'solid'
221 if idx <= len(self.colorList):
224 if self.
properties[
'raster'][
'pcolor'] !=
None:
225 rdict[r][
'pcolor'] = self.
properties[
'raster'][
'pcolor']
227 rdict[r][
'pcolor'] = self.
colorDict[self.colorList[idx]]
229 rdict[r][
'pcolor'] = self.
colorDict[self.colorList[idx]]
234 rdict[r][
'pcolor'] = ((r,g,b,255))
239 """!Set plot and text options
241 self.client.SetFont(self.
properties[
'font'][
'wxfont'])
242 self.client.SetFontSizeTitle(self.
properties[
'font'][
'prop'][
'titleSize'])
243 self.client.SetFontSizeAxis(self.
properties[
'font'][
'prop'][
'axisSize'])
245 self.client.SetEnableZoom(self.
zoom)
246 self.client.SetEnableDrag(self.
drag)
251 if self.
properties[
'x-axis'][
'prop'][
'type'] ==
'custom':
252 self.client.SetXSpec(
'min')
254 self.client.SetXSpec(self.
properties[
'x-axis'][
'prop'][
'type'])
256 if self.
properties[
'y-axis'][
'prop'][
'type'] ==
'custom':
257 self.client.SetYSpec(
'min')
259 self.client.SetYSpec(self.
properties[
'y-axis'][
'prop'])
261 if self.
properties[
'x-axis'][
'prop'][
'type'] ==
'custom' and \
268 if self.
properties[
'y-axis'][
'prop'][
'type'] ==
'custom' and \
275 if self.
properties[
'x-axis'][
'prop'][
'log'] ==
True:
277 self.client.SetXSpec(
'min')
278 if self.
properties[
'y-axis'][
'prop'][
'log'] ==
True:
280 self.client.SetYSpec(
'min')
282 self.client.setLogScale((self.
properties[
'x-axis'][
'prop'][
'log'],
288 self.client.SetEnableGrid(self.
properties[
'grid'][
'enabled'])
290 self.client.SetGridColour(wx.Colour(self.
properties[
'grid'][
'color'][0],
298 self.client.SetFontSizeLegend(self.
properties[
'font'][
'prop'][
'legendSize'])
299 self.client.SetEnableLegend(self.
properties[
'legend'][
'enabled'])
302 """!Draw line and point plot from list plot elements.
304 self.
plot = plot.PlotGraphics(plotlist,
309 if self.
properties[
'x-axis'][
'prop'][
'type'] ==
'custom':
310 self.client.SetXSpec(
'min')
312 self.client.SetXSpec(self.
properties[
'x-axis'][
'prop'][
'type'])
314 if self.
properties[
'y-axis'][
'prop'][
'type'] ==
'custom':
315 self.client.SetYSpec(
'min')
317 self.client.SetYSpec(self.
properties[
'y-axis'][
'prop'][
'type'])
323 """!This is the fuction that defines how the pointLabels are
324 plotted dc - DC that will be passed mDataDict - Dictionary
325 of data that you want to use for the pointLabel
327 As an example I have decided I want a box at the curve
328 point with some text information about the curve plotted
329 below. Any wxDC method can be used.
331 dc.SetPen(wx.Pen(wx.BLACK))
332 dc.SetBrush(wx.Brush( wx.BLACK, wx.SOLID ) )
334 sx, sy = mDataDict[
"scaledXY"]
335 dc.DrawRectangle( sx-5,sy-5, 10, 10)
336 px,py = mDataDict[
"pointXY"]
337 cNum = mDataDict[
"curveNum"]
338 pntIn = mDataDict[
"pIndex"]
339 legend = mDataDict[
"legend"]
341 s =
"Crv# %i, '%s', Pt. (%.2f,%.2f), PtInd %i" %(cNum, legend, px, py, pntIn)
342 dc.DrawText(s, sx , sy+1)
345 """!Enable zooming and disable dragging
349 self.client.SetEnableZoom(self.
zoom)
350 self.client.SetEnableDrag(self.
drag)
353 """!Enable dragging and disable zooming
357 self.client.SetEnableDrag(self.
drag)
358 self.client.SetEnableZoom(self.
zoom)
361 """!Redraw the plot window. Unzoom to original size
367 """!Erase the plot window
370 self.mapwin.ClearLines(self.mapwin.pdc)
371 self.mapwin.ClearLines(self.mapwin.pdcTmp)
372 self.mapwin.polycoords = []
373 self.mapwin.Refresh()
376 """!Save plot to graphics file
378 self.client.SaveFile()
381 self.SetStatusText(_(
"Left Mouse Down at Point:") + \
382 " (%.4f, %.4f)" % self.client._getXY(event))
386 """!Indicate when mouse is outside the plot area
388 if self.client.OnLeave(event):
print 'out of area'
390 if self.client.GetEnablePointLabel() ==
True:
393 dlst = self.client.GetClosetPoint( self.client._getXY(event), pointScaled =
True)
395 curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
397 mDataDict = {
"curveNum":curveNum,
"legend":legend,
"pIndex":pIndex,\
398 "pointXY":pointXY,
"scaledXY":scaledXY}
400 self.client.UpdatePointLabel(mDataDict)
405 """!Popup menu for plot and text options
407 point = wx.GetMousePosition()
411 settext = wx.MenuItem(popt, wx.ID_ANY, _(
'Text settings'))
412 popt.AppendItem(settext)
413 self.Bind(wx.EVT_MENU, self.
PlotText, settext)
415 setgrid = wx.MenuItem(popt, wx.ID_ANY, _(
'Plot settings'))
416 popt.AppendItem(setgrid)
425 """!Creates a 'not functional' message dialog
427 dlg = wx.MessageDialog(parent = self,
428 message = _(
'This feature is not yet functional'),
429 caption = _(
'Under Construction'),
430 style = wx.OK | wx.ICON_INFORMATION)
435 """!Custom text settings.
441 self.client.SetFont(self.
properties[
'font'][
'wxfont'])
442 self.client.SetFontSizeTitle(self.
properties[
'font'][
'prop'][
'titleSize'])
443 self.client.SetFontSizeAxis(self.
properties[
'font'][
'prop'][
'axisSize'])
446 self.plot.setTitle(dlg.ptitle)
447 self.plot.setXLabel(dlg.xlabel)
448 self.plot.setYLabel(dlg.ylabel)
453 """!Set custom text values for profile title and axis labels.
455 dlg = TextDialog(parent = self, id = wx.ID_ANY,
457 title = _(
'Text settings'))
459 btnval = dlg.ShowModal()
460 if btnval == wx.ID_SAVE
or btnval == wx.ID_OK
or btnval == wx.ID_CANCEL:
464 """!Set various profile options, including: line width, color,
465 style; marker size, color, fill, and style; grid and legend
466 options. Calls OptDialog class.
469 dlg = OptDialog(parent = self, id = wx.ID_ANY,
471 title = _(
'Plot settings'))
473 btnval = dlg.ShowModal()
475 if btnval == wx.ID_SAVE
or btnval == wx.ID_OK
or btnval == wx.ID_CANCEL:
479 """!Print options and output menu
481 point = wx.GetMousePosition()
482 printmenu = wx.Menu()
483 for title, handler
in ((_(
"Page setup"), self.
OnPageSetup),
486 item = wx.MenuItem(printmenu, wx.ID_ANY, title)
487 printmenu.AppendItem(item)
488 self.Bind(wx.EVT_MENU, handler, item)
492 self.PopupMenu(printmenu)
496 self.client.PageSetup()
499 self.client.PrintPreview()
502 self.client.Printout()
508 """!Close plot window and clean up
511 self.mapwin.ClearLines()
512 self.mapwin.mouse[
'begin'] = self.mapwin.mouse[
'end'] = (0.0, 0.0)
513 self.mapwin.mouse[
'use'] =
'pointer'
514 self.mapwin.mouse[
'box'] =
'point'
515 self.mapwin.polycoords = []
516 self.mapwin.UpdateMap(render =
False, renderVector =
False)
520 self.mapwin.SetCursor(self.Parent.cursors[
"default"])
def DrawPointLabel
This is the fuction that defines how the pointLabels are plotted dc - DC that will be passed mDataDic...
def InitRasterOpts
Initialize or update raster dictionary for plotting.
def PlotText
Set custom text values for profile title and axis labels.
def _createColorDict
Create color dictionary to return wx.Colour tuples for assigning colors to images in imagery groups...
Dialogs for different plotting routines.
def PlotOptionsMenu
Popup menu for plot and text options.
def SaveToFile
Save plot to graphics file.
def OnErase
Erase the plot window.
def OnCloseWindow
Close plot window and clean up.
def OnPlotText
Custom text settings.
Rendering map layers and overlays into map composition image.
def split
Platform spefic shlex.split.
def SetGraphStyle
Set plot and text options.
def OnZoom
Enable zooming and disable dragging.
def NotFunctional
Creates a 'not functional' message dialog.
Abstract PyPlot display frame class.
def OnRedraw
Redraw the plot window.
def OnMotion
Indicate when mouse is outside the plot area.
def PlotOptions
Set various profile options, including: line width, color, style; marker size, color, fill, and style; grid and legend options.
def DrawPlot
Draw line and point plot from list plot elements.
Global variables used by wxGUI.
def PrintMenu
Print options and output menu.
def InitPlotOpts
Initialize options for entire plot.
def OnDrag
Enable dragging and disable zooming.