From a415c73c9178a3dad211a7842a69819350c6d1dd Mon Sep 17 00:00:00 2001
From: hagrid67 <jdhwatson@gmail.com>
Date: Sat, 18 May 2019 17:03:52 +0100
Subject: [PATCH] added transparency / opacity with PIL. moved test_player.py
 to using PIL and tkinter instead of QT

---
 examples/play_model.py           |   4 +-
 examples/tkplay.py               |  59 ++++++++++++++
 flatland/utils/graphics_layer.py |   2 +-
 flatland/utils/graphics_pil.py   |  56 ++++++++++---
 flatland/utils/rendertools.py    | 132 +++++++++++++++++++------------
 images/basic-env.npz             | Bin 36398 -> 10007 bytes
 tests/test_player.py             |   5 +-
 tests/test_rendertools.py        |   4 +-
 8 files changed, 193 insertions(+), 69 deletions(-)
 create mode 100644 examples/tkplay.py

diff --git a/examples/play_model.py b/examples/play_model.py
index 5ed6feb..777f2d3 100644
--- a/examples/play_model.py
+++ b/examples/play_model.py
@@ -100,7 +100,7 @@ def max_lt(seq, val):
     return None
 
 
-def main(render=True, delay=0.0, n_trials=3, n_steps=50):
+def main(render=True, delay=0.0, n_trials=3, n_steps=50, sGL="QT"):
     random.seed(1)
     np.random.seed(1)
 
@@ -111,7 +111,7 @@ def main(render=True, delay=0.0, n_trials=3, n_steps=50):
 
     if render:
         # env_renderer = RenderTool(env, gl="QTSVG")
-        env_renderer = RenderTool(env, gl="QT")
+        env_renderer = RenderTool(env, gl=sGL)
 
     oPlayer = Player(env)
 
diff --git a/examples/tkplay.py b/examples/tkplay.py
new file mode 100644
index 0000000..b337253
--- /dev/null
+++ b/examples/tkplay.py
@@ -0,0 +1,59 @@
+
+import tkinter as tk
+from PIL import ImageTk, Image
+from examples.play_model import Player
+from flatland.envs.rail_env import RailEnv
+from flatland.envs.generators import complex_rail_generator
+from flatland.utils.rendertools import RenderTool
+import time
+
+
+def tkmain(n_trials=2):
+    # This creates the main window of an application
+    window = tk.Tk()
+    window.title("Join")
+    window.configure(background='grey')
+
+    # Example generate a random rail
+    env = RailEnv(width=15, height=15,
+                  rail_generator=complex_rail_generator(nr_start_goal=5, nr_extra=20, min_dist=12),
+                  number_of_agents=5)
+
+    env_renderer = RenderTool(env, gl="PIL")
+
+    oPlayer = Player(env)
+    n_trials = 1
+    n_steps = 20
+    delay = 0
+    for trials in range(1, n_trials + 1):
+
+        # Reset environment8
+        oPlayer.reset()
+        env_renderer.set_new_rail()
+
+        first = True
+
+        for step in range(n_steps):
+            oPlayer.step()
+            env_renderer.renderEnv(show=True, frames=True, iEpisode=trials, iStep=step,
+                action_dict=oPlayer.action_dict)
+            img = env_renderer.getImage()
+            img = Image.fromarray(img)
+            tkimg = ImageTk.PhotoImage(img)
+
+            if first:
+                panel = tk.Label(window, image = tkimg)
+                panel.pack(side = "bottom", fill = "both", expand = "yes")
+            else:
+                # update the image in situ
+                panel.configure(image=tkimg)
+                panel.image = tkimg
+
+            window.update()
+            if delay > 0:
+                time.sleep(delay)
+            first = False
+
+
+if __name__ == "__main__":
+    tkmain()
\ No newline at end of file
diff --git a/flatland/utils/graphics_layer.py b/flatland/utils/graphics_layer.py
index 4cfcc64..40bf319 100644
--- a/flatland/utils/graphics_layer.py
+++ b/flatland/utils/graphics_layer.py
@@ -51,7 +51,7 @@ class GraphicsLayer(object):
         elif type(color) is tuple:
             if type(color[0]) is not int:
                 gcolor = array(color)
-                color = tuple((gcolor[:3] * 255).astype(int))
+                color = tuple((gcolor[:4] * 255).astype(int))
         else:
             color = self.tColGrid
 
diff --git a/flatland/utils/graphics_pil.py b/flatland/utils/graphics_pil.py
index 41516fd..ceda3fd 100644
--- a/flatland/utils/graphics_pil.py
+++ b/flatland/utils/graphics_pil.py
@@ -18,28 +18,32 @@ class PILGL(GraphicsLayer):
         # Total grid size at native scale
         self.widthPx = self.width * self.nPixCell + self.linewidth
         self.heightPx = self.height * self.nPixCell + self.linewidth
