2 @package mcalc_builder.py
4 @brief Map calculator, wrapper for r.mapcalc
9 (C) 2008, 2011 by the GRASS Development Team
11 This program is free software under the GNU General Public License
12 (>=v2). Read the file COPYING that comes with GRASS for details.
14 @author Michael Barton, Arizona State University
15 @author Martin Landa <landa.martin gmail.com>
16 @author Tim Michelsen (load/save expression)
33 sys.path.append(os.path.join(globalvar.ETCWXDIR,
"compat"))
35 from preferences
import globalSettings
as UserSettings
38 """!Mapcalc Frame class. Calculator-style window to create and run
39 r(3).mapcalc statements.
41 def __init__(self, parent, cmd, id = wx.ID_ANY,
42 style = wx.DEFAULT_FRAME_STYLE | wx.RESIZE_BORDER, **kwargs):
45 self.
log = self.parent.GetLogWindow()
52 if self.
cmd ==
'r.mapcalc':
54 title = _(
'GRASS GIS Raster Map Calculator')
55 if self.
cmd ==
'r3.mapcalc':
57 title = _(
'GRASS GIS 3D Raster Map Calculator')
59 wx.Frame.__init__(self, parent, id = id, title = title, **kwargs)
60 self.SetIcon(wx.Icon(os.path.join(globalvar.ETCICONDIR,
'grass.ico'), wx.BITMAP_TYPE_ICO))
62 self.
panel = wx.Panel(parent = self, id = wx.ID_ANY)
63 self.CreateStatusBar()
74 'atan(x,y)':
'atan( , )',
76 'double(x)':
'double()',
77 'eval([x,y,...,]z)':
'eval()',
79 'exp(x,y)':
'exp( , )',
81 'graph(x,x1,y1[x2,y2..])':
'graph( , , )',
84 'if(x,a,b)':
'if( , , )',
85 'if(x,a,b,c)':
'if( , , , )',
87 'isnull(x)':
'isnull()',
89 'log(x,b)':
'log( , )',
90 'max(x,y[,z...])':
'max( , )',
91 'median(x,y[,z...])':
'median( , )',
92 'min(x,y[,z...])':
'min( , )',
93 'mode(x,y[,z...])':
'mode( , )',
95 'pow(x,y)':
'pow( , )',
96 'rand(a,b)':
'rand( , )',
101 'xor(x,y)':
'xor( , )',
119 label=
" %s " % _(
'Operators'))
121 label=
" %s " % _(
'Operands'))
123 label=
" %s " % _(
'Expression'))
128 self.
btn_clear = wx.Button(parent = self.
panel, id = wx.ID_CLEAR, label = _(
"Cl&ear"))
130 self.
btn_run = wx.Button(parent = self.
panel, id = wx.ID_ANY, label = _(
"&Run"))
131 self.btn_run.SetDefault()
134 self.btn_save.SetToolTipString(_(
'Save expression to file'))
137 self.btn_load.SetToolTipString(_(
'Load expression from file'))
140 self.
btn[
'pow'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"^")
141 self.
btn[
'pow'].SetToolTipString(_(
'exponent'))
142 self.
btn[
'div'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"/")
143 self.
btn[
'div'].SetToolTipString(_(
'divide'))
144 self.
btn[
'add'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"+")
145 self.
btn[
'add'].SetToolTipString(_(
'add'))
146 self.
btn[
'minus'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"-")
147 self.
btn[
'minus'].SetToolTipString(_(
'subtract'))
148 self.
btn[
'mod'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"%")
149 self.
btn[
'mod'].SetToolTipString(_(
'modulus'))
150 self.
btn[
'mult'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"*")
151 self.
btn[
'mult'].SetToolTipString(_(
'multiply'))
153 self.
btn[
'parenl'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"(")
154 self.
btn[
'parenr'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
")")
155 self.
btn[
'lshift'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"<<")
156 self.
btn[
'lshift'].SetToolTipString(_(
'left shift'))
157 self.
btn[
'rshift'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
">>")
158 self.
btn[
'rshift'].SetToolTipString(_(
'right shift'))
159 self.
btn[
'rshiftu'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
">>>")
160 self.
btn[
'rshiftu'].SetToolTipString(_(
'right shift (unsigned)'))
161 self.
btn[
'gt'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
">")
162 self.
btn[
'gt'].SetToolTipString(_(
'greater than'))
163 self.
btn[
'gteq'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
">=")
164 self.
btn[
'gteq'].SetToolTipString(_(
'greater than or equal to'))
165 self.
btn[
'lt'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"<")
166 self.
btn[
'lt'].SetToolTipString(_(
'less than'))
167 self.
btn[
'lteq'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"<=")
168 self.
btn[
'lteq'].SetToolTipString(_(
'less than or equal to'))
169 self.
btn[
'eq'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"==")
170 self.
btn[
'eq'].SetToolTipString(_(
'equal to'))
171 self.
btn[
'noteq'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"!=")
172 self.
btn[
'noteq'].SetToolTipString(_(
'not equal to'))
174 self.
btn[
'compl'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"~")
175 self.
btn[
'compl'].SetToolTipString(_(
'one\'s complement'))
176 self.
btn[
'not'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"!")
177 self.
btn[
'not'].SetToolTipString(_(
'NOT'))
178 self.
btn[
'andbit'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
'&&')
179 self.
btn[
'andbit'].SetToolTipString(_(
'bitwise AND'))
180 self.
btn[
'orbit'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"|")
181 self.
btn[
'orbit'].SetToolTipString(_(
'bitwise OR'))
182 self.
btn[
'and'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"&&&&")
183 self.
btn[
'and'].SetToolTipString(_(
'logical AND'))
184 self.
btn[
'andnull'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"&&&&&&")
185 self.
btn[
'andnull'].SetToolTipString(_(
'logical AND (ignores NULLs)'))
186 self.
btn[
'or'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"||")
187 self.
btn[
'or'].SetToolTipString(_(
'logical OR'))
188 self.
btn[
'ornull'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"|||")
189 self.
btn[
'ornull'].SetToolTipString(_(
'logical OR (ignores NULLs)'))
190 self.
btn[
'cond'] = wx.Button(parent = self.
panel, id = wx.ID_ANY, label =
"a ? b : c")
191 self.
btn[
'cond'].SetToolTipString(_(
'conditional'))
197 style = wx.TE_MULTILINE)
198 wx.CallAfter(self.text_mcalc.SetFocus)
204 self.newmaplabel.SetLabel(_(
'Name for new 3D raster map to create'))
206 self.newmaplabel.SetLabel(_(
'Name for new raster map to create'))
207 self.
newmaptxt = wx.TextCtrl(parent = self.
panel, id = wx.ID_ANY, size=(250, -1))
210 self.mapsellabel.SetLabel(_(
'Insert existing 3D raster map'))
212 self.mapsellabel.SetLabel(_(
'Insert existing raster map'))
214 type = element, multiple =
False)
216 label = _(
'Insert mapcalc function'))
218 size = (250, -1), choices = sorted(self.funct_dict.keys()),
219 style = wx.CB_DROPDOWN |
220 wx.CB_READONLY | wx.TE_PROCESS_ENTER)
223 label=_(
'Add created raster map into layer tree'), style = wx.NO_BORDER)
224 self.addbox.SetValue(UserSettings.Get(group=
'cmd', key=
'addNewLayer', subkey=
'enabled'))
225 if not self.
parent or self.parent.GetName() !=
'LayerManager':
231 for btn
in self.btn.keys():
232 self.
btn[btn].Bind(wx.EVT_BUTTON, self.
AddMark)
234 self.btn_close.Bind(wx.EVT_BUTTON, self.
OnClose)
235 self.btn_clear.Bind(wx.EVT_BUTTON, self.
OnClear)
236 self.btn_run.Bind(wx.EVT_BUTTON, self.
OnMCalcRun)
237 self.btn_help.Bind(wx.EVT_BUTTON, self.
OnHelp)
241 self.mapselect.Bind(wx.EVT_TEXT, self.
OnSelect)
243 self.function.Bind(wx.EVT_TEXT_ENTER, self.
OnSelect)
249 self.SetMinSize(self.GetBestSize())
251 def _return_funct(self,event):
252 i = event.GetString()
256 sizer = wx.BoxSizer(wx.VERTICAL)
258 controlSizer = wx.BoxSizer(wx.HORIZONTAL)
259 operatorSizer = wx.StaticBoxSizer(self.
operatorBox, wx.HORIZONTAL)
261 buttonSizer1 = wx.GridBagSizer(5, 1)
262 buttonSizer1.Add(item = self.
btn[
'add'], pos = (0,0))
263 buttonSizer1.Add(item = self.
btn[
'minus'], pos = (0,1))
264 buttonSizer1.Add(item = self.
btn[
'mod'], pos = (5,0))
265 buttonSizer1.Add(item = self.
btn[
'mult'], pos = (1,0))
266 buttonSizer1.Add(item = self.
btn[
'div'], pos = (1,1))
267 buttonSizer1.Add(item = self.
btn[
'pow'], pos = (5,1))
268 buttonSizer1.Add(item = self.
btn[
'gt'], pos = (2,0))
269 buttonSizer1.Add(item = self.
btn[
'gteq'], pos = (2,1))
270 buttonSizer1.Add(item = self.
btn[
'eq'], pos = (4,0))
271 buttonSizer1.Add(item = self.
btn[
'lt'], pos = (3,0))
272 buttonSizer1.Add(item = self.
btn[
'lteq'], pos = (3,1))
273 buttonSizer1.Add(item = self.
btn[
'noteq'], pos = (4,1))
275 buttonSizer2 = wx.GridBagSizer(5, 1)
276 buttonSizer2.Add(item = self.
btn[
'and'], pos = (0,0))
277 buttonSizer2.Add(item = self.
btn[
'andbit'], pos = (1,0))
278 buttonSizer2.Add(item = self.
btn[
'andnull'], pos = (2,0))
279 buttonSizer2.Add(item = self.
btn[
'or'], pos = (0,1))
280 buttonSizer2.Add(item = self.
btn[
'orbit'], pos = (1,1))
281 buttonSizer2.Add(item = self.
btn[
'ornull'], pos = (2,1))
282 buttonSizer2.Add(item = self.
btn[
'lshift'], pos = (3,0))
283 buttonSizer2.Add(item = self.
btn[
'rshift'], pos = (3,1))
284 buttonSizer2.Add(item = self.
btn[
'rshiftu'], pos = (4,0))
285 buttonSizer2.Add(item = self.
btn[
'cond'], pos = (5,0))
286 buttonSizer2.Add(item = self.
btn[
'compl'], pos = (5,1))
287 buttonSizer2.Add(item = self.
btn[
'not'], pos = (4,1))
289 operandSizer = wx.StaticBoxSizer(self.
operandBox, wx.HORIZONTAL)
290 buttonSizer3 = wx.GridBagSizer(7, 1)
291 buttonSizer3.Add(item = self.
newmaplabel, pos = (0,0),
292 span = (1, 2), flag = wx.ALIGN_CENTER)
293 buttonSizer3.Add(item = self.
newmaptxt, pos = (1,0),
295 buttonSizer3.Add(item = self.
functlabel, pos = (2,0),
296 span = (1,2), flag = wx.ALIGN_CENTER)
297 buttonSizer3.Add(item = self.
function, pos = (3,0),
299 buttonSizer3.Add(item = self.
mapsellabel, pos = (4,0),
300 span = (1,2), flag = wx.ALIGN_CENTER)
301 buttonSizer3.Add(item = self.
mapselect, pos = (5,0),
303 threebutton = wx.GridBagSizer(1, 2)
304 threebutton.Add(item = self.
btn[
'parenl'], pos = (0,0),
305 span = (1,1), flag = wx.ALIGN_LEFT)
306 threebutton.Add(item = self.
btn[
'parenr'], pos = (0,1),
307 span = (1,1), flag = wx.ALIGN_CENTER)
308 threebutton.Add(item = self.
btn_clear, pos = (0,2),
309 span = (1,1), flag = wx.ALIGN_RIGHT)
310 buttonSizer3.Add(item = threebutton, pos = (6,0),
311 span = (1,1), flag = wx.ALIGN_CENTER)
313 buttonSizer4 = wx.BoxSizer(wx.HORIZONTAL)
314 buttonSizer4.AddSpacer(10)
315 buttonSizer4.Add(item = self.
btn_load,
316 flag = wx.ALL, border = 5)
317 buttonSizer4.Add(item = self.
btn_save,
318 flag = wx.ALL, border = 5)
319 buttonSizer4.AddSpacer(30)
320 buttonSizer4.Add(item = self.
btn_help,
321 flag = wx.ALL, border = 5)
322 buttonSizer4.Add(item = self.
btn_run,
323 flag = wx.ALL, border = 5)
325 flag = wx.ALL, border = 5)
327 operatorSizer.Add(item = buttonSizer1, proportion = 0,
328 flag = wx.ALL | wx.EXPAND, border = 5)
329 operatorSizer.Add(item = buttonSizer2, proportion = 0,
330 flag = wx.TOP | wx.BOTTOM | wx.RIGHT | wx.EXPAND, border = 5)
332 operandSizer.Add(item = buttonSizer3, proportion = 0,
333 flag = wx.TOP | wx.BOTTOM | wx.RIGHT, border = 5)
335 controlSizer.Add(item = operatorSizer, proportion = 1,
336 flag = wx.RIGHT | wx.EXPAND, border = 5)
337 controlSizer.Add(item = operandSizer, proportion = 0,
340 expressSizer = wx.StaticBoxSizer(self.
expressBox, wx.HORIZONTAL)
341 expressSizer.Add(item = self.
text_mcalc, proportion = 1,
344 sizer.Add(item = controlSizer, proportion = 0,
345 flag = wx.EXPAND | wx.ALL,
347 sizer.Add(item = expressSizer, proportion = 1,
348 flag = wx.EXPAND | wx.LEFT | wx.RIGHT,
350 sizer.Add(item = buttonSizer4, proportion = 0,
351 flag = wx.ALIGN_RIGHT | wx.ALL, border = 3)
352 if self.addbox.IsShown():
353 sizer.Add(item = self.
addbox, proportion = 0,
354 flag = wx.LEFT | wx.RIGHT,
357 self.panel.SetAutoLayout(
True)
358 self.panel.SetSizer(sizer)
359 sizer.Fit(self.
panel)
364 """!Sends operators to insertion method
366 if event.GetId() == self.
btn[
'compl'].GetId(): mark =
"~"
367 elif event.GetId() == self.
btn[
'not'].GetId(): mark =
"!"
368 elif event.GetId() == self.
btn[
'pow'].GetId(): mark =
"^"
369 elif event.GetId() == self.
btn[
'div'].GetId(): mark =
"/"
370 elif event.GetId() == self.
btn[
'add'].GetId(): mark =
"+"
371 elif event.GetId() == self.
btn[
'minus'].GetId(): mark =
"-"
372 elif event.GetId() == self.
btn[
'mod'].GetId(): mark =
"%"
373 elif event.GetId() == self.
btn[
'mult'].GetId(): mark =
"*"
374 elif event.GetId() == self.
btn[
'lshift'].GetId(): mark =
"<<"
375 elif event.GetId() == self.
btn[
'rshift'].GetId(): mark =
">>"
376 elif event.GetId() == self.
btn[
'rshiftu'].GetId(): mark =
">>>"
377 elif event.GetId() == self.
btn[
'gt'].GetId(): mark =
">"
378 elif event.GetId() == self.
btn[
'gteq'].GetId(): mark =
">="
379 elif event.GetId() == self.
btn[
'lt'].GetId(): mark =
"<"
380 elif event.GetId() == self.
btn[
'lteq'].GetId(): mark =
"<="
381 elif event.GetId() == self.
btn[
'eq'].GetId(): mark =
"=="
382 elif event.GetId() == self.
btn[
'noteq'].GetId(): mark =
"!="
383 elif event.GetId() == self.
btn[
'andbit'].GetId(): mark =
"&"
384 elif event.GetId() == self.
btn[
'orbit'].GetId(): mark =
"|"
385 elif event.GetId() == self.
btn[
'or'].GetId(): mark =
"||"
386 elif event.GetId() == self.
btn[
'ornull'].GetId(): mark =
"|||"
387 elif event.GetId() == self.
btn[
'and'].GetId(): mark =
"&&"
388 elif event.GetId() == self.
btn[
'andnull'].GetId(): mark =
"&&&"
389 elif event.GetId() == self.
btn[
'cond'].GetId(): mark =
" ? : "
390 elif event.GetId() == self.
btn[
'parenl'].GetId(): mark =
"("
391 elif event.GetId() == self.
btn[
'parenr'].GetId(): mark =
")"
395 """!Gets raster map or function selection and send it to
398 item = event.GetString()
402 """!Update statusbar text"""
403 self.SetStatusText(
"r.mapcalc '%s = %s'" % (self.newmaptxt.GetValue(),
404 self.text_mcalc.GetValue()))
407 def _addSomething(self, what):
408 """!Inserts operators, map names, and functions into text area
410 self.text_mcalc.SetFocus()
411 mcalcstr = self.text_mcalc.GetValue()
412 position = self.text_mcalc.GetInsertionPoint()
414 newmcalcstr = mcalcstr[:position]
418 if newmcalcstr[-1] !=
' ':
425 position_offset += len(what)
426 newmcalcstr +=
' ' + mcalcstr[position:]
428 self.text_mcalc.SetValue(newmcalcstr)
431 self.text_mcalc.SetInsertionPoint(position + position_offset)
432 self.text_mcalc.Update()
435 """!Builds and runs r.mapcalc statement
437 name = self.newmaptxt.GetValue().strip()
440 message = _(
"You must enter the name of a new map to create"))
443 if not self.text_mcalc.GetValue().strip():
445 message = _(
"You must enter a mapcalc statement to create a new map"))
448 mctxt = self.text_mcalc.GetValue().strip().replace(
"\n",
" ")
449 mctxt = mctxt.replace(
" " ,
"")
452 cmd = [self.
cmd, str(
'%s = %s' % (name, mctxt))]
453 self.log.RunCmd(cmd, onDone = self.
OnDone)
456 gcmd.RunCommand(self.
cmd,
457 "%s=%s" % (name, mctxt))
460 """!Add create map to the layer tree"""
461 if not self.addbox.IsChecked():
463 name = self.newmaptxt.GetValue().strip() +
'@' + grass.gisenv()[
'MAPSET']
464 mapTree = self.parent.GetLayerTree()
465 if not mapTree.GetMap().GetListOfLayers(l_name = name):
466 mapTree.AddLayer(ltype =
'raster',
468 lcmd = [
'd.rast',
'map=%s' % name],
471 display = self.parent.GetLayerTree().GetMapDisplay()
472 if display
and display.IsAutoRendered():
473 display.GetWindow().UpdateMap(render =
True)
476 """!Saves expression to file
478 mctxt = self.newmaptxt.GetValue() +
' = ' + self.text_mcalc.GetValue() + os.linesep
481 dlg = wx.FileDialog(parent = self,
482 message = _(
"Choose a file name to save the expression"),
483 wildcard = _(
"Expression file (*)|*"),
484 style = wx.SAVE | wx.FD_OVERWRITE_PROMPT)
485 if dlg.ShowModal() == wx.ID_OK:
492 fobj = open(path,
'w')
500 """!Load expression from file
502 dlg = wx.FileDialog(parent = self,
503 message = _(
"Choose a file name to load the expression"),
504 wildcard = _(
"Expression file (*)|*"),
506 if dlg.ShowModal() == wx.ID_OK:
513 fobj = open(path,
'r')
519 result, exp = mctxt.split(
'=', 1)
524 self.newmaptxt.SetValue(result.strip())
525 self.text_mcalc.SetValue(exp.strip())
526 self.text_mcalc.SetFocus()
527 self.text_mcalc.SetInsertionPointEnd()
534 self.text_mcalc.SetValue(
'')
537 """!Launches r.mapcalc help
539 gcmd.RunCommand(
'g.manual', parent = self, entry = self.
cmd)
545 if __name__ ==
"__main__":