utils.py 9.4 KB

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