mcalc_builder.py 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. """
  2. MODULE: mcalc_builder.py
  3. CLASSES:
  4. * MapCalcFrame
  5. PURPOSE: GRASS builds r.mapcalc statements
  6. Usage:
  7. mcalc_builder
  8. AUTHOR(S): GRASS Development Team
  9. Original author: Michael Barton, Arizona State University
  10. COPYRIGHT: (C) 2008 by the GRASS Development Team
  11. This program is free software under the GNU General Public
  12. License (>=v2). Read the file COPYING that comes with GRASS
  13. for details.
  14. """
  15. import wx
  16. import os,sys
  17. import time
  18. import gcmd
  19. import gselect
  20. import subprocess
  21. imagePath = os.path.join( os.getenv("GISBASE"), "etc", "wxpython")
  22. sys.path.append(imagePath)
  23. import images
  24. imagepath = images.__path__[0]
  25. sys.path.append(imagepath)
  26. class MapCalcFrame(wx.Frame):
  27. """
  28. Mapcalc Frame class. Calculator-style window to create
  29. and run r.mapcalc statements
  30. """
  31. def __init__(self, parent, id, title, pos=wx.DefaultPosition,
  32. size=wx.DefaultSize, style=wx.TAB_TRAVERSAL|wx.DEFAULT_FRAME_STYLE,
  33. dimension=2):
  34. wx.Frame.__init__(self, parent, id, title, pos, size,
  35. style)
  36. self.Centre(wx.BOTH)
  37. if dimension == 3:
  38. self.SetTitle(_("GRASS %s Map Calculator") % "3D" )
  39. else:
  40. self.SetTitle(_("GRASS %s Map Calculator") % "2D" )
  41. #
  42. # variables
  43. #
  44. self.parent = parent
  45. self.heading = 'mapcalc statement'
  46. self.newmap = ''
  47. self.dimension = dimension
  48. self.funct_list = [
  49. 'abs(x)',
  50. 'acos(x)',
  51. 'asin(x)',
  52. 'atan(x)',
  53. 'atan(x,y)',
  54. 'cos(x)',
  55. 'double(x)',
  56. 'eval([x,y,...,]z)',
  57. 'exp(x)',
  58. 'exp(x,y)',
  59. 'float(x)',
  60. 'graph(x,x1,y1[x2,y2..])',
  61. 'if(x)',
  62. 'if(x,a)',
  63. 'if(x,a,b)',
  64. 'if(x,a,b,c)',
  65. 'int(x)',
  66. 'isnull(x)',
  67. 'log(x)',
  68. 'log(x,b)',
  69. 'max(x,y[,z...])',
  70. 'median(x,y[,z...])',
  71. 'min(x,y[,z...])',
  72. 'mode(x,y[,z...])',
  73. 'not(x)',
  74. 'pow(x,y)',
  75. 'rand(a,b)',
  76. 'round(x)',
  77. 'sin(x)',
  78. 'sqrt(x)',
  79. 'tan(x)',
  80. 'xor(x,y)',
  81. 'row()',
  82. 'col()',
  83. 'x()',
  84. 'y()',
  85. 'ewres()',
  86. 'nsres()',
  87. 'null()'
  88. ]
  89. if self.dimension == 3:
  90. indx = self.funct_list.index('y()') +1
  91. self.funct_list.insert(indx, 'z()')
  92. indx = self.funct_list.index('nsres()') +1
  93. self.funct_list.insert(indx, 'tbres()')
  94. maplabel = 'volume'
  95. element = 'rast3d'
  96. else:
  97. maplabel = 'map'
  98. element = 'cell'
  99. #
  100. # Buttons
  101. #
  102. self.btn_clear = wx.Button(self, -1, "Clear")
  103. self.btn_help = wx.Button(self, -1, "Help")
  104. self.btn_run = wx.Button(self, -1, "Run")
  105. self.btn_run.SetDefault()
  106. self.btn_close = wx.Button(self, -1, "Close")
  107. self.btn_pow = wx.Button(self, -1, "^")
  108. self.btn_pow.SetToolTipString('exponent')
  109. self.btn_div = wx.Button(self, -1, "/")
  110. self.btn_div.SetToolTipString('divide')
  111. self.btn_add = wx.Button(self, -1, "+")
  112. self.btn_add.SetToolTipString('add')
  113. self.btn_minus = wx.Button(self, -1, "-")
  114. self.btn_minus.SetToolTipString('subtract')
  115. self.btn_mod = wx.Button(self, -1, "%")
  116. self.btn_mod.SetToolTipString('modulus')
  117. self.btn_mult = wx.Button(self, -1, "*")
  118. self.btn_mult.SetToolTipString('multiply')
  119. self.btn_paren = wx.Button(self, -1, "( )")
  120. self.btn_lshift = wx.Button(self, -1, "<<")
  121. self.btn_lshift.SetToolTipString('left shift')
  122. self.btn_rshift = wx.Button(self, -1, ">>")
  123. self.btn_rshift.SetToolTipString('right shift')
  124. self.btn_rshiftu = wx.Button(self, -1, ">>>")
  125. self.btn_rshiftu.SetToolTipString('right shift (unsigned)')
  126. self.btn_gt = wx.Button(self, -1, ">")
  127. self.btn_gt.SetToolTipString('greater than')
  128. self.btn_gteq = wx.Button(self, -1, ">=")
  129. self.btn_gteq.SetToolTipString('greater than or equal to')
  130. self.btn_lt = wx.Button(self, -1, "<")
  131. self.btn_lt.SetToolTipString('less than or equal to')
  132. self.btn_lteq = wx.Button(self, -1, "<=")
  133. self.btn_lteq.SetToolTipString('less than')
  134. self.btn_eq = wx.Button(self, -1, "==")
  135. self.btn_eq.SetToolTipString('equal to')
  136. self.btn_noteq = wx.Button(self, -1, "!=")
  137. self.btn_noteq.SetToolTipString('not equal to')
  138. self.btn_compl = wx.Button(self, -1, "~")
  139. self.btn_compl.SetToolTipString("one's complement")
  140. self.btn_not = wx.Button(self, -1, "!")
  141. self.btn_not.SetToolTipString("NOT")
  142. self.btn_andbit = wx.Button(self, -1, '&')
  143. self.btn_andbit.SetToolTipString("bitwise AND")
  144. self.btn_orbit = wx.Button(self, -1, "|")
  145. self.btn_orbit.SetToolTipString("bitwise OR")
  146. self.btn_and = wx.Button(self, -1, "&&&")
  147. self.btn_and.SetToolTipString('logical AND')
  148. self.btn_andnull = wx.Button(self, -1, "&&&&&")
  149. self.btn_andnull.SetToolTipString('logical AND (ignores NULLs')
  150. self.btn_or = wx.Button(self, -1, "||")
  151. self.btn_or.SetToolTipString('logical OR')
  152. self.btn_ornull = wx.Button(self, -1, "|||")
  153. self.btn_ornull.SetToolTipString('logical OR (ignores NULLs')
  154. self.btn_cond = wx.Button(self, -1, "?:")
  155. self.btn_cond.SetToolTipString('conditional')
  156. #
  157. # Text area
  158. #
  159. self.text_mcalc = wx.TextCtrl(self, -1, '', size=(-1,75),style=wx.TE_MULTILINE)
  160. #
  161. # Map and function insertion text and ComboBoxes
  162. self.newmaplabel = wx.StaticText(self, -1, 'Name of new %s to create' % maplabel)
  163. self.newmaptxt = wx.TextCtrl(self, wx.ID_ANY, size=(250,-1))
  164. self.mapsellabel = wx.StaticText(self, -1, 'Insert existing %s' % maplabel)
  165. self.mapselect = gselect.Select(self, wx.ID_ANY, size=(250,-1),
  166. type=element, multiple=False)
  167. self.functlabel = wx.StaticText(self, -1, 'Insert mapcalc function')
  168. self.function = wx.ComboBox(self, wx.ID_ANY, "", (-1,-1),
  169. (250, -1), self.funct_list, wx.CB_DROPDOWN
  170. | wx.CB_READONLY
  171. | wx.TE_PROCESS_ENTER
  172. #| wx.CB_SORT
  173. )
  174. #
  175. # Bindings
  176. #
  177. self.btn_compl.Bind(wx.EVT_BUTTON, self.AddMark)
  178. self.btn_not.Bind(wx.EVT_BUTTON, self.AddMark)
  179. self.btn_pow.Bind(wx.EVT_BUTTON, self.AddMark)
  180. self.btn_div.Bind(wx.EVT_BUTTON, self.AddMark)
  181. self.btn_add.Bind(wx.EVT_BUTTON, self.AddMark)
  182. self.btn_minus.Bind(wx.EVT_BUTTON, self.AddMark)
  183. self.btn_mod.Bind(wx.EVT_BUTTON, self.AddMark)
  184. self.btn_mult.Bind(wx.EVT_BUTTON, self.AddMark)
  185. self.btn_lshift.Bind(wx.EVT_BUTTON, self.AddMark)
  186. self.btn_rshift.Bind(wx.EVT_BUTTON, self.AddMark)
  187. self.btn_rshiftu.Bind(wx.EVT_BUTTON, self.AddMark)
  188. self.btn_gt.Bind(wx.EVT_BUTTON, self.AddMark)
  189. self.btn_gteq.Bind(wx.EVT_BUTTON, self.AddMark)
  190. self.btn_lt.Bind(wx.EVT_BUTTON, self.AddMark)
  191. self.btn_lteq.Bind(wx.EVT_BUTTON, self.AddMark)
  192. self.btn_eq.Bind(wx.EVT_BUTTON, self.AddMark)
  193. self.btn_noteq.Bind(wx.EVT_BUTTON, self.AddMark)
  194. self.btn_andbit.Bind(wx.EVT_BUTTON, self.AddMark)
  195. self.btn_orbit.Bind(wx.EVT_BUTTON, self.AddMark)
  196. self.btn_and.Bind(wx.EVT_BUTTON, self.AddMark)
  197. self.btn_andnull.Bind(wx.EVT_BUTTON, self.AddMark)
  198. self.btn_or.Bind(wx.EVT_BUTTON, self.AddMark)
  199. self.btn_ornull.Bind(wx.EVT_BUTTON, self.AddMark)
  200. self.btn_cond.Bind(wx.EVT_BUTTON, self.AddMark)
  201. self.btn_paren.Bind(wx.EVT_BUTTON, self.AddMark)
  202. self.btn_close.Bind(wx.EVT_BUTTON, self.OnClose)
  203. self.btn_clear.Bind(wx.EVT_BUTTON, self.OnClear)
  204. self.btn_run.Bind(wx.EVT_BUTTON, self.OnMCalcRun)
  205. self.btn_help.Bind(wx.EVT_BUTTON, self.OnHelp)
  206. self.newmaptxt.Bind(wx.EVT_TEXT, self.OnNewmap)
  207. #self.mapselect.Bind(wx.EVT_COMBOBOX, self.OnSelect)
  208. self.mapselect.Bind(wx.EVT_TEXT, self.OnSelect)
  209. #self.mapselect.Bind(wx.EVT_TEXT_ENTER, self.OnSelect)
  210. self.function.Bind(wx.EVT_COMBOBOX, self.OnSelect)
  211. #self.function.Bind(wx.EVT_TEXT, self.OnSelect)
  212. self.function.Bind(wx.EVT_TEXT_ENTER, self.OnSelect)
  213. self.__doLayout()
  214. def __doLayout(self):
  215. pagesizer = wx.BoxSizer(wx.VERTICAL)
  216. controlsizer = wx.BoxSizer(wx.HORIZONTAL)
  217. btnpanelsizer = wx.GridBagSizer(1,1)
  218. buttonsizer1 = wx.GridBagSizer(5,1)
  219. buttonsizer1.Add(self.btn_add, (0,0))
  220. buttonsizer1.Add(self.btn_minus, (0,1))
  221. buttonsizer1.Add(self.btn_mod, (5,0))
  222. buttonsizer1.Add(self.btn_mult, (1,0))
  223. buttonsizer1.Add(self.btn_div, (1,1))
  224. buttonsizer1.Add(self.btn_pow, (5,1))
  225. buttonsizer1.Add(self.btn_gt, (2,0))
  226. buttonsizer1.Add(self.btn_gteq, (2,1))
  227. buttonsizer1.Add(self.btn_eq, (4,0))
  228. buttonsizer1.Add(self.btn_lt, (3,0))
  229. buttonsizer1.Add(self.btn_lteq, (3,1))
  230. buttonsizer1.Add(self.btn_noteq, (4,1))
  231. buttonsizer2 = wx.GridBagSizer(5,1)
  232. buttonsizer2.Add(self.btn_and, (0,0))
  233. buttonsizer2.Add(self.btn_andbit, (1,0))
  234. buttonsizer2.Add(self.btn_andnull, (2,0))
  235. buttonsizer2.Add(self.btn_or, (0,1))
  236. buttonsizer2.Add(self.btn_orbit, (1,1))
  237. buttonsizer2.Add(self.btn_ornull, (2,1))
  238. buttonsizer2.Add(self.btn_lshift, (3,0))
  239. buttonsizer2.Add(self.btn_rshift, (3,1))
  240. buttonsizer2.Add(self.btn_rshiftu, (4,0))
  241. buttonsizer2.Add(self.btn_cond, (5,0))
  242. buttonsizer2.Add(self.btn_compl, (5,1))
  243. buttonsizer2.Add(self.btn_not, (4,1))
  244. buttonsizer3 = wx.GridBagSizer(7, 1)
  245. buttonsizer3.Add(self.newmaplabel, (0,0), (1,2), wx.ALIGN_CENTER)
  246. buttonsizer3.Add(self.newmaptxt, (1,0), (1,2), wx.TOP, 4)
  247. buttonsizer3.Add(self.mapsellabel, (2,0), (1,2), wx.ALIGN_CENTER)
  248. buttonsizer3.Add(self.mapselect, (3,0), (1,2))
  249. buttonsizer3.Add(self.functlabel, (4,0), (1,2), wx.ALIGN_CENTER)
  250. buttonsizer3.Add(self.function, (5,0), (1,2))
  251. buttonsizer3.Add(self.btn_paren, (6,0), (1,1), wx.ALIGN_CENTER)
  252. buttonsizer3.Add(self.btn_clear, (6,1), (1,1), wx.ALIGN_CENTER)
  253. buttonsizer4 = wx.GridSizer(4, 3, 3, 3)
  254. buttonsizer4.Add(self.btn_run,0,wx.RIGHT,5)
  255. buttonsizer4.Add(self.btn_close,0,wx.RIGHT,5)
  256. buttonsizer4.Add(self.btn_help,0,wx.RIGHT,5)
  257. label = wx.StaticText(self, -1, 'Mapcalc operators')
  258. btnpanelsizer.Add(label, (0,0), (1,2), wx.ALIGN_CENTER)
  259. btnpanelsizer.Add(buttonsizer1, (1,0), (1,1), wx.RIGHT|wx.TOP, 5)
  260. btnpanelsizer.Add(buttonsizer2, (1,1), (1,1), wx.LEFT|wx.TOP, 5)
  261. controlsizer.Add(btnpanelsizer, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.RIGHT, border=20)
  262. controlsizer.Add(buttonsizer3, proportion=0)
  263. pagesizer.Add(controlsizer, flag=wx.EXPAND|wx.ALL,border=10)
  264. pagesizer.Add(self.text_mcalc, flag=wx.EXPAND|wx.ALL,border=5)
  265. pagesizer.Add(buttonsizer4, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, border=5)
  266. self.SetAutoLayout(True)
  267. self.SetSizer(pagesizer)
  268. pagesizer.Fit(self)
  269. #pagesizer.SetSizeHints(self)
  270. self.Layout()
  271. self.Show(True)
  272. def AddMark(self,event):
  273. """
  274. Sends operators to insertion method
  275. """
  276. if event.GetId() == self.btn_compl.GetId(): mark = "~"
  277. elif event.GetId() == self.btn_not.GetId(): mark = "!"
  278. elif event.GetId() == self.btn_pow.GetId(): mark = "^"
  279. elif event.GetId() == self.btn_div.GetId(): mark = "/"
  280. elif event.GetId() == self.btn_add.GetId(): mark = "+"
  281. elif event.GetId() == self.btn_minus.GetId(): mark = "-"
  282. elif event.GetId() == self.btn_mod.GetId(): mark = "%"
  283. elif event.GetId() == self.btn_mult.GetId(): mark = "*"
  284. elif event.GetId() == self.btn_lshift.GetId(): mark = "<<"
  285. elif event.GetId() == self.btn_rshift.GetId(): mark = ">>"
  286. elif event.GetId() == self.btn_rshiftu.GetId(): mark = ">>>"
  287. elif event.GetId() == self.btn_gt.GetId(): mark = ">"
  288. elif event.GetId() == self.btn_gteq.GetId(): mark = ">="
  289. elif event.GetId() == self.btn_lt.GetId(): mark = "<"
  290. elif event.GetId() == self.btn_lteq.GetId(): mark = "<="
  291. elif event.GetId() == self.btn_eq.GetId(): mark = "=="
  292. elif event.GetId() == self.btn_noteq.GetId(): mark = "!="
  293. elif event.GetId() == self.btn_andbit.GetId(): mark = "&"
  294. elif event.GetId() == self.btn_orbit.GetId(): mark = "|"
  295. elif event.GetId() == self.btn_or.GetId(): mark = "||"
  296. elif event.GetId() == self.btn_ornull.GetId(): mark = "|||"
  297. elif event.GetId() == self.btn_and.GetId(): mark = "&&"
  298. elif event.GetId() == self.btn_andnull.GetId(): mark = "&&&"
  299. elif event.GetId() == self.btn_cond.GetId(): mark = "?:"
  300. elif event.GetId() == self.btn_paren.GetId(): mark = "()"
  301. self.__addSomething(mark)
  302. def OnNewmap(self, event):
  303. self.newmap = event.GetString()
  304. def OnSelect(self, event):
  305. """
  306. Gets raster map or function selection and send it to insertion method
  307. """
  308. item = event.GetString()
  309. self.__addSomething(item)
  310. self.text_mcalc.SetFocus()
  311. def __addSomething(self,what):
  312. """
  313. Inserts operators, map names, and functions into text area
  314. """
  315. self.text_mcalc.SetFocus()
  316. mcalcstr = self.text_mcalc.GetValue()
  317. newmcalcstr = ''
  318. position = self.text_mcalc.GetInsertionPoint()
  319. selection = self.text_mcalc.GetSelection()
  320. newmcalcstr = mcalcstr[:position]
  321. try:
  322. if newmcalcstr[-1] != " ":
  323. newmcalcstr += " "
  324. except:
  325. pass
  326. newmcalcstr += what
  327. position_offset = len(what)
  328. newmcalcstr += " "+mcalcstr[position:]
  329. self.text_mcalc.SetValue(newmcalcstr)
  330. self.text_mcalc.SetInsertionPoint(position+position_offset)
  331. self.text_mcalc.Update()
  332. def OnMCalcRun(self,event):
  333. """
  334. Builds and runs r.mapcalc statement
  335. """
  336. if self.newmap == '':
  337. wx.MessageBox("You must enter the name of a new map to create")
  338. return
  339. if self.text_mcalc.GetValue() == '':
  340. wx.MessageBox("You must enter a mapcalc statement to create a new map")
  341. return
  342. mctxt = self.text_mcalc.GetValue().strip().replace("\n"," ")
  343. mctxt = mctxt.replace(" ","")
  344. if self.dimension == 3:
  345. gcmd.RunCommand('r3.mapcalc',
  346. expression = "%s=%s" % (self.newmap,mctxt))
  347. else:
  348. gcmd.RunCommand('r.mapcalc',
  349. expression = "%s=%s" % (self.newmap,mctxt))
  350. def OnClear(self, event):
  351. """
  352. Clears text area
  353. """
  354. self.text_mcalc.SetValue("")
  355. def OnHelp(self, event):
  356. """
  357. Launches r.mapcalc help
  358. """
  359. gcmd.RunCommand('g.manual',
  360. entry = 'r.mapcalc')
  361. def OnClose(self,event):
  362. self.Destroy()
  363. if __name__ == "__main__":
  364. if len(sys.argv) != 2:
  365. print >>sys.stderr, __doc__
  366. sys.exit()
  367. app = wx.App(0)
  368. sqlb = SQLFrame(None, -1, 'SQL Builder',sys.argv[1])
  369. app.MainLoop()