utils.py 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. """
  2. @package utils.py
  3. @brief Misc utilities for GRASS wxPython GUI
  4. (C) 2007-2008 by the GRASS Development Team
  5. This program is free software under the GNU General Public
  6. License (>=v2). Read the file COPYING that comes with GRASS
  7. for details.
  8. @author Martin Landa, Jachym Cepicky
  9. @date 2007-2008
  10. """
  11. import os
  12. import sys
  13. import globalvar
  14. grassPath = os.path.join(globalvar.ETCDIR, "python")
  15. sys.path.append(grassPath)
  16. import grass
  17. import gcmd
  18. try:
  19. import subprocess
  20. except:
  21. compatPath = os.path.join(globalvar.ETCWXDIR, "compat")
  22. sys.path.append(compatPath)
  23. import subprocess
  24. def GetTempfile(pref=None):
  25. """
  26. Creates GRASS temporary file using defined prefix.
  27. @todo Fix path on MS Windows/MSYS
  28. @param pref prefer the given path
  29. @return Path to file name (string) or None
  30. """
  31. import gcmd
  32. ret = gcmd.RunCommand('g.tempfile',
  33. read = True,
  34. pid = os.getpid())
  35. tempfile = ret.splitlines()[0].strip()
  36. # FIXME
  37. # ugly hack for MSYS (MS Windows)
  38. if subprocess.mswindows:
  39. tempfile = tempfile.replace("/", "\\")
  40. try:
  41. path, file = os.path.split(tempfile)
  42. if pref:
  43. return os.path.join(pref, file)
  44. else:
  45. return tempfile
  46. except:
  47. return None
  48. def GetLayerNameFromCmd(dcmd, fullyQualified=False, param=None,
  49. layerType=None):
  50. """Get map name from GRASS command
  51. @param dcmd GRASS command (given as tuple)
  52. @param fullyQualified change map name to be fully qualified
  53. @param force parameter otherwise 'input'/'map'
  54. @param update change map name in command
  55. @param layerType check also layer type ('raster', 'vector', '3d-raster', ...)
  56. @return map name
  57. @return '' if no map name found in command
  58. """
  59. mapname = ''
  60. if not dcmd:
  61. return mapname
  62. if 'd.grid' == dcmd[0]:
  63. mapname = 'grid'
  64. elif 'd.geodesic' in dcmd[0]:
  65. mapname = 'geodesic'
  66. elif 'd.rhumbline' in dcmd[0]:
  67. mapname = 'rhumb'
  68. elif 'labels=' in dcmd[0]:
  69. mapname = dcmd[idx].split('=')[1]+' labels'
  70. else:
  71. for idx in range(len(dcmd)):
  72. if param and param in dcmd[idx]:
  73. break
  74. elif not param:
  75. if 'map=' in dcmd[idx] or \
  76. 'input=' in dcmd[idx] or \
  77. 'red=' in dcmd[idx] or \
  78. 'h_map=' in dcmd[idx] or \
  79. 'reliefmap' in dcmd[idx]:
  80. break
  81. if idx < len(dcmd):
  82. try:
  83. mapname = dcmd[idx].split('=')[1]
  84. except IndexError:
  85. return ''
  86. if fullyQualified and '@' not in mapname:
  87. if layerType in ('raster', 'vector', '3d-raster'):
  88. try:
  89. if layerType == 'raster':
  90. findType = 'cell'
  91. else:
  92. findType = layerType
  93. result = grass.find_file(mapname, element=findType)
  94. except AttributeError, e: # not found
  95. return ''
  96. if result:
  97. mapname = result['fullname']
  98. else:
  99. mapname += '@' + grass.gisenv()['MAPSET']
  100. else:
  101. mapname += '@' + grass.gisenv()['MAPSET']
  102. dcmd[idx] = dcmd[idx].split('=')[0] + '=' + mapname
  103. return mapname
  104. def GetValidLayerName(name):
  105. """Make layer name SQL compliant, based on G_str_to_sql()
  106. @todo: Better use directly GRASS Python SWIG...
  107. """
  108. retName = str(name).strip()
  109. # check if name is fully qualified
  110. if '@' in retName:
  111. retName, mapset = retName.split('@')
  112. else:
  113. mapset = None
  114. for c in retName:
  115. # c = toascii(c)
  116. if not (c >= 'A' and c <= 'Z') and \
  117. not (c >= 'a' and c <= 'z') and \
  118. not (c >= '0' and c <= '9'):
  119. c = '_'
  120. if not (retName[0] >= 'A' and retName[0] <= 'Z') and \
  121. not (retName[0] >= 'a' and retName[0] <= 'z'):
  122. retName = 'x' + retName[1:]
  123. if mapset:
  124. retName = retName + '@' + mapset
  125. return retName
  126. def ListOfCatsToRange(cats):
  127. """Convert list of category number to range(s)
  128. Used for example for d.vect cats=[range]
  129. @param cats category list
  130. @return category range string
  131. @return '' on error
  132. """
  133. catstr = ''
  134. try:
  135. cats = map(int, cats)
  136. except:
  137. return catstr
  138. i = 0
  139. while i < len(cats):
  140. next = 0
  141. j = i + 1
  142. while j < len(cats):
  143. if cats[i + next] == cats[j] - 1:
  144. next += 1
  145. else:
  146. break
  147. j += 1
  148. if next > 1:
  149. catstr += '%d-%d,' % (cats[i], cats[i + next])
  150. i += next + 1
  151. else:
  152. catstr += '%d,' % (cats[i])
  153. i += 1
  154. return catstr.strip(',')
  155. def ListOfMapsets(all=False):
  156. """Get list of available/accessible mapsets
  157. @param all if True get list of all mapsets
  158. @return list of mapsets
  159. """
  160. mapsets = []
  161. if all:
  162. ret = gcmd.RunCommand('g.mapsets',
  163. read = True,
  164. flags = 'l',
  165. fs = '|')
  166. if ret:
  167. mapsets = ret.rstrip('\n').split('|')
  168. else:
  169. raise gcmd.CmdError(cmd = 'g.mapsets',
  170. message = _('Unable to get list of available mapsets.'))
  171. else:
  172. ret = gcmd.RunCommand('g.mapsets',
  173. read = True,
  174. flags = 'p',
  175. fs = '|')
  176. if ret:
  177. mapsets = ret.rstrip('\n').split('|')
  178. else:
  179. raise gcmd.CmdError(cmd = 'g.mapsets',
  180. message = _('Unable to get list of accessible mapsets.'))
  181. ListSortLower(mapsets)
  182. return mapsets
  183. def ListSortLower(list):
  184. """Sort list items (not case-sensitive)"""
  185. list.sort(cmp=lambda x, y: cmp(x.lower(), y.lower()))
  186. def GetVectorNumberOfLayers(vector):
  187. """Get list of vector layers"""
  188. cmdlist = ['v.category',
  189. 'input=%s' % vector,
  190. 'option=report']
  191. layers = []
  192. ret = gcmd.RunCommand('v.category',
  193. read = True,
  194. input = vector,
  195. option = 'report')
  196. if not ret:
  197. return layers
  198. for line in ret.splitlines():
  199. if not 'Layer' in line:
  200. continue
  201. value = line.split(':')[1].strip()
  202. if '/' in value: # value/name
  203. layers.append(value.split('/')[0])
  204. else:
  205. layers.append(value)
  206. return layers
  207. def Deg2DMS(lon, lat):
  208. """Convert deg value to dms string
  209. @param lat latitude
  210. @param lon longitude
  211. @return DMS string
  212. @return empty string on error
  213. """
  214. try:
  215. flat = float(lat)
  216. flon = float(lon)
  217. except ValueError:
  218. return ''
  219. # fix longitude
  220. while flon > 180.0:
  221. flon -= 360.0
  222. while flon < -180.0:
  223. flon += 360.0
  224. # hemisphere
  225. if flat < 0.0:
  226. flat = abs(flat)
  227. hlat = 'S'
  228. else:
  229. hlat = 'N'
  230. if flon < 0.0:
  231. hlon = 'W'
  232. flon = abs(flon)
  233. else:
  234. hlon = 'E'
  235. slat = __ll_parts(flat)
  236. slon = __ll_parts(flon)
  237. return slon + hlon + '; ' + slat + hlat
  238. def __ll_parts(value):
  239. """Converts deg to d:m:s string"""
  240. if value == 0.0:
  241. return '00:00:00.0000'
  242. d = int(int(value))
  243. m = int((value - d) * 60)
  244. s = ((value - d) * 60 - m) * 60
  245. if m < 0:
  246. m = '00'
  247. elif m < 10:
  248. m = '0' + str(m)
  249. else:
  250. m = str(m)
  251. if s < 0:
  252. s = '00.0000'
  253. elif s < 10.0:
  254. s = '0%.4f' % s
  255. else:
  256. s = '%.4f' % s
  257. return str(d) + ':' + m + ':' + s
  258. def GetCmdString(cmd):
  259. """
  260. Get GRASS command as string.
  261. @param cmd GRASS command given as tuple
  262. @return command string
  263. """
  264. scmd = ''
  265. if not cmd:
  266. return ''
  267. scmd = cmd[0]
  268. for k, v in cmd[1].iteritems():
  269. scmd += ' %s=%s' % (k, v)
  270. return scmd
  271. def CmdToTuple(cmd):
  272. """Convert command list to tuple for gcmd.RunCommand()"""
  273. if len(cmd) < 1:
  274. return None
  275. dcmd = {}
  276. for item in cmd[1:]:
  277. if '=' in item:
  278. key, value = item.split('=')
  279. dcmd[str(key)] = str(value)
  280. else: # -> flags
  281. if not dcmd.has_key('flags'):
  282. dcmd['flags'] = ''
  283. dcmd['flags'] += item.replace('-', '')
  284. return (cmd[0],
  285. dcmd)
  286. def reexec_with_pythonw():
  287. """Re-execute Python on Mac OS"""
  288. if sys.platform == 'darwin' and \
  289. not sys.executable.endswith('MacOS/Python'):
  290. print >> sys.stderr, 're-executing using pythonw'
  291. os.execvp('pythonw', ['pythonw', __file__] + sys.argv[1:])