mcalc_builder.py 16 KB

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