functions.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Tue Jun 26 12:38:48 2012
  4. @author: pietro
  5. """
  6. import itertools
  7. import fnmatch
  8. import os
  9. from sqlite3 import OperationalError
  10. import grass.lib.gis as libgis
  11. import grass.lib.raster as libraster
  12. from grass.script import core as grasscore
  13. from grass.pygrass.errors import GrassError
  14. from grass.pygrass.gis.region import Region
  15. def looking(obj, filter_string):
  16. """
  17. >>> import grass.lib.vector as libvect
  18. >>> sorted(looking(libvect, '*by_box*')) # doctest: +NORMALIZE_WHITESPACE
  19. ['Vect_select_areas_by_box', 'Vect_select_isles_by_box',
  20. 'Vect_select_lines_by_box', 'Vect_select_nodes_by_box']
  21. """
  22. word_list = dir(obj)
  23. word_list.sort()
  24. return fnmatch.filter(word_list, filter_string)
  25. def findfiles(dirpath, match=None):
  26. """Return a list of the files"""
  27. res = []
  28. for f in sorted(os.listdir(dirpath)):
  29. abspath = os.path.join(dirpath, f)
  30. if os.path.isdir(abspath):
  31. res.extend(findfiles(abspath, match))
  32. if match:
  33. if fnmatch.fnmatch(abspath, match):
  34. res.append(abspath)
  35. else:
  36. res.append(abspath)
  37. return res
  38. def findmaps(type, pattern=None, mapset='', location='', gisdbase=''):
  39. """Return a list of tuple contining the names of the:
  40. * map
  41. * mapset,
  42. * location,
  43. * gisdbase
  44. """
  45. from grass.pygrass.gis import Gisdbase, Location, Mapset
  46. def find_in_location(type, pattern, location):
  47. res = []
  48. for msetname in location.mapsets():
  49. mset = Mapset(msetname, location.name, location.gisdbase)
  50. res.extend([(m, mset.name, mset.location, mset.gisdbase)
  51. for m in mset.glist(type, pattern)])
  52. return res
  53. def find_in_gisdbase(type, pattern, gisdbase):
  54. res = []
  55. for loc in gisdbase.locations():
  56. res.extend(find_in_location(type, pattern,
  57. Location(loc, gisdbase.name)))
  58. return res
  59. if gisdbase and location and mapset:
  60. mset = Mapset(mapset, location, gisdbase)
  61. return [(m, mset.name, mset.location, mset.gisdbase)
  62. for m in mset.glist(type, pattern)]
  63. elif gisdbase and location:
  64. loc = Location(location, gisdbase)
  65. return find_in_location(type, pattern, loc)
  66. elif gisdbase:
  67. gis = Gisdbase(gisdbase)
  68. return find_in_gisdbase(type, pattern, gis)
  69. elif location:
  70. loc = Location(location)
  71. return find_in_location(type, pattern, loc)
  72. elif mapset:
  73. mset = Mapset(mapset)
  74. return [(m, mset.name, mset.location, mset.gisdbase)
  75. for m in mset.glist(type, pattern)]
  76. else:
  77. gis = Gisdbase()
  78. return find_in_gisdbase(type, pattern, gis)
  79. def remove(oldname, maptype, **kwargs):
  80. """Remove a map"""
  81. kwargs.update({maptype: '{old}'.format(old=oldname)})
  82. grasscore.run_command('g.remove', quiet=True, **kwargs)
  83. def rename(oldname, newname, maptype, **kwargs):
  84. """Rename a map"""
  85. kwargs.update({maptype: '{old},{new}'.format(old=oldname, new=newname), })
  86. grasscore.run_command('g.rename', quiet=True, **kwargs)
  87. def copy(existingmap, newmap, maptype, **kwargs):
  88. """Copy a map
  89. >>> copy('census', 'mycensus', 'vect')
  90. >>> rename('mycensus', 'mynewcensus', 'vect')
  91. >>> remove('mynewcensus', 'vect')
  92. """
  93. kwargs.update({maptype: '{old},{new}'.format(old=existingmap, new=newmap)})
  94. grasscore.run_command('g.copy', quiet=True, **kwargs)
  95. def getenv(env):
  96. """Return the current grass environment variables
  97. >>> getenv("MAPSET")
  98. 'user1'
  99. """
  100. return libgis.G__getenv(env)
  101. def get_mapset_raster(mapname, mapset=''):
  102. """Return the mapset of the raster map
  103. >>> get_mapset_raster('elevation')
  104. 'PERMANENT'
  105. """
  106. return libgis.G_find_raster2(mapname, mapset)
  107. def get_mapset_vector(mapname, mapset=''):
  108. """Return the mapset of the vector map
  109. >>> get_mapset_vector('census')
  110. 'PERMANENT'
  111. """
  112. return libgis.G_find_vector2(mapname, mapset)
  113. def is_clean_name(name):
  114. """Return if the name is valid
  115. >>> is_clean_name('census')
  116. True
  117. >>> is_clean_name('0census')
  118. True
  119. >>> is_clean_name('census?')
  120. False
  121. >>> is_clean_name('cénsus')
  122. False
  123. """
  124. if libgis.G_legal_filename(name) < 0:
  125. return False
  126. return True
  127. def coor2pixel(coord, region):
  128. """Convert coordinates into a pixel row and col
  129. >>> reg = Region()
  130. >>> coor2pixel((reg.west, reg.north), reg)
  131. (0.0, 0.0)
  132. >>> coor2pixel((reg.east, reg.south), reg) == (reg.rows, reg.cols)
  133. True
  134. """
  135. (east, north) = coord
  136. return (libraster.Rast_northing_to_row(north, region.c_region),
  137. libraster.Rast_easting_to_col(east, region.c_region))
  138. def pixel2coor(pixel, region):
  139. """Convert row and col of a pixel into a coordinates
  140. >>> reg = Region()
  141. >>> pixel2coor((0, 0), reg) == (reg.north, reg.west)
  142. True
  143. >>> pixel2coor((reg.cols, reg.rows), reg) == (reg.south, reg.east)
  144. True
  145. """
  146. (col, row) = pixel
  147. return (libraster.Rast_row_to_northing(row, region.c_region),
  148. libraster.Rast_col_to_easting(col, region.c_region))
  149. def get_raster_for_points(poi_vector, raster, column=None):
  150. """Query a raster map for each point feature of a vector
  151. Example
  152. >>> from grass.pygrass.vector import VectorTopo
  153. >>> from grass.pygrass.raster import RasterRow
  154. >>> ele = RasterRow('elevation')
  155. >>> copy('schools','myschools','vect')
  156. >>> sch = VectorTopo('myschools')
  157. >>> sch.open()
  158. >>> get_raster_for_points(sch, ele) # doctest: +ELLIPSIS
  159. [(1, 633649.2856743174, 221412.94434781274, 145.06602)...
  160. >>> sch.table.columns.add('elevation','double precision')
  161. >>> 'elevation' in sch.table.columns
  162. True
  163. >>> get_raster_for_points(sch, ele, 'elevation')
  164. True
  165. >>> sch.table.filters.select('NAMESHORT','elevation')
  166. Filters(u'SELECT NAMESHORT, elevation FROM myschools;')
  167. >>> cur = sch.table.execute()
  168. >>> cur.fetchall() # doctest: +ELLIPSIS
  169. [(u'SWIFT CREEK', 145.06602), ... (u'9TH GRADE CTR', None)]
  170. >>> remove('myschools','vect')
  171. :param point: point vector object
  172. :param raster: raster object
  173. :param str column: column name to update
  174. """
  175. from math import isnan
  176. if not column:
  177. result = []
  178. reg = Region()
  179. if not poi_vector.is_open():
  180. poi_vector.open()
  181. if not raster.is_open():
  182. raster.open()
  183. if poi_vector.num_primitive_of('point') == 0:
  184. raise GrassError(_("Vector doesn't contain points"))
  185. for poi in poi_vector.viter('points'):
  186. val = raster.get_value(poi, reg)
  187. if column:
  188. if val is not None and not isnan(val):
  189. poi.attrs[column] = val
  190. else:
  191. if val is not None and not isnan(val):
  192. result.append((poi.id, poi.x, poi.y, val))
  193. else:
  194. result.append((poi.id, poi.x, poi.y, None))
  195. if not column:
  196. return result
  197. else:
  198. poi.attrs.commit()
  199. return True
  200. def r_export(rast, output='', fmt='png', **kargs):
  201. from grass.pygrass.modules import Module
  202. if rast.exist():
  203. output = output if output else "%s_%s.%s" % (rast.name, rast.mapset,
  204. fmt)
  205. Module('r.out.%s' % fmt, input=rast.fullname(), output=output,
  206. overwrite=True, **kargs)
  207. return output
  208. else:
  209. raise ValueError('Raster map does not exist.')
  210. def get_lib_path(modname, libname):
  211. """Return the path of the libname contained in the module.
  212. >>> get_lib_path(modname='r.modis', libname='libmodis')
  213. """
  214. from os.path import isdir, join
  215. from os import getenv
  216. if isdir(join(getenv('GISBASE'), 'etc', modname)):
  217. path = join(os.getenv('GISBASE'), 'etc', modname)
  218. elif getenv('GRASS_ADDON_BASE') and \
  219. isdir(join(getenv('GRASS_ADDON_BASE'), 'etc', modname)):
  220. path = join(getenv('GRASS_ADDON_BASE'), 'etc', modname)
  221. elif getenv('GRASS_ADDON_BASE') and \
  222. isdir(join(getenv('GRASS_ADDON_BASE'), modname, modname)):
  223. path = join(os.getenv('GRASS_ADDON_BASE'), modname, modname)
  224. elif isdir(join('..', libname)):
  225. path = join('..', libname)
  226. else:
  227. path = None
  228. return path
  229. def split_in_chunk(iterable, lenght=10):
  230. """Split a list in chunk.
  231. >>> for chunk in split_in_chunk(range(25)): print chunk
  232. (0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
  233. (10, 11, 12, 13, 14, 15, 16, 17, 18, 19)
  234. (20, 21, 22, 23, 24)
  235. >>> for chunk in split_in_chunk(range(25), 3): print chunk
  236. (0, 1, 2)
  237. (3, 4, 5)
  238. (6, 7, 8)
  239. (9, 10, 11)
  240. (12, 13, 14)
  241. (15, 16, 17)
  242. (18, 19, 20)
  243. (21, 22, 23)
  244. (24,)
  245. """
  246. it = iter(iterable)
  247. while True:
  248. chunk = tuple(itertools.islice(it, lenght))
  249. if not chunk:
  250. return
  251. yield chunk
  252. def table_exist(cursor, table_name):
  253. """Return True if the table exist False otherwise"""
  254. try:
  255. # sqlite
  256. cursor.execute("SELECT name FROM sqlite_master"
  257. " WHERE type='table' AND name='%s';" % table_name)
  258. except OperationalError:
  259. try:
  260. # pg
  261. cursor.execute("SELECT EXISTS(SELECT * FROM "
  262. "information_schema.tables "
  263. "WHERE table_name=%s)" % table_name)
  264. except OperationalError:
  265. return False
  266. one = cursor.fetchone() if cursor else None
  267. return True if one and one[0] else False
  268. def docstring_property(class_doc):
  269. """Property attribute for docstrings.
  270. Took from: https://gist.github.com/bfroehle/4041015
  271. >>> class A(object):
  272. ... '''Main docstring'''
  273. ... def __init__(self, x):
  274. ... self.x = x
  275. ... @docstring_property(__doc__)
  276. ... def __doc__(self):
  277. ... return "My value of x is %s." % self.x
  278. >>> A.__doc__
  279. 'Main docstring'
  280. >>> a = A(10)
  281. >>> a.__doc__
  282. 'My value of x is 10.'
  283. """
  284. def wrapper(fget):
  285. return DocstringProperty(class_doc, fget)
  286. return wrapper
  287. class DocstringProperty(object):
  288. """Property for the `__doc__` attribute.
  289. Different than `property` in the following two ways:
  290. * When the attribute is accessed from the main class, it returns the value
  291. of `class_doc`, *not* the property itself. This is necessary so Sphinx
  292. and other documentation tools can access the class docstring.
  293. * Only supports getting the attribute; setting and deleting raise an
  294. `AttributeError`.
  295. """
  296. def __init__(self, class_doc, fget):
  297. self.class_doc = class_doc
  298. self.fget = fget
  299. def __get__(self, obj, type=None):
  300. if obj is None:
  301. return self.class_doc
  302. else:
  303. return self.fget(obj)
  304. def __set__(self, obj, value):
  305. raise AttributeError("can't set attribute")
  306. def __delete__(self, obj):
  307. raise AttributeError("can't delete attribute")