-        self.beginFrame()
+        self.layers = []
+        self.draws = []
 
         self.tColBg = (255, 255, 255)     # white background
         # self.tColBg = (220, 120, 40)    # background color
         self.tColRail = (0, 0, 0)         # black rails
         self.tColGrid = (230,) * 3        # light grey for grid
 
-    def plot(self, gX, gY, color=None, linewidth=3, **kwargs):
-        color = self.adaptColor(color)
+        self.beginFrame()
 
-        # print(gX, gY)
+    def plot(self, gX, gY, color=None, linewidth=3, layer=0, opacity=255, **kwargs):
+        color = self.adaptColor(color)
+        if len(color) == 3:
+            color += (opacity,)
+        elif len(color) == 4:
+            color = color[:3] + (opacity,)
         gPoints = np.stack([array(gX), -array(gY)]).T * self.nPixCell
         gPoints = list(gPoints.ravel())
-        # print(gPoints, color)
-        self.draw.line(gPoints, fill=color, width=self.linewidth)
+        self.draws[layer].line(gPoints, fill=color, width=self.linewidth)
 
-    def scatter(self, gX, gY, color=None, marker="o", s=50, *args, **kwargs):
+    def scatter(self, gX, gY, color=None, marker="o", s=50, layer=0, opacity=255, *args, **kwargs):
         color = self.adaptColor(color)
         r = np.sqrt(s)
         gPoints = np.stack([np.atleast_1d(gX), -np.atleast_1d(gY)]).T * self.nPixCell
         for x, y in gPoints:
-            self.draw.rectangle([(x - r, y - r), (x + r, y + r)], fill=color, outline=color)
+            self.draws[layer].rectangle([(x - r, y - r), (x + r, y + r)], fill=color, outline=color)
 
     def text(self, *args, **kwargs):
         pass
@@ -51,8 +55,8 @@ class PILGL(GraphicsLayer):
         pass
 
     def beginFrame(self):
-        self.img = Image.new("RGBA", (self.widthPx, self.heightPx), (255, 255, 255, 255))
-        self.draw = ImageDraw.Draw(self.img)
+        self.create_layer(0)
+        self.create_layer(1)
 
     def show(self, block=False):
         pass
@@ -62,5 +66,35 @@ class PILGL(GraphicsLayer):
         pass
         # plt.pause(seconds)
 
+    def alpha_composite_layers(self):
+        img = self.layers[0]
+        for img2 in self.layers[1:]:
+            img = Image.alpha_composite(img, img2)
+        return img
+
     def getImage(self):
-        return array(self.img)
+        """ return a blended / alpha composited image composed of all the layers,
+            with layer 0 at the "back".
+        """
+        img = self.alpha_composite_layers()
+        return array(img)
+
+    def create_image(self, opacity=255):
+        img = Image.new("RGBA", (self.widthPx, self.heightPx), (255, 255, 255, opacity))
+        return img
+
+    def create_layer(self, iLayer=0):
+        if len(self.layers) <= iLayer:
+            for i in range(len(self.layers), iLayer+1):
+                if i==0:
+                    opacity = 255  # "bottom" layer is opaque (for rails)
+                else:
+                    opacity = 0   # subsequent layers are transparent
+                img = self.create_image(opacity)
+                self.layers.append(img)
+                self.draws.append(ImageDraw.Draw(img))
+        else:
+            opacity = 0 if iLayer > 0 else 255
+            self.layers[iLayer] = img = self.create_image(opacity)
+            self.draws[iLayer] = ImageDraw.Draw(img)
+
diff --git a/flatland/utils/rendertools.py b/flatland/utils/rendertools.py
index e9a94ec..4def953 100644
--- a/flatland/utils/rendertools.py
+++ b/flatland/utils/rendertools.py
@@ -15,12 +15,14 @@ from flatland.utils.graphics_layer import GraphicsLayer
 
 
 class MPLGL(GraphicsLayer):
-    def __init__(self, width, height):
+    def __init__(self, width, height, show=False):
         self.width = width
         self.height = height
         self.yxBase = array([6, 21])  # pixel offset
         self.nPixCell = 700 / width
         self.img = None
+        if show:
+            plt.figure(figsize=(10, 10))
 
     def plot(self, *args, **kwargs):
         plt.plot(*args, **kwargs)
@@ -70,6 +72,7 @@ class MPLGL(GraphicsLayer):
     def beginFrame(self):
         self.img = None
         plt.figure(figsize=(10, 10))
