d.vect.thematic.py 29 KB

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