diff --git a/.gitignore b/.gitignore
index c862ec277a8e310ff9b8c4b26eecfe81111ee68a..03a577b0b713ed8adadda7f6f583e58774f99186 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,5 @@ venv/
 **.egg-info/
 .VSCodeCounter/
 dist/dryvr_plus_plus-0.1-py3.8.egg
-tmp/
\ No newline at end of file
+tmp/
+dist/
\ No newline at end of file
diff --git a/demo/ball_bounces.py b/demo/ball_bounces.py
index 943a2c720b4490a43667489a6c2a484abbeb1ec8..31dfb96043b89ebe2a6e283572c78ad8299c9a40 100644
--- a/demo/ball_bounces.py
+++ b/demo/ball_bounces.py
@@ -1,7 +1,7 @@
 from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor4
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
+from dryvr_plus_plus.plotter.plotter2D import *
 from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap3
 from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario
 from dryvr_plus_plus.example.example_agent.ball_agent import BallAgent
diff --git a/demo/demo1.py b/demo/demo1.py
index 8290e0ba23e4dd19bbe60aca418514d560072081..e6afd9f8742a76d703209867166890387e66b88f 100644
--- a/demo/demo1.py
+++ b/demo/demo1.py
@@ -4,7 +4,7 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
+from dryvr_plus_plus.plotter.plotter2D import *
 
 
 class VehicleMode(Enum):
diff --git a/demo/demo10.py b/demo/demo10.py
index 3a1f78481c7c7d072432b1de9fd12158b416c87f..64c4477681ed2625e7fd8c72f319e6200c02c90e 100644
--- a/demo/demo10.py
+++ b/demo/demo10.py
@@ -1,13 +1,11 @@
 from dryvr_plus_plus.example.example_agent.car_agent import CarAgent
 from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario
 from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMap3, SimpleMap5, SimpleMap6, SimpleMap3_v2
-from dryvr_plus_plus.plotter.plotter2D import *
-from dryvr_plus_plus.plotter.plotter2D_new import *
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2
+from dryvr_plus_plus.plotter.plotter2D import *
 
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
 
 
 class VehicleMode(Enum):
diff --git a/demo/demo2.py b/demo/demo2.py
index f5b27b7b643bc222ebdf555575ab68ef11e2c2b2..60c006f06681d26b6935385327d3bfea8a8a5776 100644
--- a/demo/demo2.py
+++ b/demo/demo2.py
@@ -4,7 +4,7 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
+from dryvr_plus_plus.plotter.plotter2D import *
 
 
 import numpy as np
diff --git a/demo/demo3.py b/demo/demo3.py
index edb2982c846d4b1af3933c49eea49ab325e80e2a..ad03b3005035078fb2e12231c670a98727ac382a 100644
--- a/demo/demo3.py
+++ b/demo/demo3.py
@@ -5,7 +5,7 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
+from dryvr_plus_plus.plotter.plotter2D import *
 
 
 class LaneObjectMode(Enum):
diff --git a/demo/demo4.py b/demo/demo4.py
index 12ae25b342739dee5e7da5d447266482f8d0174a..576a7cfc500d924df38caeab8bdae16d2bc4352e 100644
--- a/demo/demo4.py
+++ b/demo/demo4.py
@@ -5,9 +5,9 @@ from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMa
 from dryvr_plus_plus.plotter.plotter2D import *
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3
 from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor
+
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
 
 
 class LaneObjectMode(Enum):
diff --git a/demo/demo5.py b/demo/demo5.py
index 8aeb6a88951d7b0e98ee5798775e76a24047fd94..77bc114cfe335f4b088c995ab56299f06c0913ba 100644
--- a/demo/demo5.py
+++ b/demo/demo5.py
@@ -6,7 +6,7 @@ from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3
 from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
+from dryvr_plus_plus.plotter.plotter2D import *
 
 
 class LaneObjectMode(Enum):
diff --git a/demo/demo6.py b/demo/demo6.py
index ef0146ede1890582cb3ffb97ca8c3c0cbb846b22..19889aded1f1ad4ce97d49da8a2bc25b29355f53 100644
--- a/demo/demo6.py
+++ b/demo/demo6.py
@@ -8,7 +8,6 @@ from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor
 
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
 
 
 class LaneObjectMode(Enum):
diff --git a/demo/demo7.py b/demo/demo7.py
index 52efa2e1391ee518fd3cb00675923e935a970394..cd2a30cb4378b7fb25cc7e71b001fc953f2d4c55 100644
--- a/demo/demo7.py
+++ b/demo/demo7.py
@@ -10,7 +10,6 @@ from dryvr_plus_plus.scene_verifier.sensor.base_sensor import BaseSensor
 
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
 
 
 class LaneObjectMode(Enum):
diff --git a/demo/demo8.py b/demo/demo8.py
index b33ca221724137e95205e9de492d758bb997c6c2..73a8ca4f280d4459844074d21dc31e1dc340c44e 100644
--- a/demo/demo8.py
+++ b/demo/demo8.py
@@ -2,13 +2,11 @@ from dryvr_plus_plus.example.example_agent.car_agent import CarAgent, NPCAgent
 from dryvr_plus_plus.example.example_agent.sign_agent import SignAgent
 from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario
 from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap2, SimpleMap3, SimpleMap5, SimpleMap6
-from dryvr_plus_plus.plotter.plotter2D import *
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor3
+from dryvr_plus_plus.plotter.plotter2D import *
 
 from enum import Enum, auto
 import plotly.graph_objects as go
-from dryvr_plus_plus.plotter.plotter2D_new import *
-
 
 class LaneObjectMode(Enum):
     Vehicle = auto()
diff --git a/demo/example_two_car_sign_lane_switch.py b/demo/example_two_car_sign_lane_switch.py
index 64524b310cb1b90615dae80d0b5878298889e15f..f56a1e3fcca96b521a61761f23443ca1717a0700 100644
--- a/demo/example_two_car_sign_lane_switch.py
+++ b/demo/example_two_car_sign_lane_switch.py
@@ -1,13 +1,13 @@
-import matplotlib.pyplot as plt
 from dryvr_plus_plus.example.example_sensor.fake_sensor import FakeSensor2
-from dryvr_plus_plus.plotter.plotter2D import plot_reachtube_tree, plot_simulation_tree, generate_simulation_anime, plot_map
 from dryvr_plus_plus.example.example_map.simple_map2 import SimpleMap3
 from dryvr_plus_plus.scene_verifier.scenario.scenario import Scenario
 from dryvr_plus_plus.example.example_agent.sign_agent import SignAgent
 from dryvr_plus_plus.example.example_agent.car_agent import CarAgent
+from dryvr_plus_plus.plotter.plotter2D import *
+
 from enum import Enum, auto
 import copy
-
+import plotly.graph_objects as go
 
 class LaneObjectMode(Enum):
     Vehicle = auto()
@@ -104,15 +104,10 @@ if __name__ == "__main__":
         ]
     )
     # simulator = Simulator()
-    traces = scenario.simulate(40)
+    traces = scenario.simulate(40,0.05)
     # traces = scenario.verify(40)
 
