From b5b2ca8e3bffe7658eeccd71ba3fdf53fa29d59f Mon Sep 17 00:00:00 2001 From: hagrid67 <jdhwatson@gmail.com> Date: Sun, 12 May 2019 20:36:41 +0100 Subject: [PATCH] updated test_renderenv to use npz format. Added a test for the PIL graphics layer. --- flatland/utils/editor.py | 1 - flatland/utils/rendertools.py | 1 + images/basic-env-PIL.npz | Bin 0 -> 10007 bytes images/basic-env.npz | Bin 0 -> 36398 bytes tests/test_rendertools.py | 52 +++++++++++++++++++++------------- 5 files changed, 33 insertions(+), 21 deletions(-) create mode 100644 images/basic-env-PIL.npz create mode 100644 images/basic-env.npz diff --git a/flatland/utils/editor.py b/flatland/utils/editor.py index 5e40701a..3e55a793 100644 --- a/flatland/utils/editor.py +++ b/flatland/utils/editor.py @@ -58,7 +58,6 @@ class View(object): def init_canvas(self): # update the rendertool with the env self.new_env() - #plt.figure(figsize=(10, 10)) self.oRT.renderEnv(spacing=False, arrows=False, sRailColor="gray", show=False) img = self.oRT.getImage() plt.clf() diff --git a/flatland/utils/rendertools.py b/flatland/utils/rendertools.py index fb275116..31634402 100644 --- a/flatland/utils/rendertools.py +++ b/flatland/utils/rendertools.py @@ -93,6 +93,7 @@ class MPLGL(GraphicsLayer): color = tuple([iRGBA / 255 for iRGBA in color]) return color + class RenderTool(object): Visit = recordtype("Visit", ["rc", "iDir", "iDepth", "prev"]) diff --git a/images/basic-env-PIL.npz b/images/basic-env-PIL.npz new file mode 100644 index 0000000000000000000000000000000000000000..8ffaf023e1116b0c92702212ddb04c71b82f0655 GIT binary patch literal 10007 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 literal 0 HcmV?d00001 diff --git a/images/basic-env.npz b/images/basic-env.npz new file mode 100644 index 0000000000000000000000000000000000000000..356da5d70146b3b8081dd99c0fe5e6bd70646e53 GIT binary patch literal 36398 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 literal 0 HcmV?d00001 diff --git a/tests/test_rendertools.py b/tests/test_rendertools.py index 73b42c38..ea4ad3c4 100644 --- a/tests/test_rendertools.py +++ b/tests/test_rendertools.py @@ -7,6 +7,7 @@ Tests for `flatland` package. from flatland.envs.rail_env import RailEnv, random_rail_generator import numpy as np import os +import sys import matplotlib.pyplot as plt @@ -14,27 +15,28 @@ import flatland.utils.rendertools as rt from flatland.core.env_observation_builder import TreeObsForRailEnv -def checkFrozenImage(sFileImage): +def checkFrozenImage(oRT, sFileImage, resave=False): sDirRoot = "." - sTmpFileImage = sDirRoot + "/images/test/" + sFileImage + sDirImages = sDirRoot + "/images/" - if os.path.exists(sTmpFileImage): - os.remove(sTmpFileImage) + img_test = oRT.getImage() - plt.savefig(sTmpFileImage) + if resave: + np.savez_compressed(sDirImages + sFileImage, img=img_test) + return - bytesFrozenImage = None - for sDir in ["/images/", "/images/test/"]: - sfPath = sDirRoot + sDir + sFileImage - bytesImage = plt.imread(sfPath) - if bytesFrozenImage is None: - bytesFrozenImage = bytesImage - else: - assert (bytesFrozenImage.shape == bytesImage.shape) - assert ((np.sum(np.square(bytesFrozenImage - bytesImage)) / bytesFrozenImage.size) < 1e-3) + # this is now just for convenience - the file is not read back + np.savez_compressed(sDirImages + "test/" + sFileImage, img=img_test) + image_store = np.load(sDirImages + sFileImage) + img_expected = image_store["img"] -def test_render_env(): + assert (img_test.shape == img_expected.shape) + assert ((np.sum(np.square(img_test - img_expected)) / img_expected.size / 256) < 1e-3), \ + "Image {} does not match".format(sFileImage) + + +def test_render_env(save_new_images=False): # random.seed(100) np.random.seed(100) oEnv = RailEnv(width=10, height=10, @@ -45,15 +47,14 @@ def test_render_env(): ) sfTestEnv = "env-data/tests/test1.npy" oEnv.rail.load_transition_map(sfTestEnv) - oEnv.reset() oRT = rt.RenderTool(oEnv) - plt.figure(figsize=(10, 10)) oRT.renderEnv() + + checkFrozenImage(oRT, "basic-env.npz", resave=save_new_images) - checkFrozenImage("basic-env.png") - - plt.figure(figsize=(10, 10)) + oRT = rt.RenderTool(oEnv, gl="PIL") oRT.renderEnv() + checkFrozenImage(oRT, "basic-env-PIL.npz", resave=save_new_images) # disable the tree / observation tests until env-agent save/load is available if False: @@ -75,3 +76,14 @@ def test_render_env(): oRT.plotPath(visitDest) checkFrozenImage("env-path.png") + + +def main(): + if len(sys.argv) == 2 and sys.argv[1] == "save": + test_render_env(save_new_images=True) + else: + print("Run 'python test_rendertools.py save' to regenerate images") + + +if __name__ == "__main__": + main() \ No newline at end of file -- GitLab