class Layer(object): """Virtual class which stores information about layers (map layers and overlays) of the map composition. - For map layer use MapLayer class. - For overlays use Overlay class. """ def __init__(self, ltype, cmd, Map, name=None, active=True, hidden=False, opacity=1.0): """Create new instance .. todo:: pass cmd as tuple instead of list :param ltype: layer type ('raster', 'vector', 'overlay', 'command', etc.) :param cmd: GRASS command to render layer, given as list, e.g. ['d.rast', 'map=elevation@PERMANENT'] :param map: render.Map instance :param name: layer name, e.g. 'elevation@PERMANENT' (for layer tree) :param active: layer is active, will be rendered only if True :param hidden: layer is hidden, won't be listed in Layer Manager if True :param float opacity: layer opacity <0;1> """ # generated file for each layer if USE_GPNMCOMP or ltype == 'overlay': if ltype == 'overlay': tempfile_sfx = ".png" else: tempfile_sfx = ".ppm" mapfile = tempfile.NamedTemporaryFile(suffix=tempfile_sfx, delete=False) # we don't want it open, we just need the name self.mapfile = mapfile.name mapfile.close() self.maskfile = self.mapfile.rsplit(".",1)[0] + ".pgm" else: self.mapfile = self.maskfile = None # stores class which manages rendering instead of simple command - e.g. WMS self.renderMgr = None self.Map = Map self.type = None self.SetType(ltype) self.name = name self.environ = os.environ.copy() if self.type == 'command': self.cmd = list() for c in cmd: self.cmd.append(utils.CmdToTuple(c)) else: self.cmd = utils.CmdToTuple(cmd) self.active = active self.hidden = hidden self.opacity = opacity self.forceRender = True Debug.msg (3, "Layer.__init__(): type=%s, cmd='%s', name=%s, " \ "active=%d, opacity=%d, hidden=%d" % \ (self.type, self.GetCmd(string=True), self.name, self.active, self.opacity, self.hidden)) def __del__(self): Debug.msg (3, "Layer.__del__(): layer=%s, cmd='%s'" % (self.name, self.GetCmd(string = True))) def Render(self): """Render layer to image :return: rendered image filename :return: None on error or if cmdfile is defined """ if not self.cmd: return None # ignore in 2D if self.type == '3d-raster': return None Debug.msg (3, "Layer.Render(): type=%s, name=%s" % \ (self.type, self.name)) # prepare command for each layer layertypes = utils.command2ltype.values() + ['overlay', 'command'] if self.type not in layertypes: raise GException(_("<%(name)s>: layer type <%(type)s> is not supported") % \ {'type' : self.type, 'name' : self.name}) if self.mapfile: self.environ["GRASS_PNGFILE"] = self.mapfile # execute command try: if self.type == 'command': read = False for c in self.cmd: ret, msg = self._runCommand(c) if ret != 0: break if not read: self.environ["GRASS_PNG_READ"] = "TRUE" self.environ["GRASS_PNG_READ"] = "FALSE" else: ret, msg = self._runCommand(self.cmd) if ret != 0: sys.stderr.write(_("Command '%s' failed\n") % self.GetCmd(string = True)) if msg: sys.stderr.write(_("Details: %s\n") % msg) raise GException() except GException: # clean up after problems for f in [self.mapfile, self.maskfile]: if not f: continue try_remove(f) f = None self.forceRender = False return self.mapfile def _runCommand(self, cmd): """Run command to render data """ if self.type == 'wms': ret = 0 msg = '' self.renderMgr.Render(cmd, env=self.environ) else: ret, msg = RunCommand(cmd[0], getErrorMsg = True, quiet = True, env=self.environ, **cmd[1]) return ret, msg def GetCmd(self, string = False): """Get GRASS command as list of string. :param string: get command as string if True otherwise as list :return: command list/string """ if string: if self.type == 'command': scmd = [] for c in self.cmd: scmd.append(utils.GetCmdString(c)) return ';'.join(scmd) else: return utils.GetCmdString(self.cmd) else: return self.cmd def GetType(self): """Get map layer type""" return self.type def GetElement(self): """Get map element type""" if self.type == 'raster': return 'cell' return self.type def GetOpacity(self): """ Get layer opacity level :return: opacity level (<0, 1>) """ return self.opacity def GetName(self, fullyQualified = True): """Get map layer name :param bool fullyQualified: True to return fully qualified name as a string 'name@mapset' otherwise directory { 'name', 'mapset' } is returned :return: string / directory """ if fullyQualified: return self.name else: if '@' in self.name: return { 'name' : self.name.split('@')[0], 'mapset' : self.name.split('@')[1] } else: return { 'name' : self.name, 'mapset' : '' } def IsActive(self): """Check if layer is activated for rendering""" return self.active def IsHidden(self): """Check if layer is hidden""" return self.hidden def SetType(self, ltype): """Set layer type""" if ltype not in utils.command2ltype.values() + ['overlay', 'command']: raise GException(_("Unsupported map layer type '%s'") % ltype) if ltype == 'wms' and not isinstance(self.renderMgr, RenderWMSMgr): self.renderMgr = RenderWMSMgr(layer=self, mapfile=self.mapfile, maskfile=self.maskfile) elif self.type == 'wms' and ltype != 'wms': self.renderMgr = None self.type = ltype def SetName(self, name): """Set layer name""" self.name = name def SetActive(self, enable = True): """Active or deactive layer""" self.active = bool(enable) def SetHidden(self, enable = False): """Hide or show map layer in Layer Manager""" self.hidden = bool(enable) def SetOpacity(self, value): """Set opacity value""" if value < 0: value = 0. elif value > 1: value = 1. self.opacity = float(value) def SetCmd(self, cmd): """Set new command for layer""" if self.type == 'command': self.cmd = [] for c in cmd: self.cmd.append(utils.CmdToTuple(c)) else: self.cmd = utils.CmdToTuple(cmd) Debug.msg(3, "Layer.SetCmd(): cmd='%s'" % self.GetCmd(string = True)) # for re-rendering self.forceRender = True def SetEnvironment(self, environ): """Sets environment for rendering.""" self.environ = environ def IsDownloading(self): """Is data downloading from web server e. g. wms""" if self.renderMgr is None: return False else: return self.renderMgr.IsDownloading() def AbortThread(self): """Abort running thread e. g. downloading data""" if self.renderMgr is None: return else: self.renderMgr.Abort() def GetRenderMgr(self): """Get render manager """ return self.renderMgr
class Layer(object): """!Virtual class which stores information about layers (map layers and overlays) of the map composition. - For map layer use MapLayer class. - For overlays use Overlay class. """ def __init__( self, ltype, cmd, Map, name=None, active=True, hidden=False, opacity=1.0 ): """!Create new instance @todo pass cmd as tuple instead of list @param ltype layer type ('raster', 'vector', 'overlay', 'command', etc.) @param cmd GRASS command to render layer, given as list, e.g. ['d.rast', 'map=elevation@PERMANENT'] @param Map render.Map instance @param name layer name, e.g. 'elevation@PERMANENT' (for layer tree) @param active layer is active, will be rendered only if True @param hidden layer is hidden, won't be listed in Layer Manager if True @param opacity layer opacity <0;1> """ # generated file for each layer if USE_GPNMCOMP or ltype == "overlay": tmpfile = tempfile.mkstemp()[1] self.maskfile = tmpfile + ".pgm" if ltype == "overlay": self.mapfile = tmpfile + ".png" else: self.mapfile = tmpfile + ".ppm" grass.try_remove(tmpfile) else: self.mapfile = self.maskfile = None # stores class which manages rendering instead of simple command - e. g. wms self.renderMgr = None self.Map = Map self.type = None self.SetType(ltype) self.name = name if self.type == "command": self.cmd = list() for c in cmd: self.cmd.append(utils.CmdToTuple(c)) else: self.cmd = utils.CmdToTuple(cmd) self.active = active self.hidden = hidden self.opacity = opacity self.forceRender = True Debug.msg( 3, "Layer.__init__(): type=%s, cmd='%s', name=%s, " "active=%d, opacity=%d, hidden=%d" % ( self.type, self.GetCmd(string=True), self.name, self.active, self.opacity, self.hidden, ), ) def __del__(self): Debug.msg( 3, "Layer.__del__(): layer=%s, cmd='%s'" % (self.name, self.GetCmd(string=True)), ) def Render(self): """!Render layer to image @return rendered image filename @return None on error or if cmdfile is defined """ if not self.cmd: return None # ignore in 2D if self.type == "3d-raster": return None Debug.msg(3, "Layer.Render(): type=%s, name=%s" % (self.type, self.name)) # prepare command for each layer layertypes = utils.command2ltype.values() + ["overlay", "command"] if self.type not in layertypes: raise GException( _("<%(name)s>: layer type <%(type)s> is not supported") % {"type": self.type, "name": self.name} ) if self.mapfile: os.environ["GRASS_RENDER_FILE"] = self.mapfile # execute command try: if self.type == "command": read = False for c in self.cmd: ret, msg = self._runCommand(c) if ret != 0: break if not read: os.environ["GRASS_RENDER_FILE_READ"] = "TRUE" os.environ["GRASS_RENDER_FILE_READ"] = "FALSE" else: ret, msg = self._runCommand(self.cmd) if ret != 0: sys.stderr.write(_("Command '%s' failed\n") % self.GetCmd(string=True)) if msg: sys.stderr.write(_("Details: %s\n") % msg) raise GException() except GException: # clean up after problems for f in [self.mapfile, self.maskfile]: if not f: continue grass.try_remove(f) f = None # stop monitor if self.mapfile and "GRASS_RENDER_FILE" in os.environ: del os.environ["GRASS_RENDER_FILE"] self.forceRender = False return self.mapfile def _runCommand(self, cmd): """!Run command to render data""" if self.type == "wms": ret = 0 msg = "" self.renderMgr.Render(cmd) else: ret, msg = RunCommand(cmd[0], getErrorMsg=True, quiet=True, **cmd[1]) return ret, msg def GetCmd(self, string=False): """!Get GRASS command as list of string. @param string get command as string if True otherwise as list @return command list/string """ if string: if self.type == "command": scmd = [] for c in self.cmd: scmd.append(utils.GetCmdString(c)) return ";".join(scmd) else: return utils.GetCmdString(self.cmd) else: return self.cmd def GetType(self): """!Get map layer type""" return self.type def GetElement(self): """!Get map element type""" if self.type == "raster": return "cell" return self.type def GetOpacity(self, float=False): """ Get layer opacity level @param float get opacity level in <0,1> otherwise <0,100> @return opacity level """ if float: return self.opacity return int(self.opacity * 100) def GetName(self, fullyQualified=True): """!Get map layer name @param fullyQualified True to return fully qualified name as a string 'name@mapset' otherwise directory { 'name', 'mapset' } is returned @return string / directory """ if fullyQualified: return self.name else: if "@" in self.name: return { "name": self.name.split("@")[0], "mapset": self.name.split("@")[1], } else: return {"name": self.name, "mapset": ""} def IsActive(self): """!Check if layer is activated for rendering""" return self.active def SetType(self, ltype): """!Set layer type""" if ltype not in utils.command2ltype.values() + ["overlay", "command"]: raise GException(_("Unsupported map layer type '%s'") % ltype) if ltype == "wms" and not isinstance(self.renderMgr, RenderWMSMgr): self.renderMgr = RenderWMSMgr( receiver=self.Map.GetReceiver(), layer=self, Map=self.Map, mapfile=self.mapfile, maskfile=self.maskfile, ) elif self.type == "wms" and ltype != "wms": self.renderMgr = None self.type = ltype def SetName(self, name): """!Set layer name""" self.name = name def SetActive(self, enable=True): """!Active or deactive layer""" self.active = bool(enable) def SetHidden(self, enable=False): """!Hide or show map layer in Layer Manager""" self.hidden = bool(enable) def SetOpacity(self, value): """!Set opacity value""" if value < 0: value = 0.0 elif value > 1: value = 1.0 self.opacity = float(value) def SetCmd(self, cmd): """!Set new command for layer""" if self.type == "command": self.cmd = [] for c in cmd: self.cmd.append(utils.CmdToTuple(c)) else: self.cmd = utils.CmdToTuple(cmd) Debug.msg(3, "Layer.SetCmd(): cmd='%s'" % self.GetCmd(string=True)) # for re-rendering self.forceRender = True def IsDownloading(self): """!Is data downloading from web server e. g. wms""" if self.renderMgr is None: return False else: return self.renderMgr.IsDownloading() def AbortThread(self): """!Abort running thread e. g. downloading data""" if self.renderMgr is None: return else: self.renderMgr.Abort() def GetRenderMgr(self): """!Get render manager""" return self.renderMgr