4 @brief Misc utilities for wxGUI
6 (C) 2007-2009, 2011-2012 by the GRASS Development Team
8 This program is free software under the GNU General Public License
9 (>=v2). Read the file COPYING that comes with GRASS for details.
11 @author Martin Landa <landa.martin gmail.com>
12 @author Jachym Cepicky
25 sys.path.append(os.path.join(ETCDIR,
"python"))
34 """!Remove redundant whitespace from a string"""
35 return string.join(string.split(text),
' ')
38 """!Platform spefic shlex.split"""
39 if sys.platform ==
"win32":
40 return shlex.split(s.replace(
'\\',
r'\\'))
45 """!Creates GRASS temporary file using defined prefix.
47 @todo Fix path on MS Windows/MSYS
49 @param pref prefer the given path
51 @return Path to file name (string) or None
57 tempfile = ret.splitlines()[0].strip()
61 if platform.system() ==
'Windows':
62 tempfile = tempfile.replace(
"/",
"\\")
64 path, file = os.path.split(tempfile)
66 return os.path.join(pref, file)
74 """!Get map name from GRASS command
76 Parameter dcmd can be modified when first parameter is not
79 @param dcmd GRASS command (given as list)
80 @param fullyQualified change map name to be fully qualified
81 @param param params directory
82 @param layerType check also layer type ('raster', 'vector', '3d-raster', ...)
84 @return tuple (name, found)
92 if 'd.grid' == dcmd[0]:
94 elif 'd.geodesic' in dcmd[0]:
96 elif 'd.rhumbline' in dcmd[0]:
98 elif 'labels=' in dcmd[0]:
99 mapname = dcmd[idx].
split(
'=')[1] +
' labels'
102 for idx
in range(len(dcmd)):
104 p, v = dcmd[idx].
split(
'=', 1)
109 params = [(idx, p, v)]
112 if p
in (
'map',
'input',
113 'red',
'blue',
'green',
114 'h_map',
's_map',
'i_map',
115 'reliefmap',
'labels'):
116 params.append((idx, p, v))
122 if '=' not in dcmd[i]
and not dcmd[i].startswith(
'-'):
123 task = gtask.parse_interface(dcmd[0])
125 p = task.get_options()[
'params'][0].get(
'name',
'')
126 params.append((i, p, dcmd[i]))
130 return mapname,
False
133 return mapname,
False
137 for i, p, v
in params:
140 if fullyQualified
and '@' not in mapname:
141 if layerType
in (
'raster',
'vector',
'3d-raster',
'rgb',
'his'):
143 if layerType
in (
'raster',
'rgb',
'his'):
147 mapset = grass.find_file(mapname, element = findType)[
'mapset']
148 except AttributeError, e:
153 mapset = grass.gisenv()[
'MAPSET']
157 for i, p, v
in params:
159 dcmd[i] = p +
'=' + v
162 if i
in mapsets
and mapsets[i]:
163 dcmd[i] +=
'@' + mapsets[i]
166 for i, p, v
in params:
170 maps.append(dcmd[i].
split(
'=', 1)[1])
171 mapname =
'\n'.join(maps)
173 return mapname, found
176 """!Make layer name SQL compliant, based on G_str_to_sql()
178 @todo: Better use directly Ctypes to reuse venerable libgis C fns...
180 retName = str(name).strip()
184 retName, mapset = retName.split(
'@')
189 retNameList = list(retName)
190 for c
in retNameList:
191 if not (c >=
'A' and c <=
'Z')
and \
192 not (c >=
'a' and c <=
'z')
and \
193 not (c >=
'0' and c <=
'9'):
194 retNameList[cIdx] =
'_'
196 retName =
''.join(retNameList)
198 if not (retName[0] >=
'A' and retName[0] <=
'Z')
and \
199 not (retName[0] >=
'a' and retName[0] <=
'z'):
200 retName =
'x' + retName[1:]
203 retName = retName +
'@' + mapset
208 """!Convert list of category number to range(s)
210 Used for example for d.vect cats=[range]
212 @param cats category list
214 @return category range string
221 cats = map(int, cats)
230 if cats[i + next] == cats[j] - 1:
237 catstr +=
'%d-%d,' % (cats[i], cats[i + next])
240 catstr +=
'%d,' % (cats[i])
243 return catstr.strip(
',')
246 """!Get list of available/accessible mapsets
248 @param get method ('all', 'accessible', 'ordered')
250 @return list of mapsets
251 @return None on error
255 if get ==
'all' or get ==
'ordered':
263 mapsets = ret.splitlines()
268 if get ==
'accessible' or get ==
'ordered':
275 if get ==
'accessible':
276 mapsets = ret.splitlines()
278 mapsets_accessible = ret.splitlines()
279 for mapset
in mapsets_accessible:
280 mapsets.remove(mapset)
281 mapsets = mapsets_accessible + mapsets
288 """!Sort list items (not case-sensitive)"""
289 list.sort(cmp=
lambda x, y: cmp(x.lower(), y.lower()))
292 """!Get list of vector layers
294 @param vector name of vector map
295 @param parent parent window (to show dialog) or None
301 fullname = grass.find_file(name = vector, element =
'vector')[
'fullname']
303 Debug.msg(5,
"utils.GetVectorNumberOfLayers(): vector map '%s' not found" % vector)
313 sys.stderr.write(_(
"Vector map <%(map)s>: %(msg)s\n") % {
'map' : fullname,
'msg' : msg })
316 Debug.msg(1,
"GetVectorNumberOfLayers(): ret %s" % ret)
318 for line
in out.splitlines():
320 layer = line.split(
';')[0]
322 layer = layer.split(
'/')[0]
327 Debug.msg(3,
"utils.GetVectorNumberOfLayers(): vector=%s -> %s" % \
328 (fullname,
','.join(layers)))
333 """!Returns list of all vector layers as strings.
335 @param vector name of vector map
341 fullname = grass.find_file(name = vector, element =
'vector')[
'fullname']
343 Debug.msg(3,
"utils.GetAllVectorLayers(): vector map <%s> not found" % vector)
354 sys.stderr.write(_(
"Vector map <%(map)s>: %(msg)s\n") % {
'map' : fullname,
'msg' : msg })
357 Debug.msg(1,
"utils.GetAllVectorLayers(): ret %s" % ret)
359 for layer
in out.splitlines():
362 Debug.msg(3,
"utils.GetAllVectorLayers(): vector=%s -> %s" % \
363 (fullname,
','.join(layers)))
367 def Deg2DMS(lon, lat, string = True, hemisphere = True, precision = 3):
368 """!Convert deg value to dms string
370 @param lon longitude (x)
371 @param lat latitude (y)
372 @param string True to return string otherwise tuple
373 @param hemisphere print hemisphere
374 @param precision seconds precision
376 @return DMS string or tuple of values
377 @return empty string on error
413 slat = __ll_parts(flat, precision = precision)
414 slon = __ll_parts(flon, precision = precision)
417 return slon + hlon +
'; ' + slat + hlat
419 return (slon + hlon, slat + hlat)
422 """!Convert dms value to deg
424 @param lon longitude (x)
425 @param lat latitude (y)
427 @return tuple of converted values
428 @return ValueError on error
430 x = __ll_parts(lon, reverse =
True)
431 y = __ll_parts(lat, reverse =
True)
435 def __ll_parts(value, reverse = False, precision = 3):
436 """!Converts deg to d:m:s string
438 @param value value to be converted
439 @param reverse True to convert from d:m:s to deg
440 @param precision seconds precision (ignored if reverse is True)
442 @return converted value (string/float)
443 @return ValueError on error (reverse == True)
447 return '%s%.*f' % (
'00:00:0', precision, 0.0)
450 m = int((value - d) * 60)
451 s = ((value - d) * 60 - m) * 60
461 s =
'0%.*f' % (precision, s)
463 s =
'%.*f' % (precision, s)
465 return str(d) +
':' + m +
':' + s
468 d, m, s = value.split(
':')
473 d, m = value.split(
':')
487 if hs
not in (
'N',
'S',
'E',
'W'):
495 fs = float(s) / (60 * 60)
497 return coef * (float(d) + fm + fs)
501 Get GRASS command as string.
503 @param cmd GRASS command given as dictionary
505 @return command string
513 if 'flags' in cmd[1]:
514 for flag
in cmd[1][
'flags']:
516 for flag
in (
'verbose',
'quiet',
'overwrite'):
517 if flag
in cmd[1]
and cmd[1][flag]
is True:
520 for k, v
in cmd[1].iteritems():
521 if k
in (
'flags',
'verbose',
'quiet',
'overwrite'):
523 scmd +=
' %s=%s' % (k, v)
528 """!Convert command list to tuple for gcmd.RunCommand()"""
535 key, value = item.split(
'=', 1)
536 dcmd[str(key)] = str(value)
537 elif item[:2] ==
'--':
539 if flag
in (
'verbose',
'quiet',
'overwrite'):
540 dcmd[str(flag)] =
True
541 elif len(item) == 2
and item[0] ==
'-':
542 if 'flags' not in dcmd:
544 dcmd[
'flags'] += item[1]
546 module = gtask.parse_interface(cmd[0])
547 dcmd[module.define_first()] = item
549 return (cmd[0], dcmd)
552 """!Check path created by os.path.join"""
553 path = os.path.join(*args)
554 if platform.system() ==
'Windows' and \
556 return path[1].upper() +
':\\' + path[3:].replace(
'/',
'\\')
561 """!Read EPSG code from the file
563 @param path full path to the file with EPSG codes
565 @return dictionary of EPSG code
566 @return string on error
568 epsgCodeDict = dict()
573 return _(
"failed to open '%s'" % path)
577 for line
in f.readlines():
583 descr = line[1:].strip()
585 code, params = line.split(
" ", 1)
587 code = int(code.replace(
'<',
'').replace(
'>',
''))
592 epsgCodeDict[code] = (descr, params)
597 except StandardError, e:
603 """!Reproject coordinates
605 @param coord coordinates given as tuple
606 @param projOut output projection
607 @param projIn input projection (use location projection settings)
609 @return reprojected coordinates (returned as tuple)
619 stdin =
'%f|%f' % (coord[0], coord[1]),
622 coors = coors.split(
'\t')
624 n = coors[1].
split(
' ')[0].strip()
626 proj = projOut.split(
' ')[0].
split(
'=')[1]
629 if proj
in (
'll',
'latlong',
'longlat')
and 'd' not in flags:
630 return (proj, (e, n))
633 return (proj, (float(e), float(n)))
640 """!Get list of GRASS locations in given dbase
642 @param dbase GRASS database path
644 @return list of locations (sorted)
646 listOfLocations = list()
649 for location
in glob.glob(os.path.join(dbase,
"*")):
651 if os.path.join(location,
"PERMANENT")
in glob.glob(os.path.join(location,
"*")):
652 listOfLocations.append(os.path.basename(location))
655 except UnicodeEncodeError, e:
660 return listOfLocations
663 """!Get list of mapsets in given GRASS location
665 @param dbase GRASS database path
666 @param location GRASS location
667 @param selectable True to get list of selectable mapsets, otherwise all
669 @return list of mapsets - sorted (PERMANENT first)
671 listOfMapsets = list()
683 for line
in ret.rstrip().splitlines():
684 listOfMapsets += line.split(
' ')
686 for mapset
in glob.glob(os.path.join(dbase, location,
"*")):
687 if os.path.isdir(mapset)
and \
688 os.path.isfile(os.path.join(dbase, location, mapset,
"WIND")):
689 listOfMapsets.append(os.path.basename(mapset))
695 """!Get list of color tables"""
702 return ret.splitlines()
705 """!Decode string using system encoding
707 @param string string to be decoded
709 @return decoded string
714 enc = locale.getdefaultlocale()[1]
716 Debug.msg(5,
"DecodeString(): enc=%s" % enc)
717 return string.decode(enc)
722 """!Return encoded string using system locales
724 @param string string to be encoded
726 @return encoded string
730 enc = locale.getdefaultlocale()[1]
732 Debug.msg(5,
"EncodeString(): enc=%s" % enc)
733 return string.encode(enc)
737 def _getGDALFormats():
738 """!Get dictionary of avaialble GDAL drivers"""
740 ret = grass.read_command(
'r.in.gdal',
746 return _parseFormats(ret)
748 def _getOGRFormats():
749 """!Get dictionary of avaialble OGR drivers"""
751 ret = grass.read_command(
'v.in.ogr',
757 return _parseFormats(ret)
759 def _parseFormats(output):
760 """!Parse r.in.gdal/v.in.ogr -f output"""
761 formats = {
'file' : list(),
769 for line
in output.splitlines():
770 format = line.strip().rsplit(
':', -1)[1].strip()
771 if format
in (
'Memory',
'Virtual Raster',
'In Memory Raster'):
773 if format
in (
'PostgreSQL',
'SQLite',
774 'ODBC',
'ESRI Personal GeoDatabase',
776 'PostGIS WKT Raster driver',
778 formats[
'database'].append(format)
779 elif format
in (
'GeoJSON',
780 'OGC Web Coverage Service',
781 'OGC Web Map Service',
784 'HTTP Fetching Wrapper'):
785 formats[
'protocol'].append(format)
787 formats[
'file'].append(format)
789 for items
in formats.itervalues():
797 """!Get GDAL/OGR formats"""
801 'gdal' : _getGDALFormats(),
802 'ogr' : _getOGRFormats()
808 """!Get full path to the settings directory
811 verFd = open(os.path.join(ETCDIR,
"VERSIONNUMBER"))
812 version = int(verFd.readlines()[0].
split(
' ')[0].
split(
'.')[0])
813 except (IOError, ValueError, TypeError, IndexError), e:
814 sys.exit(_(
"ERROR: Unable to determine GRASS version. Details: %s") % e)
820 if sys.platform ==
'win32':
821 return os.path.join(os.getenv(
'APPDATA'),
'GRASS%d' % version)
823 return os.path.join(os.getenv(
'HOME'),
'.grass%d' % version)
826 """!Store environmental variable
828 If value is not given (is None) then environmental variable is
832 @param value env value
833 @param envFile path to the environmental file (None for default location)
835 windows = sys.platform ==
'win32'
838 envFile = os.path.join(os.getenv(
'HOME'),
'.grass.bashrc')
840 gVersion = grass.version()[
'version'].
split(
'.', 1)[0]
841 envFile = os.path.join(os.getenv(
'APPDATA'),
'GRASS%s' % gVersion,
'env.bat')
846 if os.path.exists(envFile):
850 sys.stderr.write(_(
"Unable to open file '%s'\n") % envFile)
852 for line
in fd.readlines():
853 line = line.rstrip(os.linesep)
855 k, v = map(
lambda x: x.strip(), line.split(
' ', 1)[1].
split(
'=', 1))
856 except StandardError, e:
857 sys.stderr.write(_(
"%s: line skipped - unable to parse '%s'\n"
858 "Reason: %s\n") % (envFile, line, e))
859 lineSkipped.append(line)
862 sys.stderr.write(_(
"Duplicated key: %s\n") % k)
868 if value
is None and key
in environ:
875 fd = open(envFile,
'w')
877 sys.stderr.write(_(
"Unable to create file '%s'\n") % envFile)
884 for key, value
in environ.iteritems():
885 fd.write(
'%s %s=%s\n' % (expCmd, key, value))
888 for line
in lineSkipped:
889 fd.write(line + os.linesep)
894 """!Set default AddOn path
896 @addonPath path to addons (None for default)
898 gVersion = grass.version()[
'version'].
split(
'.', 1)[0]
901 if sys.platform !=
'win32':
902 addonPath = os.path.join(os.path.join(os.getenv(
'HOME'),
903 '.grass%s' % gVersion,
906 addonPath = os.path.join(os.path.join(os.getenv(
'APPDATA'),
907 'GRASS%s' % gVersion,
911 os.environ[
'GRASS_ADDON_PATH'] = addonPath
def CmdToTuple
Convert command list to tuple for gcmd.RunCommand()
def GetListOfLocations
Get list of GRASS locations in given dbase.
def normalize_whitespace
Remove redundant whitespace from a string.
def ListOfCatsToRange
Convert list of category number to range(s)
def GetSettingsPath
Get full path to the settings directory.
def GetListOfMapsets
Get list of mapsets in given GRASS location.
def split
Platform spefic shlex.split.
def GetFormats
Get GDAL/OGR formats.
def StoreEnvVariable
Store environmental variable.
def SetAddOnPath
Set default AddOn path.
def ListOfMapsets
Get list of available/accessible mapsets.
def GetLayerNameFromCmd
Get map name from GRASS command.
def EncodeString
Return encoded string using system locales.
def ReadEpsgCodes
Read EPSG code from the file.
def ListSortLower
Sort list items (not case-sensitive)
def DMS2Deg
Convert dms value to deg.
def GetValidLayerName
Make layer name SQL compliant, based on G_str_to_sql()
def GetTempfile
Creates GRASS temporary file using defined prefix.
def DecodeString
Decode string using system encoding.
def GetColorTables
Get list of color tables.
def GetAllVectorLayers
Returns list of all vector layers as strings.
def PathJoin
Check path created by os.path.join.
Global variables used by wxGUI.
def ReprojectCoordinates
Reproject coordinates.
def GetVectorNumberOfLayers
Get list of vector layers.
def RunCommand
Run GRASS command.
def Deg2DMS
Convert deg value to dms string.