-    fig = plt.figure()
-    fig = plot_map(SimpleMap3(), 'g', fig)
-    # fig = plot_simulation_tree(traces, 'car1', 1, [2], 'b', fig)
-    # fig = plot_simulation_tree(traces, 'car2', 1, [2], 'r', fig)
-    fig = plot_reachtube_tree(traces, 'car1', 1, [2], 'b', fig)
-    fig = plot_reachtube_tree(traces, 'car2', 1, [2], 'r', fig)
-
-    # generate_simulation_anime(traces, SimpleMap3(), fig)
-    plt.show()
+    fig = go.Figure()
+    fig = simulation_anime(traces, None, fig, 1,
+                           2, 'lines', 'trace', print_dim_list=[1, 2])
+    fig.show()
diff --git a/demo/plot2.py b/demo/plot2.py
deleted file mode 100644
index cf6115a0db987e7baa36f947e222b713ac35f7b2..0000000000000000000000000000000000000000
--- a/demo/plot2.py
+++ /dev/null
@@ -1,142 +0,0 @@
-from matplotlib import markers
-import plotly.graph_objects as go
-
-import pandas as pd
-
-url = "https://raw.githubusercontent.com/plotly/datasets/master/gapminderDataFiveYear.csv"
-dataset = pd.read_csv(url)
-
-years = ["1952", "1962", "1967", "1972", "1977", "1982", "1987", "1992", "1997", "2002",
-         "2007"]
-
-# make list of continents
-continents = []
-for continent in dataset["continent"]:
-    if continent not in continents:
-        continents.append(continent)
-# make figure
-fig_dict = {
-    "data": [],
-    "layout": {},
-    "frames": []
-}
-
-# fill in most of layout
-fig_dict["layout"]["xaxis"] = {"range": [30, 85], "title": "Life Expectancy"}
-fig_dict["layout"]["yaxis"] = {"title": "GDP per Capita", "type": "log"}
-fig_dict["layout"]["hovermode"] = "closest"
-fig_dict["layout"]["updatemenus"] = [
-    {
-        "buttons": [
-            {
-                "args": [None, {"frame": {"duration": 500, "redraw": False},
-                                "fromcurrent": True, "transition": {"duration": 300,
-                                                                    "easing": "quadratic-in-out"}}],
-                "label": "Play",
-                "method": "animate"
-            },
-            {
-                "args": [[None], {"frame": {"duration": 0, "redraw": False},
-                                  "mode": "immediate",
-                                  "transition": {"duration": 0}}],
-                "label": "Pause",
-                "method": "animate"
-            }
-        ],
-        "direction": "left",
-        "pad": {"r": 10, "t": 87},
-        "showactive": False,
-        "type": "buttons",
-        "x": 0.1,
-        "xanchor": "right",
-        "y": 0,
-        "yanchor": "top"
-    }
-]
-
-sliders_dict = {
-    "active": 0,
-    "yanchor": "top",
-    "xanchor": "left",
-    "currentvalue": {
-        "font": {"size": 20},
-        "prefix": "Year:",
-        "visible": True,
-        "xanchor": "right"
-    },
-    "transition": {"duration": 300, "easing": "cubic-in-out"},
-    "pad": {"b": 10, "t": 50},
-    "len": 0.9,
-    "x": 0.1,
-    "y": 0,
-    "steps": []
-}
-
-# make data
-year = 1952
-# for continent in continents:
-continent = continents[2]
-dataset_by_year = dataset[dataset["year"] == year]
-dataset_by_year_and_cont = dataset_by_year[
-    dataset_by_year["continent"] == continent]
-
-data_dict = {
-    "x": list(dataset_by_year_and_cont["lifeExp"]),
-    "y": list(dataset_by_year_and_cont["gdpPercap"]),
-    "mode": "markers",
-    "text": list(dataset_by_year_and_cont["country"]),
-    "marker": {
-        "sizemode": "area",
-        "sizeref": 200000,
-        "size": list(dataset_by_year_and_cont["pop"]),
-        "gradient": dict(type='none', color='#000000'),
-        # "symbol": 'diamond-wide'
-    },
-    "name": continent
-}
-fig_dict["data"].append(data_dict)
-
-# make frames
-for year in years:
-    frame = {"data": [], "name": str(year)}
-    # for continent in continents:
-    continent = continents[2]
-    dataset_by_year = dataset[dataset["year"] == int(year)]
-    dataset_by_year_and_cont = dataset_by_year[
-        dataset_by_year["continent"] == continent]
-
-    data_dict = {
-        "x": list(dataset_by_year_and_cont["lifeExp"]),
-        "y": list(dataset_by_year_and_cont["gdpPercap"]),
-        "mode": "markers",
-        "text": list(dataset_by_year_and_cont["country"]),
-        "marker": {
-            "sizemode": "area",
-            "sizeref": 200000,
-            "size": list(dataset_by_year_and_cont["pop"]),
-            "gradient": dict(type='none', color='#000000'),
-            # "symbol": 'diamond-wide'
-
-        },
-        "name": continent
-    }
-    frame["data"].append(data_dict)
-
-    fig_dict["frames"].append(frame)
-    slider_step = {"args": [
-        [year],
-        {"frame": {"duration": 300, "redraw": False},
-         "mode": "immediate",
-         "transition": {"duration": 300}}
-    ],
-        "label": year,
-        "method": "animate"}
-    sliders_dict["steps"].append(slider_step)
-
-
-fig_dict["layout"]["sliders"] = [sliders_dict]
-
-fig = go.Figure(fig_dict)
-# .update_traces(marker={"gradient": dict(type='radial')})
-
-fig.show()
diff --git a/demo/plot_test.py b/demo/plot_test.py
deleted file mode 100644
index 83bedd06d50750323deaa0716b8113b3bdd10023..0000000000000000000000000000000000000000
--- a/demo/plot_test.py
+++ /dev/null
@@ -1,164 +0,0 @@
-from turtle import color
-import plotly.graph_objects as go
-import numpy as np
-
-
-x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
-x_rev = x[::-1]
-x2 = [11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
-x2_rev = x2[::-1]
-
-
-# Line 1
-y1 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
-y1_upper = [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
-y1_lower = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
-y1_lower = y1_lower[::-1]
-
-# Line 2
-y2 = [5, 2.5, 5, 7.5, 5, 2.5, 7.5, 4.5, 5.5, 5]
-y2_upper = [5.5, 3, 5.5, 8, 6, 3, 8, 5, 6, 5.5]
-y2_lower = [4.5, 2, 4.4, 7, 4, 2, 7, 4, 5, 4.75]
-y2_lower = y2_lower[::-1]
-
-# Line 3
-y3 = [10, 8, 6, 4, 2, 0, 2, 4, 2, 0]
-y3_upper = [11, 9, 7, 5, 3, 1, 3, 5, 3, 1]
-y3_lower = [9, 7, 5, 3, 1, -.5, 1, 3, 1, -1]
-y3_lower = y3_lower[::-1]
-
-
-fig = go.Figure()
-
-# fig.add_trace(go.Scatter(
-#     x=x+x_rev + x2+x2_rev,
-#     y=y1_upper+y1_lower+y1_upper+y1_lower,
-#     fill='toself',
-#     marker=dict(
-#         symbol='square',
-#         size=16,
-#         cmax=39,
-#         cmin=0,
-#         color='rgb(0,100,80)',
-#         colorbar=dict(
-#             title="Colorbar"
-#         ),
-#         colorscale="Viridis"
-#     ),
-#     # fillcolor='rgba(0,100,80,0.2)',
-#     # line_color='rgba(255,255,255,0)',
-#     showlegend=False,
-#     name='Fair',
-#     mode="markers"
-# ))
-# fig.add_trace(go.Scatter(
-#     x=[1, 2, 2, 1,  2, 3, 3, 2],
-#     y=[1, 1, 2, 2,  3, 3, 4, 4],
-#     fill='toself',
-#     marker=dict(
-#         symbol='square',
-#         size=16,
-#         cmax=3,
-#         cmin=0,
-#         color=[1, 2],
-#         colorbar=dict(
-#             title="Colorbar"
-#         ),
-#         colorscale="Viridis"
-#     ),
-#     # fillcolor='rgba(0,100,80,0.2)',
-#     # line_color='rgba(255,255,255,0)',
-#     showlegend=False,
-#     name='Fair',
-#     mode="markers"
-# ))
-start = [0, 0, 255, 0.5]
-end = [255, 0, 0, 0.5]
-rgb = [0, 0, 255, 0.5]
-pot = 4
-for i in range(len(rgb)-1):
-    rgb[i] = rgb[i] + (pot-0)/(4-0)*(end[i]-start[i])
-print(rgb)
-fig.add_trace(go.Scatter(
-    x=[1, 2, 2, 1],
-    y=[1, 1, 2, 2],
-    fill='toself',
-    marker=dict(
-        symbol='square',
-        size=16,
-        cmax=4,
-        cmin=0,
-        # color=[3, 3, 3, 3],
-        colorbar=dict(
-            title="Colorbar"
-        ),
-        colorscale=[[0, 'rgba(0,0,255,0.5)'], [1, 'rgba(255,0,0,0.5)']]
-    ),
-
-    fillcolor='rgba'+str(tuple(rgb)),
-    # fillcolor='rgba(0,100,80,0.2)',
-    # line_color='rgba(255,255,255,0)',
-    showlegend=False,
-    name='Fair',
-    mode="markers"
-))
-# for i in range(10):
-#     fig.add_trace(go.Scatter(
-#         x=x+x_rev,
-#         y=y3_upper+y3_lower,
-#         fill='toself',
-#         marker=dict(
-#             symbol='square',
-#             size=16,
-#             cmax=39,
-#             cmin=0,
-#             color='rgb(0,100,80)',
-#             colorbar=dict(
-#                 title="Colorbar"
-#             ),
-#             colorscale="Viridis"
-#         ),
-#         # fillcolor='rgba(0,100,80,0.2)',
-#         # line_color='rgba(255,255,255,0)',
-#         showlegend=False,
-#         name='Fair',
-#         mode="markers"
-#     ))
-# fig.add_trace(go.Scatter(
-#     x=x+x_rev,
-#     y=y2_upper+y2_lower,
-#     fill='toself',
-#     fillcolor='rgba(0,176,246,0.2)',
-#     line_color='rgba(255,255,255,0)',
-#     name='Premium',
-#     showlegend=False,
-# ))
-# fig.add_trace(go.Scatter(
-#     x=x+x_rev,
-#     y=y3_upper+y3_lower,
-#     fill='toself',
-#     fillcolor='rgba(231,107,243,0.2)',
-#     line_color='rgba(255,255,255,0)',
-#     showlegend=False,
-#     name='Ideal',
-# ))
-# fig.add_trace(go.Scatter(
-#     x=x, y=y1,
-#     line_color='rgb(0,100,80)',
-#     name='Fair',
-# ))
-# fig.add_trace(go.Scatter(
-#     x=x, y=y2,
-#     line_color='rgb(0,176,246)',
-#     name='Premium',
-# ))
-# fig.add_trace(go.Scatter(
-#     x=x, y=y3,
-#     line_color='rgb(231,107,243)',
-#     name='Ideal',
-# ))
-
-# fig.update_traces(mode='lines')
-fig.show()
-# print(x+x_rev)
-# print(y1_upper+y1_lower)
diff --git a/demo/plot_test1.py b/demo/plot_test1.py
deleted file mode 100644
index 3ba2de2619df0f8ab8f132f866a584f737bd6822..0000000000000000000000000000000000000000
--- a/demo/plot_test1.py
+++ /dev/null
@@ -1,23 +0,0 @@
-import plotly.graph_objects as go
-import numpy as np
-
-fig = go.Figure()
-values = [1, 2, 3]
-fig.add_trace(go.Scatter(
-    x=values,
-    y=values,
-    marker=dict(
-        symbol='square',
-        size=16,
-        cmax=39,
-        cmin=0,
-        color=values,
-        colorbar=dict(
-            title="Colorbar"
-        ),
-        colorscale="Viridis"
-    ),
-    # marker_symbol='square', marker_line_color="midnightblue", marker_color="lightskyblue",
-    # marker_line_width=2, marker_size=15,
-    mode="markers"))
-fig.show()
diff --git a/dist/dryvr_plus_plus-0.1-py3.8.egg b/dist/dryvr_plus_plus-0.1-py3.8.egg
deleted file mode 100644
index cdd7c8753229a16431604862518b4f6f9d13a03d..0000000000000000000000000000000000000000
Binary files a/dist/dryvr_plus_plus-0.1-py3.8.egg and /dev/null differ
diff --git a/dryvr_plus_plus/plotter/plotter2D.py b/dryvr_plus_plus/plotter/plotter2D.py
index 8dc9f5e644c22a97adee89d0cc1902050257660d..0f8cd26c781efb5ef3b81bf408f7428f802117fa 100644
--- a/dryvr_plus_plus/plotter/plotter2D.py
+++ b/dryvr_plus_plus/plotter/plotter2D.py
@@ -3,113 +3,73 @@ This file consist main plotter code for DryVR reachtube output
 """
 
 from __future__ import annotations
-from audioop import reverse
-# from curses import start_color
-from re import A
-import matplotlib.patches as patches
-import matplotlib.pyplot as plt
 import numpy as np
 from math import pi
 import plotly.graph_objects as go
-from typing import List
-from PIL import Image, ImageDraw
-import io
+from typing import List, Tuple
 import copy
-import operator
-from collections import OrderedDict
-
-from torch import layout
-from dryvr_plus_plus.scene_verifier.analysis.analysis_tree_node import AnalysisTreeNode
-
-colors = ['red', 'green', 'blue', 'yellow', 'black']
-
-def plotly_plot(data,
-                x_dim: int = 0,
-                y_dim_list: List[int] = [1],
-                color='blue',
-                fig=None,
-                x_lim=None,
-                y_lim=None
-                ):
-    if fig is None:
-        fig = plt.figure()
-
-    x_min, x_max = float('inf'), -float('inf')
-    y_min, y_max = float('inf'), -float('inf')
-    for rect in data:
-        lb = rect[0]
-        ub = rect[1]
-        for y_dim in y_dim_list:
-            fig.add_shape(type="rect",
-                          x0=lb[x_dim], y0=lb[y_dim], x1=ub[x_dim], y1=ub[y_dim],
-                          line=dict(color=color),
-                          fillcolor=color
-                          )
-            # rect_patch = patches.Rectangle(
-            #     (lb[x_dim], lb[y_dim]), ub[x_dim]-lb[x_dim], ub[y_dim]-lb[y_dim], color=color)
-            # ax.add_patch(rect_patch)
-            x_min = min(lb[x_dim], x_min)
-            y_min = min(lb[y_dim], y_min)
-            x_max = max(ub[x_dim], x_max)
-            y_max = max(ub[y_dim], y_max)
-    fig.update_shapes(dict(xref='x', yref='y'))
-    # ax.set_xlim([x_min-1, x_max+1])
-    # ax.set_ylim([y_min-1, y_max+1])
-    # fig.update_xaxes(range=[x_min-1, x_max+1], showgrid=False)
-    # fig.update_yaxes(range=[y_min-1, y_max+1])
-    return fig, (x_min, x_max), (y_min, y_max)
-
-def plot(
-    data,
-    x_dim: int = 0,
-    y_dim_list: List[int] = [1],
-    color='b',
-    fig=None,
-    x_lim=None,
-    y_lim=None
-):
-    if fig is None:
-        fig = plt.figure()
-
-    ax = fig.gca()
-    if x_lim is None:
-        x_lim = ax.get_xlim()
-    if y_lim is None:
-        y_lim = ax.get_ylim()
-
-    x_min, x_max = x_lim
-    y_min, y_max = y_lim
-    for rect in data:
-        lb = rect[0]
-        ub = rect[1]
-        for y_dim in y_dim_list:
-            rect_patch = patches.Rectangle(
-                (lb[x_dim], lb[y_dim]), ub[x_dim]-lb[x_dim], ub[y_dim]-lb[y_dim], color=color)
-            ax.add_patch(rect_patch)
-            x_min = min(lb[x_dim], x_min)
-            y_min = min(lb[y_dim], y_min)
-            x_max = max(ub[x_dim], x_max)
-            y_max = max(ub[y_dim], y_max)
-
-    ax.set_xlim([x_min-1, x_max+1])
-    ax.set_ylim([y_min-1, y_max+1])
-    return fig, (x_min, x_max), (y_min, y_max)
+# from dryvr_plus_plus.scene_verifier.analysis.analysis_tree_node import AnalysisTreeNode
+
+colors = [['#CC0000', '#FF0000', '#FF3333', '#FF6666', '#FF9999'],
+          ['#CC6600', '#FF8000', '#FF9933', '#FFB266', '#FFCC99'],
+          ['#CCCC00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99'],
+          ['#66CC00', '#80FF00', '#99FF33', '#B2FF66', '#CCFF99'],
+          ['#00CC00', '#00FF00', '#33FF33', '#66FF66', '#99FF99'],
+          ['#00CC66', '#00FF80', '#33FF99', '#66FFB2', '#99FFCC'],
+          ['#00CCCC', '#00FFFF', '#33FFFF', '#66FFFF', '#99FFFF'],
+          ['#0066CC', '#0080FF', '#3399FF', '#66B2FF', '#99CCFF'],
+          ['#0000CC', '#0000FF', '#3333FF', '#6666FF', '#9999FF'],
+          ['#6600CC', '#7F00FF', '#9933FF', '#B266FF', '#CC99FF'],
+          ['#CC00CC', '#FF00FF', '#FF33FF', '#FF66FF', '#FF99FF'],
+          ['#CC0066', '#FF007F', '#FF3399', '#FF66B2', '#FF99CC']
+          ]
+scheme_dict = {'red': 0, 'orange': 1, 'yellow': 2, 'yellowgreen': 3, 'lime': 4,
+               'springgreen': 5, 'cyan': 6, 'cyanblue': 7, 'blue': 8, 'purple': 9, 'magenta': 10, 'pink': 11}
+color_cnt = 0
+text_size = 8
+scale_factor = 0.25
+mode_point_color = 'rgba(0,0,0,0.5)'
+mode_text_color = 'black'
+duration = 10
+
+
+"""These 5 Functions below are high-level functions and are recommended to use."""
+"""
+API
+These 5 functions share the same API.
+
+- root: the root node of the trace, should be the return value of Scenario.verify() or Scenario.simulate().
+- map: the map of the scenario, templates are in dryvr_plus_plus.example.example_map.simple_map2.py.
+- fig: the object of the figure, its type should be plotly.graph_objects.Figure().
+- x_dim: the dimension of x coordinate in the trace list of every time step. The default value is 1.
+- y_dim: the dimension of y coordinate in the trace list of every time step. The default value is 2.
+- map_type the way to draw the map. It should be 'lines' or 'fill' or 'detailed'. The default value is 'lines'.
+--  For the 'lines' mode, map is only drawn by margins of lanes.
+--  For the 'fill' mode, the lanes will be filled with semitransparent colors.
+--  For the 'detailed' mode, the lanes will be filled some colors according to the speed limits of lanes(if the information is given). 
+    Otherwise, it is the same as the 'lines' mode.
+- scale_type the way to scale the coordinate axises. It should be 'trace' or 'map'. The default value is 'trace'.
+--  For the 'trace' mode, the traces will be in the center of the plot with an appropriate scale.
+--  For the 'map' mode, the map will be in the center of the plot with an appropriate scale.
+- print_dim_list the list containing the dimensions of data which will be shown directly or indirectly when the mouse hovers on the point. 
+    The default value is None. And then all dimensions will be shown.
+"""
 
 
-def generate_reachtube_anime(root, map=None, fig=None):
-    # make figure
-    fig_dict = {
-        "data": [],
-        "layout": {},
-        "frames": []
-    }
-    # fig = plot_map(map, 'g', fig)
+def reachtube_anime(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, map_type='lines', scale_type='trace', print_dim_list=None):
+    """It gives the animation of the verfication."""
+    agent_list = list(root.agent.keys())
     timed_point_dict = {}
     stack = [root]
     x_min, x_max = float('inf'), -float('inf')
     y_min, y_max = float('inf'), -float('inf')
-    print("reachtude")
-    end_time = 0
+    # input check
+    num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1]
+    check_dim(num_dim, x_dim, y_dim, print_dim_list)
+    if print_dim_list is None:
+        print_dim_list = range(0, num_dim)
+    scheme_list = list(scheme_dict.keys())
+
     while stack != []:
         node = stack.pop()
         traces = node.trace
@@ -117,27 +77,13 @@ def generate_reachtube_anime(root, map=None, fig=None):
             trace = np.array(traces[agent_id])
             if trace[0][0] > 0:
                 trace = trace[4:]
-            # print(trace)
-            end_time = trace[-1][0]
-            for i in range(0, len(trace), 2):
-                x_min = min(x_min, trace[i][1])
-                x_max = max(x_max, trace[i][1])
-                y_min = min(y_min, trace[i][2])
-                y_max = max(y_max, trace[i][2])
-                # if round(trace[i][0], 2) not in timed_point_dict:
-                #     timed_point_dict[round(trace[i][0], 2)] = [
-                #         trace[i][1:].tolist()]
-                # else:
-                #     init = False
-                #     for record in timed_point_dict[round(trace[i][0], 2)]:
-                #         if record == trace[i][1:].tolist():
-                #             init = True
-                #             break
-                #     if init == False:
-                #         timed_point_dict[round(trace[i][0], 2)].append(
-                #             trace[i][1:].tolist())
+            for i in range(0, len(trace)-1, 2):
+                x_min = min(x_min, trace[i][x_dim])
+                x_max = max(x_max, trace[i][x_dim])
+                y_min = min(y_min, trace[i][y_dim])
+                y_max = max(y_max, trace[i][y_dim])
                 time_point = round(trace[i][0], 2)
-                rect = [trace[i][1:].tolist(), trace[i+1][1:].tolist()]
+                rect = [trace[i][0:].tolist(), trace[i+1][0:].tolist()]
                 if time_point not in timed_point_dict:
                     timed_point_dict[time_point] = {agent_id: [rect]}
                 else:
@@ -147,796 +93,817 @@ def generate_reachtube_anime(root, map=None, fig=None):
                         timed_point_dict[time_point][agent_id] = [rect]
 
         stack += node.child
-    # fill in most of layout
-    # print(end_time)
-    duration = int(100/end_time)
-    fig_dict["layout"]["xaxis"] = {
-        "range": [(x_min-10), (x_max+10)],
-        "title": "x position"}
-    fig_dict["layout"]["yaxis"] = {
-        "range": [(y_min-2), (y_max+2)],
-        "title": "y position"}
-    fig_dict["layout"]["hovermode"] = "closest"
-    fig_dict["layout"]["updatemenus"] = [
-        {
-            "buttons": [
-                {
-                    "args": [None, {"frame": {"duration": duration, "redraw": False},
-                                    "fromcurrent": True, "transition": {"duration": duration,
-                                                                        "easing": "quadratic-in-out"}}],
-                    "label": "Play",
-                    "method": "animate"
-                },
-                {
-                    "args": [[None], {"frame": {"duration": 0, "redraw": False},
-                                      "mode": "immediate",
-                                      "transition": {"duration": 0}}],
-                    "label": "Pause",
-                    "method": "animate"
-                }
-            ],
-            "direction": "left",
-            "pad": {"r": 10, "t": 87},
-            "showactive": False,
-            "type": "buttons",
-            "x": 0.1,
-            "xanchor": "right",
-            "y": 0,
-            "yanchor": "top"
-        }
-    ]
-    sliders_dict = {
-        "active": 0,
-        "yanchor": "top",
-        "xanchor": "left",
-        "currentvalue": {
-            "font": {"size": 20},
-            "prefix": "time:",
-            "visible": True,
-            "xanchor": "right"
-        },
-        # "method": "update",
-        "transition": {"duration": duration, "easing": "cubic-in-out"},
-        "pad": {"b": 10, "t": 50},
-        "len": 0.9,
-        "x": 0.1,
-        "y": 0,
-        "steps": []
-    }
-    # make data
-    agent_dict = timed_point_dict[0]  # {agent1:[rect1,..], ...}
-    x_list = []
-    y_list = []
-    text_list = []
-    for agent_id, rect_list in agent_dict.items():
-        for rect in rect_list:
-            # trace = list(data.values())[0]
-            print(rect)
-            x_list.append((rect[0][0]+rect[1][0])/2)
-            y_list.append((rect[0][1]+rect[1][1])/2)
-            text_list.append(
-                ('{:.2f}'.format((rect[0][2]+rect[1][2])/pi*90), '{:.3f}'.format(rect[0][3]+rect[1][3])))
-    # data_dict = {
-    #     "x": x_list,
-    #     "y": y_list,
-    #     "mode": "markers + text",
-    #     "text": text_list,
-    #     "textposition": "bottom center",
-    #     # "marker": {
-    #     #     "sizemode": "area",
-    #     #     "sizeref": 200000,
-    #     #     "size": 2
-    #     # },
-    #     "name": "Current Position"
-    # }
-    # fig_dict["data"].append(data_dict)
-
-    # make frames
+    fig_dict, sliders_dict = create_anime_dict(duration)
     for time_point in timed_point_dict:
         frame = {"data": [], "layout": {
             "annotations": [], "shapes": []}, "name": str(time_point)}
         agent_dict = timed_point_dict[time_point]
-        trace_x = []
-        trace_y = []
-        trace_theta = []
-        trace_v = []
         for agent_id, rect_list in agent_dict.items():
             for rect in rect_list:
-                trace_x.append((rect[0][0]+rect[1][0])/2)
-                trace_y.append((rect[0][1]+rect[1][1])/2)
-                trace_theta.append((rect[0][2]+rect[1][2])/2)
-                trace_v.append((rect[0][3]+rect[1][3])/2)
                 shape_dict = {
                     "type": 'rect',
-                    "x0": rect[0][0],
-                    "y0": rect[0][1],
-                    "x1": rect[1][0],
-                    "y1": rect[1][1],
-                    "fillcolor": 'rgba(255,255,255,0.5)',
+                    "x0": rect[0][x_dim],
+                    "y0": rect[0][y_dim],
+                    "x1": rect[1][x_dim],
+                    "y1": rect[1][y_dim],
+                    "fillcolor": 'rgba(0,0,0,0.5)',
                     "line": dict(color='rgba(255,255,255,0)'),
+                    "visible": True
 
                 }
                 frame["layout"]["shapes"].append(shape_dict)
-        # data_dict = {
-        #     "x": trace_x,
-        #     "y": trace_y,
-        #     "mode": "markers + text",
-        #     "text": [('{:.2f}'.format(trace_theta[i]/pi*180), '{:.3f}'.format(trace_v[i])) for i in range(len(trace_theta))],
-        #     "textposition": "bottom center",
-        #     # "marker": {
-        #     #     "sizemode": "area",
-        #     #     "sizeref": 200000,
-        #     #     "size": 2
-        #     # },
-        #     "name": "current position"
-        # }
-        # frame["data"].append(data_dict)
-        # print(trace_x)
+
         fig_dict["frames"].append(frame)
         slider_step = {"args": [
-            [time_point],
+            ['{:.2f}'.format(time_point)],
             {"frame": {"duration": duration, "redraw": False},
              "mode": "immediate",
              "transition": {"duration": duration}}
         ],
-            "label": time_point,
+            "label": '{:.2f}'.format(time_point),
             "method": "animate"}
         sliders_dict["steps"].append(slider_step)
-        # print(len(frame["layout"]["annotations"]))
 
     fig_dict["layout"]["sliders"] = [sliders_dict]
 
     fig = go.Figure(fig_dict)
-    # fig = plotly_map(map, 'g', fig)
-    i = 1
-    for agent_id in traces:
-        fig = plotly_reachtube_tree_v2(root, agent_id, 1, [2], i, fig)
-        i += 2
+    fig = draw_map(map=map, fig=fig, fill_type=map_type)
+    i = 0
+    for agent_id in agent_list:
+        fig = reachtube_tree_single(
+            root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list)
+        i = (i+1) % 12
+    if scale_type == 'trace':
+        queue = [root]
+        x_min, x_max = float('inf'), -float('inf')
+        y_min, y_max = float('inf'), -float('inf')
+    i = 0
+    queue = [root]
+    previous_mode = {}
+    for agent_id in root.mode:
+        previous_mode[agent_id] = []
+    text_pos = 'middle center'
+    while queue != []:
+        node = queue.pop(0)
+        traces = node.trace
+        for agent_id in traces:
+            trace = np.array(traces[agent_id])
+            if scale_type == 'trace':
+                x_min = min(x_min, min(trace[:, x_dim]))
+                x_max = max(x_max, max(trace[:, x_dim]))
+                y_min = min(y_min, min(trace[:, y_dim]))
+                y_max = max(y_max, max(trace[:, y_dim]))
+            if previous_mode[agent_id] != node.mode[agent_id]:
+                text_pos, text = get_text_pos(node.mode[agent_id][0])
+                x0 = trace[0, x_dim]
+                x1 = trace[1, x_dim]
+                y0 = trace[0, y_dim]
+                y1 = trace[1, y_dim]
+                mode_point_color = colors[agent_list.index(agent_id) % 12][0]
+                fig.add_trace(go.Scatter(x=[(x0+x1)/2], y=[(y0+y1)/2],
+                                         mode='markers+text',
+                                         line_color=mode_point_color,
+                                         text=str(agent_id)+': ' + text,
+                                         textposition=text_pos,
+                                         opacity=0.5,
+                                         textfont=dict(
+                    size=text_size,
+                                             color=mode_text_color),
+                                         showlegend=False,
+                                         ))
+                previous_mode[agent_id] = node.mode[agent_id]
+        queue += node.child
+    if scale_type == 'trace':
+        fig.update_xaxes(
+            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
+        fig.update_yaxes(
+            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
+    return fig
 
+
+def reachtube_tree(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
+    """It statically shows all the traces of the verfication."""
+    fig = draw_map(map=map, fig=fig, fill_type=map_type)
+    agent_list = list(root.agent.keys())
+    # input check
+    num_dim = np.array(root.trace[agent_list[0]]).shape[1]
+    check_dim(num_dim, x_dim, y_dim, print_dim_list)
+    if print_dim_list is None:
+        print_dim_list = range(0, num_dim)
+
+    scheme_list = list(scheme_dict.keys())
+    i = 0
+    for agent_id in agent_list:
+        fig = reachtube_tree_single(
+            root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list)
+        i = (i+1) % 12
+    if scale_type == 'trace':
+        queue = [root]
+        x_min, x_max = float('inf'), -float('inf')
+        y_min, y_max = float('inf'), -float('inf')
+    i = 0
+    queue = [root]
+    previous_mode = {}
+    for agent_id in root.mode:
+        previous_mode[agent_id] = []
+    text_pos = 'middle center'
+    while queue != []:
+        node = queue.pop(0)
+        traces = node.trace
+        i = 0
+        for agent_id in traces:
+            trace = np.array(traces[agent_id])
+            if scale_type == 'trace':
+                x_min = min(x_min, min(trace[:, x_dim]))
+                x_max = max(x_max, max(trace[:, x_dim]))
+                y_min = min(y_min, min(trace[:, y_dim]))
+                y_max = max(y_max, max(trace[:, y_dim]))
+            i = agent_list.index(agent_id)
+            if previous_mode[agent_id] != node.mode[agent_id]:
+                text_pos, text = get_text_pos(node.mode[agent_id][0])
+                mode_point_color = colors[agent_list.index(agent_id) % 12][0]
+                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
+                                         mode='markers+text',
+                                         line_color=mode_point_color,
+                                         opacity=0.5,
+                                         text=str(agent_id)+': ' + text,
+                                         textposition=text_pos,
+                                         textfont=dict(
+                    size=text_size,
+                                             color=mode_text_color),
+                                         showlegend=False,
+                                         ))
+                previous_mode[agent_id] = node.mode[agent_id]
+        queue += node.child
+    if scale_type == 'trace':
+        fig.update_xaxes(
+            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
+        fig.update_yaxes(
+            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
     return fig
 
 
-def plotly_reachtube_tree(root, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='blue', fig=None, x_lim=None, y_lim=None):
-    if fig is None:
-        fig = go.Figure()
+def simulation_tree(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
+    """It statically shows all the traces of the simulation."""
+    fig = draw_map(map=map, fig=fig, fill_type=map_type)
+    agent_list = list(root.agent.keys())
+    # input check
+    num_dim = np.array(root.trace[agent_list[0]]).shape[1]
+    check_dim(num_dim, x_dim, y_dim, print_dim_list)
+    if print_dim_list is None:
+        print_dim_list = range(0, num_dim)
 
-    # ax = fig.gca()
-    # if x_lim is None:
-    #     x_lim = ax.get_xlim()
-    # if y_lim is None:
-    #     y_lim = ax.get_ylim()
+    scheme_list = list(scheme_dict.keys())
+    i = 0
+    for agent_id in agent_list:
+        fig = simulation_tree_single(
+            root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list)
+        i = (i+1) % 12
+    if scale_type == 'trace':
+        queue = [root]
+        x_min, x_max = float('inf'), -float('inf')
+        y_min, y_max = float('inf'), -float('inf')
+    i = 0
+    queue = [root]
+    previous_mode = {}
+    for agent_id in root.mode:
+        previous_mode[agent_id] = []
+    text_pos = 'middle center'
+    while queue != []:
+        node = queue.pop(0)
+        traces = node.trace
+        i = 0
+        for agent_id in traces:
+            trace = np.array(traces[agent_id])
+            if scale_type == 'trace':
+                x_min = min(x_min, min(trace[:, x_dim]))
+                x_max = max(x_max, max(trace[:, x_dim]))
+                y_min = min(y_min, min(trace[:, y_dim]))
+                y_max = max(y_max, max(trace[:, y_dim]))
+            i = agent_list.index(agent_id)
+            mode_point_color = colors[agent_list.index(agent_id) % 12][0]
+            if previous_mode[agent_id] != node.mode[agent_id]:
+                text_pos, text = get_text_pos(node.mode[agent_id][0])
+                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
+                                         mode='markers+text',
+                                         line_color=mode_point_color,
+                                         opacity=0.5,
+                                         text=str(agent_id)+': ' + text,
+                                         textposition=text_pos,
+                                         textfont=dict(
+                    size=text_size,
+                    color=mode_text_color
+                ),
+                    showlegend=False,
+                ))
+                previous_mode[agent_id] = node.mode[agent_id]
+        queue += node.child
+    if scale_type == 'trace':
+        fig.update_xaxes(
+            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
+        fig.update_yaxes(
+            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
+    fig.update_xaxes(title='x')
+    fig.update_yaxes(title='y')
+    fig.update_layout(legend_title_text='Agent list')
+    return fig
 
+
+def simulation_anime(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
+    """It gives the animation of the simulation without trail but is faster."""
+    timed_point_dict = {}
+    stack = [root]
+    x_min, x_max = float('inf'), -float('inf')
+    y_min, y_max = float('inf'), -float('inf')
+    # input check
+    num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1]
+    check_dim(num_dim, x_dim, y_dim, print_dim_list)
+    if print_dim_list is None:
+        print_dim_list = range(0, num_dim)
+    agent_list = list(root.agent.keys())
+    while stack != []:
+        node = stack.pop()
+        traces = node.trace
+        for agent_id in traces:
+            trace = np.array(traces[agent_id])
+            for i in range(len(trace)):
+                x_min = min(x_min, trace[i][x_dim])
+                x_max = max(x_max, trace[i][x_dim])
+                y_min = min(y_min, trace[i][y_dim])
+                y_max = max(y_max, trace[i][y_dim])
+                time_point = round(trace[i][0], 2)
+                tmp_trace = trace[i][0:].tolist()
+                if time_point not in timed_point_dict:
+                    timed_point_dict[time_point] = {agent_id: [tmp_trace]}
+                else:
+                    if agent_id not in timed_point_dict[time_point].keys():
+                        timed_point_dict[time_point][agent_id] = [tmp_trace]
+                    elif tmp_trace not in timed_point_dict[time_point][agent_id]:
+                        timed_point_dict[time_point][agent_id].append(
+                            tmp_trace)
+            time = round(trace[i][0], 2)
+        stack += node.child
+    fig_dict, sliders_dict = create_anime_dict(duration)
+    # make data
+    trace_dict = timed_point_dict[0]
+    for agent_id, trace_list in trace_dict.items():
+        color = colors[agent_list.index(agent_id) % 12][1]
+        x_list = []
+        y_list = []
+        text_list = []
+        branch_cnt = 0
+        for trace in trace_list:
+            x_list.append(trace[x_dim])
+            y_list.append(trace[y_dim])
+            text_list.append(['{:.2f}'.format(trace[i])
+                              for i in print_dim_list])
+            branch_cnt += 1
+        data_dict = {
+            "x": x_list,
+            "y": y_list,
+            "text": text_list,
+            "mode": "markers + text",
+            "textfont": dict(size=text_size, color="black"),
+            "textposition": "bottom center",
+            "marker": {
+                "color": color,
+            },
+            "name": agent_id,
+            "showlegend": True
+        }
+        fig_dict["data"].append(data_dict)
+    # make frames
+    for time_point in timed_point_dict:
+        frame = {"data": [], "layout": {
+            "annotations": []}, "name": '{:.2f}'.format(time_point)}
+        point_list = timed_point_dict[time_point]
+        for agent_id, trace_list in point_list.items():
+            color = colors[agent_list.index(agent_id) % 12][1]
+            x_list = []
+            y_list = []
+            text_list = []
+            branch_cnt = 0
+            for trace in trace_list:
+                x_list.append(trace[x_dim])
+                y_list.append(trace[y_dim])
+                text_list.append(['{:.2f}'.format(trace[i])
+                                  for i in print_dim_list])
+                branch_cnt += 1
+            data_dict = {
+                "x": x_list,
+                "y": y_list,
+                "text": text_list,
+                "mode": "markers + text",
+                "marker": {
+                    "color": color,
+                },
+                "textfont": dict(size=text_size, color="black"),
+                "textposition": "bottom center",
+                # "name": "Branch-"+str(branch_cnt),
+                "name": agent_id,
+                "showlegend": True
+            }
+            frame["data"].append(data_dict)
+        fig_dict["frames"].append(frame)
+        slider_step = {"args": [
+            ['{:.2f}'.format(time_point)],
+            {"frame": {"duration": duration, "redraw": True},
+             "mode": "immediate",
+             "transition": {"duration": duration}}
+        ],
+            "label": '{:.2f}'.format(time_point),
+            "method": "animate"}
+        sliders_dict["steps"].append(slider_step)
+
+    fig_dict["layout"]["sliders"] = [sliders_dict]
+
+    fig = go.Figure(fig_dict)
+    fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type)
+    i = 0
     queue = [root]
+    previous_mode = {}
+    agent_list = list(root.agent.keys())
+    for agent_id in root.mode:
+        previous_mode[agent_id] = []
+    text_pos = 'middle center'
     while queue != []:
         node = queue.pop(0)
         traces = node.trace
-        trace = traces[agent_id]
-        # print(trace)
-        data = []
-        for i in range(0, len(trace)-1, 2):
-            data.append([trace[i], trace[i+1]])
-        fig, x_lim, y_lim = plotly_plot(
-            data, x_dim, y_dim_list, color, fig, x_lim, y_lim)
-        # print(data)
+        for agent_id in traces:
+            trace = np.array(traces[agent_id])
+            mode_point_color = colors[agent_list.index(agent_id) % 12][0]
+            if previous_mode[agent_id] != node.mode[agent_id]:
+                text_pos, text = get_text_pos(node.mode[agent_id][0])
+                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
+                                         mode='markers+text',
+                                         line_color=mode_point_color,
+                                         text=str(agent_id)+': ' + text,
+                                         textposition=text_pos,
+                                         opacity=0.5,
+                                         textfont=dict(
+                    size=text_size,
+                    color=mode_text_color),
+                    showlegend=False,
+                ))
+                previous_mode[agent_id] = node.mode[agent_id]
         queue += node.child
+    if scale_type == 'trace':
+        fig.update_xaxes(
+            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
+        fig.update_yaxes(
+            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
+    fig.update_layout(legend_title_text='Agent list')
+    return fig
+
 
+def simulation_anime_trail(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
+    """It gives the animation of the simulation with trail."""
+    timed_point_dict = {}
+    stack = [root]
+    x_min, x_max = float('inf'), -float('inf')
+    y_min, y_max = float('inf'), -float('inf')
+    # input check
+    num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1]
+    check_dim(num_dim, x_dim, y_dim, print_dim_list)
+    if print_dim_list is None:
+        print_dim_list = range(0, num_dim)
+
+    while stack != []:
+        node = stack.pop()
+        traces = node.trace
+        for agent_id in traces:
+            trace = np.array(traces[agent_id])
+            for i in range(len(trace)):
+                x_min = min(x_min, trace[i][x_dim])
+                x_max = max(x_max, trace[i][x_dim])
+                y_min = min(y_min, trace[i][y_dim])
+                y_max = max(y_max, trace[i][y_dim])
+                time_point = round(trace[i][0], 3)
+                tmp_trace = trace[i][0:].tolist()
+                if time_point not in timed_point_dict:
+                    timed_point_dict[time_point] = {agent_id: [tmp_trace]}
+                else:
+                    if agent_id not in timed_point_dict[time_point].keys():
+                        timed_point_dict[time_point][agent_id] = [tmp_trace]
+                    elif tmp_trace not in timed_point_dict[time_point][agent_id]:
+                        timed_point_dict[time_point][agent_id].append(
+                            tmp_trace)
+            time = round(trace[i][0], 2)
+        stack += node.child
+    fig_dict, sliders_dict = create_anime_dict(duration)
+    time_list = list(timed_point_dict.keys())
+    agent_list = list(root.agent.keys())
+    trail_limit = min(10, len(time_list))
+    trail_len = trail_limit
+    opacity_step = 1/trail_len
+    size_step = 2/trail_len
+    min_size = 5
+    step = 2
+    # # make data
+    trace_dict = timed_point_dict[0]
+
+    for time_point in list(timed_point_dict.keys())[0:int(trail_limit/step)]:
+        trace_dict = timed_point_dict[time_point]
+        for agent_id, point_list in trace_dict.items():
+            x_list = []
+            y_list = []
+            text_list = []
+            for point in point_list:
+                x_list.append(point[x_dim])
+                y_list.append(point[y_dim])
+                text_list.append(['{:.2f}'.format(point[i])
+                                  for i in print_dim_list])
+            data_dict = {
+                "x": x_list,
+                "y": y_list,
+                "mode": "markers",
+                "text": text_list,
+                "textfont": dict(size=text_size, color="black"),
+                "visible": False,
+                "textposition": "bottom center",
+                "name": agent_id
+            }
+            fig_dict["data"].append(data_dict)
+
+    # make frames
+    for time_point_id in range(trail_limit, len(time_list)):
+        time_point = time_list[time_point_id]
+        frame = {"data": [], "layout": {
+            "annotations": []}, "name": '{:.2f}'.format(time_point)}
+        for agent_id in agent_list:
+            color = colors[agent_list.index(agent_id) % 12][1]
+            for id in range(0, trail_len, step):
+                tmp_point_list = timed_point_dict[time_list[time_point_id-id]][agent_id]
+                trace_x = []
+                trace_y = []
+                text_list = []
+                for point in tmp_point_list:
+                    trace_x.append(point[x_dim])
+                    trace_y.append(point[y_dim])
+                    text_list.append(['{:.2f}'.format(point[i])
+                                      for i in print_dim_list])
+                if id == 0:
+                    data_dict = {
+                        "x": trace_x,
+                        "y": trace_y,
+                        "mode": "markers+text",
+                        "text": text_list,
+                        "textfont": dict(size=text_size, color="black"),
+                        "textposition": "bottom center",
+                        "visible": True,  # 'legendonly'
+                        "marker": {
+                            "color": color,
+                            "opacity": opacity_step*(trail_len-id),
+                            "size": min_size + size_step*(trail_len-id)
+                        },
+                        "name": agent_id,
+                        "showlegend": True
+                    }
+                else:
+                    data_dict = {
+                        "x": trace_x,
+                        "y": trace_y,
+                        "mode": "markers",
+                        "text": text_list,
+                        "visible": True,  # 'legendonly'
+                        "marker": {
+                            "color": color,
+                            "opacity": opacity_step*(trail_len-id),
+                            "size": min_size + size_step*(trail_len-id)
+                        },
+                        "name": agent_id,
+                        "showlegend": True
+                    }
+                frame["data"].append(data_dict)
+
+        fig_dict["frames"].append(frame)
+        slider_step = {"args": [
+            ['{:.2f}'.format(time_point)],
+            {"frame": {"duration": duration, "redraw": False},
+             "mode": "immediate",
+             "transition": {"duration": duration}}
+        ],
+            "label": '{:.2f}'.format(time_point),
+            "method": "animate"}
+        sliders_dict["steps"].append(slider_step)
+
+    fig_dict["layout"]["sliders"] = [sliders_dict]
+
+    fig = go.Figure(fig_dict)
+    fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type)
+    i = 0
+    queue = [root]
+    previous_mode = {}
+    agent_list = list(root.agent.keys())
+    for agent_id in root.mode:
+        previous_mode[agent_id] = []
+    text_pos = 'middle center'
+    while queue != []:
+        node = queue.pop(0)
+        traces = node.trace
+        i = 0
+        for agent_id in traces:
+            trace = np.array(traces[agent_id])
+            trace_y = trace[:, y_dim].tolist()
+            trace_x = trace[:, x_dim].tolist()
+            i = agent_list.index(agent_id)
+            mode_point_color = colors[agent_list.index(agent_id) % 12][0]
+            if previous_mode[agent_id] != node.mode[agent_id]:
+                text_pos, text = get_text_pos(node.mode[agent_id][0])
+                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
+                                         mode='markers+text',
+                                         line_color=mode_point_color,
+                                         text=str(agent_id)+': ' + text,
+                                         opacity=0.5,
+                                         textposition=text_pos,
+                                         textfont=dict(
+                    size=text_size,
+                    color=mode_text_color
+                ),
+                    showlegend=False,
+                ))
+                previous_mode[agent_id] = node.mode[agent_id]
+        queue += node.child
+    if scale_type == 'trace':
+        fig.update_xaxes(
+            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
+        fig.update_yaxes(
+            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
+    fig.update_layout(legend_title_text='Agent list')
     return fig
 
 
-def plotly_reachtube_tree_v2(root, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color=0, fig=None, x_lim=None, y_lim=None):
-    if fig is None:
-        fig = go.Figure()
+"""Functions below are low-level functions and usually are not called outside this file."""
+
 
-    # ax = fig.gca()
-    # if x_lim is None:
-    #     x_lim = ax.get_xlim()
-    # if y_lim is None:
-    #     y_lim = ax.get_ylim()
-    bg_color = ['rgba(31,119,180,1)', 'rgba(255,127,14,0.2)', 'rgba(44,160,44,0.2)', 'rgba(214,39,40,0.2)', 'rgba(148,103,189,0.2)',
-                'rgba(140,86,75,0.2)', 'rgba(227,119,194,0.2)', 'rgba(127,127,127,0.2)', 'rgba(188,189,34,0.2)', 'rgba(23,190,207,0.2)']
+def reachtube_tree_single(root, agent_id, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None):
+    """It statically shows the verfication traces of one given agent."""
+    global color_cnt
+    if color == None:
+        color = list(scheme_dict.keys())[color_cnt]
+        color_cnt = (color_cnt+1) % 12
     queue = [root]
     show_legend = False
+    fillcolor = colors[scheme_dict[color]][4]
     while queue != []:
         node = queue.pop(0)
         traces = node.trace
         trace = np.array(traces[agent_id])
-        # print(trace[0], trace[1], trace[-2], trace[-1])
         max_id = len(trace)-1
-        # trace_x = np.zeros(max_id+1)
-        # trace_x_2 = np.zeros(max_id+1)
-        # trace_y = np.zeros(max_id+1)
-        # trace_y_2 = np.zeros(max_id+1)
-        # for y_dim in y_dim_list:
-        #     for i in range(0, max_id, 2):
-        #         id = int(i/2)
-        #         trace_x[id] = trace[i+1][x_dim]
-        #         trace_x[max_id-id] = trace[i][x_dim]
-        #         trace_x_2[id] = trace[i][x_dim]
-        #         trace_x_2[max_id-id] = trace[i+1][x_dim]
-        #         trace_y[id] = trace[i][y_dim]
-        #         trace_y[max_id-id] = trace[i+1][y_dim]
-        # fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-        #                          fill='toself',
-        #                          fillcolor='blue',
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=False))
-        # fig.add_trace(go.Scatter(x=trace_x_2, y=trace_y,
-        #                          fill='toself',
-        #                          fillcolor='red',
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=False))
-        # fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2],
-        #                          mode='lines',
-        #                          line_color="black",
-        #                          text=[range(0, max_id+1)],
-        #                          name='lines',
-        #                          showlegend=False))
-        trace_x_odd = np.array([trace[i][1] for i in range(0, max_id, 2)])
-        trace_x_even = np.array([trace[i][1] for i in range(1, max_id+1, 2)])
-        trace_y_odd = np.array([trace[i][2] for i in range(0, max_id, 2)])
-        trace_y_even = np.array([trace[i][2] for i in range(1, max_id+1, 2)])
+        trace_x_odd = np.array([trace[i][x_dim] for i in range(0, max_id, 2)])
+        trace_x_even = np.array([trace[i][x_dim]
+                                for i in range(1, max_id+1, 2)])
+        trace_y_odd = np.array([trace[i][y_dim] for i in range(0, max_id, 2)])
+        trace_y_even = np.array([trace[i][y_dim]
+                                for i in range(1, max_id+1, 2)])
         fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
                                  fill='toself',
-                                 fillcolor=bg_color[color],
+                                 fillcolor=fillcolor,
+                                 opacity=0.5,
                                  line_color='rgba(255,255,255,0)',
                                  showlegend=show_legend
                                  ))
         fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
                                  fill='toself',
-                                 fillcolor=bg_color[color],
+                                 fillcolor=fillcolor,
+                                 opacity=0.5,
                                  line_color='rgba(255,255,255,0)',
                                  showlegend=show_legend))
         fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
                                  fill='toself',
-                                 fillcolor=bg_color[color],
+                                 fillcolor=fillcolor,
+                                 opacity=0.5,
                                  line_color='rgba(255,255,255,0)',
                                  showlegend=show_legend
                                  ))
         fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
                                  fill='toself',
-                                 fillcolor=bg_color[color],
+                                 fillcolor=fillcolor,
+                                 opacity=0.5,
                                  line_color='rgba(255,255,255,0)',
                                  showlegend=show_legend))
-        # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_odd.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True
-        #                          ))
-        # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_odd.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True))
-        # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_even.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid",shape="spline"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True
-        #                          ))
-        # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_even.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True))
-        # fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2],
-        #                          mode='markers',
-        #                          #  fill='toself',
-        #                          #  line=dict(dash="dot"),
-        #                          line_color="black",
-        #                          text=[range(0, max_id+1)],
-        #                          name='lines',
-        #                          showlegend=False))
         queue += node.child
+
     queue = [root]
     while queue != []:
         node = queue.pop(0)
         traces = node.trace
         trace = np.array(traces[agent_id])
-        # print(trace[0], trace[1], trace[-2], trace[-1])
         max_id = len(trace)-1
-        # trace_x = np.zeros(max_id+1)
-        # trace_x_2 = np.zeros(max_id+1)
-        # trace_y = np.zeros(max_id+1)
-        # trace_y_2 = np.zeros(max_id+1)
-        # for y_dim in y_dim_list:
-        #     for i in range(0, max_id, 2):
-        #         id = int(i/2)
-        #         trace_x[id] = trace[i+1][x_dim]
-        #         trace_x[max_id-id] = trace[i][x_dim]
-        #         trace_x_2[id] = trace[i][x_dim]
-        #         trace_x_2[max_id-id] = trace[i+1][x_dim]
-        #         trace_y[id] = trace[i][y_dim]
-        #         trace_y[max_id-id] = trace[i+1][y_dim]
-        # fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-        #                          fill='toself',
-        #                          fillcolor='blue',
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=False))
-        # fig.add_trace(go.Scatter(x=trace_x_2, y=trace_y,
-        #                          fill='toself',
-        #                          fillcolor='red',
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=False))
-        # fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2],
-        #                          mode='lines',
-        #                          line_color="black",
-        #                          text=[range(0, max_id+1)],
-        #                          name='lines',
-        #                          showlegend=False))
-        # trace_x_odd = np.array([trace[i][1] for i in range(0, max_id, 2)])
-        # trace_x_even = np.array([trace[i][1] for i in range(1, max_id+1, 2)])
-        # trace_y_odd = np.array([trace[i][2] for i in range(0, max_id, 2)])
-        # trace_y_even = np.array([trace[i][2] for i in range(1, max_id+1, 2)])
-        # fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-        #                          fill='toself',
-        #                          fillcolor=bg_color[0],
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=True
-        #                          ))
-        # fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-        #                          fill='toself',
-        #                          fillcolor=bg_color[0],
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=True))
-        # fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-        #                          fill='toself',
-        #                          fillcolor=bg_color[0],
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=True
-        #                          ))
-        # fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-        #                          fill='toself',
-        #                          fillcolor=bg_color[0],
-        #                          line_color='rgba(255,255,255,0)',
-        #                          showlegend=True))
-        # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_odd.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True
-        #                          ))
-        # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_odd.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True))
-        # fig.add_trace(go.Scatter(x=trace_x_odd.tolist(), y=trace_y_even.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid",shape="spline"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True
-        #                          ))
-        # fig.add_trace(go.Scatter(x=trace_x_even.tolist(), y=trace_y_even.tolist(), mode='lines',
-        #                          #  fill='toself',
-        #                          #  fillcolor=bg_color[0],
-        #                          #  line=dict(width=1, dash="solid"),
-        #                          line_color=bg_color[0],
-        #                          showlegend=True))
-        fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2],
+        fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim],
                                  mode='markers',
-                                 #  fill='toself',
-                                 #  line=dict(dash="dot"),
-                                 line_color="black",
+                                 text=[
+                                     ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(0, trace.shape[0])],
+                                 line_color=colors[scheme_dict[color]][0],
                                  marker={
             "sizemode": "area",
             "sizeref": 200000,
             "size": 2
         },
-            text=[range(0, max_id+1)],
             name='lines',
             showlegend=False))
         queue += node.child
-    # fig.update_traces(line_dash="dash")
     return fig
 
 
-def plot_reachtube_tree(root, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='b', fig=None, x_lim=None, y_lim=None):
-    if fig is None:
-        fig = plt.figure()
-
-    ax = fig.gca()
-    if x_lim is None:
-        x_lim = ax.get_xlim()
-    if y_lim is None:
-        y_lim = ax.get_ylim()
-
+def simulation_tree_single(root, agent_id, fig: go.Figure() = go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None):
+    """It statically shows the simulation traces of one given agent."""
+    global color_cnt
     queue = [root]
+    color_id = 0
+    if color == None:
+        color = list(scheme_dict.keys())[color_cnt]
+        color_cnt = (color_cnt+1) % 12
+    start_list = []
+    end_list = []
+    count_dict = {}
     while queue != []:
         node = queue.pop(0)
         traces = node.trace
-        trace = traces[agent_id]
-        # print(trace)
-        data = []
-
-        for i in range(0, len(trace)-1, 2):
-            data.append([trace[i], trace[i+1]])
-        fig, x_lim, y_lim = plot(
-            data, x_dim, y_dim_list, color, fig, x_lim, y_lim)
-        queue += node.child
-    return fig
-
-def plot_reachtube_tree_branch(root, agent_id, x_dim: int=0, y_dim_list: List[int]=[1], color='b', fig = None, x_lim = None, y_lim = None):
-    if fig is None:
-        fig = plt.figure()
-    
-    ax = fig.gca()
-    if x_lim is None:
-        x_lim = ax.get_xlim()
-    if y_lim is None:
-        y_lim = ax.get_ylim()
-
-    stack = [root]
-    while stack != []:
-        node = stack.pop()
-        traces = node.trace
-        trace = traces[agent_id]
-        data = []
-        for i in range(0,len(trace),2):
-            data.append([trace[i], trace[i+1]])
-        fig, x_lim, y_lim = plot(data, x_dim, y_dim_list, color, fig, x_lim, y_lim)
-
-        if node.child:
-            stack += [node.child[0]]
-    return fig
-
-
-def plotly_map(map, color='b', fig: go.Figure() = None, x_lim=None, y_lim=None):
-    if fig is None:
-        fig = go.Figure()
-    all_x = []
-    all_y = []
-    all_v = []
-    for lane_idx in map.lane_dict:
-        lane = map.lane_dict[lane_idx]
-        for lane_seg in lane.segment_list:
-            if lane_seg.type == 'Straight':
-                start1 = lane_seg.start + lane_seg.width/2 * lane_seg.direction_lateral
-                end1 = lane_seg.end + lane_seg.width/2 * lane_seg.direction_lateral
-                # fig.add_trace(go.Scatter(x=[start1[0], end1[0]], y=[start1[1], end1[1]],
-                #                          mode='lines',
-                #                          line_color='black',
-                #                          showlegend=False,
-                #                          # text=theta,
-                #                          name='lines'))
-                start2 = lane_seg.start - lane_seg.width/2 * lane_seg.direction_lateral
-                end2 = lane_seg.end - lane_seg.width/2 * lane_seg.direction_lateral
-                # fig.add_trace(go.Scatter(x=[start2[0], end2[0]], y=[start2[1], end2[1]],
-                #                          mode='lines',
-                #                          line_color='black',
-                #                          showlegend=False,
-                #                          # text=theta,
-                #                          name='lines'))
-                fig.add_trace(go.Scatter(x=[start1[0], end1[0], end2[0], start2[0]], y=[start1[1], end1[1], end2[1], start2[1]],
-                                         mode='lines',
-                                         line_color='black',
-                                         #  fill='toself',
-                                         #  fillcolor='rgba(255,255,255,0)',
-                                         #  line_color='rgba(0,0,0,0)',
-                                         showlegend=False,
-                                         # text=theta,
-                                         name='lines'))
-                # fig = go.Figure().add_heatmap(x=)
-                seg_x, seg_y, seg_v = lane_seg.get_all_speed()
-                all_x += seg_x
-                all_y += seg_y
-                all_v += seg_v
-            elif lane_seg.type == "Circular":
-                phase_array = np.linspace(
-                    start=lane_seg.start_phase, stop=lane_seg.end_phase, num=100)
-                r1 = lane_seg.radius - lane_seg.width/2
-                x = np.cos(phase_array)*r1 + lane_seg.center[0]
-                y = np.sin(phase_array)*r1 + lane_seg.center[1]
-                fig.add_trace(go.Scatter(x=x, y=y,
-                                         mode='lines',
-                                         line_color='black',
-                                         showlegend=False,
-                                         # text=theta,
-                                         name='lines'))
-
-                r2 = lane_seg.radius + lane_seg.width/2
-                x = np.cos(phase_array)*r2 + lane_seg.center[0]
-                y = np.sin(phase_array)*r2 + lane_seg.center[1]
-                fig.add_trace(go.Scatter(x=x, y=y,
-                                         mode='lines',
-                                         line_color='black',
-                                         showlegend=False,
-                                         # text=theta,
-                                         name='lines'))
-            else:
-                raise ValueError(f'Unknown lane segment type {lane_seg.type}')
-    start_color = [0, 0, 255, 0.2]
-    end_color = [255, 0, 0, 0.2]
-    curr_color = copy.deepcopy(start_color)
-    max_speed = max(all_v)
-    min_speed = min(all_v)
-
-    for i in range(len(all_v)):
-        # print(all_x[i])
-        # print(all_y[i])
-        # print(all_v[i])
-        curr_color = copy.deepcopy(start_color)
-        for j in range(len(curr_color)-1):
-            curr_color[j] += (all_v[i]-min_speed)/(max_speed -
-                                                   min_speed)*(end_color[j]-start_color[j])
-        fig.add_trace(go.Scatter(x=all_x[i], y=all_y[i],
+        if agent_id not in traces.keys():
+            return fig
+        trace = np.array(traces[agent_id])
+        start = list(trace[0])
+        end = list(trace[-1])
+        if (start in start_list) and (end in end_list):
+            continue
+        time = tuple([round(start[0], 2), round(end[0], 2)])
+        if time in count_dict.keys():
+            count_dict[time] += 1
+        else:
+            count_dict[time] = 1
+        start_list.append(start)
+        end_list.append(end)
+        fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim],
                                  mode='lines',
-                                 line_color='rgba(0,0,0,0)',
-                                 fill='toself',
-                                 fillcolor='rgba'+str(tuple(curr_color)),
-                                 #  marker=dict(
-                                 #     symbol='square',
-                                 #     size=16,
-                                 #     cmax=max_speed,
-                                 #     cmin=min_speed,
-                                 #     # color=all_v[i],
-                                 #     colorbar=dict(
-                                 #         title="Colorbar"
-                                 #     ),
-                                 #     colorscale=[
-                                 #         [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]]
-                                 # ),
-                                 showlegend=False,
-                                 ))
-    fig.add_trace(go.Scatter(x=[0], y=[0],
-                             mode='markers',
-                             # fill='toself',
-                             # fillcolor='rgba'+str(tuple(curr_color)),
-                             marker=dict(
-                                 symbol='square',
-                                 size=16,
-                                 cmax=max_speed,
-                                 cmin=min_speed,
-                                 color='rgba(0,0,0,0)',
-                                 colorbar=dict(
-                                        title="Speed Limit"
-                                 ),
-                                 colorscale=[
-                                     [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]]
-    ),
-        showlegend=False,
+                                 line_color=colors[scheme_dict[color]
+                                                   ][color_id],
+                                 text=[
+                                     ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(trace.shape[0])],
+                                 legendgroup=agent_id,
+                                 legendgrouptitle_text=agent_id,
+                                 name=str(round(start[0], 2))+'-'+str(round(end[0], 2)) +
+                                 '-'+str(count_dict[time]),
+                                 showlegend=True))
+        color_id = (color_id+4) % 5
+        queue += node.child
+    fig.update_layout(legend=dict(
+        groupclick="toggleitem",
+        itemclick="toggle",
+        itemdoubleclick="toggleothers"
     ))
-    # fig.update_coloraxes(colorbar=dict(title="Colorbar"), colorscale=[
-    #                      [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]])
     return fig
 
 
-def plot_map(map, color='b', fig=None, x_lim=None, y_lim=None):
-    if fig is None:
-        fig = plt.figure()
-
-    ax = fig.gca()
-    if x_lim is None:
-        x_lim = ax.get_xlim()
-    if y_lim is None:
-        y_lim = ax.get_ylim()
-
+def draw_map(map, color='rgba(0,0,0,1)', fig: go.Figure() = go.Figure(), fill_type='lines'):
+    """It draws the the map"""
+    x_min, x_max = float('inf'), -float('inf')
+    y_min, y_max = float('inf'), -float('inf')
+    if map is None:
+        return fig
+    if fill_type == 'detailed':
+        speed_dict = map.get_all_speed_limit()
+        speed_list = list(filter(None, speed_dict.values()))
+        speed_min = min(speed_list)
+        speed_max = max(speed_list)
+        start_color = [255, 255, 255, 0.2]
+        end_color = [0, 0, 0, 0.2]
+        curr_color = [0, 0, 0, 0]
+    speed_limit = None
     for lane_idx in map.lane_dict:
         lane = map.lane_dict[lane_idx]
+        curr_color = [0, 0, 0, 0]
+        if fill_type == 'detailed':
+            speed_limit = speed_dict[lane_idx]
+            if speed_limit is not None:
+                lens = len(curr_color)-1
+                for j in range(lens):
+                    curr_color[j] = int(start_color[j]+(speed_limit-speed_min)/(speed_max -
+                                                                                speed_min)*(end_color[j]-start_color[j]))
+                curr_color[lens] = start_color[lens]+(speed_limit-speed_min)/(speed_max -
+                                                                              speed_min)*(end_color[lens]-start_color[lens])
         for lane_seg in lane.segment_list:
             if lane_seg.type == 'Straight':
                 start1 = lane_seg.start + lane_seg.width/2 * lane_seg.direction_lateral
                 end1 = lane_seg.end + lane_seg.width/2 * lane_seg.direction_lateral
-                ax.plot([start1[0], end1[0]], [start1[1], end1[1]], color)
                 start2 = lane_seg.start - lane_seg.width/2 * lane_seg.direction_lateral
                 end2 = lane_seg.end - lane_seg.width/2 * lane_seg.direction_lateral
-                ax.plot([start2[0], end2[0]], [start2[1], end2[1]], color)
+                trace_x = [start1[0], end1[0], end2[0], start2[0], start1[0]]
+                trace_y = [start1[1], end1[1], end2[1], start2[1], start1[1]]
+                x_min = min(x_min, min(trace_x))
+                y_min = min(y_min, min(trace_y))
+                x_max = max(x_max, max(trace_x))
+                y_max = max(y_max, max(trace_y))
+                if fill_type == 'lines' or (fill_type == 'detailed' and speed_limit is None):
+                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
+                                             mode='lines',
+                                             line_color=color,
+                                             showlegend=False,
+                                             name='lines'))
+                elif fill_type == 'detailed' and speed_limit is not None:
+                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
+                                             mode='lines',
+                                             line_color=color,
+                                             fill='toself',
+                                             fillcolor='rgba' +
+                                             str(tuple(curr_color)),
+                                             showlegend=False,
+                                             name='limit'))
+                elif fill_type == 'fill':
+                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
+                                             mode='lines',
+                                             line_color=color,
+                                             fill='toself',
+                                             fillcolor='rgba(0,0,0,0.1)',
+                                             showlegend=False,
+                                             # text=theta,
+                                             name='lines'))
             elif lane_seg.type == "Circular":
                 phase_array = np.linspace(
                     start=lane_seg.start_phase, stop=lane_seg.end_phase, num=100)
                 r1 = lane_seg.radius - lane_seg.width/2
-                x = np.cos(phase_array)*r1 + lane_seg.center[0]
-                y = np.sin(phase_array)*r1 + lane_seg.center[1]
-                ax.plot(x, y, color)
-
+                x1 = (np.cos(phase_array)*r1 + lane_seg.center[0]).tolist()
+                y1 = (np.sin(phase_array)*r1 + lane_seg.center[1]).tolist()
                 r2 = lane_seg.radius + lane_seg.width/2
-                x = np.cos(phase_array)*r2 + lane_seg.center[0]
-                y = np.sin(phase_array)*r2 + lane_seg.center[1]
-                ax.plot(x, y, color)
+                x2 = (np.cos(phase_array)*r2 +
+                      lane_seg.center[0]).tolist().reverse()
+                y2 = (np.sin(phase_array)*r2 +
+                      lane_seg.center[1]).tolist().reverse()
+                trace_x = x1+x2+[x1[0]]
+                trace_y = y1+y2+[y1[0]]
+                x_min = min(x_min, min(trace_x))
+                y_min = min(y_min, min(trace_y))
+                x_max = max(x_max, max(trace_x))
+                y_max = max(y_max, max(trace_y))
+                if fill_type == 'lines':
+                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
+                                             mode='lines',
+                                             line_color=color,
+                                             showlegend=False,
+                                             name='lines'))
+                elif fill_type == 'detailed' and speed_limit != None:
+                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
+                                             mode='lines',
+                                             line_color=color,
+                                             fill='toself',
+                                             fillcolor='rgba' +
+                                             str(tuple(curr_color)),
+                                             showlegend=False,
+                                             name='lines'))
+                elif fill_type == 'fill':
+                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
+                                             mode='lines',
+                                             line_color=color,
+                                             fill='toself',
+                                             showlegend=False,
+                                             name='lines'))
             else:
                 raise ValueError(f'Unknown lane segment type {lane_seg.type}')
+    if fill_type == 'detailed':
+        fig.add_trace(go.Scatter(x=[0], y=[0],
+                                 mode='markers',
+                                 marker=dict(
+            symbol='square',
+            size=16,
+            cmax=speed_max,
+            cmin=speed_min,
+            color='rgba(0,0,0,0)',
+            colorbar=dict(
+                title="Speed Limit",
+                orientation='h'
+            ),
+            colorscale=[
+                [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]]
+        ),
+            showlegend=False,
+        ))
+    fig.update_xaxes(range=[x_min, x_max])
+    fig.update_yaxes(range=[y_min, y_max])
     return fig
 
 
-def plotly_simulation_tree(root: AnalysisTreeNode, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='b', fig=None, x_lim=None, y_lim=None):
-    if fig is None:
-        fig = go.Figure()
-    i = 0
-    fg_color = ['rgb(31,119,180)', 'rgb(255,127,14)', 'rgb(44,160,44)', 'rgb(214,39,40)', 'rgb(148,103,189)',
-                'rgb(140,86,75)', 'rgb(227,119,194)', 'rgb(127,127,127)', 'rgb(188,189,34)', 'rgb(23,190,207)']
-    bg_color = ['rgba(31,119,180,0.2)', 'rgba(255,127,14,0.2)', 'rgba(44,160,44,0.2)', 'rgba(214,39,40,0.2)', 'rgba(148,103,189,0.2)',
-                'rgba(140,86,75,0.2)', 'rgba(227,119,194,0.2)', 'rgba(127,127,127,0.2)', 'rgba(188,189,34,0.2)', 'rgba(23,190,207,0.2)']
-    queue = [root]
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        print(node.mode)
-        # [[time,x,y,theta,v]...]
-        trace = np.array(traces[agent_id])
-        # print(trace)
-        for y_dim in y_dim_list:
-            trace_y = trace[:, y_dim].tolist()
-            trace_x = trace[:, x_dim].tolist()
-            theta = [i/pi*180 for i in trace[:, x_dim+2]]
-            trace_x_rev = trace_x[::-1]
-            # print(trace_x)
-            trace_upper = [i+1 for i in trace_y]
-            trace_lower = [i-1 for i in trace_y]
-            trace_lower = trace_lower[::-1]
-            # print(trace_upper)
-            # print(trace[:, y_dim])
-            fig.add_trace(go.Scatter(x=trace_x+trace_x_rev, y=trace_upper+trace_lower,
-                                     fill='toself',
-                                     fillcolor=bg_color[i % 10],
-                                     line_color='rgba(255,255,255,0)',
-                                     showlegend=False))
-            fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim],
-                                     mode='lines',
-                                     line_color=fg_color[i % 10],
-                                     text=theta,
-                                     name='lines'))
-            i += 1
-        queue += node.child
-    fig.update_traces(mode='lines')
-    return fig
-
-
-def plot_simulation_tree(root: AnalysisTreeNode, agent_id, x_dim: int = 0, y_dim_list: List[int] = [1], color='b', fig=None, x_lim=None, y_lim=None):
-    if fig is None:
-        fig = plt.figure()
-
-    ax = fig.gca()
-    if x_lim is None:
-        x_lim = ax.get_xlim()
-    if y_lim is None:
-        y_lim = ax.get_ylim()
-
-    x_min, x_max = x_lim
-    y_min, y_max = y_lim
-
-    queue = [root]
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        print(node.mode)
-        # [[time,x,y,theta,v]...]
-        trace = np.array(traces[agent_id])
-        # print(trace)
-        for y_dim in y_dim_list:
-            ax.plot(trace[:, x_dim], trace[:, y_dim], color)
-            x_min = min(x_min, trace[:, x_dim].min())
-            x_max = max(x_max, trace[:, x_dim].max())
-            y_min = min(y_min, trace[:, y_dim].min())
-            y_max = max(y_max, trace[:, y_dim].max())
-        queue += node.child
-    ax.set_xlim([x_min-1, x_max+1])
-    ax.set_ylim([y_min-1, y_max+1])
-    return fig
-
-
-def generate_simulation_anime(root, map, fig=None):
-    if fig is None:
-        fig = plt.figure()
-    # fig = plot_map(map, 'g', fig)
-    timed_point_dict = {}
-    stack = [root]
-    ax = fig.gca()
-    x_min, x_max = float('inf'), -float('inf')
-    y_min, y_max = ax.get_ylim()
-    while stack != []:
-        node = stack.pop()
-        traces = node.trace
-        for agent_id in traces:
-            trace = traces[agent_id]
-            color = 'b'
-            if agent_id == 'car2':
-                color = 'r'
-            for i in range(len(trace)):
-                x_min = min(x_min, trace[i][1])
-                x_max = max(x_max, trace[i][1])
-                y_min = min(y_min, trace[i][2])
-                y_max = max(y_max, trace[i][2])
-                if round(trace[i][0], 5) not in timed_point_dict:
-                    timed_point_dict[round(trace[i][0], 5)] = [
-                        (trace[i][1:], color)]
-                else:
-                    timed_point_dict[round(trace[i][0], 5)].append(
-                        (trace[i][1:], color))
-        stack += node.child
-
-    frames = []
-    for time_point in timed_point_dict:
-        point_list = timed_point_dict[time_point]
-        plt.xlim((x_min-2, x_max+2))
-        plt.ylim((y_min-2, y_max+2))
-        # plot_map(map, color='g', fig=fig)
-        for data in point_list:
-            point = data
-            color = data[1]
-            ax = plt.gca()
-            ax.plot([point[0]], [point[1]], markerfacecolor=color,
-                    markeredgecolor=color, marker='.', markersize=20)
-            x_tail = point[0]
-            y_tail = point[1]
-            dx = np.cos(point[2])*point[3]
-            dy = np.sin(point[2])*point[3]
-            ax.arrow(x_tail, y_tail, dx, dy, head_width=1, head_length=0.5)
-        plt.pause(0.05)
-        plt.clf()
-    return fig
-    #     img_buf = io.BytesIO()
-    #     plt.savefig(img_buf, format = 'png')
-    #     im = Image.open(img_buf)
-    #     frames.append(im)
-    #     plt.clf()
-    # frame_one = frames[0]
-    # frame_one.save(fn, format = "GIF", append_images = frames, save_all = True, duration = 100, loop = 0)
+def check_dim(num_dim: int, x_dim: int = 1, y_dim: int = 2, print_dim_list: List(int) = None):
+    if x_dim <= 0 or x_dim >= num_dim:
+        raise ValueError(f'wrong x dimension value {x_dim}')
+    if y_dim <= 0 or y_dim >= num_dim:
+        raise ValueError(f'wrong y dimension value {y_dim}')
+    if print_dim_list is None:
+        return True
+    for i in print_dim_list:
+        if y_dim <= 0 or y_dim >= num_dim:
+            raise ValueError(f'wrong printed dimension value {i}')
+    return True
 
 
-def plotly_simulation_anime(root, map=None, fig=None):
-    # make figure
+def create_anime_dict(duration=10):
     fig_dict = {
         "data": [],
         "layout": {},
         "frames": []
     }
-    # fig = plot_map(map, 'g', fig)
-    timed_point_dict = {}
-    stack = [root]
-
-    # print("plot")
-    # print(root.mode)
-    x_min, x_max = float('inf'), -float('inf')
-    y_min, y_max = float('inf'), -float('inf')
-    # segment_start = set()
-    # previous_mode = {}
-    # for agent_id in root.mode:
-    #     previous_mode[agent_id] = []
-
-    while stack != []:
-        node = stack.pop()
-        traces = node.trace
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-
-            for i in range(len(trace)):
-                x_min = min(x_min, trace[i][1])
-                x_max = max(x_max, trace[i][1])
-                y_min = min(y_min, trace[i][2])
-                y_max = max(y_max, trace[i][2])
-                # print(round(trace[i][0], 2))
-                time_point = round(trace[i][0], 2)
-                if time_point not in timed_point_dict:
-                    timed_point_dict[time_point] = [
-                        {agent_id: trace[i][1:].tolist()}]
-                else:
-                    init = False
-                    for record in timed_point_dict[time_point]:
-                        if list(record.values())[0] == trace[i][1:].tolist():
-                            init = True
-                            break
-                    if init == False:
-                        timed_point_dict[time_point].append(
-                            {agent_id: trace[i][1:].tolist()})
-            time = round(trace[i][0], 2)
-        stack += node.child
-    # fill in most of layout
-    # print(segment_start)
-    # print(timed_point_dict.keys())
-
-    duration = int(600/time)
     fig_dict["layout"]["xaxis"] = {
-        "range": [(x_min-10), (x_max+10)],
         "title": "x position"}
     fig_dict["layout"]["yaxis"] = {
-        "range": [(y_min-2), (y_max+2)],
         "title": "y position"}
     fig_dict["layout"]["hovermode"] = "closest"
     fig_dict["layout"]["updatemenus"] = [
@@ -984,225 +951,29 @@ def plotly_simulation_anime(root, map=None, fig=None):
         "y": 0,
         "steps": []
     }
-    # make data
-    point_list = timed_point_dict[0]
-
-    print(point_list)
-    x_list = []
-    y_list = []
-    text_list = []
-    for data in point_list:
-        trace = list(data.values())[0]
-        # print(trace)
-        x_list.append(trace[0])
-        y_list.append(trace[1])
-        text_list.append(
-            ('{:.2f}'.format(trace[2]/pi*180), '{:.3f}'.format(trace[3])))
-    data_dict = {
-        "x": x_list,
-        "y": y_list,
-        "mode": "markers + text",
-        "text": text_list,
-        "textfont": dict(size=14, color="black"),
-        "textposition": "bottom center",
-        # "marker": {
-        #     "sizemode": "area",
-        #     "sizeref": 200000,
-        #     "size": 2
-        # },
-        "name": "Current Position"
-    }
-    fig_dict["data"].append(data_dict)
-
-    # make frames
-    for time_point in timed_point_dict:
-
-        # print(time_point)
-        frame = {"data": [], "layout": {
-            "annotations": []}, "name": '{:.2f}'.format(time_point)}
-        # print(timed_point_dict[time_point][0])
-        point_list = timed_point_dict[time_point]
-        # point_list = list(OrderedDict.fromkeys(timed_point_dict[time_point]))
-        # todokeyi
-        trace_x = []
-        trace_y = []
-        trace_theta = []
-        trace_v = []
-        for data in point_list:
-            trace = list(data.values())[0]
-            # print(trace)
-            trace_x.append(trace[0])
-            trace_y.append(trace[1])
-            trace_theta.append(trace[2])
-            trace_v.append(trace[3])
-        data_dict = {
-            "x": trace_x,
-            "y": trace_y,
-            "mode": "markers + text",
-
-            # "text": [(round(trace_theta[i]/pi*180, 2), round(trace_v[i], 3)) for i in range(len(trace_theta))],
-            "text": [('{:.2f}'.format(trace_theta[i]/pi*180), '{:.3f}'.format(trace_v[i])) for i in range(len(trace_theta))],
-            "textfont": dict(size=14, color="black"),
-            "textposition": "bottom center",
-            # "marker": {
-            #     "sizemode": "area",
-            #     "sizeref": 200000,
-            #     "size": 2
-            # },
-            "name": "current position",
-            # "show_legend": False
-        }
-        frame["data"].append(data_dict)
-        for i in range(len(trace_x)):
-            ax = np.cos(trace_theta[i])*trace_v[i]
-            ay = np.sin(trace_theta[i])*trace_v[i]
-            # print(trace_x[i]+ax, trace_y[i]+ay)
-            annotations_dict = {"x": trace_x[i]+ax, "y": trace_y[i]+ay,
-                                # "xshift": ax, "yshift": ay,
-                                "ax": trace_x[i], "ay": trace_y[i],
-                                "arrowwidth": 2,
-                                # "arrowside": 'end',
-                                "showarrow": True,
-                                # "arrowsize": 1,
-                                "xref": 'x', "yref": 'y',
-                                "axref": 'x', "ayref": 'y',
-                                # "text": "erver",
-                                "arrowhead": 1,
-                                "arrowcolor": "black"}
-            frame["layout"]["annotations"].append(annotations_dict)
-        fig_dict["frames"].append(frame)
-        slider_step = {"args": [
-            [time_point],
-            {"frame": {"duration": duration, "redraw": False},
-             "mode": "immediate",
-             "transition": {"duration": duration}}
-        ],
-            "label": time_point,
-            "method": "animate"}
-        sliders_dict["steps"].append(slider_step)
-        # print(len(frame["layout"]["annotations"]))
-
-    fig_dict["layout"]["sliders"] = [sliders_dict]
-
-    fig = go.Figure(fig_dict)
-    fig = plotly_map(map, 'g', fig)
-    i = 0
-    queue = [root]
-    previous_mode = {}
-    agent_list = []
-    for agent_id in root.mode:
-        previous_mode[agent_id] = []
-        agent_list.append(agent_id)
-    text_pos = 'middle center'
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        # print(node.mode)
-        # [[time,x,y,theta,v]...]
-        i = 0
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            # print(trace)
-            trace_y = trace[:, 2].tolist()
-            trace_x = trace[:, 1].tolist()
-            # theta = [i/pi*180 for i in trace[:, 3]]
-
-            i = agent_list.index(agent_id)
-            color = colors[i % 5]
-            fig.add_trace(go.Scatter(x=trace[:, 1], y=trace[:, 2],
-                                     mode='lines',
-                                     line_color=color,
-                                     text=[(round(trace[i, 3]/pi*180, 2), round(trace[i, 4], 3))
-                                           for i in range(len(trace_y))],
-                                     showlegend=False)
-                          #  name='lines')
-                          )
-            if previous_mode[agent_id] != node.mode[agent_id]:
-                theta = trace[0, 3]
-                veh_mode = node.mode[agent_id][0]
-                if veh_mode == 'Normal':
-                    text_pos = 'middle center'
-                elif veh_mode == 'Brake':
-                    if theta >= -pi/2 and theta <= pi/2:
-                        text_pos = 'middle left'
-                    else:
-                        text_pos = 'middle right'
-                elif veh_mode == 'Accelerate':
-                    if theta >= -pi/2 and theta <= pi/2:
-                        text_pos = 'middle right'
-                    else:
-                        text_pos = 'middle left'
-                elif veh_mode == 'SwitchLeft':
-                    if theta >= -pi/2 and theta <= pi/2:
-                        text_pos = 'top center'
-                    else:
-                        text_pos = 'bottom center'
-                elif veh_mode == 'SwitchRight':
-                    if theta >= -pi/2 and theta <= pi/2:
-                        text_pos = 'bottom center'
-                    else:
-                        text_pos = 'top center'
-                fig.add_trace(go.Scatter(x=[trace[0, 1]], y=[trace[0, 2]],
-                                         mode='markers+text',
-                                         line_color='rgba(255,255,255,0.3)',
-                                         text=str(agent_id)+': ' +
-                                         str(node.mode[agent_id][0]),
-                                         textposition=text_pos,
-                                         textfont=dict(
-                    #  family="sans serif",
-                    size=10,
-                                             color="grey"),
-                                         showlegend=False,
-                                         ))
-                # i += 1
-                previous_mode[agent_id] = node.mode[agent_id]
-        queue += node.child
-    fig.update_traces(showlegend=False)
-    # fig.update_annotations(textfont=dict(size=14, color="black"))
-    # print(fig.frames[0].layout["annotations"])
-    return fig
-    # fig.show()
-
-
-# The 'color' property is a color and may be specified as:
-#       - A hex string (e.g. '#ff0000')
-#       - An rgb/rgba string (e.g. 'rgb(255,0,0)')
-#       - An hsl/hsla string (e.g. 'hsl(0,100%,50%)')
-#       - An hsv/hsva string (e.g. 'hsv(0,100%,100%)')
-#       - A named CSS color:
-#             aliceblue, antiquewhite, aqua, aquamarine, azure,
-#             beige, bisque, black, blanchedalmond, blue,
-#             blueviolet, brown, burlywood, cadetblue,
-#             chartreuse, chocolate, coral, cornflowerblue,
-#             cornsilk, crimson, cyan, darkblue, darkcyan,
-#             darkgoldenrod, darkgray, darkgrey, darkgreen,
-#             darkkhaki, darkmagenta, darkolivegreen, darkorange,
-#             darkorchid, darkred, darksalmon, darkseagreen,
-#             darkslateblue, darkslategray, darkslategrey,
-#             darkturquoise, darkviolet, deeppink, deepskyblue,
-#             dimgray, dimgrey, dodgerblue, firebrick,
-#             floralwhite, forestgreen, fuchsia, gainsboro,
-#             ghostwhite, gold, goldenrod, gray, grey, green,
-#             greenyellow, honeydew, hotpink, indianred, indigo,
-#             ivory, khaki, lavender, lavenderblush, lawngreen,
-#             lemonchiffon, lightblue, lightcoral, lightcyan,
-#             lightgoldenrodyellow, lightgray, lightgrey,
-#             lightgreen, lightpink, lightsalmon, lightseagreen,
-#             lightskyblue, lightslategray, lightslategrey,
-#             lightsteelblue, lightyellow, lime, limegreen,
-#             linen, magenta, maroon, mediumaquamarine,
-#             mediumblue, mediumorchid, mediumpurple,
-#             mediumseagreen, mediumslateblue, mediumspringgreen,
-#             mediumturquoise, mediumvioletred, midnightblue,
-#             mintcream, mistyrose, moccasin, navajowhite, navy,
-#             oldlace, olive, olivedrab, orange, orangered,
-#             orchid, palegoldenrod, palegreen, paleturquoise,
-#             palevioletred, papayawhip, peachpuff, peru, pink,
-#             plum, powderblue, purple, red, rosybrown,
-#             royalblue, rebeccapurple, saddlebrown, salmon,
-#             sandybrown, seagreen, seashell, sienna, silver,
-#             skyblue, slateblue, slategray, slategrey, snow,
-#             springgreen, steelblue, tan, teal, thistle, tomato,
-#             turquoise, violet, wheat, white, whitesmoke,
-#             yellow, yellowgreen
-
+    return fig_dict, sliders_dict
+
+
+def get_text_pos(veh_mode):
+    if veh_mode == 'Normal':
+        text_pos = 'middle center'
+        text = 'N'
+    elif veh_mode == 'Brake':
+        text_pos = 'middle left'
+        text = 'B'
+    elif veh_mode == 'Accelerate':
+        text_pos = 'middle right'
+        text = 'A'
+    elif veh_mode == 'SwitchLeft':
+        text_pos = 'top center'
+        text = 'SL'
+    elif veh_mode == 'SwitchRight':
+        text_pos = 'bottom center'
+        text = 'SR'
+    elif veh_mode == 'Stop':
+        text_pos = 'middle center'
+        text = 'S'
+    else:
+        print(veh_mode)
+        raise ValueError
+    return text_pos, text
diff --git a/dryvr_plus_plus/plotter/plotter2D_new.py b/dryvr_plus_plus/plotter/plotter2D_new.py
deleted file mode 100644
index 0f8cd26c781efb5ef3b81bf408f7428f802117fa..0000000000000000000000000000000000000000
--- a/dryvr_plus_plus/plotter/plotter2D_new.py
+++ /dev/null
@@ -1,979 +0,0 @@
-"""
-This file consist main plotter code for DryVR reachtube output
-"""
-
-from __future__ import annotations
-import numpy as np
-from math import pi
-import plotly.graph_objects as go
-from typing import List, Tuple
-import copy
-# from dryvr_plus_plus.scene_verifier.analysis.analysis_tree_node import AnalysisTreeNode
-
-colors = [['#CC0000', '#FF0000', '#FF3333', '#FF6666', '#FF9999'],
-          ['#CC6600', '#FF8000', '#FF9933', '#FFB266', '#FFCC99'],
-          ['#CCCC00', '#FFFF00', '#FFFF33', '#FFFF66', '#FFFF99'],
-          ['#66CC00', '#80FF00', '#99FF33', '#B2FF66', '#CCFF99'],
-          ['#00CC00', '#00FF00', '#33FF33', '#66FF66', '#99FF99'],
-          ['#00CC66', '#00FF80', '#33FF99', '#66FFB2', '#99FFCC'],
-          ['#00CCCC', '#00FFFF', '#33FFFF', '#66FFFF', '#99FFFF'],
-          ['#0066CC', '#0080FF', '#3399FF', '#66B2FF', '#99CCFF'],
-          ['#0000CC', '#0000FF', '#3333FF', '#6666FF', '#9999FF'],
-          ['#6600CC', '#7F00FF', '#9933FF', '#B266FF', '#CC99FF'],
-          ['#CC00CC', '#FF00FF', '#FF33FF', '#FF66FF', '#FF99FF'],
-          ['#CC0066', '#FF007F', '#FF3399', '#FF66B2', '#FF99CC']
-          ]
-scheme_dict = {'red': 0, 'orange': 1, 'yellow': 2, 'yellowgreen': 3, 'lime': 4,
-               'springgreen': 5, 'cyan': 6, 'cyanblue': 7, 'blue': 8, 'purple': 9, 'magenta': 10, 'pink': 11}
-color_cnt = 0
-text_size = 8
-scale_factor = 0.25
-mode_point_color = 'rgba(0,0,0,0.5)'
-mode_text_color = 'black'
-duration = 10
-
-
-"""These 5 Functions below are high-level functions and are recommended to use."""
-"""
-API
-These 5 functions share the same API.
-
-- root: the root node of the trace, should be the return value of Scenario.verify() or Scenario.simulate().
-- map: the map of the scenario, templates are in dryvr_plus_plus.example.example_map.simple_map2.py.
-- fig: the object of the figure, its type should be plotly.graph_objects.Figure().
-- x_dim: the dimension of x coordinate in the trace list of every time step. The default value is 1.
-- y_dim: the dimension of y coordinate in the trace list of every time step. The default value is 2.
-- map_type the way to draw the map. It should be 'lines' or 'fill' or 'detailed'. The default value is 'lines'.
---  For the 'lines' mode, map is only drawn by margins of lanes.
---  For the 'fill' mode, the lanes will be filled with semitransparent colors.
---  For the 'detailed' mode, the lanes will be filled some colors according to the speed limits of lanes(if the information is given). 
-    Otherwise, it is the same as the 'lines' mode.
-- scale_type the way to scale the coordinate axises. It should be 'trace' or 'map'. The default value is 'trace'.
---  For the 'trace' mode, the traces will be in the center of the plot with an appropriate scale.
---  For the 'map' mode, the map will be in the center of the plot with an appropriate scale.
-- print_dim_list the list containing the dimensions of data which will be shown directly or indirectly when the mouse hovers on the point. 
-    The default value is None. And then all dimensions will be shown.
-"""
-
-
-def reachtube_anime(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, map_type='lines', scale_type='trace', print_dim_list=None):
-    """It gives the animation of the verfication."""
-    agent_list = list(root.agent.keys())
-    timed_point_dict = {}
-    stack = [root]
-    x_min, x_max = float('inf'), -float('inf')
-    y_min, y_max = float('inf'), -float('inf')
-    # input check
-    num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1]
-    check_dim(num_dim, x_dim, y_dim, print_dim_list)
-    if print_dim_list is None:
-        print_dim_list = range(0, num_dim)
-    scheme_list = list(scheme_dict.keys())
-
-    while stack != []:
-        node = stack.pop()
-        traces = node.trace
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            if trace[0][0] > 0:
-                trace = trace[4:]
-            for i in range(0, len(trace)-1, 2):
-                x_min = min(x_min, trace[i][x_dim])
-                x_max = max(x_max, trace[i][x_dim])
-                y_min = min(y_min, trace[i][y_dim])
-                y_max = max(y_max, trace[i][y_dim])
-                time_point = round(trace[i][0], 2)
-                rect = [trace[i][0:].tolist(), trace[i+1][0:].tolist()]
-                if time_point not in timed_point_dict:
-                    timed_point_dict[time_point] = {agent_id: [rect]}
-                else:
-                    if agent_id in timed_point_dict[time_point].keys():
-                        timed_point_dict[time_point][agent_id].append(rect)
-                    else:
-                        timed_point_dict[time_point][agent_id] = [rect]
-
-        stack += node.child
-    fig_dict, sliders_dict = create_anime_dict(duration)
-    for time_point in timed_point_dict:
-        frame = {"data": [], "layout": {
-            "annotations": [], "shapes": []}, "name": str(time_point)}
-        agent_dict = timed_point_dict[time_point]
-        for agent_id, rect_list in agent_dict.items():
-            for rect in rect_list:
-                shape_dict = {
-                    "type": 'rect',
-                    "x0": rect[0][x_dim],
-                    "y0": rect[0][y_dim],
-                    "x1": rect[1][x_dim],
-                    "y1": rect[1][y_dim],
-                    "fillcolor": 'rgba(0,0,0,0.5)',
-                    "line": dict(color='rgba(255,255,255,0)'),
-                    "visible": True
-
-                }
-                frame["layout"]["shapes"].append(shape_dict)
-
-        fig_dict["frames"].append(frame)
-        slider_step = {"args": [
-            ['{:.2f}'.format(time_point)],
-            {"frame": {"duration": duration, "redraw": False},
-             "mode": "immediate",
-             "transition": {"duration": duration}}
-        ],
-            "label": '{:.2f}'.format(time_point),
-            "method": "animate"}
-        sliders_dict["steps"].append(slider_step)
-
-    fig_dict["layout"]["sliders"] = [sliders_dict]
-
-    fig = go.Figure(fig_dict)
-    fig = draw_map(map=map, fig=fig, fill_type=map_type)
-    i = 0
-    for agent_id in agent_list:
-        fig = reachtube_tree_single(
-            root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list)
-        i = (i+1) % 12
-    if scale_type == 'trace':
-        queue = [root]
-        x_min, x_max = float('inf'), -float('inf')
-        y_min, y_max = float('inf'), -float('inf')
-    i = 0
-    queue = [root]
-    previous_mode = {}
-    for agent_id in root.mode:
-        previous_mode[agent_id] = []
-    text_pos = 'middle center'
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            if scale_type == 'trace':
-                x_min = min(x_min, min(trace[:, x_dim]))
-                x_max = max(x_max, max(trace[:, x_dim]))
-                y_min = min(y_min, min(trace[:, y_dim]))
-                y_max = max(y_max, max(trace[:, y_dim]))
-            if previous_mode[agent_id] != node.mode[agent_id]:
-                text_pos, text = get_text_pos(node.mode[agent_id][0])
-                x0 = trace[0, x_dim]
-                x1 = trace[1, x_dim]
-                y0 = trace[0, y_dim]
-                y1 = trace[1, y_dim]
-                mode_point_color = colors[agent_list.index(agent_id) % 12][0]
-                fig.add_trace(go.Scatter(x=[(x0+x1)/2], y=[(y0+y1)/2],
-                                         mode='markers+text',
-                                         line_color=mode_point_color,
-                                         text=str(agent_id)+': ' + text,
-                                         textposition=text_pos,
-                                         opacity=0.5,
-                                         textfont=dict(
-                    size=text_size,
-                                             color=mode_text_color),
-                                         showlegend=False,
-                                         ))
-                previous_mode[agent_id] = node.mode[agent_id]
-        queue += node.child
-    if scale_type == 'trace':
-        fig.update_xaxes(
-            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
-        fig.update_yaxes(
-            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
-    return fig
-
-
-def reachtube_tree(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
-    """It statically shows all the traces of the verfication."""
-    fig = draw_map(map=map, fig=fig, fill_type=map_type)
-    agent_list = list(root.agent.keys())
-    # input check
-    num_dim = np.array(root.trace[agent_list[0]]).shape[1]
-    check_dim(num_dim, x_dim, y_dim, print_dim_list)
-    if print_dim_list is None:
-        print_dim_list = range(0, num_dim)
-
-    scheme_list = list(scheme_dict.keys())
-    i = 0
-    for agent_id in agent_list:
-        fig = reachtube_tree_single(
-            root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list)
-        i = (i+1) % 12
-    if scale_type == 'trace':
-        queue = [root]
-        x_min, x_max = float('inf'), -float('inf')
-        y_min, y_max = float('inf'), -float('inf')
-    i = 0
-    queue = [root]
-    previous_mode = {}
-    for agent_id in root.mode:
-        previous_mode[agent_id] = []
-    text_pos = 'middle center'
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        i = 0
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            if scale_type == 'trace':
-                x_min = min(x_min, min(trace[:, x_dim]))
-                x_max = max(x_max, max(trace[:, x_dim]))
-                y_min = min(y_min, min(trace[:, y_dim]))
-                y_max = max(y_max, max(trace[:, y_dim]))
-            i = agent_list.index(agent_id)
-            if previous_mode[agent_id] != node.mode[agent_id]:
-                text_pos, text = get_text_pos(node.mode[agent_id][0])
-                mode_point_color = colors[agent_list.index(agent_id) % 12][0]
-                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
-                                         mode='markers+text',
-                                         line_color=mode_point_color,
-                                         opacity=0.5,
-                                         text=str(agent_id)+': ' + text,
-                                         textposition=text_pos,
-                                         textfont=dict(
-                    size=text_size,
-                                             color=mode_text_color),
-                                         showlegend=False,
-                                         ))
-                previous_mode[agent_id] = node.mode[agent_id]
-        queue += node.child
-    if scale_type == 'trace':
-        fig.update_xaxes(
-            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
-        fig.update_yaxes(
-            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
-    return fig
-
-
-def simulation_tree(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
-    """It statically shows all the traces of the simulation."""
-    fig = draw_map(map=map, fig=fig, fill_type=map_type)
-    agent_list = list(root.agent.keys())
-    # input check
-    num_dim = np.array(root.trace[agent_list[0]]).shape[1]
-    check_dim(num_dim, x_dim, y_dim, print_dim_list)
-    if print_dim_list is None:
-        print_dim_list = range(0, num_dim)
-
-    scheme_list = list(scheme_dict.keys())
-    i = 0
-    for agent_id in agent_list:
-        fig = simulation_tree_single(
-            root, agent_id, fig, x_dim, y_dim, scheme_list[i], print_dim_list)
-        i = (i+1) % 12
-    if scale_type == 'trace':
-        queue = [root]
-        x_min, x_max = float('inf'), -float('inf')
-        y_min, y_max = float('inf'), -float('inf')
-    i = 0
-    queue = [root]
-    previous_mode = {}
-    for agent_id in root.mode:
-        previous_mode[agent_id] = []
-    text_pos = 'middle center'
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        i = 0
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            if scale_type == 'trace':
-                x_min = min(x_min, min(trace[:, x_dim]))
-                x_max = max(x_max, max(trace[:, x_dim]))
-                y_min = min(y_min, min(trace[:, y_dim]))
-                y_max = max(y_max, max(trace[:, y_dim]))
-            i = agent_list.index(agent_id)
-            mode_point_color = colors[agent_list.index(agent_id) % 12][0]
-            if previous_mode[agent_id] != node.mode[agent_id]:
-                text_pos, text = get_text_pos(node.mode[agent_id][0])
-                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
-                                         mode='markers+text',
-                                         line_color=mode_point_color,
-                                         opacity=0.5,
-                                         text=str(agent_id)+': ' + text,
-                                         textposition=text_pos,
-                                         textfont=dict(
-                    size=text_size,
-                    color=mode_text_color
-                ),
-                    showlegend=False,
-                ))
-                previous_mode[agent_id] = node.mode[agent_id]
-        queue += node.child
-    if scale_type == 'trace':
-        fig.update_xaxes(
-            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
-        fig.update_yaxes(
-            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
-    fig.update_xaxes(title='x')
-    fig.update_yaxes(title='y')
-    fig.update_layout(legend_title_text='Agent list')
-    return fig
-
-
-def simulation_anime(root, map=None, fig=None, x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
-    """It gives the animation of the simulation without trail but is faster."""
-    timed_point_dict = {}
-    stack = [root]
-    x_min, x_max = float('inf'), -float('inf')
-    y_min, y_max = float('inf'), -float('inf')
-    # input check
-    num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1]
-    check_dim(num_dim, x_dim, y_dim, print_dim_list)
-    if print_dim_list is None:
-        print_dim_list = range(0, num_dim)
-    agent_list = list(root.agent.keys())
-    while stack != []:
-        node = stack.pop()
-        traces = node.trace
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            for i in range(len(trace)):
-                x_min = min(x_min, trace[i][x_dim])
-                x_max = max(x_max, trace[i][x_dim])
-                y_min = min(y_min, trace[i][y_dim])
-                y_max = max(y_max, trace[i][y_dim])
-                time_point = round(trace[i][0], 2)
-                tmp_trace = trace[i][0:].tolist()
-                if time_point not in timed_point_dict:
-                    timed_point_dict[time_point] = {agent_id: [tmp_trace]}
-                else:
-                    if agent_id not in timed_point_dict[time_point].keys():
-                        timed_point_dict[time_point][agent_id] = [tmp_trace]
-                    elif tmp_trace not in timed_point_dict[time_point][agent_id]:
-                        timed_point_dict[time_point][agent_id].append(
-                            tmp_trace)
-            time = round(trace[i][0], 2)
-        stack += node.child
-    fig_dict, sliders_dict = create_anime_dict(duration)
-    # make data
-    trace_dict = timed_point_dict[0]
-    for agent_id, trace_list in trace_dict.items():
-        color = colors[agent_list.index(agent_id) % 12][1]
-        x_list = []
-        y_list = []
-        text_list = []
-        branch_cnt = 0
-        for trace in trace_list:
-            x_list.append(trace[x_dim])
-            y_list.append(trace[y_dim])
-            text_list.append(['{:.2f}'.format(trace[i])
-                              for i in print_dim_list])
-            branch_cnt += 1
-        data_dict = {
-            "x": x_list,
-            "y": y_list,
-            "text": text_list,
-            "mode": "markers + text",
-            "textfont": dict(size=text_size, color="black"),
-            "textposition": "bottom center",
-            "marker": {
-                "color": color,
-            },
-            "name": agent_id,
-            "showlegend": True
-        }
-        fig_dict["data"].append(data_dict)
-    # make frames
-    for time_point in timed_point_dict:
-        frame = {"data": [], "layout": {
-            "annotations": []}, "name": '{:.2f}'.format(time_point)}
-        point_list = timed_point_dict[time_point]
-        for agent_id, trace_list in point_list.items():
-            color = colors[agent_list.index(agent_id) % 12][1]
-            x_list = []
-            y_list = []
-            text_list = []
-            branch_cnt = 0
-            for trace in trace_list:
-                x_list.append(trace[x_dim])
-                y_list.append(trace[y_dim])
-                text_list.append(['{:.2f}'.format(trace[i])
-                                  for i in print_dim_list])
-                branch_cnt += 1
-            data_dict = {
-                "x": x_list,
-                "y": y_list,
-                "text": text_list,
-                "mode": "markers + text",
-                "marker": {
-                    "color": color,
-                },
-                "textfont": dict(size=text_size, color="black"),
-                "textposition": "bottom center",
-                # "name": "Branch-"+str(branch_cnt),
-                "name": agent_id,
-                "showlegend": True
-            }
-            frame["data"].append(data_dict)
-        fig_dict["frames"].append(frame)
-        slider_step = {"args": [
-            ['{:.2f}'.format(time_point)],
-            {"frame": {"duration": duration, "redraw": True},
-             "mode": "immediate",
-             "transition": {"duration": duration}}
-        ],
-            "label": '{:.2f}'.format(time_point),
-            "method": "animate"}
-        sliders_dict["steps"].append(slider_step)
-
-    fig_dict["layout"]["sliders"] = [sliders_dict]
-
-    fig = go.Figure(fig_dict)
-    fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type)
-    i = 0
-    queue = [root]
-    previous_mode = {}
-    agent_list = list(root.agent.keys())
-    for agent_id in root.mode:
-        previous_mode[agent_id] = []
-    text_pos = 'middle center'
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            mode_point_color = colors[agent_list.index(agent_id) % 12][0]
-            if previous_mode[agent_id] != node.mode[agent_id]:
-                text_pos, text = get_text_pos(node.mode[agent_id][0])
-                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
-                                         mode='markers+text',
-                                         line_color=mode_point_color,
-                                         text=str(agent_id)+': ' + text,
-                                         textposition=text_pos,
-                                         opacity=0.5,
-                                         textfont=dict(
-                    size=text_size,
-                    color=mode_text_color),
-                    showlegend=False,
-                ))
-                previous_mode[agent_id] = node.mode[agent_id]
-        queue += node.child
-    if scale_type == 'trace':
-        fig.update_xaxes(
-            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
-        fig.update_yaxes(
-            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
-    fig.update_layout(legend_title_text='Agent list')
-    return fig
-
-
-def simulation_anime_trail(root, map=None, fig=go.Figure(), x_dim: int = 1, y_dim=2, map_type='lines', scale_type='trace', print_dim_list=None):
-    """It gives the animation of the simulation with trail."""
-    timed_point_dict = {}
-    stack = [root]
-    x_min, x_max = float('inf'), -float('inf')
-    y_min, y_max = float('inf'), -float('inf')
-    # input check
-    num_dim = np.array(root.trace[list(root.agent.keys())[0]]).shape[1]
-    check_dim(num_dim, x_dim, y_dim, print_dim_list)
-    if print_dim_list is None:
-        print_dim_list = range(0, num_dim)
-
-    while stack != []:
-        node = stack.pop()
-        traces = node.trace
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            for i in range(len(trace)):
-                x_min = min(x_min, trace[i][x_dim])
-                x_max = max(x_max, trace[i][x_dim])
-                y_min = min(y_min, trace[i][y_dim])
-                y_max = max(y_max, trace[i][y_dim])
-                time_point = round(trace[i][0], 3)
-                tmp_trace = trace[i][0:].tolist()
-                if time_point not in timed_point_dict:
-                    timed_point_dict[time_point] = {agent_id: [tmp_trace]}
-                else:
-                    if agent_id not in timed_point_dict[time_point].keys():
-                        timed_point_dict[time_point][agent_id] = [tmp_trace]
-                    elif tmp_trace not in timed_point_dict[time_point][agent_id]:
-                        timed_point_dict[time_point][agent_id].append(
-                            tmp_trace)
-            time = round(trace[i][0], 2)
-        stack += node.child
-    fig_dict, sliders_dict = create_anime_dict(duration)
-    time_list = list(timed_point_dict.keys())
-    agent_list = list(root.agent.keys())
-    trail_limit = min(10, len(time_list))
-    trail_len = trail_limit
-    opacity_step = 1/trail_len
-    size_step = 2/trail_len
-    min_size = 5
-    step = 2
-    # # make data
-    trace_dict = timed_point_dict[0]
-
-    for time_point in list(timed_point_dict.keys())[0:int(trail_limit/step)]:
-        trace_dict = timed_point_dict[time_point]
-        for agent_id, point_list in trace_dict.items():
-            x_list = []
-            y_list = []
-            text_list = []
-            for point in point_list:
-                x_list.append(point[x_dim])
-                y_list.append(point[y_dim])
-                text_list.append(['{:.2f}'.format(point[i])
-                                  for i in print_dim_list])
-            data_dict = {
-                "x": x_list,
-                "y": y_list,
-                "mode": "markers",
-                "text": text_list,
-                "textfont": dict(size=text_size, color="black"),
-                "visible": False,
-                "textposition": "bottom center",
-                "name": agent_id
-            }
-            fig_dict["data"].append(data_dict)
-
-    # make frames
-    for time_point_id in range(trail_limit, len(time_list)):
-        time_point = time_list[time_point_id]
-        frame = {"data": [], "layout": {
-            "annotations": []}, "name": '{:.2f}'.format(time_point)}
-        for agent_id in agent_list:
-            color = colors[agent_list.index(agent_id) % 12][1]
-            for id in range(0, trail_len, step):
-                tmp_point_list = timed_point_dict[time_list[time_point_id-id]][agent_id]
-                trace_x = []
-                trace_y = []
-                text_list = []
-                for point in tmp_point_list:
-                    trace_x.append(point[x_dim])
-                    trace_y.append(point[y_dim])
-                    text_list.append(['{:.2f}'.format(point[i])
-                                      for i in print_dim_list])
-                if id == 0:
-                    data_dict = {
-                        "x": trace_x,
-                        "y": trace_y,
-                        "mode": "markers+text",
-                        "text": text_list,
-                        "textfont": dict(size=text_size, color="black"),
-                        "textposition": "bottom center",
-                        "visible": True,  # 'legendonly'
-                        "marker": {
-                            "color": color,
-                            "opacity": opacity_step*(trail_len-id),
-                            "size": min_size + size_step*(trail_len-id)
-                        },
-                        "name": agent_id,
-                        "showlegend": True
-                    }
-                else:
-                    data_dict = {
-                        "x": trace_x,
-                        "y": trace_y,
-                        "mode": "markers",
-                        "text": text_list,
-                        "visible": True,  # 'legendonly'
-                        "marker": {
-                            "color": color,
-                            "opacity": opacity_step*(trail_len-id),
-                            "size": min_size + size_step*(trail_len-id)
-                        },
-                        "name": agent_id,
-                        "showlegend": True
-                    }
-                frame["data"].append(data_dict)
-
-        fig_dict["frames"].append(frame)
-        slider_step = {"args": [
-            ['{:.2f}'.format(time_point)],
-            {"frame": {"duration": duration, "redraw": False},
-             "mode": "immediate",
-             "transition": {"duration": duration}}
-        ],
-            "label": '{:.2f}'.format(time_point),
-            "method": "animate"}
-        sliders_dict["steps"].append(slider_step)
-
-    fig_dict["layout"]["sliders"] = [sliders_dict]
-
-    fig = go.Figure(fig_dict)
-    fig = draw_map(map, 'rgba(0,0,0,1)', fig, map_type)
-    i = 0
-    queue = [root]
-    previous_mode = {}
-    agent_list = list(root.agent.keys())
-    for agent_id in root.mode:
-        previous_mode[agent_id] = []
-    text_pos = 'middle center'
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        i = 0
-        for agent_id in traces:
-            trace = np.array(traces[agent_id])
-            trace_y = trace[:, y_dim].tolist()
-            trace_x = trace[:, x_dim].tolist()
-            i = agent_list.index(agent_id)
-            mode_point_color = colors[agent_list.index(agent_id) % 12][0]
-            if previous_mode[agent_id] != node.mode[agent_id]:
-                text_pos, text = get_text_pos(node.mode[agent_id][0])
-                fig.add_trace(go.Scatter(x=[trace[0, x_dim]], y=[trace[0, y_dim]],
-                                         mode='markers+text',
-                                         line_color=mode_point_color,
-                                         text=str(agent_id)+': ' + text,
-                                         opacity=0.5,
-                                         textposition=text_pos,
-                                         textfont=dict(
-                    size=text_size,
-                    color=mode_text_color
-                ),
-                    showlegend=False,
-                ))
-                previous_mode[agent_id] = node.mode[agent_id]
-        queue += node.child
-    if scale_type == 'trace':
-        fig.update_xaxes(
-            range=[x_min-scale_factor*(x_max-x_min), x_max+scale_factor*(x_max-x_min)])
-        fig.update_yaxes(
-            range=[y_min-scale_factor*(y_max-y_min), y_max+scale_factor*(y_max-y_min)])
-    fig.update_layout(legend_title_text='Agent list')
-    return fig
-
-
-"""Functions below are low-level functions and usually are not called outside this file."""
-
-
-def reachtube_tree_single(root, agent_id, fig=go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None):
-    """It statically shows the verfication traces of one given agent."""
-    global color_cnt
-    if color == None:
-        color = list(scheme_dict.keys())[color_cnt]
-        color_cnt = (color_cnt+1) % 12
-    queue = [root]
-    show_legend = False
-    fillcolor = colors[scheme_dict[color]][4]
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        trace = np.array(traces[agent_id])
-        max_id = len(trace)-1
-        trace_x_odd = np.array([trace[i][x_dim] for i in range(0, max_id, 2)])
-        trace_x_even = np.array([trace[i][x_dim]
-                                for i in range(1, max_id+1, 2)])
-        trace_y_odd = np.array([trace[i][y_dim] for i in range(0, max_id, 2)])
-        trace_y_even = np.array([trace[i][y_dim]
-                                for i in range(1, max_id+1, 2)])
-        fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-                                 fill='toself',
-                                 fillcolor=fillcolor,
-                                 opacity=0.5,
-                                 line_color='rgba(255,255,255,0)',
-                                 showlegend=show_legend
-                                 ))
-        fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-                                 fill='toself',
-                                 fillcolor=fillcolor,
-                                 opacity=0.5,
-                                 line_color='rgba(255,255,255,0)',
-                                 showlegend=show_legend))
-        fig.add_trace(go.Scatter(x=trace_x_odd.tolist()+trace_x_even[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-                                 fill='toself',
-                                 fillcolor=fillcolor,
-                                 opacity=0.5,
-                                 line_color='rgba(255,255,255,0)',
-                                 showlegend=show_legend
-                                 ))
-        fig.add_trace(go.Scatter(x=trace_x_even.tolist()+trace_x_odd[::-1].tolist(), y=trace_y_odd.tolist()+trace_y_even[::-1].tolist(), mode='lines',
-                                 fill='toself',
-                                 fillcolor=fillcolor,
-                                 opacity=0.5,
-                                 line_color='rgba(255,255,255,0)',
-                                 showlegend=show_legend))
-        queue += node.child
-
-    queue = [root]
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        trace = np.array(traces[agent_id])
-        max_id = len(trace)-1
-        fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim],
-                                 mode='markers',
-                                 text=[
-                                     ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(0, trace.shape[0])],
-                                 line_color=colors[scheme_dict[color]][0],
-                                 marker={
-            "sizemode": "area",
-            "sizeref": 200000,
-            "size": 2
-        },
-            name='lines',
-            showlegend=False))
-        queue += node.child
-    return fig
-
-
-def simulation_tree_single(root, agent_id, fig: go.Figure() = go.Figure(), x_dim: int = 1, y_dim: int = 2, color=None, print_dim_list=None):
-    """It statically shows the simulation traces of one given agent."""
-    global color_cnt
-    queue = [root]
-    color_id = 0
-    if color == None:
-        color = list(scheme_dict.keys())[color_cnt]
-        color_cnt = (color_cnt+1) % 12
-    start_list = []
-    end_list = []
-    count_dict = {}
-    while queue != []:
-        node = queue.pop(0)
-        traces = node.trace
-        if agent_id not in traces.keys():
-            return fig
-        trace = np.array(traces[agent_id])
-        start = list(trace[0])
-        end = list(trace[-1])
-        if (start in start_list) and (end in end_list):
-            continue
-        time = tuple([round(start[0], 2), round(end[0], 2)])
-        if time in count_dict.keys():
-            count_dict[time] += 1
-        else:
-            count_dict[time] = 1
-        start_list.append(start)
-        end_list.append(end)
-        fig.add_trace(go.Scatter(x=trace[:, x_dim], y=trace[:, y_dim],
-                                 mode='lines',
-                                 line_color=colors[scheme_dict[color]
-                                                   ][color_id],
-                                 text=[
-                                     ['{:.2f}'.format(trace[i, j])for j in print_dim_list] for i in range(trace.shape[0])],
-                                 legendgroup=agent_id,
-                                 legendgrouptitle_text=agent_id,
-                                 name=str(round(start[0], 2))+'-'+str(round(end[0], 2)) +
-                                 '-'+str(count_dict[time]),
-                                 showlegend=True))
-        color_id = (color_id+4) % 5
-        queue += node.child
-    fig.update_layout(legend=dict(
-        groupclick="toggleitem",
-        itemclick="toggle",
-        itemdoubleclick="toggleothers"
-    ))
-    return fig
-
-
-def draw_map(map, color='rgba(0,0,0,1)', fig: go.Figure() = go.Figure(), fill_type='lines'):
-    """It draws the the map"""
-    x_min, x_max = float('inf'), -float('inf')
-    y_min, y_max = float('inf'), -float('inf')
-    if map is None:
-        return fig
-    if fill_type == 'detailed':
-        speed_dict = map.get_all_speed_limit()
-        speed_list = list(filter(None, speed_dict.values()))
-        speed_min = min(speed_list)
-        speed_max = max(speed_list)
-        start_color = [255, 255, 255, 0.2]
-        end_color = [0, 0, 0, 0.2]
-        curr_color = [0, 0, 0, 0]
-    speed_limit = None
-    for lane_idx in map.lane_dict:
-        lane = map.lane_dict[lane_idx]
-        curr_color = [0, 0, 0, 0]
-        if fill_type == 'detailed':
-            speed_limit = speed_dict[lane_idx]
-            if speed_limit is not None:
-                lens = len(curr_color)-1
-                for j in range(lens):
-                    curr_color[j] = int(start_color[j]+(speed_limit-speed_min)/(speed_max -
-                                                                                speed_min)*(end_color[j]-start_color[j]))
-                curr_color[lens] = start_color[lens]+(speed_limit-speed_min)/(speed_max -
-                                                                              speed_min)*(end_color[lens]-start_color[lens])
-        for lane_seg in lane.segment_list:
-            if lane_seg.type == 'Straight':
-                start1 = lane_seg.start + lane_seg.width/2 * lane_seg.direction_lateral
-                end1 = lane_seg.end + lane_seg.width/2 * lane_seg.direction_lateral
-                start2 = lane_seg.start - lane_seg.width/2 * lane_seg.direction_lateral
-                end2 = lane_seg.end - lane_seg.width/2 * lane_seg.direction_lateral
-                trace_x = [start1[0], end1[0], end2[0], start2[0], start1[0]]
-                trace_y = [start1[1], end1[1], end2[1], start2[1], start1[1]]
-                x_min = min(x_min, min(trace_x))
-                y_min = min(y_min, min(trace_y))
-                x_max = max(x_max, max(trace_x))
-                y_max = max(y_max, max(trace_y))
-                if fill_type == 'lines' or (fill_type == 'detailed' and speed_limit is None):
-                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-                                             mode='lines',
-                                             line_color=color,
-                                             showlegend=False,
-                                             name='lines'))
-                elif fill_type == 'detailed' and speed_limit is not None:
-                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-                                             mode='lines',
-                                             line_color=color,
-                                             fill='toself',
-                                             fillcolor='rgba' +
-                                             str(tuple(curr_color)),
-                                             showlegend=False,
-                                             name='limit'))
-                elif fill_type == 'fill':
-                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-                                             mode='lines',
-                                             line_color=color,
-                                             fill='toself',
-                                             fillcolor='rgba(0,0,0,0.1)',
-                                             showlegend=False,
-                                             # text=theta,
-                                             name='lines'))
-            elif lane_seg.type == "Circular":
-                phase_array = np.linspace(
-                    start=lane_seg.start_phase, stop=lane_seg.end_phase, num=100)
-                r1 = lane_seg.radius - lane_seg.width/2
-                x1 = (np.cos(phase_array)*r1 + lane_seg.center[0]).tolist()
-                y1 = (np.sin(phase_array)*r1 + lane_seg.center[1]).tolist()
-                r2 = lane_seg.radius + lane_seg.width/2
-                x2 = (np.cos(phase_array)*r2 +
-                      lane_seg.center[0]).tolist().reverse()
-                y2 = (np.sin(phase_array)*r2 +
-                      lane_seg.center[1]).tolist().reverse()
-                trace_x = x1+x2+[x1[0]]
-                trace_y = y1+y2+[y1[0]]
-                x_min = min(x_min, min(trace_x))
-                y_min = min(y_min, min(trace_y))
-                x_max = max(x_max, max(trace_x))
-                y_max = max(y_max, max(trace_y))
-                if fill_type == 'lines':
-                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-                                             mode='lines',
-                                             line_color=color,
-                                             showlegend=False,
-                                             name='lines'))
-                elif fill_type == 'detailed' and speed_limit != None:
-                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-                                             mode='lines',
-                                             line_color=color,
-                                             fill='toself',
-                                             fillcolor='rgba' +
-                                             str(tuple(curr_color)),
-                                             showlegend=False,
-                                             name='lines'))
-                elif fill_type == 'fill':
-                    fig.add_trace(go.Scatter(x=trace_x, y=trace_y,
-                                             mode='lines',
-                                             line_color=color,
-                                             fill='toself',
-                                             showlegend=False,
-                                             name='lines'))
-            else:
-                raise ValueError(f'Unknown lane segment type {lane_seg.type}')
-    if fill_type == 'detailed':
-        fig.add_trace(go.Scatter(x=[0], y=[0],
-                                 mode='markers',
-                                 marker=dict(
-            symbol='square',
-            size=16,
-            cmax=speed_max,
-            cmin=speed_min,
-            color='rgba(0,0,0,0)',
-            colorbar=dict(
-                title="Speed Limit",
-                orientation='h'
-            ),
-            colorscale=[
-                [0, 'rgba'+str(tuple(start_color))], [1, 'rgba'+str(tuple(end_color))]]
-        ),
-            showlegend=False,
-        ))
-    fig.update_xaxes(range=[x_min, x_max])
-    fig.update_yaxes(range=[y_min, y_max])
-    return fig
-
-
-def check_dim(num_dim: int, x_dim: int = 1, y_dim: int = 2, print_dim_list: List(int) = None):
-    if x_dim <= 0 or x_dim >= num_dim:
-        raise ValueError(f'wrong x dimension value {x_dim}')
-    if y_dim <= 0 or y_dim >= num_dim:
-        raise ValueError(f'wrong y dimension value {y_dim}')
-    if print_dim_list is None:
-        return True
-    for i in print_dim_list:
-        if y_dim <= 0 or y_dim >= num_dim:
-            raise ValueError(f'wrong printed dimension value {i}')
-    return True
-
-
-def create_anime_dict(duration=10):
-    fig_dict = {
-        "data": [],
-        "layout": {},
-        "frames": []
-    }
-    fig_dict["layout"]["xaxis"] = {
-        "title": "x position"}
-    fig_dict["layout"]["yaxis"] = {
-        "title": "y position"}
-    fig_dict["layout"]["hovermode"] = "closest"
-    fig_dict["layout"]["updatemenus"] = [
-        {
-            "buttons": [
-                {
-                    "args": [None, {"frame": {"duration": duration, "redraw": False},
-                                    "fromcurrent": True, "transition": {"duration": duration,
-                                                                        "easing": "quadratic-in-out"}}],
-                    "label": "Play",
-                    "method": "animate"
-                },
-                {
-                    "args": [[None], {"frame": {"duration": 0, "redraw": False},
-                                      "mode": "immediate",
-                                      "transition": {"duration": 0}}],
-                    "label": "Pause",
-                    "method": "animate"
-                }
-            ],
-            "direction": "left",
-            "pad": {"r": 10, "t": 87},
-            "showactive": False,
-            "type": "buttons",
-            "x": 0.1,
-            "xanchor": "right",
-            "y": 0,
-            "yanchor": "top"
-        }
-    ]
-    sliders_dict = {
-        "active": 0,
-        "yanchor": "top",
-        "xanchor": "left",
-        "currentvalue": {
-            "font": {"size": 20},
-            "prefix": "time:",
-            "visible": True,
-            "xanchor": "right"
-        },
-        "transition": {"duration": duration, "easing": "cubic-in-out"},
-        "pad": {"b": 10, "t": 50},
-        "len": 0.9,
-        "x": 0.1,
-        "y": 0,
-        "steps": []
-    }
-    return fig_dict, sliders_dict
-
-
-def get_text_pos(veh_mode):
-    if veh_mode == 'Normal':
-        text_pos = 'middle center'
-        text = 'N'
-    elif veh_mode == 'Brake':
-        text_pos = 'middle left'
-        text = 'B'
-    elif veh_mode == 'Accelerate':
-        text_pos = 'middle right'
-        text = 'A'
-    elif veh_mode == 'SwitchLeft':
-        text_pos = 'top center'
-        text = 'SL'
-    elif veh_mode == 'SwitchRight':
-        text_pos = 'bottom center'
-        text = 'SR'
-    elif veh_mode == 'Stop':
-        text_pos = 'middle center'
-        text = 'S'
-    else:
-        print(veh_mode)
-        raise ValueError
-    return text_pos, text