4 @brief Misc utilities for wxGUI
6 (C) 2007-2009, 2011 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"""
739 ret = grass.read_command(
'r.in.gdal',
743 return _parseFormats(ret)
745 def _getOGRFormats():
746 """!Get dictionary of avaialble OGR drivers"""
747 ret = grass.read_command(
'v.in.ogr',
751 return _parseFormats(ret)
753 def _parseFormats(output):
754 """!Parse r.in.gdal/v.in.ogr -f output"""
755 formats = {
'file' : list(),
763 for line
in output.splitlines():
764 format = line.strip().rsplit(
':', -1)[1].strip()
765 if format
in (
'Memory',
'Virtual Raster',
'In Memory Raster'):
767 if format
in (
'PostgreSQL',
'SQLite',
768 'ODBC',
'ESRI Personal GeoDatabase',
770 'PostGIS WKT Raster driver',
772 formats[
'database'].append(format)
773 elif format
in (
'GeoJSON',
774 'OGC Web Coverage Service',
775 'OGC Web Map Service',
778 'HTTP Fetching Wrapper'):
779 formats[
'protocol'].append(format)
781 formats[
'file'].append(format)
783 for items
in formats.itervalues():
791 """!Get GDAL/OGR formats"""
795 'gdal' : _getGDALFormats(),
796 'ogr' : _getOGRFormats()
802 """!Get full path to the settings directory
805 verFd = open(os.path.join(ETCDIR,
"VERSIONNUMBER"))
806 version = int(verFd.readlines()[0].
split(
' ')[0].
split(
'.')[0])
807 except (IOError, ValueError, TypeError, IndexError), e:
808 sys.exit(_(
"ERROR: Unable to determine GRASS version. Details: %s") % e)
814 if sys.platform ==
'win32':
815 return os.path.join(os.getenv(
'APPDATA'),
'GRASS%d' % version)
817 return os.path.join(os.getenv(
'HOME'),
'.grass%d' % version)
820 """!Store environmental variable
822 If value is not given (is None) then environmental variable is
826 @param value env value
827 @param envFile path to the environmental file (None for default location)
829 windows = sys.platform ==
'win32'
832 envFile = os.path.join(os.getenv(
'HOME'),
'.grass.bashrc')
834 gVersion = grass.version()[
'version'].
split(
'.', 1)[0]
835 envFile = os.path.join(os.getenv(
'APPDATA'),
'GRASS%s' % gVersion,
'env.bat')
840 if os.path.exists(envFile):
844 sys.stderr.write(_(
"Unable to open file '%s'\n") % envFile)
846 for line
in fd.readlines():
847 line = line.rstrip(os.linesep)
849 k, v = map(
lambda x: x.strip(), line.split(
' ', 1)[1].
split(
'=', 1))
850 except StandardError, e:
852 sys.stderr.write(_(
"%(env)s: line skipped - unable to parse "
853 "Reason: %(e)s\n") % {
'env': envFile,
854 'line': line,
'e': e})
855 lineSkipped.append(line)
858 sys.stderr.write(_(
"Duplicated key: %s\n") % k)
864 if value
is None and key
in environ:
871 fd = open(envFile,
'w')
873 sys.stderr.write(_(
"Unable to create file '%s'\n") % envFile)
880 for key, value
in environ.iteritems():
881 fd.write(
'%s %s=%s\n' % (expCmd, key, value))
884 for line
in lineSkipped:
885 fd.write(line + os.linesep)
890 """!Set default AddOn path
892 @addonPath path to addons (None for default)
894 gVersion = grass.version()[
'version'].
split(
'.', 1)[0]
897 if sys.platform !=
'win32':
898 addonPath = os.path.join(os.path.join(os.getenv(
'HOME'),
899 '.grass%s' % gVersion,
902 addonPath = os.path.join(os.path.join(os.getenv(
'APPDATA'),
903 'GRASS%s' % gVersion,
907 os.environ[
'GRASS_ADDON_PATH'] = addonPath
def PathJoin(args)
Check path created by os.path.join.
def GetValidLayerName(name)
Make layer name SQL compliant, based on G_str_to_sql()
def GetFormats()
Get GDAL/OGR formats.
def GetListOfMapsets
Get list of mapsets in given GRASS location.
def GetColorTables()
Get list of color tables.
def DecodeString(string)
Decode string using system encoding.
def ListSortLower(list)
Sort list items (not case-sensitive)
def GetListOfLocations(dbase)
Get list of GRASS locations in given dbase.
def GetAllVectorLayers(vector)
Returns list of all vector layers as strings.
def StoreEnvVariable
Store environmental variable.
def SetAddOnPath
Set default AddOn path.
def ListOfMapsets
Get list of available/accessible mapsets.
def split(s)
Platform spefic shlex.split.
def DMS2Deg(lon, lat)
Convert dms value to deg.
def GetLayerNameFromCmd
Get map name from GRASS command.
def GetSettingsPath()
Get full path to the settings directory.
def ReadEpsgCodes(path)
Read EPSG code from the file.
def GetTempfile
Creates GRASS temporary file using defined prefix.
def EncodeString(string)
Return encoded string using system locales.
def CmdToTuple(cmd)
Convert command list to tuple for gcmd.RunCommand()
def ListOfCatsToRange(cats)
Convert list of category number to range(s)
def normalize_whitespace(text)
Remove redundant whitespace from a string.
Global variables used by wxGUI.
def RunCommand(prog, flags="", overwrite=False, quiet=False, verbose=False, parent=None, read=False, stdin=None, getErrorMsg=False, kwargs)
Run GRASS command.
def ReprojectCoordinates
Reproject coordinates.
def GetVectorNumberOfLayers
Get list of vector layers.
def Deg2DMS
Convert deg value to dms string.