d.vect.thematic.py 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  1. #!/usr/bin/env python
  2. #
  3. ############################################################################
  4. #
  5. # MODULE: d.vect.thematic
  6. # AUTHOR(S): Michael Barton, Arizona State University with contributions
  7. # by Martin Landa, Jachym Cepicky, Daniel Calvelo Aros and Moritz Lennert
  8. # PURPOSE: Displays thematic vector map with graduated colors
  9. # or graduated points and line thickneses
  10. # COPYRIGHT: (C) 2006 by the GRASS Development Team
  11. #
  12. # This program is free software under the GNU General Public
  13. # License (>=v2). Read the file COPYING that comes with GRASS
  14. # for details.
  15. #
  16. #############################################################################
  17. #%module
  18. #% description: Displays thematic vector map
  19. #% keywords: display
  20. #% keywords: cartography
  21. #% keywords: vector
  22. #% keywords: thematic
  23. #% keywords: legend
  24. #%end
  25. #%option G_OPT_V_MAP
  26. #%end
  27. #%option G_OPT_V_FIELD
  28. #%end
  29. #%option G_OPT_DB_COLUMN
  30. #% description: Name of attribute column to use for thematic display (must be numeric)
  31. #% required: yes
  32. #%end
  33. #%option G_OPT_V_TYPE
  34. #% answer: area
  35. #%end
  36. #%option
  37. #% key: themetype
  38. #% type: string
  39. #% options: graduated_colors,graduated_points,graduated_lines
  40. #% answer: graduated_colors
  41. #% description: Type of thematic display
  42. #% required: yes
  43. #% guisection: Theme
  44. #%end
  45. #%option
  46. #% key: themecalc
  47. #% type: string
  48. #% options: interval,std_deviation,quartiles,custom_breaks
  49. #% answer: interval
  50. #% description: Thematic divisions of data for display
  51. #% required: yes
  52. #% guisection: Theme
  53. #%end
  54. #%option
  55. #% key: breakpoints
  56. #% type: string
  57. #% label: Break points for custom breaks option
  58. #% description: Separate values by spaces (0 10 20 30 ...)
  59. #% required: no
  60. #% guisection: Theme
  61. #%end
  62. #%option
  63. #% key: icon
  64. #% type: string
  65. #% description: Vector point icon for point data
  66. #% options: basic/box,basic/circle,basic/cross2,basic/diamond,basic/star,basic/cross1,basic/x
  67. #% answer: basic/circle
  68. #% required: no
  69. #% guisection: Points
  70. #%end
  71. #%option
  72. #% key: size
  73. #% type: double
  74. #% label: Icon size for point data
  75. #% description: Minimum icon size/line width for graduated points/lines)
  76. #% answer: 5
  77. #% required: no
  78. #% guisection: Points
  79. #%end
  80. #%option
  81. #% key: maxsize
  82. #% type: double
  83. #% description: Maximum icon size/line width for graduated points and lines
  84. #% answer: 20
  85. #% required: no
  86. #% guisection: Points
  87. #%end
  88. #%option
  89. #% key: nint
  90. #% type: integer
  91. #% description: Number of classes for interval theme (integer)
  92. #% answer: 4
  93. #% required: no
  94. #% guisection: Theme
  95. #%end
  96. #%option
  97. #% key: colorscheme
  98. #% type: string
  99. #% label: Color scheme for graduated color mapping
  100. #% description: Select 'single_color' for graduated point/line display
  101. #% options: blue-red,red-blue,green-red,red-green,blue-green,green-blue,cyan-yellow,yellow-cyan,custom_gradient,single_color
  102. #% answer: blue-red
  103. #% required: yes
  104. #% guisection: Color
  105. #%end
  106. #% option
  107. #% key: pointcolor
  108. #% type: string
  109. #% label: Color for graduated points map
  110. #% description: GRASS named color or R:G:B triplet. Set color scheme to single color
  111. #% answer: 255:0:0
  112. #% required: no
  113. #% guisection: Color
  114. #%end
  115. #% option
  116. #% key: linecolor
  117. #% type: string
  118. #% label: Color for graduated lines or point/area outlines
  119. #% description: GRASS named color or R:G:B triplet. Set color scheme to single color.
  120. #% answer: 0:0:0
  121. #% required: no
  122. #% guisection: Color
  123. #%end
  124. #% option
  125. #% key: startcolor
  126. #% type: string
  127. #% label: Beginning color for custom color gradient
  128. #% description: Must be expressed as R:G:B triplet
  129. #% answer: 255:0:0
  130. #% required: no
  131. #% guisection: Color
  132. #%end
  133. #% option
  134. #% key: endcolor
  135. #% type: string
  136. #% label: Ending color for custom color gradient
  137. #% description: Must be expressed as R:G:B triplet
  138. #% answer: 0:0:255
  139. #% required: no
  140. #% guisection: Color
  141. #%end
  142. #% option
  143. #% key: monitor
  144. #% type: string
  145. #% description: Select WXGUI display monitor for legend
  146. #% options: wx0,wx1,wx2,wx3,wx4,wx5,wx6,none
  147. #% answer: wx1
  148. #% required: no
  149. #% guisection: Misc
  150. #%end
  151. #%flag
  152. #% guisection: Files
  153. #% key: g
  154. #%description: Save thematic map commands to group file for GIS Manager
  155. #%end
  156. #%option G_OPT_DB_WHERE
  157. #% guisection: Theme
  158. #%end
  159. #%option
  160. #% key: psmap
  161. #% type: string
  162. #% label: Root for the name of psmap instruction files to be in current directory
  163. #% description: If not set, no psmap instruction files will be created)
  164. #% required: no
  165. #% guisection: Files
  166. #%end
  167. #%option G_OPT_I_GROUP
  168. #% description: Name of group file where thematic map commands will be saved
  169. #% required: no
  170. #% guisection: Files
  171. #%end
  172. #%flag
  173. #% guisection: Theme
  174. #%key: l
  175. #%description: Create graphic legend in x11 display monitor
  176. #%end
  177. #%flag
  178. #% guisection: Color
  179. #% key: f
  180. #% description: Only draw fills (no outlines) for areas and points
  181. #%end
  182. #%flag
  183. #% guisection: Color
  184. #% key: u
  185. #% description: Update color values to GRASSRGB column in attribute table
  186. #%end
  187. #%flag
  188. #% guisection: Misc
  189. #%key: s
  190. #%description: Output legend for GIS Manager (for scripting use only)
  191. #%end
  192. #%flag
  193. #% guisection: Misc
  194. #%key: m
  195. #%description: Use math notation brackets in legend
  196. #%end
  197. import sys
  198. import os
  199. import string
  200. import shutil
  201. import atexit
  202. import grass.script as grass
  203. tmp_graph = None
  204. tmp_group = None
  205. tmp_psmap = None
  206. tmp_psleg = None
  207. tmp_gisleg = None
  208. def cleanup():
  209. for file in [tmp_graph, tmp_group, tmp_psmap, tmp_psleg, tmp_gisleg]:
  210. if file:
  211. grass.try_remove(file)
  212. # hard-coded parameter: the maximum number of legend items before
  213. # we strip them using a middle ellipsis
  214. max_leg_items = 18
  215. def subs(vars, tmpl):
  216. return string.Template(tmpl).substitute(vars)
  217. def msg(vars, tmpl):
  218. grass.message(subs(vars, tmpl))
  219. def out(fh, vars, tmpl):
  220. fh.write(subs(vars, tmpl))
  221. def main():
  222. global tmp_graph, tmp_group, tmp_psmap, tmp_psleg, tmp_gisleg
  223. breakpoints = options['breakpoints']
  224. colorscheme = options['colorscheme']
  225. column = options['column']
  226. endcolor = options['endcolor']
  227. group = options['group']
  228. layer = options['layer']
  229. linecolor = options['linecolor']
  230. map = options['map']
  231. maxsize = options['maxsize']
  232. monitor = options['monitor']
  233. nint = options['nint']
  234. pointcolor = options['pointcolor']
  235. psmap = options['psmap']
  236. size = options['size']
  237. startcolor = options['startcolor']
  238. themecalc = options['themecalc']
  239. themetype = options['themetype']
  240. type = options['type']
  241. where = options['where']
  242. icon = options['icon']
  243. flag_f = flags['f']
  244. flag_g = flags['g']
  245. flag_l = flags['l']
  246. flag_m = flags['m']
  247. flag_s = flags['s']
  248. flag_u = flags['u']
  249. layer = int(layer)
  250. nint = int(nint)
  251. size = float(size)
  252. maxsize = float(maxsize)
  253. # check column type
  254. inf = grass.vector_columns(map, layer)
  255. if column not in inf:
  256. grass.fatal(_("No such column <%s>") % column)
  257. coltype = inf[column]['type'].lower()
  258. if coltype not in ["integer", "double precision"]:
  259. grass.fatal(_("Column <%s> is of type <%s> which is not numeric.") % (column, coltype))
  260. # create temporary file to hold d.graph commands for legend
  261. tmp_graph = grass.tempfile()
  262. # Create temporary file to commands for GIS Manager group
  263. tmp_group = grass.tempfile()
  264. # Create temporary file for commands for ps.map map file
  265. tmp_psmap = grass.tempfile()
  266. # Create temporary file for commands for ps.map legend file
  267. tmp_psleg = grass.tempfile()
  268. # create file to hold elements for GIS Manager legend
  269. tmp_gisleg = grass.tempfile()
  270. # Set display variables for group
  271. atype = int(type == "area")
  272. ptype = int(type == "point")
  273. ctype = int(type == "centroid")
  274. ltype = int(type == "line")
  275. btype = int(type == "boundary")
  276. # if running in the GUI, do not create a graphic legend in an xmon
  277. if flag_s:
  278. flag_l = False
  279. # if running in GUI, turn off immediate mode rendering so that the
  280. # iterated d.vect commands will composite using the display driver
  281. os.environ['GRASS_PNG_READ'] = 'TRUE'
  282. os.environ['GRASS_PNG_AUTO_WRITE'] = 'FALSE'
  283. db = grass.vector_db(map)[1]
  284. if not db or not db['table']:
  285. grass.fatal(_("No table connected or layer <%s> does not exist.") % layer)
  286. table = db['table']
  287. database = db['database']
  288. driver = db['driver']
  289. # update color values to the table?
  290. if flag_u:
  291. # test, if the column GRASSRGB is in the table
  292. s = grass.read_command('db.columns', table = table, database = database, driver = driver)
  293. if 'grassrgb' not in s.splitlines():
  294. msg(locals(), _("Creating column 'grassrgb' in table <$table>"))
  295. sql = "ALTER TABLE %s ADD COLUMN grassrgb varchar(11)" % table
  296. grass.write_command('db.execute', database = database, driver = driver, stdin = sql)
  297. # Group name
  298. if not group:
  299. group = "themes"
  300. f_group = file(tmp_group, 'w')
  301. f_group.write("Group %s\n" % group)
  302. # Calculate statistics for thematic intervals
  303. if type == "line":
  304. stype = "line"
  305. else:
  306. stype = ["point", "centroid"]
  307. if not where:
  308. where = None
  309. stats = grass.read_command('v.univar', flags = 'eg', map = map, type = stype, column = column, where = where, layer = layer)
  310. stats = grass.parse_key_val(stats)
  311. min = float(stats['min'])
  312. max = float(stats['max'])
  313. mean = float(stats['mean'])
  314. sd = float(stats['population_stddev'])
  315. q1 = float(stats['first_quartile'])
  316. q2 = float(stats['median'])
  317. q3 = float(stats['third_quartile'])
  318. q4 = max
  319. ptsize = size
  320. if breakpoints and themecalc != "custom_breaks":
  321. grass.warning(_("Custom breakpoints ignored due to themecalc setting."))
  322. # set interval for each thematic map calculation type
  323. if themecalc == "interval":
  324. numint = nint
  325. step = float(max - min) / numint
  326. breakpoints = [min + i * step for i in xrange(numint + 1)]
  327. annotations = ""
  328. elif themecalc == "std_deviation":
  329. # 2 standard deviation units on either side of mean,
  330. # plus min to -2 sd units and +2 sd units to max, if applicable
  331. breakpoints = [min] + [i for i in [(mean + i * sd) for i in [-2,-1,0,1,2]] if min < i < max] + [max]
  332. annotations = [""] + [("%dsd" % i) for (i, j) in [(i, mean + i * sd) for i in [-2,-1,0,1,2]] if (min < j < max)] + [""]
  333. annotations = ";".join(annotations)
  334. numint = len(breakpoints) - 1
  335. elif themecalc == "quartiles":
  336. numint=4
  337. # one for each quartile
  338. breakpoints = [min, q1, q2, q3, max]
  339. annotations = " %f; %f; %f; %f" % (q1, q2, q3, q4)
  340. elif themecalc == "custom_breaks":
  341. if not breakpoints:
  342. breakpoints = sys.stdin.read()
  343. breakpoints = [int(x) for x in breakpoints.split()]
  344. numint = len(breakpoints) - 1
  345. annotations = ""
  346. else:
  347. grass.fatal(_("Unknown themecalc type <%s>") % themecalc)
  348. pointstep = (maxsize - ptsize) / (numint - 1)
  349. # Prepare legend cuts for too large numint
  350. if numint > max_leg_items:
  351. xupper = int(numint - max_leg_items / 2) + 1
  352. xlower = int(max_leg_items / 2) + 1
  353. else:
  354. xupper = 0
  355. xlower = 0
  356. # legend title
  357. f_graph = file(tmp_graph, 'w')
  358. out(f_graph, locals(), """\
  359. color 0:0:0
  360. size 2 2
  361. move 1 95
  362. text Thematic map legend for column $column of map $map
  363. size 1.5 1.8
  364. move 4 90
  365. text Value range: $min - $max
  366. """)
  367. f_gisleg = file(tmp_gisleg, 'w')
  368. out(f_gisleg, locals(), """\
  369. title - - - {Thematic map legend for column $column of map $map}
  370. """)
  371. f_psleg = file(tmp_psleg, 'w')
  372. out(f_psleg, locals(), """\
  373. text 1% 95% Thematic map legend for column $column of map $map
  374. ref bottom left
  375. end
  376. text 4% 90% Value range: $min - $max
  377. ref bottom left
  378. end
  379. """)
  380. msg(locals(), _("Thematic map legend for column $column of map $map"))
  381. msg(locals(), _("Value range: $min - $max"))
  382. colorschemes = {
  383. "blue-red": ("0:0:255", "255:0:0"),
  384. "red-blue": ("255:0:0", "0:0:255"),
  385. "green-red": ("0:255:0", "255:0:0"),
  386. "red-green": ("255:0:0", "0:255:0"),
  387. "blue-green": ("0:0:255", "0:255:0"),
  388. "green-blue": ("0:255:0", "0:0:255"),
  389. "cyan-yellow": ("0:255:255", "255:255:0"),
  390. "yellow-cyan": ("255:255:0", "0:255:255"),
  391. "custom_gradient": (startcolor, endcolor)
  392. }
  393. # open file for psmap instructions
  394. f_psmap = file(tmp_psmap, 'w')
  395. # graduated color thematic mapping
  396. if themetype == "graduated_colors":
  397. if colorscheme in colorschemes:
  398. startc, endc = colorschemes[colorscheme]
  399. # set color schemes for graduated color maps
  400. elif colorscheme == "single_color":
  401. if themetype == "graduated_points":
  402. startc = endc = linecolor
  403. else:
  404. startc = endc = pointcolor
  405. else:
  406. grass.fatal(_("This should not happen: parser error. Unknown color scheme %s") % colorscheme)
  407. color = __builtins__.map(int, startc.split(":"))
  408. endcolor = __builtins__.map(int, endc.split(":"))
  409. #The number of color steps is one less then the number of classes
  410. nclrstep = numint - 1
  411. clrstep = [(a - b) / nclrstep for a, b in zip(color, endcolor)]
  412. themecolor = startc
  413. # display graduated color themes
  414. if themecalc == "interval":
  415. out(f_graph, locals(), """\
  416. move 4 87
  417. text Mapped by $numint intervals of $step
  418. """)
  419. out(f_gisleg, locals(), """\
  420. subtitle - - - {Mapped by $numint intervals of $step}
  421. """)
  422. out(f_psleg, locals(), """\
  423. text 4% 87% Mapped by $numint intervals of $step
  424. ref bottom left
  425. end
  426. """)
  427. msg(locals(), _("Mapped by $numint intervals of $step"))
  428. # display graduated color themes for standard deviation units
  429. if themecalc == "std_deviation":
  430. out(f_graph, locals(), """\
  431. move 4 87
  432. text Mapped by standard deviation units of $sd (mean = $mean)
  433. """)
  434. out(f_gisleg, locals(), """\
  435. subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)}
  436. """)
  437. out(f_psleg, locals(), """\
  438. text 4% 87% Mapped by standard deviation units of $sd (mean = $mean)
  439. ref bottom left
  440. end
  441. """)
  442. msg(locals(), _("Mapped by standard deviation units of $sd (mean = $mean)"))
  443. # display graduated color themes for quartiles
  444. if themecalc == "quartiles":
  445. out(f_graph, locals(), """\
  446. move 4 87
  447. text Mapped by quartiles (median = $q2)
  448. """)
  449. out(f_gisleg, locals(), """\
  450. subtitle - - - {Mapped by quartiles (median = $q2)}
  451. """)
  452. out(f_psleg, locals(), """\
  453. text 4% 87% Mapped by quartiles (median = $q2)
  454. ref bottom left
  455. end
  456. """)
  457. msg(locals(), _("Mapped by quartiles (median = $q2)"))
  458. f_graph.write("""\
  459. move 4 83
  460. text Color
  461. move 14 83
  462. text Value
  463. move 4 80
  464. text =====
  465. move 14 80
  466. text ============
  467. """)
  468. f_psleg.write("""\
  469. text 4% 83% Color
  470. ref bottom left
  471. end
  472. text 14% 83% Value
  473. ref bottom left
  474. end
  475. text 4% 80% =====
  476. ref bottom left
  477. end
  478. text 14% 80% ============
  479. ref bottom left
  480. end
  481. """)
  482. sys.stdout.write("Color(R:G:B)\tValue\n")
  483. sys.stdout.write("============\t==========\n")
  484. line1 = 78
  485. line2 = 76
  486. line3 = 75
  487. i = 1
  488. first = True
  489. while i < numint:
  490. if flag_m:
  491. # math notation
  492. if first:
  493. closebracket = "]"
  494. openbracket = "["
  495. mincomparison = ">="
  496. first = False
  497. else:
  498. closebracket = "]"
  499. openbracket = "]"
  500. mincomparison = ">"
  501. else:
  502. closebracket = ""
  503. openbracket = ""
  504. if first:
  505. mincomparison = ">="
  506. first = False
  507. else:
  508. mincomparison = ">"
  509. themecolor = ":".join(__builtins__.map(str,color))
  510. if flag_f:
  511. linecolor = "none"
  512. else:
  513. if type in ["line", "boundary"]:
  514. linecolor = themecolor
  515. else:
  516. linecolor = linecolor
  517. rangemin = __builtins__.min(breakpoints)
  518. rangemax = __builtins__.max(breakpoints)
  519. if not annotations:
  520. extranote = ""
  521. else:
  522. extranote = annotations[i]
  523. if i < xlower or i >= xupper:
  524. xline1 = line2 + 2
  525. xline3 = line2 - 1
  526. out(f_graph, locals(), """\
  527. color $themecolor
  528. polygon
  529. 5 $xline1
  530. 8 $xline1
  531. 8 $xline3
  532. 5 $xline3
  533. color $linecolor
  534. move 5 $xline1
  535. draw 8 $xline1
  536. draw 8 $xline3
  537. draw 5 $xline3
  538. draw 5 $xline1
  539. move 14 $line2
  540. color 0:0:0
  541. text $openbracket$rangemin - $rangemax$closebracket $extranote
  542. """)
  543. else:
  544. if i == xlower:
  545. out(f_graph, locals(), """\
  546. color 0:0:0
  547. move 10 $line2
  548. text ...
  549. """)
  550. else:
  551. #undo next increment
  552. line2 += 4
  553. if i < xlower or i >= xupper:
  554. out(f_gisleg, locals(), """\
  555. area $themecolor $linecolor - {$openbracket$rangemin - $rangemax$closebracket $extranote}
  556. """)
  557. if type in ["line", "boundary"]:
  558. out(f_psleg, locals(), """\
  559. line 5% $xline1% 8% $xline1%
  560. color $linecolor
  561. end
  562. text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote
  563. ref center left
  564. end
  565. """)
  566. elif type in ["point", "centroid"]:
  567. out(f_psleg, locals(), """\
  568. point 8% $xline1%
  569. color $linecolor
  570. fcolor $themecolor
  571. size $size
  572. symbol $icon
  573. end
  574. text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote
  575. ref center left
  576. end
  577. """)
  578. else:
  579. out(f_psleg, locals(), """\
  580. rectangle 5% $xline1% 8% $xline3%
  581. color 0:0:0
  582. fcolor $themecolor
  583. end
  584. text 14% $xline3% $openbracket$rangemin - $rangemax$closebracket DCADCA $extranote
  585. ref bottom left
  586. end
  587. """)
  588. else:
  589. if i == xlower:
  590. out(f_psleg, locals(), """\
  591. color 0:0:0
  592. text 14% $xline3% ...
  593. ref bottom left
  594. end
  595. """)
  596. f_gisleg.write("text - - - {...}\n")
  597. sys.stdout.write(subs(locals(), "$themecolor\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n"))
  598. if not where:
  599. sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax")
  600. else:
  601. sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax AND $where")
  602. # update color to database?
  603. if flag_u:
  604. sql = subs(locals(), "UPDATE $table SET GRASSRGB = '$themecolor' WHERE $sqlwhere")
  605. grass.write_command('db.execute', database = database, driver = driver, stdin = sql)
  606. # Create group for GIS Manager
  607. if flag_g:
  608. # change rgb colors to hex
  609. xthemecolor = "#%02X%02X%02X" % tuple(__builtins__.map(int, themecolor.split(":")))
  610. #xlinecolor=`echo $linecolor | awk -F: '{printf("#%02X%02X%02X\n",$1,$2,$3)}'`
  611. if "$linecolor" == "black":
  612. xlinecolor = "#000000"
  613. else:
  614. xlinecolor = xthemecolor
  615. # create group entry
  616. out(f_group, locals(), """\
  617. _check 1
  618. Vector $column = $rangemin - $rangemax
  619. _check 1
  620. map $map
  621. display_shape 1
  622. display_cat 0
  623. display_topo 0
  624. display_dir 0
  625. display_attr 0
  626. type_point $ptype
  627. type_line $ltype
  628. type_boundary $btype
  629. type_centroid $ctype
  630. type_area $atype
  631. type_face 0
  632. color $xlinecolor
  633. fcolor $xthemecolor
  634. width $ptsize
  635. _use_fcolor 1
  636. lcolor #000000
  637. sqlcolor 0
  638. icon $icon
  639. size $ptsize
  640. field $layer
  641. lfield $layer
  642. attribute
  643. xref left
  644. yref center
  645. lsize 8
  646. cat
  647. where $sqlwhere
  648. _query_text 0
  649. _query_edit 1
  650. _use_where 1
  651. minreg
  652. maxreg
  653. _width 0.1
  654. End
  655. """)
  656. # display theme vector map
  657. grass.run_command('d.vect', map = map, type = type, layer = layer,
  658. where = sqlwhere,
  659. color = linecolor, fcolor = themecolor, icon = icon, size = ptsize)
  660. if type in ["line", "boundary"]:
  661. out(f_psmap, locals(), """\
  662. vlines $map
  663. type $type
  664. layer $layer
  665. where $sqlwhere
  666. color $linecolor
  667. label $rangemin - $rangemax
  668. end
  669. """)
  670. elif type in ["point", "centroid"]:
  671. out(f_psmap, locals(), """\
  672. vpoints $map
  673. type $type
  674. layer $layer
  675. where $sqlwhere
  676. color $linecolor
  677. fcolor $themecolor
  678. symbol $icon
  679. label $rangemin - $rangemax
  680. end
  681. """)
  682. else:
  683. out(f_psmap, locals(), """\
  684. vareas $map
  685. layer $layer
  686. where $sqlwhere
  687. color $linecolor
  688. fcolor $themecolor
  689. label $rangemin - $rangemax
  690. end
  691. """)
  692. # increment for next theme
  693. i += 1
  694. if i == numint:
  695. color = endcolor
  696. else:
  697. color = [a - b for a, b in zip(color, clrstep)]
  698. line1 -= 4
  699. line2 -= 4
  700. line3 -= 4
  701. #graduated points and line widths thematic mapping
  702. if themetype in ["graduated_points", "graduated_lines"]:
  703. #display graduated points/lines by intervals
  704. if themecalc == "interval":
  705. out(f_graph, locals(), """\
  706. move 4 87
  707. text Mapped by $numint intervals of $step
  708. """)
  709. out(f_gisleg, locals(), """\
  710. subtitle - - - {Mapped by $numint intervals of $step}
  711. """)
  712. out(f_psleg, locals(), """\
  713. text 4% 87% Mapped by $numint intervals of $step
  714. ref bottom left
  715. end
  716. """)
  717. msg(locals(), _("Mapped by $numint intervals of $step"))
  718. # display graduated points/lines for standard deviation units
  719. if themecalc == "std_deviation":
  720. out(f_graph, locals(), """\
  721. move 4 87
  722. text Mapped by standard deviation units of $sd (mean = $mean)
  723. """)
  724. out(f_gisleg, locals(), """\
  725. subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)}
  726. """)
  727. out(f_psleg, locals(), """\
  728. text 4% 87% Mapped by standard deviation units of $sd (mean = $mean)
  729. ref bottom left
  730. end
  731. """)
  732. msg(locals(), _("Mapped by standard deviation units of $sd (mean = $mean)"))
  733. # display graduated points/lines for quartiles
  734. if themecalc == "quartiles":
  735. out(f_graph, locals(), """\
  736. move 4 87
  737. text Mapped by quartiles (median = $q2)
  738. """)
  739. out(f_gisleg, locals(), """\
  740. subtitle - - - {Mapped by quartiles (median = $q2)}
  741. """)
  742. out(f_psleg, locals(), """\
  743. text 4% 87% Mapped by quartiles (median = $q2)
  744. ref bottom left
  745. end
  746. """)
  747. msg(locals(), _("Mapped by quartiles (median = $q2)"))
  748. line1 = 76
  749. line2 = 75
  750. out(f_graph, locals(), """\
  751. move 4 83
  752. text Size/width
  753. move 25 83
  754. text Value
  755. move 4 80
  756. text ==============
  757. move 25 80
  758. text ==============
  759. """)
  760. out(f_psleg, locals(), """\
  761. text 4% 83% Icon size
  762. ref bottom left
  763. end
  764. text 25% 83% Value
  765. ref bottom left
  766. end
  767. text 4% 80% ============
  768. ref bottom left
  769. end
  770. text 25% 80% ============
  771. ref bottom left
  772. end
  773. """)
  774. sys.stdout.write("Size/width\tValue\n")
  775. sys.stdout.write("==========\t=====\n")
  776. themecolor = pointcolor
  777. if flag_f:
  778. linecolor = "none"
  779. i = numint
  780. ptsize = maxsize
  781. while i >= 1:
  782. if flag_m:
  783. # math notation
  784. if i == 1:
  785. closebracket = "]"
  786. openbracket = "["
  787. mincomparison = ">="
  788. else:
  789. closebracket = "]"
  790. openbracket = "]"
  791. mincomparison = ">"
  792. else:
  793. closebracket = ""
  794. openbracket = ""
  795. if i == 1:
  796. mincomparison = ">="
  797. else:
  798. mincomparison = ">"
  799. themecolor = pointcolor
  800. if flag_f:
  801. linecolor = "none"
  802. rangemin = __builtins__.min(breakpoints)
  803. rangemax = __builtins__.max(breakpoints)
  804. if not annotations:
  805. extranote = ""
  806. else:
  807. extranote = annotations[i]
  808. iconsize = int(ptsize / 2)
  809. lineht = int(ptsize / 4)
  810. if lineht < 4:
  811. lineht = 4
  812. if i < xlower or i >= xupper:
  813. if themetype == "graduated_lines":
  814. out(f_graph, locals(), """\
  815. color $linecolor
  816. """)
  817. out(f_gisleg, locals(), """\
  818. line $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote}
  819. """)
  820. else:
  821. out(f_graph, locals(), """\
  822. color $themecolor
  823. """)
  824. out(f_gisleg, locals(), """\
  825. point $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote}
  826. """)
  827. out(f_graph, locals(), """\
  828. icon + $iconsize 5 $line1
  829. color 0:0:0
  830. move 10 $line2
  831. text $ptsize pts
  832. move 25 $line2
  833. text $openbracket$rangemin - $rangemax$closebracket $extranote
  834. """)
  835. else:
  836. if i == xlower:
  837. out(f_graph, locals(), """\
  838. color 0:0:0
  839. move 10 $line2
  840. text ...
  841. """)
  842. out(f_gisleg, locals(), """\
  843. text - - - ...
  844. """)
  845. else:
  846. # undo future line increment
  847. line2 += lineht
  848. if i < xlower or i >= xupper:
  849. out(f_psleg, locals(), """\
  850. point 8% $line1%
  851. color $linecolor
  852. fcolor $themecolor
  853. size $iconsize
  854. symbol $icon
  855. end
  856. text 25% $line1% $openbracket$rangemin - $rangemax$closebracket $extranote
  857. ref center left
  858. end
  859. """)
  860. else:
  861. if i == xlower:
  862. out(f_psleg, locals(), """\
  863. text 25% $xline1% ...
  864. ref center left
  865. end
  866. """)
  867. sys.stdout.write(subs(locals(), "$ptsize\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n"))
  868. if not where:
  869. sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax")
  870. else:
  871. sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax AND $where")
  872. # update color to database?
  873. if flag_u:
  874. sql = subs(locals(), "UPDATE $table SET grassrgb = '$themecolor' WHERE $sqlwhere")
  875. grass.write_command('db.execute', database = database, driver = driver, stdin = sql)
  876. # Create group for GIS Manager
  877. if flag_g:
  878. # change rgb colors to hex
  879. xthemecolor = "#%02X%02X%02X" % tuple(__builtins__.map(int,themecolor.split(":")))
  880. xlinecolor = "#000000"
  881. # create group entry
  882. out(f_group, locals(), """\
  883. _check 1
  884. Vector $column = $rangemin - $rangemax
  885. _check 1
  886. map $map
  887. display_shape 1
  888. display_cat 0
  889. display_topo 0
  890. display_dir 0
  891. display_attr 0
  892. type_point $ptype
  893. type_line $ltype
  894. type_boundary $btype
  895. type_centroid $ctype
  896. type_area $atype
  897. type_face 0
  898. color $xlinecolor
  899. width $ptsize
  900. fcolor $xthemecolor
  901. _use_fcolor 1
  902. lcolor #000000
  903. sqlcolor 0
  904. icon $icon
  905. size $ptsize
  906. field $layer
  907. lfield $layer
  908. attribute
  909. xref left
  910. yref center
  911. lsize 8
  912. cat
  913. where $sqlwhere
  914. _query_text 0
  915. _query_edit 1
  916. _use_where 1
  917. minreg
  918. maxreg
  919. _width 0.1
  920. End
  921. """)
  922. #graduates line widths or point sizes
  923. if themetype == "graduated_lines":
  924. grass.run_command('d.vect', map = map, type = type, layer = layer,
  925. where = sqlwhere,
  926. color = linecolor, fcolor = themecolor, icon = icon, size = ptsize,
  927. width = ptsize)
  928. else:
  929. grass.run_command('d.vect', map = map, type = type, layer = layer,
  930. where = sqlwhere,
  931. color = linecolor, fcolor = themecolor, icon = icon, size = ptsize)
  932. out(f_psmap, locals(), """\
  933. vpoints $map
  934. type $type
  935. layer $layer
  936. where $sqlwhere
  937. color $linecolor
  938. fcolor $themecolor
  939. symbol $icon
  940. size $ptsize
  941. label $rangemin - $rangemax
  942. end
  943. """)
  944. ptsize -= pointstep
  945. line1 -= lineht
  946. line2 -= lineht
  947. i -= 1
  948. # Create graphic legend
  949. f_graph.close()
  950. if flag_l:
  951. grass.run_command('d.erase')
  952. grass.run_command('d.graph', input = tmp_graph)
  953. # Create group file for GIS Manager
  954. f_group.write("End\n")
  955. f_group.close()
  956. if flag_g:
  957. shutil.copyfile(tmp_group, "%s.dm" % group)
  958. # Create ps.map map file
  959. f_psmap.write("end\n")
  960. f_psmap.close()
  961. if psmap:
  962. shutil.copyfile(tmp_psmap, "%s.psmap" % psmap)
  963. # Create ps.map legend file
  964. f_psleg.write("end\n")
  965. f_psleg.close()
  966. if psmap:
  967. shutil.copyfile(tmp_psleg, "%s_legend.psmap" % psmap)
  968. # Create text file to use with d.graph in GIS Manager
  969. f_gisleg.close()
  970. if flag_s:
  971. tmpdir = os.path.dirname(tmp_gisleg)
  972. tlegfile = os.path.join(tmpdir, "gismlegend.txt")
  973. shutil.copyfile(tmp_gisleg, tlegfile)
  974. if __name__ == "__main__":
  975. options, flags = grass.parser()
  976. atexit.register(cleanup)
  977. main()