+        plt.clf()
         pass
 
     def endFrame(self):
@@ -115,7 +118,7 @@ class RenderTool(object):
     gTheta = np.linspace(0, np.pi / 2, 5)
     gArc = array([np.cos(gTheta), np.sin(gTheta)]).T  # from [1,0] to [0,1]
 
-    def __init__(self, env, gl="MPL"):
+    def __init__(self, env, gl="MPL", show=False):
         self.env = env
         self.iFrame = 0
         self.time1 = time.time()
@@ -123,7 +126,7 @@ class RenderTool(object):
         # self.gl = MPLGL()
 
         if gl == "MPL":
-            self.gl = MPLGL(env.width, env.height)
+            self.gl = MPLGL(env.width, env.height, show=show)
         elif gl == "QT":
             self.gl = QTGL(env.width, env.height)
         elif gl == "PIL":
@@ -219,17 +222,19 @@ class RenderTool(object):
         if static:
             color = self.gl.adaptColor(color, lighten=True)
 
+        color = color
+
         # print("Agent:", rcPos, iDir, rcDir, xyDir, xyPos)
-        self.gl.scatter(*xyPos, color=color, marker="o", s=100)  # agent location
+        self.gl.scatter(*xyPos, color=color, layer=1, marker="o", s=100)  # agent location
         xyDirLine = array([xyPos, xyPos + xyDir / 2]).T  # line for agent orient.
-        self.gl.plot(*xyDirLine, color=color, lw=5, ms=0, alpha=0.6)
+        self.gl.plot(*xyDirLine, color=color, layer=1, lw=5, ms=0, alpha=0.6)
         if selected:
             self._draw_square(xyPos, 1, color)
 
         if target is not None:
             rcTarget = array(target)
             xyTarget = np.matmul(rcTarget, rt.grc2xy) + rt.xyHalf
