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, "histogram2.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. parent = self,
  306. input=raster,
  307. flags=freqflag,
  308. nsteps=self.bins,
  309. fs=',',
  310. quiet = True,
  311. read = True)
  312. if not ret:
  313. return datalist
  314. for line in ret.splitlines():
  315. cellval, histval = line.strip().split(',')
  316. histval = histval.strip()
  317. if self.raster[raster]['datatype'] != 'CELL':
  318. cellval = cellval.split('-')[0]
  319. if self.histtype == 'percent':
  320. histval = histval.rstrip('%')
  321. datalist.append((cellval,histval))
  322. return datalist
  323. except gcmd.GException, e:
  324. gcmd.GError(parent = self,
  325. message = e.value)
  326. return None
  327. #### Maybe add a barplot routine to make an 'area' graph. Could make it slow down a lot
  328. def DrawPlot(self):
  329. """!Draw line and point plot from transect datalist and
  330. transect segment endpoint coordinates.
  331. """
  332. # graph the cell value, frequency pairs for the histogram
  333. self.plotlist = []
  334. for r in self.rasterList:
  335. if len(self.raster[r]['datalist']) > 0:
  336. col = wx.Color(self.raster[r]['pcolor'][0],
  337. self.raster[r]['pcolor'][1],
  338. self.raster[r]['pcolor'][2],
  339. 255)
  340. self.raster[r]['pline'] = plot.PolyLine(self.raster[r]['datalist'],
  341. colour=col,
  342. width=self.raster[r]['pwidth'],
  343. style=self.pstyledict[self.raster[r]['pstyle']],
  344. legend=self.raster[r]['plegend'])
  345. self.plotlist.append(self.raster[r]['pline'])
  346. self.histogram = plot.PlotGraphics(self.plotlist,
  347. self.ptitle,
  348. self.xlabel,
  349. self.ylabel)
  350. if self.properties['x-axis']['prop']['type'] == 'custom':
  351. self.client.SetXSpec('min')
  352. else:
  353. self.client.SetXSpec(self.properties['x-axis']['prop']['type'])
  354. if self.properties['y-axis']['prop']['type'] == 'custom':
  355. self.client.SetYSpec('min')
  356. else:
  357. self.client.SetYSpec(self.properties['y-axis']['prop']['type'])
  358. self.client.Draw(self.histogram, self.properties['x-axis']['axis'],
  359. self.properties['y-axis']['axis'])
  360. def OnZoom(self, event):
  361. """!Enable zooming and disable dragging
  362. """
  363. self.zoom = True
  364. self.drag = False
  365. self.client.SetEnableZoom(self.zoom)
  366. self.client.SetEnableDrag(self.drag)
  367. def OnDrag(self, event):
  368. """!Enable dragging and disable zooming
  369. """
  370. self.zoom = False
  371. self.drag = True
  372. self.client.SetEnableDrag(self.drag)
  373. self.client.SetEnableZoom(self.zoom)
  374. def OnRedraw(self, event):
  375. """!Redraw the hisogram window. Unzoom to original size
  376. """
  377. self.client.Reset()
  378. self.client.Redraw()
  379. def Update(self):
  380. """!Update histogram after changing options
  381. """
  382. self.SetGraphStyle()
  383. self.DrawPlot()
  384. def OnErase(self, event):
  385. """!Erase the histogram window
  386. """
  387. self.client.Clear()
  388. self.mapwin.ClearLines(self.mapwin.pdc)
  389. self.mapwin.ClearLines(self.mapwin.pdcTmp)
  390. self.mapwin.polycoords = []
  391. self.mapwin.Refresh()
  392. def SaveToFile(self, event):
  393. """!Save histogram to graphics file
  394. """
  395. self.client.SaveFile()
  396. def OnMouseLeftDown(self,event):
  397. s= "Left Mouse Down at Point: (%.4f, %.4f)" % self.client._getXY(event)
  398. self.SetStatusText(s)
  399. event.Skip() #allows plotCanvas OnMouseLeftDown to be called
  400. def OnMotion(self, event):
  401. # indicate when mouse is outside the plot area
  402. if self.client.OnLeave(event): print 'out of area'
  403. #show closest point (when enbled)
  404. if self.client.GetEnablePointLabel() == True:
  405. #make up dict with info for the pointLabel
  406. #I've decided to mark the closest point on the closest curve
  407. dlst= self.client.GetClosetPoint( self.client._getXY(event), pointScaled= True)
  408. if dlst != []: #returns [] if none
  409. curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
  410. #make up dictionary to pass to my user function (see DrawPointLabel)
  411. mDataDict= {"curveNum":curveNum, "legend":legend, "pIndex":pIndex,\
  412. "pointXY":pointXY, "scaledXY":scaledXY}
  413. #pass dict to update the pointLabel
  414. self.client.UpdatePointLabel(mDataDict)
  415. event.Skip() #go to next handler
  416. def HistOptionsMenu(self, event):
  417. """!Popup menu for histogram and text options
  418. """
  419. point = wx.GetMousePosition()
  420. popt = wx.Menu()
  421. # Add items to the menu
  422. settext = wx.MenuItem(popt, -1, 'Histogram text settings')
  423. popt.AppendItem(settext)
  424. self.Bind(wx.EVT_MENU, self.PText, settext)
  425. setgrid = wx.MenuItem(popt, -1, 'Histogram plot settings')
  426. popt.AppendItem(setgrid)
  427. self.Bind(wx.EVT_MENU, self.POptions, setgrid)
  428. # Popup the menu. If an item is selected then its handler
  429. # will be called before PopupMenu returns.
  430. self.PopupMenu(popt)
  431. popt.Destroy()
  432. def NotFunctional(self):
  433. """!Creates a 'not functional' message dialog
  434. """
  435. dlg = wx.MessageDialog(parent = self,
  436. message = _('This feature is not yet functional'),
  437. caption = _('Under Construction'),
  438. style = wx.OK | wx.ICON_INFORMATION)
  439. dlg.ShowModal()
  440. dlg.Destroy()
  441. def OnPText(self, dlg):
  442. """!Custom text settings for histogram plot.
  443. """
  444. self.ptitle = dlg.ptitle
  445. self.xlabel = dlg.xlabel
  446. self.ylabel = dlg.ylabel
  447. dlg.UpdateSettings()
  448. self.client.SetFont(self.properties['font']['wxfont'])
  449. self.client.SetFontSizeTitle(self.properties['font']['prop']['titleSize'])
  450. self.client.SetFontSizeAxis(self.properties['font']['prop']['axisSize'])
  451. if self.histogram:
  452. self.histogram.setTitle(dlg.ptitle)
  453. self.histogram.setXLabel(dlg.xlabel)
  454. self.histogram.setYLabel(dlg.ylabel)
  455. self.OnRedraw(event=None)
  456. def PText(self, event):
  457. """!Set custom text values for profile title and axis labels.
  458. """
  459. dlg = TextDialog(parent=self, id=wx.ID_ANY, title=_('Histogram text settings'))
  460. if dlg.ShowModal() == wx.ID_OK:
  461. self.OnPText(dlg)
  462. dlg.Destroy()
  463. def POptions(self, event):
  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.
  467. """
  468. dlg = OptDialog(parent=self, id=wx.ID_ANY, title=_('Histogram settings'))
  469. btnval = dlg.ShowModal()
  470. if btnval == wx.ID_SAVE:
  471. dlg.UpdateSettings()
  472. self.SetGraphStyle()
  473. dlg.Destroy()
  474. elif btnval == wx.ID_CANCEL:
  475. dlg.Destroy()
  476. def PrintMenu(self, event):
  477. """!Print options and output menu
  478. """
  479. point = wx.GetMousePosition()
  480. printmenu = wx.Menu()
  481. # Add items to the menu
  482. setup = wx.MenuItem(printmenu, -1,'Page setup')
  483. printmenu.AppendItem(setup)
  484. self.Bind(wx.EVT_MENU, self.OnPageSetup, setup)
  485. preview = wx.MenuItem(printmenu, -1,'Print preview')
  486. printmenu.AppendItem(preview)
  487. self.Bind(wx.EVT_MENU, self.OnPrintPreview, preview)
  488. doprint = wx.MenuItem(printmenu, -1,'Print display')
  489. printmenu.AppendItem(doprint)
  490. self.Bind(wx.EVT_MENU, self.OnDoPrint, doprint)
  491. # Popup the menu. If an item is selected then its handler
  492. # will be called before PopupMenu returns.
  493. self.PopupMenu(printmenu)
  494. printmenu.Destroy()
  495. def OnPageSetup(self, event):
  496. self.client.PageSetup()
  497. def OnPrintPreview(self, event):
  498. self.client.PrintPreview()
  499. def OnDoPrint(self, event):
  500. self.client.Printout()
  501. def OnQuit(self, event):
  502. self.Close(True)
  503. def OnCloseWindow(self, event):
  504. """
  505. Close histogram window and clean up
  506. """
  507. self.mapwin.SetCursor(self.Parent.cursors["default"])
  508. self.Destroy()
  509. class SetRasterDialog(wx.Dialog):
  510. def __init__(self, parent, id=wx.ID_ANY,
  511. title=_("Select raster map or imagery group to histogram"),
  512. pos=wx.DefaultPosition, size=wx.DefaultSize,
  513. style=wx.DEFAULT_DIALOG_STYLE):
  514. """!Dialog to select raster maps to histogram.
  515. """
  516. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  517. self.parent = parent
  518. self.rasterList = self.parent.rasterList
  519. self.group = self.parent.group
  520. self.bins = self.parent.bins
  521. self.histtype = self.parent.histtype
  522. self.maptype = self.parent.maptype
  523. self.spinbins = ''
  524. self._do_layout()
  525. def _do_layout(self):
  526. sizer = wx.BoxSizer(wx.VERTICAL)
  527. box = wx.GridBagSizer (hgap=3, vgap=3)
  528. #
  529. # select single raster or image group to histogram radio buttons
  530. #
  531. self.rasterRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("Histogram single raster"), style = wx.RB_GROUP)
  532. self.groupRadio = wx.RadioButton(self, id = wx.ID_ANY, label = " %s " % _("Histogram imagery group"))
  533. if self.maptype == 'raster':
  534. self.rasterRadio.SetValue(True)
  535. elif self.maptype == 'group':
  536. self.groupRadio.SetValue(True)
  537. box.Add(item=self.rasterRadio, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  538. box.Add(item=self.groupRadio, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 1))
  539. #
  540. # Select a raster to histogram
  541. #
  542. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  543. label=_("Select raster map:"))
  544. box.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  545. self.rselection = gselect.Select(self, id=wx.ID_ANY,
  546. size=globalvar.DIALOG_GSELECT_SIZE,
  547. type='cell')
  548. if self.groupRadio.GetValue() == True:
  549. self.rselection.Disable()
  550. else:
  551. if len(self.rasterList) > 0: self.rselection.SetValue(self.rasterList[0])
  552. box.Add(item=self.rselection, pos=(1, 1))
  553. #
  554. # Select an image group to histogram
  555. #
  556. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  557. label=_("Select image group:"))
  558. box.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  559. self.gselection = gselect.Select(self, id=wx.ID_ANY,
  560. size=globalvar.DIALOG_GSELECT_SIZE,
  561. type='group')
  562. if self.rasterRadio.GetValue() == True:
  563. self.gselection.Disable()
  564. else:
  565. if self.group != None: self.gselection.SetValue(self.group)
  566. box.Add(item=self.gselection, pos=(2, 1))
  567. #
  568. # Nsteps for FP maps and histogram type selection
  569. #
  570. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  571. label=_("Number of bins (for FP maps)"))
  572. box.Add(item=label,
  573. flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  574. self.spinbins = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  575. size=(100,-1), style=wx.SP_ARROW_KEYS)
  576. self.spinbins.SetRange(1,1000)
  577. self.spinbins.SetValue(self.bins)
  578. box.Add(item=self.spinbins,
  579. flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 1))
  580. label = wx.StaticText(parent=self, id=wx.ID_ANY,
  581. label=_("Histogram type"))
  582. box.Add(item=label,
  583. flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  584. types = ['count', 'percent', 'area']
  585. histtype = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(250, -1),
  586. choices=types, style=wx.CB_DROPDOWN)
  587. histtype.SetStringSelection(self.histtype)
  588. box.Add(item=histtype,
  589. flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 1))
  590. sizer.Add(item=box, proportion=0,
  591. flag=wx.ALL, border=10)
  592. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  593. sizer.Add(item=line, proportion=0,
  594. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=5)
  595. btnsizer = wx.StdDialogButtonSizer()
  596. btn = wx.Button(self, wx.ID_OK)
  597. btn.SetDefault()
  598. btnsizer.AddButton(btn)
  599. btn = wx.Button(self, wx.ID_CANCEL)
  600. btnsizer.AddButton(btn)
  601. btnsizer.Realize()
  602. sizer.Add(item=btnsizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  603. #
  604. # bindings
  605. #
  606. self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.rasterRadio)
  607. self.Bind(wx.EVT_RADIOBUTTON, self.OnHistMap, self.groupRadio)
  608. self.rselection.Bind(wx.EVT_TEXT, self.OnRasterSelection)
  609. self.gselection.Bind(wx.EVT_TEXT, self.OnGroupSelection)
  610. self.spinbins.Bind(wx.EVT_TEXT, self.OnSetBins)
  611. self.spinbins.Bind(wx.EVT_SPINCTRL, self.OnSetBins)
  612. histtype.Bind(wx.EVT_TEXT, self.OnSetHisttypes)
  613. self.SetSizer(sizer)
  614. sizer.Fit(self)
  615. def OnHistMap(self, event):
  616. """!Hander for radio buttons to choose between histogramming a
  617. single raster and an imagery group
  618. """
  619. if self.rasterRadio.GetValue() == True:
  620. self.maptype = 'raster'
  621. self.rselection.Enable()
  622. self.gselection.Disable()
  623. self.gselection.SetValue('')
  624. elif self.groupRadio.GetValue() == True:
  625. self.maptype = 'group'
  626. self.gselection.Enable()
  627. self.rselection.Disable()
  628. self.rselection.SetValue('')
  629. else:
  630. pass
  631. def OnRasterSelection(self, event):
  632. """!Handler for selecting a single raster map
  633. """
  634. self.rasterList = []
  635. self.rasterList.append(event.GetString())
  636. def OnGroupSelection(self, event):
  637. """!Handler for selecting imagery group
  638. """
  639. self.rasterList = []
  640. self.group = event.GetString()
  641. self.rasterList = grass.read_command('i.group',
  642. group='%s' % self.group,
  643. quiet=True,
  644. flags='g').strip().split('\n')
  645. def OnSetBins(self, event):
  646. """!Bins for histogramming FP maps (=nsteps in r.stats)
  647. """
  648. self.bins = self.spinbins.GetValue()
  649. def OnSetHisttypes(self, event):
  650. self.histtype = event.GetString()
  651. print 'histtype = ' + self.histtype
  652. class TextDialog(wx.Dialog):
  653. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  654. style=wx.DEFAULT_DIALOG_STYLE):
  655. """!Dialog to set histogram text options: font, title
  656. and font size, axis labels and font size
  657. """
  658. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  659. #
  660. # initialize variables
  661. #
  662. # combo box entry lists
  663. self.ffamilydict = { 'default' : wx.FONTFAMILY_DEFAULT,
  664. 'decorative' : wx.FONTFAMILY_DECORATIVE,
  665. 'roman' : wx.FONTFAMILY_ROMAN,
  666. 'script' : wx.FONTFAMILY_SCRIPT,
  667. 'swiss' : wx.FONTFAMILY_SWISS,
  668. 'modern' : wx.FONTFAMILY_MODERN,
  669. 'teletype' : wx.FONTFAMILY_TELETYPE }
  670. self.fstyledict = { 'normal' : wx.FONTSTYLE_NORMAL,
  671. 'slant' : wx.FONTSTYLE_SLANT,
  672. 'italic' : wx.FONTSTYLE_ITALIC }
  673. self.fwtdict = { 'normal' : wx.FONTWEIGHT_NORMAL,
  674. 'light' : wx.FONTWEIGHT_LIGHT,
  675. 'bold' : wx.FONTWEIGHT_BOLD }
  676. self.parent = parent
  677. self.ptitle = self.parent.ptitle
  678. self.xlabel = self.parent.xlabel
  679. self.ylabel = self.parent.ylabel
  680. self.properties = self.parent.properties # read-only
  681. # font size
  682. self.fontfamily = self.properties['font']['wxfont'].GetFamily()
  683. self.fontstyle = self.properties['font']['wxfont'].GetStyle()
  684. self.fontweight = self.properties['font']['wxfont'].GetWeight()
  685. self._do_layout()
  686. #### This stays with relevant changes to dictionary/list names
  687. def _do_layout(self):
  688. """!Do layout"""
  689. # dialog layout
  690. sizer = wx.BoxSizer(wx.VERTICAL)
  691. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  692. label=" %s " % _("Text settings"))
  693. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  694. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  695. #
  696. # profile title
  697. #
  698. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Profile title:"))
  699. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  700. self.ptitleentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(250,-1))
  701. # self.ptitleentry.SetFont(self.font)
  702. self.ptitleentry.SetValue(self.ptitle)
  703. gridSizer.Add(item=self.ptitleentry, pos=(0, 1))
  704. #
  705. # title font
  706. #
  707. tlabel = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Title font size (pts):"))
  708. gridSizer.Add(item=tlabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  709. self.ptitlesize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  710. size=(50,-1), style=wx.SP_ARROW_KEYS)
  711. self.ptitlesize.SetRange(5,100)
  712. self.ptitlesize.SetValue(int(self.properties['font']['prop']['titleSize']))
  713. gridSizer.Add(item=self.ptitlesize, pos=(1, 1))
  714. #
  715. # x-axis label
  716. #
  717. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("X-axis label:"))
  718. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  719. self.xlabelentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(250,-1))
  720. # self.xlabelentry.SetFont(self.font)
  721. self.xlabelentry.SetValue(self.xlabel)
  722. gridSizer.Add(item=self.xlabelentry, pos=(2, 1))
  723. #
  724. # y-axis label
  725. #
  726. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Y-axis label:"))
  727. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(3, 0))
  728. self.ylabelentry = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(250,-1))
  729. # self.ylabelentry.SetFont(self.font)
  730. self.ylabelentry.SetValue(self.ylabel)
  731. gridSizer.Add(item=self.ylabelentry, pos=(3, 1))
  732. #
  733. # font size
  734. #
  735. llabel = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Label font size (pts):"))
  736. gridSizer.Add(item=llabel, flag=wx.ALIGN_CENTER_VERTICAL, pos=(4, 0))
  737. self.axislabelsize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="", pos=(30, 50),
  738. size=(50, -1), style=wx.SP_ARROW_KEYS)
  739. self.axislabelsize.SetRange(5, 100)
  740. self.axislabelsize.SetValue(int(self.properties['font']['prop']['axisSize']))
  741. gridSizer.Add(item=self.axislabelsize, pos=(4,1))
  742. boxSizer.Add(item=gridSizer)
  743. sizer.Add(item=boxSizer, flag=wx.ALL | wx.EXPAND, border=3)
  744. #
  745. # font settings
  746. #
  747. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  748. label=" %s " % _("Font settings"))
  749. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  750. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  751. gridSizer.AddGrowableCol(1)
  752. #
  753. # font family
  754. #
  755. label1 = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Font family:"))
  756. gridSizer.Add(item=label1, flag=wx.ALIGN_CENTER_VERTICAL, pos=(0, 0))
  757. self.ffamilycb = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(250, -1),
  758. choices=self.ffamilydict.keys(), style=wx.CB_DROPDOWN)
  759. self.ffamilycb.SetStringSelection('swiss')
  760. for item in self.ffamilydict.items():
  761. if self.fontfamily == item[1]:
  762. self.ffamilycb.SetStringSelection(item[0])
  763. break
  764. gridSizer.Add(item=self.ffamilycb, pos=(0, 1), flag=wx.ALIGN_RIGHT)
  765. #
  766. # font style
  767. #
  768. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Style:"))
  769. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(1, 0))
  770. self.fstylecb = wx.ComboBox(parent=self, id=wx.ID_ANY, size=(250, -1),
  771. choices=self.fstyledict.keys(), style=wx.CB_DROPDOWN)
  772. self.fstylecb.SetStringSelection('normal')
  773. for item in self.fstyledict.items():
  774. if self.fontstyle == item[1]:
  775. self.fstylecb.SetStringSelection(item[0])
  776. break
  777. gridSizer.Add(item=self.fstylecb, pos=(1, 1), flag=wx.ALIGN_RIGHT)
  778. #
  779. # font weight
  780. #
  781. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Weight:"))
  782. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(2, 0))
  783. self.fwtcb = wx.ComboBox(parent=self, size=(250, -1),
  784. choices=self.fwtdict.keys(), style=wx.CB_DROPDOWN)
  785. self.fwtcb.SetStringSelection('normal')
  786. for item in self.fwtdict.items():
  787. if self.fontweight == item[1]:
  788. self.fwtcb.SetStringSelection(item[0])
  789. break
  790. gridSizer.Add(item=self.fwtcb, pos=(2, 1), flag=wx.ALIGN_RIGHT)
  791. boxSizer.Add(item=gridSizer, flag=wx.EXPAND)
  792. sizer.Add(item=boxSizer, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  793. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  794. sizer.Add(item=line, proportion=0,
  795. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=3)
  796. #
  797. # buttons
  798. #
  799. btnSave = wx.Button(self, wx.ID_SAVE)
  800. btnApply = wx.Button(self, wx.ID_APPLY)
  801. btnOk = wx.Button(self, wx.ID_OK)
  802. btnCancel = wx.Button(self, wx.ID_CANCEL)
  803. btnOk.SetDefault()
  804. # bindings
  805. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  806. btnApply.SetToolTipString(_("Apply changes for the current session"))
  807. btnOk.Bind(wx.EVT_BUTTON, self.OnOk)
  808. btnOk.SetToolTipString(_("Apply changes for the current session and close dialog"))
  809. btnOk.SetDefault()
  810. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  811. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  812. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  813. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  814. # sizers
  815. btnStdSizer = wx.StdDialogButtonSizer()
  816. btnStdSizer.AddButton(btnOk)
  817. btnStdSizer.AddButton(btnApply)
  818. btnStdSizer.AddButton(btnCancel)
  819. btnStdSizer.Realize()
  820. btnSizer = wx.BoxSizer(wx.HORIZONTAL)
  821. btnSizer.Add(item=btnSave, proportion=0, flag=wx.ALIGN_LEFT | wx.ALL, border=5)
  822. btnSizer.Add(item=btnStdSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  823. sizer.Add(item=btnSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  824. #
  825. # bindings
  826. #
  827. self.ptitleentry.Bind(wx.EVT_TEXT, self.OnTitle)
  828. self.xlabelentry.Bind(wx.EVT_TEXT, self.OnXLabel)
  829. self.ylabelentry.Bind(wx.EVT_TEXT, self.OnYLabel)
  830. self.SetSizer(sizer)
  831. sizer.Fit(self)
  832. def OnTitle(self, event):
  833. self.ptitle = event.GetString()
  834. def OnXLabel(self, event):
  835. self.xlabel = event.GetString()
  836. def OnYLabel(self, event):
  837. self.ylabel = event.GetString()
  838. def UpdateSettings(self):
  839. self.properties['font']['prop']['titleSize'] = self.ptitlesize.GetValue()
  840. self.properties['font']['prop']['axisSize'] = self.axislabelsize.GetValue()
  841. family = self.ffamilydict[self.ffamilycb.GetStringSelection()]
  842. self.properties['font']['wxfont'].SetFamily(family)
  843. style = self.fstyledict[self.fstylecb.GetStringSelection()]
  844. self.properties['font']['wxfont'].SetStyle(style)
  845. weight = self.fwtdict[self.fwtcb.GetStringSelection()]
  846. self.properties['font']['wxfont'].SetWeight(weight)
  847. def OnSave(self, event):
  848. """!Button 'Save' pressed"""
  849. self.UpdateSettings()
  850. fileSettings = {}
  851. UserSettings.ReadSettingsFile(settings=fileSettings)
  852. fileSettings['histogram'] = UserSettings.Get(group='histogram')
  853. file = UserSettings.SaveToFile(fileSettings)
  854. self.parent.parent.GetLayerManager().goutput.WriteLog(_('Histogram settings saved to file \'%s\'.') % file)
  855. self.EndModal(wx.ID_OK)
  856. def OnApply(self, event):
  857. """!Button 'Apply' pressed"""
  858. self.UpdateSettings()
  859. self.parent.OnPText(self)
  860. def OnOk(self, event):
  861. """!Button 'OK' pressed"""
  862. self.UpdateSettings()
  863. self.EndModal(wx.ID_OK)
  864. def OnCancel(self, event):
  865. """!Button 'Cancel' pressed"""
  866. self.EndModal(wx.ID_CANCEL)
  867. class OptDialog(wx.Dialog):
  868. def __init__(self, parent, id, title, pos=wx.DefaultPosition, size=wx.DefaultSize,
  869. style=wx.DEFAULT_DIALOG_STYLE):
  870. """!Dialog to set various profile options, including: line
  871. width, color, style; marker size, color, fill, and style; grid
  872. and legend options.
  873. """
  874. wx.Dialog.__init__(self, parent, id, title, pos, size, style)
  875. # init variables
  876. self.pstyledict = parent.pstyledict
  877. self.ptfilldict = parent.ptfilldict
  878. self.axislist = ['min',
  879. 'auto',
  880. 'custom']
  881. # widgets ids
  882. self.wxId = {}
  883. self.parent = parent
  884. # read-only
  885. self.raster = self.parent.raster
  886. self.rasterList = self.parent.rasterList
  887. self.properties = self.parent.properties
  888. self.map = ''
  889. if len(self.rasterList) == 0:
  890. wx.MessageBox(parent = self,
  891. message = _("No map or image group selected to histogram."),
  892. caption = _("Warning"), style = wx.OK | wx.ICON_ERROR)
  893. self._do_layout()
  894. def _do_layout(self):
  895. """!Do layout"""
  896. # dialog layout
  897. sizer = wx.BoxSizer(wx.VERTICAL)
  898. #
  899. # histogram line settings
  900. #
  901. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  902. label=" %s " % _("Histogram settings"))
  903. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  904. self.wxId['pcolor'] = 0
  905. self.wxId['pwidth'] = 0
  906. self.wxId['pstyle'] = 0
  907. self.wxId['plegend'] = 0
  908. if len(self.rasterList) > 0:
  909. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  910. label=_("Map/image histogrammed"))
  911. boxSizer = wx.StaticBoxSizer(box, wx.VERTICAL)
  912. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  913. row = 0
  914. self.mapchoice = wx.Choice(parent = self, id = wx.ID_ANY, size = (300, -1),
  915. choices = self.rasterList)
  916. if self.map == None or self.map == '':
  917. self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
  918. else:
  919. self.mapchoice.SetStringSelection(self.map)
  920. gridSizer.Add(item=self.mapchoice, flag=wx.ALIGN_CENTER_VERTICAL,
  921. pos=(row, 0), span=(1, 2))
  922. row +=1
  923. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line color"))
  924. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  925. pcolor = csel.ColourSelect(parent=self, id=wx.ID_ANY, colour=self.raster[self.map]['pcolor'])
  926. self.wxId['pcolor'] = pcolor.GetId()
  927. gridSizer.Add(item=pcolor, pos=(row, 1))
  928. row += 1
  929. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line width"))
  930. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  931. pwidth = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  932. size=(50,-1), style=wx.SP_ARROW_KEYS)
  933. pwidth.SetRange(1, 10)
  934. pwidth.SetValue(self.raster[self.map]['pwidth'])
  935. self.wxId['pwidth'] = pwidth.GetId()
  936. gridSizer.Add(item=pwidth, pos=(row, 1))
  937. row +=1
  938. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Line style"))
  939. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  940. pstyle = wx.Choice(parent=self, id=wx.ID_ANY,
  941. size=(120, -1), choices=self.pstyledict.keys(), style=wx.CB_DROPDOWN)
  942. pstyle.SetStringSelection(self.raster[self.map]['pstyle'])
  943. self.wxId['pstyle'] = pstyle.GetId()
  944. gridSizer.Add(item=pstyle, pos=(row, 1))
  945. row += 1
  946. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Legend"))
  947. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  948. plegend = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(200,-1))
  949. plegend.SetValue(self.raster[self.map]['plegend'])
  950. gridSizer.Add(item=plegend, pos=(row, 1))
  951. self.wxId['plegend'] = plegend.GetId()
  952. boxSizer.Add(item=gridSizer)
  953. flag = wx.ALL
  954. boxMainSizer.Add(item=boxSizer, flag=flag, border=3)
  955. sizer.Add(item=boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  956. middleSizer = wx.BoxSizer(wx.HORIZONTAL)
  957. #
  958. # axis options
  959. #
  960. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  961. label=" %s " % _("Axis settings"))
  962. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  963. self.wxId['x-axis'] = {}
  964. self.wxId['y-axis'] = {}
  965. idx = 0
  966. for axis, atype in [(_("X-Axis"), 'x-axis'),
  967. (_("Y-Axis"), 'y-axis')]:
  968. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  969. label=" %s " % axis)
  970. boxSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  971. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  972. prop = self.properties[atype]['prop']
  973. row = 0
  974. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Style"))
  975. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  976. type = wx.Choice(parent=self, id=wx.ID_ANY,
  977. size=(100, -1), choices=self.axislist, style=wx.CB_DROPDOWN)
  978. type.SetStringSelection(prop['type'])
  979. self.wxId[atype]['type'] = type.GetId()
  980. gridSizer.Add(item=type, pos=(row, 1))
  981. row += 1
  982. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Custom min"))
  983. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  984. min = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(70, -1))
  985. min.SetValue(str(prop['min']))
  986. self.wxId[atype]['min'] = min.GetId()
  987. gridSizer.Add(item=min, pos=(row, 1))
  988. row += 1
  989. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Custom max"))
  990. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  991. max = wx.TextCtrl(parent=self, id=wx.ID_ANY, value="", size=(70, -1))
  992. max.SetValue(str(prop['max']))
  993. self.wxId[atype]['max'] = max.GetId()
  994. gridSizer.Add(item=max, pos=(row, 1))
  995. row += 1
  996. log = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Log scale"))
  997. log.SetValue(prop['log'])
  998. self.wxId[atype]['log'] = log.GetId()
  999. gridSizer.Add(item=log, pos=(row, 0), span=(1, 2))
  1000. if idx == 0:
  1001. flag = wx.ALL | wx.EXPAND
  1002. else:
  1003. flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND
  1004. boxSizer.Add(item=gridSizer, flag=wx.ALL, border=3)
  1005. boxMainSizer.Add(item=boxSizer, flag=flag, border=3)
  1006. idx += 1
  1007. middleSizer.Add(item=boxMainSizer, flag=wx.ALL | wx.EXPAND, border=3)
  1008. #
  1009. # grid & legend options
  1010. #
  1011. self.wxId['grid'] = {}
  1012. self.wxId['legend'] = {}
  1013. self.wxId['font'] = {}
  1014. box = wx.StaticBox(parent=self, id=wx.ID_ANY,
  1015. label=" %s " % _("Grid and Legend settings"))
  1016. boxMainSizer = wx.StaticBoxSizer(box, wx.HORIZONTAL)
  1017. gridSizer = wx.GridBagSizer(vgap=5, hgap=5)
  1018. row = 0
  1019. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Grid color"))
  1020. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1021. gridcolor = csel.ColourSelect(parent=self, id=wx.ID_ANY, colour=self.properties['grid']['color'])
  1022. self.wxId['grid']['color'] = gridcolor.GetId()
  1023. gridSizer.Add(item=gridcolor, pos=(row, 1))
  1024. row +=1
  1025. gridshow = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Show grid"))
  1026. gridshow.SetValue(self.properties['grid']['enabled'])
  1027. self.wxId['grid']['enabled'] = gridshow.GetId()
  1028. gridSizer.Add(item=gridshow, pos=(row, 0), span=(1, 2))
  1029. row +=1
  1030. label = wx.StaticText(parent=self, id=wx.ID_ANY, label=_("Legend font size"))
  1031. gridSizer.Add(item=label, flag=wx.ALIGN_CENTER_VERTICAL, pos=(row, 0))
  1032. legendfontsize = wx.SpinCtrl(parent=self, id=wx.ID_ANY, value="",
  1033. size=(50, -1), style=wx.SP_ARROW_KEYS)
  1034. legendfontsize.SetRange(5,100)
  1035. legendfontsize.SetValue(int(self.properties['font']['prop']['legendSize']))
  1036. self.wxId['font']['legendSize'] = legendfontsize.GetId()
  1037. gridSizer.Add(item=legendfontsize, pos=(row, 1))
  1038. row += 1
  1039. legendshow = wx.CheckBox(parent=self, id=wx.ID_ANY, label=_("Show legend"))
  1040. legendshow.SetValue(self.properties['legend']['enabled'])
  1041. self.wxId['legend']['enabled'] = legendshow.GetId()
  1042. gridSizer.Add(item=legendshow, pos=(row, 0), span=(1, 2))
  1043. boxMainSizer.Add(item=gridSizer, flag=flag, border=3)
  1044. middleSizer.Add(item=boxMainSizer, flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.EXPAND, border=3)
  1045. sizer.Add(item=middleSizer, flag=wx.ALL, border=0)
  1046. #
  1047. # line & buttons
  1048. #
  1049. line = wx.StaticLine(parent=self, id=wx.ID_ANY, size=(20, -1), style=wx.LI_HORIZONTAL)
  1050. sizer.Add(item=line, proportion=0,
  1051. flag=wx.GROW|wx.ALIGN_CENTER_VERTICAL|wx.LEFT|wx.RIGHT, border=3)
  1052. #
  1053. # buttons
  1054. #
  1055. btnSave = wx.Button(self, wx.ID_SAVE)
  1056. btnApply = wx.Button(self, wx.ID_APPLY)
  1057. btnCancel = wx.Button(self, wx.ID_CANCEL)
  1058. btnSave.SetDefault()
  1059. # tooltips for buttons
  1060. btnApply.SetToolTipString(_("Apply changes for the current session"))
  1061. btnSave.SetToolTipString(_("Apply and save changes to user settings file (default for next sessions)"))
  1062. btnSave.SetDefault()
  1063. btnCancel.SetToolTipString(_("Close dialog and ignore changes"))
  1064. # sizers
  1065. btnStdSizer = wx.StdDialogButtonSizer()
  1066. btnStdSizer.AddButton(btnCancel)
  1067. btnStdSizer.AddButton(btnSave)
  1068. btnStdSizer.AddButton(btnApply)
  1069. btnStdSizer.Realize()
  1070. sizer.Add(item=btnStdSizer, proportion=0, flag=wx.ALIGN_RIGHT | wx.ALL, border=5)
  1071. #
  1072. # bindings for buttons and map plot settings controls
  1073. #
  1074. self.mapchoice.Bind(wx.EVT_CHOICE, self.OnSetMap)
  1075. pcolor.Bind(csel.EVT_COLOURSELECT, self.OnSetOpt)
  1076. pwidth.Bind(wx.EVT_SPINCTRL, self.OnSetOpt)
  1077. pstyle.Bind(wx.EVT_CHOICE, self.OnSetOpt)
  1078. plegend.Bind(wx.EVT_TEXT, self.OnSetOpt)
  1079. btnApply.Bind(wx.EVT_BUTTON, self.OnApply)
  1080. btnSave.Bind(wx.EVT_BUTTON, self.OnSave)
  1081. btnCancel.Bind(wx.EVT_BUTTON, self.OnCancel)
  1082. self.SetSizer(sizer)
  1083. sizer.Fit(self)
  1084. def OnSetMap(self, event):
  1085. """!Handler for changing map selection"""
  1086. self.map = event.GetString()
  1087. # update plot settings controls for selected map
  1088. self.FindWindowById(self.wxId['pcolor']).SetColour(self.raster[self.map]['pcolor'])
  1089. self.FindWindowById(self.wxId['pwidth']).SetValue(self.raster[self.map]['pwidth'])
  1090. self.FindWindowById(self.wxId['pstyle']).SetStringSelection(self.raster[self.map]['pstyle'])
  1091. self.FindWindowById(self.wxId['plegend']).SetValue(self.raster[self.map]['plegend'])
  1092. self.Refresh()
  1093. def OnSetOpt(self, event):
  1094. """!Handler for changing any other option"""
  1095. self.map = self.rasterList[self.mapchoice.GetCurrentSelection()]
  1096. self.UpdateSettings()
  1097. self.parent.SetGraphStyle()
  1098. if self.parent.histogram:
  1099. self.parent.DrawPlot()
  1100. def UpdateSettings(self):
  1101. """!Apply settings to each map and to entire plot"""
  1102. # update plot settings for selected map
  1103. self.raster[self.map]['pcolor'] = self.FindWindowById(self.wxId['pcolor']).GetColour()
  1104. self.raster[self.map]['pwidth'] = int(self.FindWindowById(self.wxId['pwidth']).GetValue())
  1105. self.raster[self.map]['pstyle'] = self.FindWindowById(self.wxId['pstyle']).GetStringSelection()
  1106. self.raster[self.map]['plegend'] = self.FindWindowById(self.wxId['plegend']).GetValue()
  1107. # update settings for entire plot
  1108. for axis in ('x-axis', 'y-axis'):
  1109. self.properties[axis]['prop']['type'] = self.FindWindowById(self.wxId[axis]['type']).GetStringSelection()
  1110. self.properties[axis]['prop']['min'] = float(self.FindWindowById(self.wxId[axis]['min']).GetValue())
  1111. self.properties[axis]['prop']['max'] = float(self.FindWindowById(self.wxId[axis]['max']).GetValue())
  1112. self.properties[axis]['prop']['log'] = self.FindWindowById(self.wxId[axis]['log']).IsChecked()
  1113. self.properties['grid']['color'] = self.FindWindowById(self.wxId['grid']['color']).GetColour()
  1114. self.properties['grid']['enabled'] = self.FindWindowById(self.wxId['grid']['enabled']).IsChecked()
  1115. self.properties['font']['prop']['legendSize'] = self.FindWindowById(self.wxId['font']['legendSize']).GetValue()
  1116. self.properties['legend']['enabled'] = self.FindWindowById(self.wxId['legend']['enabled']).IsChecked()
  1117. def OnSave(self, event):
  1118. """!Button 'Save' pressed"""
  1119. self.UpdateSettings()
  1120. fileSettings = {}
  1121. UserSettings.ReadSettingsFile(settings=fileSettings)
  1122. fileSettings['histogram'] = UserSettings.Get(group='histogram')
  1123. file = UserSettings.SaveToFile(fileSettings)
  1124. self.parent.parent.GetLayerManager().goutput.WriteLog(_('Histogram settings saved to file \'%s\'.') % file)
  1125. self.parent.SetGraphStyle()
  1126. if self.parent.histogram:
  1127. self.parent.DrawPlot()
  1128. self.Close()
  1129. def OnApply(self, event):
  1130. """!Button 'Apply' pressed. Does not close dialog"""
  1131. self.UpdateSettings()
  1132. self.parent.SetGraphStyle()
  1133. if self.parent.histogram:
  1134. self.parent.DrawPlot()
  1135. def OnCancel(self, event):
  1136. """!Button 'Cancel' pressed"""
  1137. self.Close()