histogram2.py 54 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381
  1. """!
  2. @package histogram2.py
  3. Raster histogramming using PyPlot (wx.lib.plot.py); replacement for d.hist
  4. Classes:
  5. - HistFrame
  6. - SetRasterDialog
  7. - TextDialog
  8. - OptDialog
  9. (C) 2011 by the GRASS Development Team
  10. This program is free software under the GNU General Public License
  11. (>=v2). Read the file COPYING that comes with GRASS for details.
  12. @author Michael Barton, Arizona State University
  13. """
  14. import os
  15. import sys
  16. import math
  17. import random
  18. import wx
  19. import wx.lib.colourselect as csel
  20. import os
  21. import sys
  22. import wx
  23. import render
  24. import menuform
  25. import disp_print
  26. import utils
  27. import gdialogs
  28. import globalvar
  29. import gselect
  30. import gcmd
  31. import toolbars
  32. from preferences import DefaultFontDialog
  33. from debug import Debug as Debug
  34. from icon import Icons as Icons
  35. from gcmd import GError
  36. from preferences import globalSettings as UserSettings
  37. from grass.script import core as grass
  38. from grass.script import raster as raster
  39. try:
  40. import numpy
  41. import wx.lib.plot as plot
  42. except ImportError:
  43. msg= _("This module requires the NumPy module, which could not be "
  44. "imported. It probably is not installed (it's not part of the "
  45. "standard Python distribution). See the Numeric Python site "
  46. "(http://numpy.scipy.org) for information on downloading source or "
  47. "binaries.")
  48. print >> sys.stderr, "profile.py: " + msg
  49. class HistFrame(wx.Frame):
  50. """!Mainframe for displaying profile of raster map. Uses wx.lib.plot.
  51. """
  52. def __init__(self, parent=None, id=wx.ID_ANY, title=_("GRASS Histogramming Tool"),
  53. rasterList=[],
  54. pos=wx.DefaultPosition, size=wx.DefaultSize,
  55. style=wx.DEFAULT_FRAME_STYLE):
  56. self.parent = parent # MapFrame
  57. self.mapwin = self.parent.MapWindow
  58. self.Map = render.Map() # instance of render.Map to be associated with display
  59. self.rasterList = rasterList #list of rasters to histogram; could come from layer manager
  60. self.pstyledict = { 'solid' : wx.SOLID,
  61. 'dot' : wx.DOT,
  62. 'long-dash' : wx.LONG_DASH,
  63. 'short-dash' : wx.SHORT_DASH,
  64. 'dot-dash' : wx.DOT_DASH }
  65. self.ptfilldict = { 'transparent' : wx.TRANSPARENT,
  66. 'solid' : wx.SOLID }
  67. wx.Frame.__init__(self, parent, id, title, pos, size, style)
  68. #
  69. # Icon
  70. #
  71. self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR, 'grass.ico'), wx.BITMAP_TYPE_ICO))
  72. #
  73. # Add toolbar
  74. #
  75. self.toolbar = toolbars.Histogram2Toolbar(parent=self)
  76. self.SetToolBar(self.toolbar)
  77. #
  78. # Set the size & cursor
  79. #
  80. self.SetClientSize(size)
  81. #
  82. # Add statusbar
  83. #
  84. self.statusbar = self.CreateStatusBar(number=2, style=0)
  85. self.statusbar.SetStatusWidths([-2, -1])
  86. #
  87. # Define canvas
  88. #
  89. self.client = plot.PlotCanvas(self) # plot canvas settings
  90. # Create mouse event for showing cursor coords in status bar
  91. self.client.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
  92. # Show closest point when enabled
  93. self.client.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
  94. #
  95. # Init variables
  96. #
  97. self.group = ''
  98. self.raster = {}
  99. if len(self.rasterList) > 0: # set 1 raster name from layer manager if a map is selected
  100. self.raster[self.rasterList[0]] = UserSettings.Get(group='histogram', key='raster') # some default settings
  101. self.raster[self.rasterList[0]]['units'] = ''
  102. self.raster[self.rasterList[0]]['plegend'] = ''
  103. self.raster[self.rasterList[0]]['datalist'] = [] # list of cell value,frequency pairs for plotting histogram
  104. self.raster[self.rasterList[0]]['pline'] = None
  105. colstr = str(self.raster[self.rasterList[0]]['pcolor']) # changing color string to tuple
  106. self.raster[self.rasterList[0]]['pcolor'] = tuple(int(colval) for colval in colstr.strip('()').split(','))
  107. self.plotlist = [] # list of things to plot
  108. self.histogram = None # plot draw object
  109. self.ptitle = _('Histogram of') # title of window
  110. self.xlabel = _("Raster cell values") # default X-axis label
  111. self.ylabel = _("Cell counts") # default Y-axis label
  112. self.maptype = 'raster' # default type of histogram to plot
  113. self.properties = {} # plot properties
  114. self.properties['font'] = {}
  115. self.properties['font']['prop'] = UserSettings.Get(group='histogram', key='font')
  116. self.properties['font']['wxfont'] = wx.Font(11, wx.FONTFAMILY_SWISS,
  117. wx.FONTSTYLE_NORMAL,
  118. wx.FONTWEIGHT_NORMAL)
  119. self.properties['grid'] = UserSettings.Get(group='histogram', key='grid')
  120. colstr = str(self.properties['grid']['color']) # changing color string to tuple
  121. self.properties['grid']['color'] = tuple(int(colval) for colval in colstr.strip('()').split(','))
  122. self.properties['x-axis'] = {}
  123. self.properties['x-axis']['prop'] = UserSettings.Get(group='histogram', key='x-axis')
  124. self.properties['x-axis']['axis'] = None
  125. self.properties['y-axis'] = {}
  126. self.properties['y-axis']['prop'] = UserSettings.Get(group='histogram', key='y-axis')
  127. self.properties['y-axis']['axis'] = None
  128. self.properties['legend'] = UserSettings.Get(group='histogram', key='legend')
  129. self.histtype = 'count'
  130. self.bins = 255
  131. self.zoom = False # zooming disabled
  132. self.drag = False # draging disabled
  133. self.client.SetShowScrollbars(True) # vertical and horizontal scrollbars
  134. # x and y axis set to normal (non-log)
  135. self.client.setLogScale((False, False))
  136. if self.properties['x-axis']['prop']['type']:
  137. self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
  138. else:
  139. self.client.SetXSpec('auto')
  140. if self.properties['y-axis']['prop']['type']:
  141. self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
  142. else:
  143. self.client.SetYSpec('auto')
  144. #
  145. # Bind various events
  146. #
  147. self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
  148. self.CentreOnScreen()
  149. self._createColorDict()
  150. def _createColorDict(self):
  151. """!Create color dictionary to return wx.Color tuples
  152. for assigning colors to images in imagery groups"""
  153. self.colorDict = {}
  154. for clr in grass.named_colors.iterkeys():
  155. if clr == 'white' or clr == 'black': continue
  156. r = grass.named_colors[clr][0] * 255
  157. g = grass.named_colors[clr][1] * 255
  158. b = grass.named_colors[clr][2] * 255
  159. self.colorDict[clr] = (r,g,b,255)
  160. def OnSelectRaster(self, event):
  161. """!Select raster map(s) to profile
  162. """
  163. dlg = SetRasterDialog(parent=self)
  164. if dlg.ShowModal() == wx.ID_OK:
  165. self.rasterList = dlg.rasterList
  166. self.group = dlg.group
  167. self.bins = dlg.bins
  168. self.histtype = dlg.histtype
  169. self.maptype = dlg.maptype
  170. # plot profile
  171. if len(self.rasterList) > 0:
  172. self.OnCreateHist(event=None)
  173. dlg.Destroy()
  174. def OnCreateHist(self, event):
  175. """!Main routine for creating a histogram. Uses r.stats to
  176. create a list of cell value and count/percent/area pairs. This is passed to
  177. plot to create a line graph of the histogram.
  178. """
  179. self.SetCursor(self.parent.cursors["default"])
  180. self.SetGraphStyle()
  181. self.SetRaster()
  182. self.DrawPlot()
  183. def SetGraphStyle(self):
  184. """!Set plot and text options
  185. """
  186. self.client.SetFont(self.properties['font']['wxfont'])
  187. self.client.SetFontSizeTitle(self.properties['font']['prop']['titleSize'])
  188. self.client.SetFontSizeAxis(self.properties['font']['prop']['axisSize'])
  189. self.client.SetEnableZoom(self.zoom)
  190. self.client.SetEnableDrag(self.drag)
  191. #
  192. # axis settings
  193. #
  194. if self.properties['x-axis']['prop']['type'] == 'custom':
  195. self.client.SetXSpec('min')
  196. else:
  197. self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
  198. if self.properties['y-axis']['prop']['type'] == 'custom':
  199. self.client.SetYSpec('min')
  200. else:
  201. self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
  202. if self.properties['x-axis']['prop']['type'] == 'custom' and \
  203. self.properties['x-axis']['prop']['min'] < self.properties['x-axis']['prop']['max']:
  204. self.properties['x-axis']['axis'] = (self.properties['x-axis']['prop']['min'],
  205. self.properties['x-axis']['prop']['max'])
  206. else:
  207. self.properties['x-axis']['axis'] = None
  208. if self.properties['y-axis']['prop']['type'] == 'custom' and \
  209. self.properties['y-axis']['prop']['min'] < self.properties['y-axis']['prop']['max']:
  210. self.properties['y-axis']['axis'] = (self.properties['y-axis']['prop']['min'],
  211. self.properties['y-axis']['prop']['max'])
  212. else:
  213. self.properties['y-axis']['axis'] = None
  214. self.client.SetEnableGrid(self.properties['grid']['enabled'])
  215. self.client.SetGridColour(wx.Color(self.properties['grid']['color'][0],
  216. self.properties['grid']['color'][1],
  217. self.properties['grid']['color'][2],
  218. 255))
  219. self.client.SetFontSizeLegend(self.properties['font']['prop']['legendSize'])
  220. self.client.SetEnableLegend(self.properties['legend']['enabled'])
  221. if self.properties['x-axis']['prop']['log'] == True:
  222. self.properties['x-axis']['axis'] = None
  223. self.client.SetXSpec('min')
  224. if self.properties['y-axis']['prop']['log'] == True:
  225. self.properties['y-axis']['axis'] = None
  226. self.client.SetYSpec('min')
  227. self.client.setLogScale((self.properties['x-axis']['prop']['log'],
  228. self.properties['y-axis']['prop']['log']))
  229. def SetRaster(self):
  230. """!Build data list for ploting each raster."""
  231. #
  232. # populate raster dictionary
  233. #
  234. if len(self.rasterList) == 0: return # nothing selected
  235. colorList = []
  236. for clr in ["blue", "green", "red", "yellow", "magenta", "cyan", \
  237. "aqua", "grey", "orange", "brown", "purple", "violet", \
  238. "indigo"]:
  239. colorList.append(self.colorDict[clr])
  240. if len(self.rasterList) > len(colorList):
  241. # just in case the imagery group has many maps
  242. diff = len(self.rasterList) - len(colorList)
  243. for x in range(0, diff):
  244. r = randint(0, 255)
  245. b = randint(0, 255)
  246. g = randint(0, 255)
  247. colorList.append((r,g,b,255))
  248. rastcolor = zip(self.rasterList, colorList)
  249. for r,c in rastcolor:
  250. if r in self.raster: continue # only reset values if rasters have changed
  251. self.raster[r] = {}
  252. try:
  253. ret = raster.raster_info(r)
  254. except:
  255. continue
  256. self.raster[r]['datatype'] = 'CELL'
  257. self.raster[r]['datatype'] = ret['datatype']
  258. self.raster[r]['units'] = ret['units']
  259. self.raster[r]['plegend'] = r # raster name to use in legend
  260. self.raster[r]['datalist'] = [] # list of cell value,frequency pairs for plotting histogram
  261. self.raster[r]['pline'] = None
  262. if 'pcolor' not in self.raster[r]:
  263. self.raster[r]['pcolor'] = c
  264. if 'pwidth' not in self.raster[r]:
  265. self.raster[r]['pwidth'] = 1
  266. if 'pstyle' not in self.raster[r]:
  267. self.raster[r]['pstyle'] = 'solid'
  268. self.ptitle = _('Histogram of') # reset window title
  269. #
  270. # create datalist for each raster map
  271. #
  272. for r in self.rasterList:
  273. self.raster[r]['datalist'] = self.CreateDatalist(r)
  274. #
  275. # update title
  276. #
  277. if self.maptype == 'group':
  278. self.ptitle = _('Histogram of %s') % self.group.split('@')[0]
  279. else:
  280. self.ptitle = _('Histogram of %s') % self.rasterList[0].split('@')[0]
  281. #
  282. # set xlabel based on first raster map in list to be histogrammed
  283. #
  284. units = self.raster[self.rasterList[0]]['units']
  285. if units != '' and units != '(none)' and units != None:
  286. self.xlabel = _('Raster cell values %s') % units
  287. else:
  288. self.xlabel = _('Raster cell values')
  289. #
  290. # set ylabel from self.histtype
  291. #
  292. if self.histtype == 'count': self.ylabel = _('Cell counts')
  293. if self.histtype == 'percent': self.ylabel = _('Percent of total cells')
  294. if self.histtype == 'area': self.ylabel = _('Area')
  295. def CreateDatalist(self, raster):
  296. """!Build a list of cell value, frequency pairs for histogram
  297. frequency can be in cell counts, percents, or area
  298. """
  299. datalist = []
  300. if self.histtype == 'count': freqflag = 'cn'
  301. if self.histtype == 'percent': freqflag = 'pn'
  302. if self.histtype == 'area': freqflag = 'an'
  303. try:
  304. ret = gcmd.RunCommand("r.stats",
  305. input=raster,
  306. flags=freqflag,
  307. nsteps=self.bins,
  308. fs=',',
  309. quiet=True,
  310. read = True)
  311. if not ret:
  312. return dataset
  313. for line in ret.splitlines():
  314. cellval, histval = line.strip().split(',')
  315. histval = histval.strip()
  316. if self.raster[raster]['datatype'] != 'CELL':
  317. cellval = cellval.split('-')[0]
  318. if self.histtype == 'percent':
  319. histval = histval.rstrip('%')
  320. datalist.append((cellval,histval))
  321. return datalist
  322. except gcmd.GException, e:
  323. gcmd.GError(parent = self,
  324. message = e.value)
  325. return None
  326. #### Maybe add a barplot routine to make an 'area' graph. Could make it slow down a lot
  327. def DrawPlot(self):
  328. """!Draw line and point plot from transect datalist and
  329. transect segment endpoint coordinates.
  330. """
  331. # graph the cell value, frequency pairs for the histogram
  332. self.plotlist = []
  333. for r in self.rasterList:
  334. if len(self.raster[r]['datalist']) > 0:
  335. col = wx.Color(self.raster[r]['pcolor'][0],
  336. self.raster[r]['pcolor'][1],
  337. self.raster[r]['pcolor'][2],
  338. 255)
  339. self.raster[r]['pline'] = plot.PolyLine(self.raster[r]['datalist'],
  340. colour=col,
  341. width=self.raster[r]['pwidth'],
  342. style=self.pstyledict[self.raster[r]['pstyle']],
  343. legend=self.raster[r]['plegend'])
  344. self.plotlist.append(self.raster[r]['pline'])
  345. self.histogram = plot.PlotGraphics(self.plotlist,
  346. self.ptitle,
  347. self.xlabel,
  348. self.ylabel)
  349. if self.properties['x-axis']['prop']['type'] == 'custom':
  350. self.client.SetXSpec('min')
  351. else:
  352. self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
  353. if self.properties['y-axis']['prop']['type'] == 'custom':
  354. self.client.SetYSpec('min')
  355. else:
  356. self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
  357. self.client.Draw(self.histogram, self.properties['x-axis']['axis'],
  358. self.properties['y-axis']['axis'])
  359. def OnZoom(self, event):
  360. """!Enable zooming and disable dragging
  361. """
  362. self.zoom = True
  363. self.drag = False
  364. self.client.SetEnableZoom(self.zoom)
  365. self.client.SetEnableDrag(self.drag)
  366. def OnDrag(self, event):
  367. """!Enable dragging and disable zooming
  368. """
  369. self.zoom = False
  370. self.drag = True
  371. self.client.SetEnableDrag(self.drag)
  372. self.client.SetEnableZoom(self.zoom)
  373. def OnRedraw(self, event):
  374. """!Redraw the hisogram window. Unzoom to original size
  375. """
  376. self.client.Reset()
  377. self.client.Redraw()
  378. def Update(self):
  379. """!Update histogram after changing options
  380. """
  381. self.SetGraphStyle()
  382. self.DrawPlot()
  383. def OnErase(self, event):
  384. """!Erase the histogram window
  385. """
  386. self.client.Clear()
  387. self.mapwin.ClearLines(self.mapwin.pdc)
  388. self.mapwin.ClearLines(self.mapwin.pdcTmp)
  389. self.mapwin.polycoords = []
  390. self.mapwin.Refresh()
  391. def SaveToFile(self, event):
  392. """!Save histogram to graphics file
  393. """
  394. self.client.SaveFile()
  395. def OnMouseLeftDown(self,event):
  396. s= "Left Mouse Down at Point: (%.4f, %.4f)" % self.client._getXY(event)
  397. self.SetStatusText(s)
  398. event.Skip() #allows plotCanvas OnMouseLeftDown to be called
  399. def OnMotion(self, event):
  400. # indicate when mouse is outside the plot area
  401. if self.client.OnLeave(event): print 'out of area'
  402. #show closest point (when enbled)
  403. if self.client.GetEnablePointLabel() == True:
  404. #make up dict with info for the pointLabel
  405. #I've decided to mark the closest point on the closest curve
  406. dlst= self.client.GetClosetPoint( self.client._getXY(event), pointScaled= True)
  407. if dlst != []: #returns [] if none
  408. curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
  409. #make up dictionary to pass to my user function (see DrawPointLabel)
  410. mDataDict= {"curveNum":curveNum, "legend":legend, "pIndex":pIndex,\
  411. "pointXY":pointXY, "scaledXY":scaledXY}
  412. #pass dict to update the pointLabel
  413. self.client.UpdatePointLabel(mDataDict)
  414. event.Skip() #go to next handler
  415. def HistOptionsMenu(self, event):
  416. """!Popup menu for histogram and text options
  417. """
  418. point = wx.GetMousePosition()
  419. popt = wx.Menu()
  420. # Add items to the menu
  421. settext = wx.MenuItem(popt, -1, 'Histogram text settings')
  422. popt.AppendItem(settext)
  423. self.Bind(wx.EVT_MENU, self.PText, settext)
  424. setgrid = wx.MenuItem(popt, -1, 'Histogram plot settings')
  425. popt.AppendItem(setgrid)
  426. self.Bind(wx.EVT_MENU, self.POptions, setgrid)
  427. # Popup the menu. If an item is selected then its handler
  428. # will be called before PopupMenu returns.
  429. self.PopupMenu(popt)
  430. popt.Destroy()
  431. def NotFunctional(self):
  432. """!Creates a 'not functional' message dialog
  433. """
  434. dlg = wx.MessageDialog(parent = self,
  435. message = _('This feature is not yet functional'),
  436. caption = _('Under Construction'),
  437. style = wx.OK | wx.ICON_INFORMATION)
  438. dlg.ShowModal()
  439. dlg.Destroy()
  440. def OnPText(self, dlg):
  441. """!Custom text settings for histogram plot.
  442. """
  443. self.ptitle = dlg.ptitle
  444. self.xlabel = dlg.xlabel
  445. self.ylabel = dlg.ylabel
  446. dlg.UpdateSettings()
  447. self.client.SetFont(self.properties['font']['wxfont'])
  448. self.client.SetFontSizeTitle(self.properties['font']['prop']['titleSize'])
  449. self.client.SetFontSizeAxis(self.properties['font']['prop']['axisSize'])
  450. if self.histogram:
  451. self.histogram.setTitle(dlg.ptitle)
  452. self.histogram.setXLabel(dlg.xlabel)
  453. self.histogram.setYLabel(dlg.ylabel)
  454. self.OnRedraw(event=None)
  455. def PText(self, event):
  456. """!Set custom text values for profile title and axis labels.
  457. """
  458. dlg = TextDialog(parent=self, id=wx.ID_ANY, title=_('Histogram text settings'))
  459. if dlg.ShowModal() == wx.ID_OK:
  460. self.OnPText(dlg)
  461. dlg.Destroy()
  462. def POptions(self, event):
  463. """!Set various profile options, including: line width, color,
  464. style; marker size, color, fill, and style; grid and legend
  465. options. Calls OptDialog class.
  466. """
  467. dlg = OptDialog(parent=self, id=wx.ID_ANY, title=_('Histogram settings'))
  468. btnval = dlg.ShowModal()
  469. if btnval == wx.ID_SAVE:
  470. dlg.UpdateSettings()
  471. self.SetGraphStyle()
  472. dlg.Destroy()
  473. elif btnval == wx.ID_CANCEL:
  474. dlg.Destroy()
  475. def PrintMenu(self, event):
  476. """!Print options and output menu
  477. """
  478. point = wx.GetMousePosition()
  479. printmenu = wx.Menu()
  480. # Add items to the menu
  481. setup = wx.MenuItem(printmenu, -1,'Page setup')
  482. printmenu.AppendItem(setup)
  483. self.Bind(wx.EVT_MENU, self.OnPageSetup, setup)
  484. preview = wx.MenuItem(printmenu, -1,'Print preview')
  485. printmenu.AppendItem(preview)
  486. self.Bind(wx.EVT_MENU, self.OnPrintPreview, preview)
  487. doprint = wx.MenuItem(printmenu, -1,'Print display')
  488. printmenu.AppendItem(doprint)
  489. self.Bind(wx.EVT_MENU, self.OnDoPrint, doprint)
  490. # Popup the menu. If an item is selected then its handler
  491. # will be called before PopupMenu returns.
  492. self.PopupMenu(printmenu)
  493. printmenu.Destroy()
  494. def OnPageSetup(self, event):
  495. self.client.PageSetup()
  496. def OnPrintPreview(self, event):
  497. self.client.PrintPreview()
  498. def OnDoPrint(self, event):
  499. self.client.Printout()
  500. def OnQuit(self, event):
  501. self.Close(True)
  502. def OnCloseWindow(self, event):
  503. """
  504. Close histogram window and clean up
  505. """
  506. self.mapwin.SetCursor(self.Parent.cursors["default"])
  507. self.Destroy()
  508. class SetRasterDialog(wx.Dialog):
  509. def __init__(self, parent, id=wx.ID_ANY,
  510. title=_("Select raster map or imagery group to histogram"),
  511. pos=wx.DefaultPosition, size=wx.DefaultSize,
  512. style=wx.DEFAULT_DIALOG_STYLE):
  513. """!Dialog to select raster maps to histogram.
  514. """
  515. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  516. self.parent = parent
  517. self.rasterList = self.parent.rasterList
  518. self.group = self.parent.group
  519. self.bins = self.parent.bins
  520. self.histtype = self.parent.histtype
  521. self.maptype = self.parent.maptype
  522. self._do_layout()
  523. def _do_layout(self):
  524. sizer = wx.BoxSizer(wx.VERTICAL)
  525. box = wx.GridBagSizer (hgap=3, vgap=3)
  526. #
  527. # select single raster or image group to histogram radio buttons
  528. #
  529. self.rasterRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("Histogram single raster"), style = wx.RB_GROUP)
  530. self.groupRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("Histogram imagery group"))
  531. if self.maptype == 'raster':
  532. self.rasterRadio.SetValue(True)
  533. elif self.maptype == 'group':
  534. self.groupRadio.SetValue(True)
  535. box.Add(item=self.rasterRadio, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  536. box.Add(item=self.groupRadio, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 1))
  537. #
  538. # Select a raster to histogram
  539. #
  540. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  541. label=_("Select raster map:"))
  542. box.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  543. self.rselection = gselect.Select(self, id=wx.ID_ANY,
  544. size=globalvar.DIALOG_GSELECT_SIZE,
  545. type='cell')
  546. if self.groupRadio.GetValue() == True:
  547. self.rselection.Disable()
  548. else:
  549. if len(self.rasterList) > 0: self.rselection.SetValue(self.rasterList[0])
  550. box.Add(item=self.rselection, pos=(1, 1))
  551. #
  552. # Select an image group to histogram
  553. #
  554. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  555. label=_("Select image group:"))
  556. box.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  557. self.gselection = gselect.Select(self, id=wx.ID_ANY,
  558. size=globalvar.DIALOG_GSELECT_SIZE,
  559. type='group')
  560. if self.rasterRadio.GetValue() == True:
  561. self.gselection.Disable()
  562. else:
  563. if self.group != None: self.gselection.SetValue(self.group)
  564. box.Add(item=self.gselection, pos=(2, 1))
  565. #
  566. # Nsteps for FP maps and histogram type selection
  567. #
  568. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  569. label=_("Number of bins (for FP maps)"))
  570. box.Add(item=label,
  571. flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  572. bins = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  573. size=(100,-1), style=wx.SP_ARROW_KEYS)
  574. bins.SetRange(1,1000)
  575. bins.SetValue(self.bins)
  576. box.Add(item=bins,
  577. flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 1))
  578. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  579. label=_("Histogram type"))
  580. box.Add(item=label,
  581. flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  582. types = ['count', 'percent', 'area']
  583. histtype = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(250, -1),
  584. choices=types, style=wx.CB_DROPDOWN)
  585. histtype.SetStringSelection(self.histtype)
  586. box.Add(item=histtype,
  587. flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 1))
  588. sizer.Add(item=box, proportion=0,
  589. flag=wx.ALL, border=10)
  590. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  591. sizer.Add(item=line, proportion=0,
  592. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=5)
  593. btnsizer = wx.StdDialogButtonSizer()
  594. btn = wx.Button(self, wx.ID_OK)
  595. btn.SetDefault()
  596. btnsizer.AddButton(btn)
  597. btn = wx.Button(self, wx.ID_CANCEL)
  598. btnsizer.AddButton(btn)
  599. btnsizer.Realize()
  600. sizer.Add(item=btnsizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  601. #
  602. # bindings
  603. #
  604. self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.rasterRadio)
  605. self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.groupRadio)
  606. self.rselection.Bind(wx.EVT_TEXT, self.OnRasterSelection)
  607. self.gselection.Bind(wx.EVT_TEXT, self.OnGroupSelection)
  608. bins.Bind(wx.EVT_TEXT, self.OnSetBins)
  609. bins.Bind(wx.EVT_SPINCTRL, self.OnSetBins)
  610. histtype.Bind(wx.EVT_TEXT, self.OnSetHisttypes)
  611. self.SetSizer(sizer)
  612. sizer.Fit(self)
  613. def OnHistMap(self, event):
  614. """!Hander for radio buttons to choose between histogramming a
  615. single raster and an imagery group
  616. """
  617. if self.rasterRadio.GetValue() == True:
  618. self.maptype = 'raster'
  619. self.rselection.Enable()
  620. self.gselection.Disable()
  621. self.gselection.SetValue('')
  622. elif self.groupRadio.GetValue() == True:
  623. self.maptype = 'group'
  624. self.gselection.Enable()
  625. self.rselection.Disable()
  626. self.rselection.SetValue('')
  627. else:
  628. pass
  629. def OnRasterSelection(self, event):
  630. """!Handler for selecting a single raster map
  631. """
  632. self.rasterList = []
  633. self.rasterList.append(event.GetString())
  634. def OnGroupSelection(self, event):
  635. """!Handler for selecting imagery group
  636. """
  637. self.rasterList = []
  638. self.group = event.GetString()
  639. self.rasterList = grass.read_command('i.group',
  640. group='%s' % self.group,
  641. quiet=True,
  642. flags='g').strip().split('\n')
  643. def OnSetBins(self, event):
  644. """!Bins for histogramming FP maps (=nsteps in r.stats)
  645. """
  646. if event.GetValue() != None:
  647. self.bins = event.GetValue()
  648. elif event.GetString() != None and int(event.GetString()) > 0:
  649. self.bins = int(event.GetString())
  650. def OnSetHisttypes(self, event):
  651. self.histtype = event.GetString()
  652. print 'histtype = ' + self.histtype
  653. class TextDialog(wx.Dialog):
  654. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  655. style=wx.DEFAULT_DIALOG_STYLE):
  656. """!Dialog to set histogram text options: font, title
  657. and font size, axis labels and font size
  658. """
  659. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  660. #
  661. # initialize variables
  662. #
  663. # combo box entry lists
  664. self.ffamilydict = { 'default' : wx.FONTFAMILY_DEFAULT,
  665. 'decorative' : wx.FONTFAMILY_DECORATIVE,
  666. 'roman' : wx.FONTFAMILY_ROMAN,
  667. 'script' : wx.FONTFAMILY_SCRIPT,
  668. 'swiss' : wx.FONTFAMILY_SWISS,
  669. 'modern' : wx.FONTFAMILY_MODERN,
  670. 'teletype' : wx.FONTFAMILY_TELETYPE }
  671. self.fstyledict = { 'normal' : wx.FONTSTYLE_NORMAL,
  672. 'slant' : wx.FONTSTYLE_SLANT,
  673. 'italic' : wx.FONTSTYLE_ITALIC }
  674. self.fwtdict = { 'normal' : wx.FONTWEIGHT_NORMAL,
  675. 'light' : wx.FONTWEIGHT_LIGHT,
  676. 'bold' : wx.FONTWEIGHT_BOLD }
  677. self.parent = parent
  678. self.ptitle = self.parent.ptitle
  679. self.xlabel = self.parent.xlabel
  680. self.ylabel = self.parent.ylabel
  681. self.properties = self.parent.properties # read-only
  682. # font size
  683. self.fontfamily = self.properties['font']['wxfont'].GetFamily()
  684. self.fontstyle = self.properties['font']['wxfont'].GetStyle()
  685. self.fontweight = self.properties['font']['wxfont'].GetWeight()
  686. self._do_layout()
  687. #### This stays with relevant changes to dictionary/list names
  688. def _do_layout(self):
  689. """!Do layout"""
  690. # dialog layout
  691. sizer = wx.BoxSizer(wx.VERTICAL)
  692. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  693. label=" %s " % _("Text settings"))
  694. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  695. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  696. #
  697. # profile title
  698. #
  699. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Profile title:"))
  700. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  701. self.ptitleentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(250,-1))
  702. # self.ptitleentry.SetFont(self.font)
  703. self.ptitleentry.SetValue(self.ptitle)
  704. gridSizer.Add(item=self.ptitleentry, pos=(0, 1))
  705. #
  706. # title font
  707. #
  708. tlabel = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Title font size (pts):"))
  709. gridSizer.Add(item=tlabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  710. self.ptitlesize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  711. size=(50,-1), style=wx.SP_ARROW_KEYS)
  712. self.ptitlesize.SetRange(5,100)
  713. self.ptitlesize.SetValue(int(self.properties['font']['prop']['titleSize']))
  714. gridSizer.Add(item=self.ptitlesize, pos=(1, 1))
  715. #
  716. # x-axis label
  717. #
  718. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("X-axis label:"))
  719. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  720. self.xlabelentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(250,-1))
  721. # self.xlabelentry.SetFont(self.font)
  722. self.xlabelentry.SetValue(self.xlabel)
  723. gridSizer.Add(item=self.xlabelentry, pos=(2, 1))
  724. #
  725. # y-axis label
  726. #
  727. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Y-axis label:"))
  728. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  729. self.ylabelentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(250,-1))
  730. # self.ylabelentry.SetFont(self.font)
  731. self.ylabelentry.SetValue(self.ylabel)
  732. gridSizer.Add(item=self.ylabelentry, pos=(3, 1))
  733. #
  734. # font size
  735. #
  736. llabel = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Label font size (pts):"))
  737. gridSizer.Add(item=llabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  738. self.axislabelsize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  739. size=(50, -1), style=wx.SP_ARROW_KEYS)
  740. self.axislabelsize.SetRange(5, 100)
  741. self.axislabelsize.SetValue(int(self.properties['font']['prop']['axisSize']))
  742. gridSizer.Add(item=self.axislabelsize, pos=(4,1))
  743. boxSizer.Add(item=gridSizer)
  744. sizer.Add(item=boxSizer, flag=wx.ALL | wx.EXPAND, border=3)
  745. #
  746. # font settings
  747. #
  748. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  749. label=" %s " % _("Font settings"))
  750. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  751. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  752. gridSizer.AddGrowableCol(1)
  753. #
  754. # font family
  755. #
  756. label1 = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Font family:"))
  757. gridSizer.Add(item=label1, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  758. self.ffamilycb = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(250, -1),
  759. choices=self.ffamilydict.keys(), style=wx.CB_DROPDOWN)
  760. self.ffamilycb.SetStringSelection('swiss')
  761. for item in self.ffamilydict.items():
  762. if self.fontfamily == item[1]:
  763. self.ffamilycb.SetStringSelection(item[0])
  764. break
  765. gridSizer.Add(item=self.ffamilycb, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  766. #
  767. # font style
  768. #
  769. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Style:"))
  770. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  771. self.fstylecb = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(250, -1),
  772. choices=self.fstyledict.keys(), style=wx.CB_DROPDOWN)
  773. self.fstylecb.SetStringSelection('normal')
  774. for item in self.fstyledict.items():
  775. if self.fontstyle == item[1]:
  776. self.fstylecb.SetStringSelection(item[0])
  777. break
  778. gridSizer.Add(item=self.fstylecb, pos=(1, 1), flag=wx.ALIGN_RIGHT)
  779. #
  780. # font weight
  781. #
  782. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Weight:"))
  783. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  784. self.fwtcb = wx.ComboBox(parent=self, size=(250, -1),
  785. choices=self.fwtdict.keys(), style=wx.CB_DROPDOWN)
  786. self.fwtcb.SetStringSelection('normal')
  787. for item in self.fwtdict.items():
  788. if self.fontweight == item[1]:
  789. self.fwtcb.SetStringSelection(item[0])
  790. break
  791. gridSizer.Add(item=self.fwtcb, pos=(2, 1), flag=wx.ALIGN_RIGHT)
  792. boxSizer.Add(item=gridSizer, flag=wx.EXPAND)
  793. sizer.Add(item=boxSizer, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  794. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  795. sizer.Add(item=line, proportion=0,
  796. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=3)
  797. #
  798. # buttons
  799. #
  800. btnSave = wx.Button(self, wx.ID_SAVE)
  801. btnApply = wx.Button(self, wx.ID_APPLY)
  802. btnOk = wx.Button(self, wx.ID_OK)
  803. btnCancel = wx.Button(self, wx.ID_CANCEL)
  804. btnOk.SetDefault()
  805. # bindings
  806. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  807. btnApply.SetToolTipString(_("Apply changes for the current session"))
  808. btnOk.Bind(wx.EVT_BUTTON, self.OnOk)
  809. btnOk.SetToolTipString(_("Apply changes for the current session and close dialog"))
  810. btnOk.SetDefault()
  811. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  812. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  813. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  814. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  815. # sizers
  816. btnStdSizer = wx.StdDialogButtonSizer()
  817. btnStdSizer.AddButton(btnOk)
  818. btnStdSizer.AddButton(btnApply)
  819. btnStdSizer.AddButton(btnCancel)
  820. btnStdSizer.Realize()
  821. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  822. btnSizer.Add(item=btnSave, proportion=0, flag=wx.ALIGN_LEFT | wx.ALL, border=5)
  823. btnSizer.Add(item=btnStdSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  824. sizer.Add(item=btnSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  825. #
  826. # bindings
  827. #
  828. self.ptitleentry.Bind(wx.EVT_TEXT, self.OnTitle)
  829. self.xlabelentry.Bind(wx.EVT_TEXT, self.OnXLabel)
  830. self.ylabelentry.Bind(wx.EVT_TEXT, self.OnYLabel)
  831. self.SetSizer(sizer)
  832. sizer.Fit(self)
  833. def OnTitle(self, event):
  834. self.ptitle = event.GetString()
  835. def OnXLabel(self, event):
  836. self.xlabel = event.GetString()
  837. def OnYLabel(self, event):
  838. self.ylabel = event.GetString()
  839. def UpdateSettings(self):
  840. self.properties['font']['prop']['titleSize'] = self.ptitlesize.GetValue()
  841. self.properties['font']['prop']['axisSize'] = self.axislabelsize.GetValue()
  842. family = self.ffamilydict[self.ffamilycb.GetStringSelection()]
  843. self.properties['font']['wxfont'].SetFamily(family)
  844. style = self.fstyledict[self.fstylecb.GetStringSelection()]
  845. self.properties['font']['wxfont'].SetStyle(style)
  846. weight = self.fwtdict[self.fwtcb.GetStringSelection()]
  847. self.properties['font']['wxfont'].SetWeight(weight)
  848. def OnSave(self, event):
  849. """!Button 'Save' pressed"""
  850. self.UpdateSettings()
  851. fileSettings = {}
  852. UserSettings.ReadSettingsFile(settings=fileSettings)
  853. fileSettings['histogram'] = UserSettings.Get(group='histogram')
  854. file = UserSettings.SaveToFile(fileSettings)
  855. self.parent.parent.GetLayerManager().goutput.WriteLog(_('Histogram settings saved to file \'%s\'.') % file)
  856. self.EndModal(wx.ID_OK)
  857. def OnApply(self, event):
  858. """!Button 'Apply' pressed"""
  859. self.UpdateSettings()
  860. self.parent.OnPText(self)
  861. def OnOk(self, event):
  862. """!Button 'OK' pressed"""
  863. self.UpdateSettings()
  864. self.EndModal(wx.ID_OK)
  865. def OnCancel(self, event):
  866. """!Button 'Cancel' pressed"""
  867. self.EndModal(wx.ID_CANCEL)
  868. class OptDialog(wx.Dialog):
  869. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  870. style=wx.DEFAULT_DIALOG_STYLE):
  871. """!Dialog to set various profile options, including: line
  872. width, color, style; marker size, color, fill, and style; grid
  873. and legend options.
  874. """
  875. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  876. # init variables
  877. self.pstyledict = parent.pstyledict
  878. self.ptfilldict = parent.ptfilldict
  879. self.axislist = ['min',
  880. 'auto',
  881. 'custom']
  882. # widgets ids
  883. self.wxId = {}
  884. self.parent = parent
  885. # read-only
  886. self.raster = self.parent.raster
  887. self.rasterList = self.parent.rasterList
  888. self.properties = self.parent.properties
  889. self.map = ''
  890. if len(self.rasterList) == 0:
  891. wx.MessageBox(parent = self,
  892. message = _("No map or image group selected to histogram."),
  893. caption = _("Warning"), style = wx.OK | wx.ICON_ERROR)
  894. self._do_layout()
  895. def _do_layout(self):
  896. """!Do layout"""
  897. # dialog layout
  898. sizer = wx.BoxSizer(wx.VERTICAL)
  899. #
  900. # histogram line settings
  901. #
  902. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  903. label=" %s " % _("Histogram settings"))
  904. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  905. self.wxId['pcolor'] = 0
  906. self.wxId['pwidth'] = 0
  907. self.wxId['pstyle'] = 0
  908. self.wxId['plegend'] = 0
  909. if len(self.rasterList) > 0:
  910. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  911. label=_("Map/image histogrammed"))
  912. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  913. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  914. row = 0
  915. self.mapchoice = wx.Choice(parent = self, id = wx.ID_ANY, size = (300, -1),
  916. choices = self.rasterList)
  917. if self.map == None or self.map == '':
  918. self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
  919. else:
  920. self.mapchoice.SetStringSelection(self.map)
  921. gridSizer.Add(item=self.mapchoice, flag=wx.ALIGN_CENTER_VERTICAL,
  922. pos=(row, 0), span=(1, 2))
  923. row +=1
  924. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line color"))
  925. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  926. pcolor = csel.ColourSelect(parent=self, id=wx.ID_ANY, colour=self.raster[self.map]['pcolor'])
  927. self.wxId['pcolor'] = pcolor.GetId()
  928. gridSizer.Add(item=pcolor, pos=(row, 1))
  929. row += 1
  930. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line width"))
  931. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  932. pwidth = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  933. size=(50,-1), style=wx.SP_ARROW_KEYS)
  934. pwidth.SetRange(1, 10)
  935. pwidth.SetValue(self.raster[self.map]['pwidth'])
  936. self.wxId['pwidth'] = pwidth.GetId()
  937. gridSizer.Add(item=pwidth, pos=(row, 1))
  938. row +=1
  939. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line style"))
  940. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  941. pstyle = wx.Choice(parent=self, id=wx.ID_ANY,
  942. size=(120, -1), choices=self.pstyledict.keys(), style=wx.CB_DROPDOWN)
  943. pstyle.SetStringSelection(self.raster[self.map]['pstyle'])
  944. self.wxId['pstyle'] = pstyle.GetId()
  945. gridSizer.Add(item=pstyle, pos=(row, 1))
  946. row += 1
  947. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Legend"))
  948. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  949. plegend = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(200,-1))
  950. plegend.SetValue(self.raster[self.map]['plegend'])
  951. gridSizer.Add(item=plegend, pos=(row, 1))
  952. self.wxId['plegend'] = plegend.GetId()
  953. boxSizer.Add(item=gridSizer)
  954. flag = wx.ALL
  955. boxMainSizer.Add(item=boxSizer, flag=flag, border=3)
  956. sizer.Add(item=boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  957. middleSizer = wx.BoxSizer(wx.HORIZONTAL)
  958. #
  959. # axis options
  960. #
  961. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  962. label=" %s " % _("Axis settings"))
  963. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  964. self.wxId['x-axis'] = {}
  965. self.wxId['y-axis'] = {}
  966. idx = 0
  967. for axis, atype in [(_("X-Axis"), 'x-axis'),
  968. (_("Y-Axis"), 'y-axis')]:
  969. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  970. label=" %s " % axis)
  971. boxSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  972. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  973. prop = self.properties[atype]['prop']
  974. row = 0
  975. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Style"))
  976. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  977. type = wx.Choice(parent=self, id=wx.ID_ANY,
  978. size=(100, -1), choices=self.axislist, style=wx.CB_DROPDOWN)
  979. type.SetStringSelection(prop['type'])
  980. self.wxId[atype]['type'] = type.GetId()
  981. gridSizer.Add(item=type, pos=(row, 1))
  982. row += 1
  983. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Custom min"))
  984. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  985. min = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(70, -1))
  986. min.SetValue(str(prop['min']))
  987. self.wxId[atype]['min'] = min.GetId()
  988. gridSizer.Add(item=min, pos=(row, 1))
  989. row += 1
  990. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Custom max"))
  991. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  992. max = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(70, -1))
  993. max.SetValue(str(prop['max']))
  994. self.wxId[atype]['max'] = max.GetId()
  995. gridSizer.Add(item=max, pos=(row, 1))
  996. row += 1
  997. log = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Log scale"))
  998. log.SetValue(prop['log'])
  999. self.wxId[atype]['log'] = log.GetId()
  1000. gridSizer.Add(item=log, pos=(row, 0), span=(1, 2))
  1001. if idx == 0:
  1002. flag = wx.ALL | wx.EXPAND
  1003. else:
  1004. flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND
  1005. boxSizer.Add(item=gridSizer, flag=wx.ALL, border=3)
  1006. boxMainSizer.Add(item=boxSizer, flag=flag, border=3)
  1007. idx += 1
  1008. middleSizer.Add(item=boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  1009. #
  1010. # grid & legend options
  1011. #
  1012. self.wxId['grid'] = {}
  1013. self.wxId['legend'] = {}
  1014. self.wxId['font'] = {}
  1015. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  1016. label=" %s " % _("Grid and Legend settings"))
  1017. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1018. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  1019. row = 0
  1020. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Grid color"))
  1021. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1022. gridcolor = csel.ColourSelect(parent=self, id=wx.ID_ANY, colour=self.properties['grid']['color'])
  1023. self.wxId['grid']['color'] = gridcolor.GetId()
  1024. gridSizer.Add(item=gridcolor, pos=(row, 1))
  1025. row +=1
  1026. gridshow = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Show grid"))
  1027. gridshow.SetValue(self.properties['grid']['enabled'])
  1028. self.wxId['grid']['enabled'] = gridshow.GetId()
  1029. gridSizer.Add(item=gridshow, pos=(row, 0), span=(1, 2))
  1030. row +=1
  1031. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Legend font size"))
  1032. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1033. legendfontsize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  1034. size=(50, -1), style=wx.SP_ARROW_KEYS)
  1035. legendfontsize.SetRange(5,100)
  1036. legendfontsize.SetValue(int(self.properties['font']['prop']['legendSize']))
  1037. self.wxId['font']['legendSize'] = legendfontsize.GetId()
  1038. gridSizer.Add(item=legendfontsize, pos=(row, 1))
  1039. row += 1
  1040. legendshow = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Show legend"))
  1041. legendshow.SetValue(self.properties['legend']['enabled'])
  1042. self.wxId['legend']['enabled'] = legendshow.GetId()
  1043. gridSizer.Add(item=legendshow, pos=(row, 0), span=(1, 2))
  1044. boxMainSizer.Add(item=gridSizer, flag=flag, border=3)
  1045. middleSizer.Add(item=boxMainSizer, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  1046. sizer.Add(item=middleSizer, flag=wx.ALL, border=0)
  1047. #
  1048. # line & buttons
  1049. #
  1050. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  1051. sizer.Add(item=line, proportion=0,
  1052. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=3)
  1053. #
  1054. # buttons
  1055. #
  1056. btnSave = wx.Button(self, wx.ID_SAVE)
  1057. btnApply = wx.Button(self, wx.ID_APPLY)
  1058. btnCancel = wx.Button(self, wx.ID_CANCEL)
  1059. btnSave.SetDefault()
  1060. # tooltips for buttons
  1061. btnApply.SetToolTipString(_("Apply changes for the current session"))
  1062. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  1063. btnSave.SetDefault()
  1064. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  1065. # sizers
  1066. btnStdSizer = wx.StdDialogButtonSizer()
  1067. btnStdSizer.AddButton(btnCancel)
  1068. btnStdSizer.AddButton(btnSave)
  1069. btnStdSizer.AddButton(btnApply)
  1070. btnStdSizer.Realize()
  1071. sizer.Add(item=btnStdSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  1072. #
  1073. # bindings for buttons and map plot settings controls
  1074. #
  1075. self.mapchoice.Bind(wx.EVT_CHOICE, self.OnSetMap)
  1076. pcolor.Bind(csel.EVT_COLOURSELECT, self.OnSetOpt)
  1077. pwidth.Bind(wx.EVT_SPINCTRL, self.OnSetOpt)
  1078. pstyle.Bind(wx.EVT_CHOICE, self.OnSetOpt)
  1079. plegend.Bind(wx.EVT_TEXT, self.OnSetOpt)
  1080. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1081. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  1082. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  1083. self.SetSizer(sizer)
  1084. sizer.Fit(self)
  1085. def OnSetMap(self, event):
  1086. """!Handler for changing map selection"""
  1087. self.map = event.GetString()
  1088. # update plot settings controls for selected map
  1089. self.FindWindowById(self.wxId['pcolor']).SetColour(self.raster[self.map]['pcolor'])
  1090. self.FindWindowById(self.wxId['pwidth']).SetValue(self.raster[self.map]['pwidth'])
  1091. self.FindWindowById(self.wxId['pstyle']).SetStringSelection(self.raster[self.map]['pstyle'])
  1092. self.FindWindowById(self.wxId['plegend']).SetValue(self.raster[self.map]['plegend'])
  1093. self.Refresh()
  1094. def OnSetOpt(self, event):
  1095. """!Handler for changing any other option"""
  1096. self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
  1097. self.UpdateSettings()
  1098. self.parent.SetGraphStyle()
  1099. if self.parent.histogram:
  1100. self.parent.DrawPlot()
  1101. def UpdateSettings(self):
  1102. """!Apply settings to each map and to entire plot"""
  1103. # update plot settings for selected map
  1104. self.raster[self.map]['pcolor'] = self.FindWindowById(self.wxId['pcolor']).GetColour()
  1105. self.raster[self.map]['pwidth'] = int(self.FindWindowById(self.wxId['pwidth']).GetValue())
  1106. self.raster[self.map]['pstyle'] = self.FindWindowById(self.wxId['pstyle']).GetStringSelection()
  1107. self.raster[self.map]['plegend'] = self.FindWindowById(self.wxId['plegend']).GetValue()
  1108. # update settings for entire plot
  1109. for axis in ('x-axis', 'y-axis'):
  1110. self.properties[axis]['prop']['type'] = self.FindWindowById(self.wxId[axis]['type']).GetStringSelection()
  1111. self.properties[axis]['prop']['min'] = float(self.FindWindowById(self.wxId[axis]['min']).GetValue())
  1112. self.properties[axis]['prop']['max'] = float(self.FindWindowById(self.wxId[axis]['max']).GetValue())
  1113. self.properties[axis]['prop']['log'] = self.FindWindowById(self.wxId[axis]['log']).IsChecked()
  1114. self.properties['grid']['color'] = self.FindWindowById(self.wxId['grid']['color']).GetColour()
  1115. self.properties['grid']['enabled'] = self.FindWindowById(self.wxId['grid']['enabled']).IsChecked()
  1116. self.properties['font']['prop']['legendSize'] = self.FindWindowById(self.wxId['font']['legendSize']).GetValue()
  1117. self.properties['legend']['enabled'] = self.FindWindowById(self.wxId['legend']['enabled']).IsChecked()
  1118. def OnSave(self, event):
  1119. """!Button 'Save' pressed"""
  1120. self.UpdateSettings()
  1121. fileSettings = {}
  1122. UserSettings.ReadSettingsFile(settings=fileSettings)
  1123. fileSettings['histogram'] = UserSettings.Get(group='histogram')
  1124. file = UserSettings.SaveToFile(fileSettings)
  1125. self.parent.parent.GetLayerManager().goutput.WriteLog(_('Histogram settings saved to file \'%s\'.') % file)
  1126. self.parent.SetGraphStyle()
  1127. if self.parent.histogram:
  1128. self.parent.DrawPlot()
  1129. self.Close()
  1130. def OnApply(self, event):
  1131. """!Button 'Apply' pressed. Does not close dialog"""
  1132. self.UpdateSettings()
  1133. self.parent.SetGraphStyle()
  1134. if self.parent.histogram:
  1135. self.parent.DrawPlot()
  1136. def OnCancel(self, event):
  1137. """!Button 'Cancel' pressed"""
  1138. self.Close()