-            self._draw_square(xyTarget, 1 / 3, color)
+            self._draw_square(xyTarget, 1 / 3, color, layer=1)
 
     def plotTrans(self, rcPos, gTransRCAg, color="r", depth=None):
         """
@@ -397,6 +402,13 @@ class RenderTool(object):
                 visit = visit.prev
                 xyPrev = xy
 
+    def drawTrans(self, oFrom, oTo, sColor="gray"):
+        self.gl.plot(
+            [oFrom[0], oTo[0]],  # x
+            [oFrom[1], oTo[1]],  # y
+            color=sColor
+        )
+
     def drawTrans2(
         self,
             xyLine, xyCentre,
@@ -489,47 +501,14 @@ class RenderTool(object):
             for visited_cell in observation_dict[agent]:
                 cell_coord = array(visited_cell[:2])
                 cell_coord_trans = np.matmul(cell_coord, rt.grc2xy) + rt.xyHalf
-                self._draw_square(cell_coord_trans, 1 / 3, color)
-
-    def renderEnv(
-        self, show=False, curves=True, spacing=False,
-            arrows=False, agents=True, obsrender=True, sRailColor="gray", frames=False, iEpisode=None, iStep=None,
-            iSelectedAgent=None, action_dict=None):
-        """
-        Draw the environment using matplotlib.
-        Draw into the figure if provided.
-
-        Call pyplot.show() if show==True.
-        (Use show=False from a Jupyter notebook with %matplotlib inline)
-        """
-
-        if not self.gl.is_raster():
-            self.renderEnv2(show, curves, spacing,
-                            arrows, agents, sRailColor,
-                            frames, iEpisode, iStep,
-                            iSelectedAgent, action_dict)
-            return
-
-        # cell_size is a bit pointless with matplotlib - it does not relate to pixels,
-        # so for now I've changed it to 1 (from 10)
-        cell_size = 1
-        self.gl.beginFrame()
+                self._draw_square(cell_coord_trans, 1 / (agent+1.1), color, layer=1, opacity=100)
 
-        # self.gl.clf()
-        # if oFigure is None:
-        #    oFigure = self.gl.figure()
 
-        def drawTrans(oFrom, oTo, sColor="gray"):
-            self.gl.plot(
-                [oFrom[0], oTo[0]],  # x
-                [oFrom[1], oTo[1]],  # y
-                color=sColor
-            )
+    def renderRail(self, spacing=False, sRailColor="gray", curves=True, arrows=False):
 
+        cell_size = 1  # TODO: remove cell_size
         env = self.env
 
-        # t1 = time.time()
-
         # Draw cells grid
         grid_color = [0.95, 0.95, 0.95]
         for r in range(env.height + 1):
@@ -613,7 +592,7 @@ class RenderTool(object):
                                         rotation, spacing=spacing, bArrow=arrows,
                                         sColor=sRailColor)
                                 else:
-                                    drawTrans(from_xy, to_xy, sRailColor)
+                                    self.drawTrans(self, from_xy, to_xy, sRailColor)
 
                             if False:
                                 print(
@@ -626,6 +605,54 @@ class RenderTool(object):
                                     "rot:", rotation,
                                 )
 
+
+
+    def renderEnv(
+        self, show=False, curves=True, spacing=False,
+            arrows=False, agents=True, obsrender=True, sRailColor="gray", frames=False,
+            iEpisode=None, iStep=None,
+            iSelectedAgent=None, action_dict=None):
+        """
+        Draw the environment using matplotlib.
+        Draw into the figure if provided.
+
+        Call pyplot.show() if show==True.
+        (Use show=False from a Jupyter notebook with %matplotlib inline)
+        """
+
+        if not self.gl.is_raster():
+            self.renderEnv2(show, curves, spacing,
+                            arrows, agents, sRailColor,
+                            frames, iEpisode, iStep,
+                            iSelectedAgent, action_dict)
+            return
+
+        # cell_size is a bit pointless with matplotlib - it does not relate to pixels,
+        # so for now I've changed it to 1 (from 10)
+        cell_size = 1
+
+        if type(self.gl) in (QTGL, PILGL):
+            self.gl.beginFrame()
+
+        if type(self.gl) is MPLGL:
+            #self.gl.clf()
+            # plt.clf()
+            self.gl.beginFrame()
+            pass
+
+        # self.gl.clf()
+        # if oFigure is None:
+        #    oFigure = self.gl.figure()
+
+
+
+        env = self.env
+
+        # t1 = time.time()
+
+
+        self.renderRail()
+
         # Draw each agent + its orientation + its target
         if agents:
             self.plotAgents(targets=True, iSelectedAgent=iSelectedAgent)
@@ -657,23 +684,26 @@ class RenderTool(object):
         # TODO: for MPL, we don't want to call clf (called by endframe)
         # for QT, we need to call endFrame()
         # if not show:
-        self.gl.endFrame()
+        if type(self.gl) is QTGL:
+            self.gl.endFrame()
+            if show:
+                self.gl.show(block=False)
 
-        # t2 = time.time()
-        # print(t2 - t1, "seconds")
+        if type(self.gl) is MPLGL:
+            if show:
+                self.gl.show(block=False)
+            #self.gl.endFrame()
 
-        if show:
-            self.gl.show(block=False)
-            self.gl.pause(0.00001)
+        self.gl.pause(0.00001)
 
         return
 
-    def _draw_square(self, center, size, color):
+    def _draw_square(self, center, size, color, opacity=255, layer=0):
         x0 = center[0] - size / 2
         x1 = center[0] + size / 2
         y0 = center[1] - size / 2
         y1 = center[1] + size / 2
-        self.gl.plot([x0, x1, x1, x0, x0], [y0, y0, y1, y1, y0], color=color)
+        self.gl.plot([x0, x1, x1, x0, x0], [y0, y0, y1, y1, y0], color=color, layer=layer, opacity=opacity)
 
     def getImage(self):
         return self.gl.getImage()
diff --git a/images/basic-env.npz b/images/basic-env.npz
index 356da5d70146b3b8081dd99c0fe5e6bd70646e53..8ffaf023e1116b0c92702212ddb04c71b82f0655 100644
GIT binary patch
literal 10007
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

literal 36398
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

diff --git a/tests/test_player.py b/tests/test_player.py
index 82f6f67..7b2745f 100644
--- a/tests/test_player.py
+++ b/tests/test_player.py
@@ -1,7 +1,8 @@
 
-from examples.play_model import main
+# from examples.play_model import main
+from examples.tkplay import tkmain
 
 
 def test_main():
-    main(n_trials=2)
+    tkmain(n_trials=2)
 
diff --git a/tests/test_rendertools.py b/tests/test_rendertools.py
index 3259ed3..7d3ddf6 100644
--- a/tests/test_rendertools.py
+++ b/tests/test_rendertools.py
@@ -46,8 +46,8 @@ def test_render_env(save_new_images=False):
                    )
     sfTestEnv = "env-data/tests/test1.npy"
     oEnv.rail.load_transition_map(sfTestEnv)
-    oRT = rt.RenderTool(oEnv)
-    oRT.renderEnv()
+    oRT = rt.RenderTool(oEnv, gl="PIL", show=False)
+    oRT.renderEnv(show=False)
 
     checkFrozenImage(oRT, "basic-env.npz", resave=save_new_images)
 
-- 
GitLab