utils.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413
  1. # -*- coding: utf-8 -*-
  2. import itertools
  3. import fnmatch
  4. import os
  5. from sqlite3 import OperationalError
  6. import grass.lib.gis as libgis
  7. libgis.G_gisinit('')
  8. import grass.lib.raster as libraster
  9. from grass.script import core as grasscore
  10. from grass.pygrass.errors import GrassError
  11. def looking(obj, filter_string):
  12. """
  13. >>> import grass.lib.vector as libvect
  14. >>> sorted(looking(libvect, '*by_box*')) # doctest: +NORMALIZE_WHITESPACE
  15. ['Vect_select_areas_by_box', 'Vect_select_isles_by_box',
  16. 'Vect_select_lines_by_box', 'Vect_select_nodes_by_box']
  17. """
  18. word_list = dir(obj)
  19. word_list.sort()
  20. return fnmatch.filter(word_list, filter_string)
  21. def findfiles(dirpath, match=None):
  22. """Return a list of the files"""
  23. res = []
  24. for f in sorted(os.listdir(dirpath)):
  25. abspath = os.path.join(dirpath, f)
  26. if os.path.isdir(abspath):
  27. res.extend(findfiles(abspath, match))
  28. if match:
  29. if fnmatch.fnmatch(abspath, match):
  30. res.append(abspath)
  31. else:
  32. res.append(abspath)
  33. return res
  34. def findmaps(type, pattern=None, mapset='', location='', gisdbase=''):
  35. """Return a list of tuple contining the names of the:
  36. * map
  37. * mapset,
  38. * location,
  39. * gisdbase
  40. """
  41. from grass.pygrass.gis import Gisdbase, Location, Mapset
  42. def find_in_location(type, pattern, location):
  43. res = []
  44. for msetname in location.mapsets():
  45. mset = Mapset(msetname, location.name, location.gisdbase)
  46. res.extend([(m, mset.name, mset.location, mset.gisdbase)
  47. for m in mset.glist(type, pattern)])
  48. return res
  49. def find_in_gisdbase(type, pattern, gisdbase):
  50. res = []
  51. for loc in gisdbase.locations():
  52. res.extend(find_in_location(type, pattern,
  53. Location(loc, gisdbase.name)))
  54. return res
  55. if gisdbase and location and mapset:
  56. mset = Mapset(mapset, location, gisdbase)
  57. return [(m, mset.name, mset.location, mset.gisdbase)
  58. for m in mset.glist(type, pattern)]
  59. elif gisdbase and location:
  60. loc = Location(location, gisdbase)
  61. return find_in_location(type, pattern, loc)
  62. elif gisdbase:
  63. gis = Gisdbase(gisdbase)
  64. return find_in_gisdbase(type, pattern, gis)
  65. elif location:
  66. loc = Location(location)
  67. return find_in_location(type, pattern, loc)
  68. elif mapset:
  69. mset = Mapset(mapset)
  70. return [(m, mset.name, mset.location, mset.gisdbase)
  71. for m in mset.glist(type, pattern)]
  72. else:
  73. gis = Gisdbase()
  74. return find_in_gisdbase(type, pattern, gis)
  75. def remove(oldname, maptype):
  76. """Remove a map"""
  77. grasscore.run_command('g.remove', quiet=True, flags='f',
  78. type=maptype, name=oldname)
  79. def rename(oldname, newname, maptype, **kwargs):
  80. """Rename a map"""
  81. kwargs.update({maptype: '{old},{new}'.format(old=oldname, new=newname), })
  82. grasscore.run_command('g.rename', quiet=True, **kwargs)
  83. def copy(existingmap, newmap, maptype, **kwargs):
  84. """Copy a map
  85. >>> copy('census', 'mycensus', 'vector')
  86. >>> rename('mycensus', 'mynewcensus', 'vector')
  87. >>> remove('mynewcensus', 'vector')
  88. """
  89. kwargs.update({maptype: '{old},{new}'.format(old=existingmap, new=newmap)})
  90. grasscore.run_command('g.copy', quiet=True, **kwargs)
  91. def getenv(env):
  92. """Return the current grass environment variables
  93. >>> from grass.script.core import gisenv
  94. >>> getenv("MAPSET") == gisenv()["MAPSET"]
  95. True
  96. """
  97. return libgis.G_getenv_nofatal(env)
  98. def get_mapset_raster(mapname, mapset=''):
  99. """Return the mapset of the raster map
  100. >>> get_mapset_raster('elevation')
  101. 'PERMANENT'
  102. """
  103. return libgis.G_find_raster2(mapname, mapset)
  104. def get_mapset_vector(mapname, mapset=''):
  105. """Return the mapset of the vector map
  106. >>> get_mapset_vector('census')
  107. 'PERMANENT'
  108. """
  109. return libgis.G_find_vector2(mapname, mapset)
  110. def is_clean_name(name):
  111. """Return if the name is valid
  112. >>> is_clean_name('census')
  113. True
  114. >>> is_clean_name('0census')
  115. True
  116. >>> is_clean_name('census?')
  117. True
  118. >>> is_clean_name('cénsus')
  119. False
  120. """
  121. if libgis.G_legal_filename(name) < 0:
  122. return False
  123. return True
  124. def coor2pixel(coord, region):
  125. """Convert coordinates into a pixel row and col
  126. >>> from grass.pygrass.gis.region import Region
  127. >>> reg = Region()
  128. >>> coor2pixel((reg.west, reg.north), reg)
  129. (0.0, 0.0)
  130. >>> coor2pixel((reg.east, reg.south), reg) == (reg.rows, reg.cols)
  131. True
  132. """
  133. (east, north) = coord
  134. return (libraster.Rast_northing_to_row(north, region.c_region),
  135. libraster.Rast_easting_to_col(east, region.c_region))
  136. def pixel2coor(pixel, region):
  137. """Convert row and col of a pixel into a coordinates
  138. >>> from grass.pygrass.gis.region import Region
  139. >>> reg = Region()
  140. >>> pixel2coor((0, 0), reg) == (reg.north, reg.west)
  141. True
  142. >>> pixel2coor((reg.cols, reg.rows), reg) == (reg.south, reg.east)
  143. True
  144. """
  145. (col, row) = pixel
  146. return (libraster.Rast_row_to_northing(row, region.c_region),
  147. libraster.Rast_col_to_easting(col, region.c_region))
  148. def get_raster_for_points(poi_vector, raster, column=None, region=None):
  149. """Query a raster map for each point feature of a vector
  150. Example
  151. >>> from grass.pygrass.vector import VectorTopo
  152. >>> from grass.pygrass.raster import RasterRow
  153. >>> ele = RasterRow('elevation')
  154. >>> copy('schools','myschools','vector')
  155. >>> sch = VectorTopo('myschools')
  156. >>> sch.open(mode='r')
  157. >>> get_raster_for_points(sch, ele) # doctest: +ELLIPSIS
  158. [(1, 633649.2856743174, 221412.94434781274, 145.06602), ...]
  159. >>> sch.table.columns.add('elevation','double precision')
  160. >>> 'elevation' in sch.table.columns
  161. True
  162. >>> get_raster_for_points(sch, ele, column='elevation')
  163. True
  164. >>> sch.table.filters.select('NAMESHORT','elevation')
  165. Filters(u'SELECT NAMESHORT, elevation FROM myschools;')
  166. >>> cur = sch.table.execute()
  167. >>> cur.fetchall() # doctest: +ELLIPSIS
  168. [(u'SWIFT CREEK', 145.06602), ... (u'9TH GRADE CTR', None)]
  169. >>> remove('myschools','vect')
  170. :param point: point vector object
  171. :param raster: raster object
  172. :param str column: column name to update
  173. """
  174. from math import isnan
  175. if not column:
  176. result = []
  177. if region is None:
  178. from grass.pygrass.gis.region import Region
  179. region = Region()
  180. if not poi_vector.is_open():
  181. poi_vector.open()
  182. if not raster.is_open():
  183. raster.open()
  184. if poi_vector.num_primitive_of('point') == 0:
  185. raise GrassError(_("Vector doesn't contain points"))
  186. for poi in poi_vector.viter('points'):
  187. val = raster.get_value(poi, region)
  188. if column:
  189. if val is not None and not isnan(val):
  190. poi.attrs[column] = val
  191. else:
  192. if val is not None and not isnan(val):
  193. result.append((poi.id, poi.x, poi.y, val))
  194. else:
  195. result.append((poi.id, poi.x, poi.y, None))
  196. if not column:
  197. return result
  198. else:
  199. poi.attrs.commit()
  200. return True
  201. def r_export(rast, output='', fmt='png', **kargs):
  202. from grass.pygrass.modules import Module
  203. if rast.exist():
  204. output = output if output else "%s_%s.%s" % (rast.name, rast.mapset,
  205. fmt)
  206. Module('r.out.%s' % fmt, input=rast.fullname(), output=output,
  207. overwrite=True, **kargs)
  208. return output
  209. else:
  210. raise ValueError('Raster map does not exist.')
  211. def get_lib_path(modname, libname):
  212. """Return the path of the libname contained in the module.
  213. >>> get_lib_path(modname='r.modis', libname='libmodis')
  214. """
  215. from os.path import isdir, join
  216. from os import getenv
  217. if isdir(join(getenv('GISBASE'), 'etc', modname)):
  218. path = join(os.getenv('GISBASE'), 'etc', modname)
  219. elif getenv('GRASS_ADDON_BASE') and \
  220. isdir(join(getenv('GRASS_ADDON_BASE'), 'etc', modname)):
  221. path = join(getenv('GRASS_ADDON_BASE'), 'etc', modname)
  222. elif getenv('GRASS_ADDON_BASE') and \
  223. isdir(join(getenv('GRASS_ADDON_BASE'), modname, modname)):
  224. path = join(os.getenv('GRASS_ADDON_BASE'), modname, modname)
  225. elif isdir(join('..', libname)):
  226. path = join('..', libname)
  227. else:
  228. path = None
  229. return path
  230. def set_path(modulename, dirname, path='.'):
  231. import sys
  232. """Set sys.path looking in the the local directory GRASS directories."""
  233. pathlib = os.path.join(path, dirname)
  234. if os.path.exists(pathlib):
  235. # we are running the script from the script directory
  236. sys.path.append(os.path.abspath(path))
  237. else:
  238. # running from GRASS GIS session
  239. path = get_lib_path(modulename, dirname)
  240. if path is None:
  241. raise ImportError("Not able to find the path %s directory." % path)
  242. sys.path.append(path)
  243. def split_in_chunk(iterable, length=10):
  244. """Split a list in chunk.
  245. >>> for chunk in split_in_chunk(range(25)): print chunk
  246. (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  247. (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
  248. (20, 21, 22, 23, 24)
  249. >>> for chunk in split_in_chunk(range(25), 3): print chunk
  250. (0, 1, 2)
  251. (3, 4, 5)
  252. (6, 7, 8)
  253. (9, 10, 11)
  254. (12, 13, 14)
  255. (15, 16, 17)
  256. (18, 19, 20)
  257. (21, 22, 23)
  258. (24,)
  259. """
  260. it = iter(iterable)
  261. while True:
  262. chunk = tuple(itertools.islice(it, length))
  263. if not chunk:
  264. return
  265. yield chunk
  266. def table_exist(cursor, table_name):
  267. """Return True if the table exist False otherwise"""
  268. try:
  269. # sqlite
  270. cursor.execute("SELECT name FROM sqlite_master"
  271. " WHERE type='table' AND name='%s';" % table_name)
  272. except OperationalError:
  273. try:
  274. # pg
  275. cursor.execute("SELECT EXISTS(SELECT * FROM "
  276. "information_schema.tables "
  277. "WHERE table_name=%s)" % table_name)
  278. except OperationalError:
  279. return False
  280. one = cursor.fetchone() if cursor else None
  281. return True if one and one[0] else False
  282. def create_test_vector_map(map_name="test_vector"):
  283. """This functions creates a vector map layer with points, lines, boundaries,
  284. centroids, areas, isles and attributes for testing purposes
  285. This should be used in doc and unit tests to create location/mapset
  286. independent vector map layer. This map includes 3 points, 3 lines,
  287. 11 boundaries and 4 centroids. The attribute table contains cat and name
  288. columns.
  289. param map_name: The vector map name that should be used
  290. """
  291. from grass.pygrass.vector import VectorTopo
  292. from grass.pygrass.vector.geometry import Point, Line, Centroid, Boundary, Area
  293. cols = [(u'cat', 'INTEGER PRIMARY KEY'),
  294. (u'name','varchar(50)'),
  295. (u'value', 'double precision')]
  296. with VectorTopo(map_name, mode='w', tab_name=map_name,
  297. tab_cols=cols) as vect:
  298. # Write 3 points, 3 lines and 11 boundaries with one nested isle and 4 centroids
  299. #
  300. #
  301. # ______ ___ ___ * * *
  302. # |1 __ *|3 *|4 *| | | |
  303. # | |2*| | | | | | |
  304. # | |__| | | | | | |
  305. # |______|___|___| | | |
  306. #
  307. # Write 3 points
  308. vect.write(Point(10, 6), cat=1, attrs=("point", 1))
  309. vect.write(Point(12, 6), cat=1)
  310. vect.write(Point(14, 6), cat=1)
  311. # Write 3 lines
  312. vect.write(Line([(10, 4), (10, 2), (10,0)]), cat=2, attrs=("line", 2))
  313. vect.write(Line([(12, 4), (12, 2), (12,0)]), cat=2)
  314. vect.write(Line([(14, 4), (14, 2), (14,0)]), cat=2)
  315. # boundaries 1 - 4
  316. vect.write(Boundary(points=[(0, 0), (0,4)]))
  317. vect.write(Boundary(points=[(0, 4), (4,4)]))
  318. vect.write(Boundary(points=[(4, 4), (4,0)]))
  319. vect.write(Boundary(points=[(4, 0), (0,0)]))
  320. # 5. boundary (Isle)
  321. vect.write(Boundary(points=[(1, 1), (1,3), (3, 3), (3,1), (1,1)]))
  322. # boundaries 6 - 8
  323. vect.write(Boundary(points=[(4, 4), (6,4)]))
  324. vect.write(Boundary(points=[(6, 4), (6,0)]))
  325. vect.write(Boundary(points=[(6, 0), (4,0)]))
  326. # boundaries 9 - 11
  327. vect.write(Boundary(points=[(6, 4), (8,4)]))
  328. vect.write(Boundary(points=[(8, 4), (8,0)]))
  329. vect.write(Boundary(points=[(8, 0), (6,0)]))
  330. # Centroids, all have the same cat and attribute
  331. vect.write(Centroid(x=3.5, y=3.5), cat=3, attrs=("centroid", 3))
  332. vect.write(Centroid(x=2.5, y=2.5), cat=3)
  333. vect.write(Centroid(x=5.5, y=3.5), cat=3)
  334. vect.write(Centroid(x=7.5, y=3.5), cat=3)
  335. vect.table.conn.commit()
  336. vect.close()