Esempio n. 1
0
def generate_symbols_on_trajectory(cfg, Xs, Ys, mindist, nscales):
    # sample symbol location from unit sphere
    i = 0
    denom = 20.0

    coord = np.array([Xs[i], Ys[i]])
    symbols = [spawn_symbol(cfg, coord, mindist/denom, nscales)]

    for i in range(1, len(Xs)):
        coord = np.array([Xs[i], Ys[i]])
        _, dist = utils.get_closest_symbol(symbols, coord)
        if dist >= mindist:
            symbols.append(spawn_symbol(cfg, coord, mindist/denom, nscales))

    return symbols
def main():
    args = parse_args()

    # start and target symbols
    Start = np.array(uv2xyz(-.75 * np.pi, 0.4 * np.pi)).flatten()
    Target = np.array(uv2xyz(+np.pi / 20, 0.4 * np.pi)).flatten()

    # 'agent' for ground truth. simply used as integrator
    agent = Agent3DSphere(speed=0.01, A=Start, B=Target)

    # particle setup
    particles_json_path = 'data/particles.1M.010.json'
    Nsymbols = 5000
    mindist = 0.10
    # output setup
    trajectorysamples_json_path = 'data/trajectorysamples.1M.010.json'

    #particles_json_path = 'data/particles.1M.005.json'
    #Nsymbols = 10000
    #mindist = 0.05

    particles_args = {
        'dist_type': 'euclidean',
        'mindist': mindist,
        'maxdist': 2.0 * 0.1,
        'mindist_rnd_threshold': 0.9,
        'mindist_rnd_chance': 0.1,
        'alpha': 0.1,
        'alpha_decay': 0.9999,
        'mem': 0.9,
    }
    particles = PushPullParticleSystem(**particles_args)
    # load_json will also load the particle state_dict
    particles.load_json(particles_json_path)

    # plot setup
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.set_aspect('equal', 'box')
    ax.set_xlim(-1, 1)
    ax.set_ylim(-1, 1)
    ax.set_zlim(-1, 1)
    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    hide_axes(ax)

    vis_sphere = None
    vis_agent = None
    vis_coord = None
    vis_trace = None
    vis_particles = None
    draw_hidden_aspect_cube(ax)

    print("Computing ground truth geodesic")
    for timestep in range(1000):
        # move around
        agent.move(random_walk=False)
        dist = np.linalg.norm(agent.X - Target)
        if dist <= agent.speed / 2:
            # reached goal, or would overshoot
            break

    # get some random points on the hemisphere
    print("Picking symbols randomly")
    sym_xs, sym_ys, sym_zs = pick_npoints_on_hemisphere(N=Nsymbols)
    if False:
        ax.scatter(sym_xs, sym_ys, sym_zs, color='#7a7a7a', s=0.3)
    symbols = xs2symbols(sym_xs, sym_ys, sym_zs)

    # get indices of start and target symbols
    i_start_sym, _ = utils.get_closest_symbol(symbols, Start)
    i_target_sym, _ = utils.get_closest_symbol(symbols, Target)

    # create transition layer and associate it with all symbols
    print("Generating transition layers")
    layer = modules.TransitionLayer(particles_args['mindist'],
                                    -1.0,
                                    -1.0,
                                    pointgen_fn='particles',
                                    particles=particles)
    layer.associate(symbols, 0)

    # record everything!11
    recorder = utils.Recorder(1)

    # find sequence using the layer. Note that this is not guaranteed to work if
    # there is no viable trajectory...
    print("Searching trajectory...")
    hits = algorithms.find_sequence_on_scale([layer], 0, symbols, i_start_sym,
                                             i_target_sym, recorder)
    print("Trajectory found.")

    # Monte Carlo Sampling: compute M sample trajectories
    print("Monte Carlo Sampling")
    M = 50
    ps = []
    for i in range(M):
        ps.append([])
        p = symbols[i_target_sym]
        ps[i].append(p)
        while not (p == symbols[i_start_sym]):
            p = symbols[p.getRandomParent()]
            ps[i].append(p)

    # compute sample average
    avg_trace = []
    Ns = len(ps[0])
    for n in range(Ns):
        avg = ps[0][n].coord.copy()
        for m in range(1, M):
            avg += ps[m][n].coord
        avg /= np.linalg.norm(avg)
        avg_trace.append(avg)

    # draw calls
    clean_all(ax, vis_sphere, vis_agent, vis_coord, vis_trace)
    if vis_particles is not None:
        ax.collections.remove(vis_particles)

    # draw grid field centers
    vis_particles = draw_particles(ax, particles, color='gray', s=1)
    vis_sphere, _, _, _, _, _ = draw_all(ax,
                                         agent=agent,
                                         A=Start,
                                         B=Target,
                                         plot_trace=True,
                                         plot_agent=False)

    # draw monte carlo samples
    for k in range(M):
        for i in range(1, len(ps[k])):
            s = ps[k][i - 1]
            t = ps[k][i]

            v = t.coord - s.coord
            draw_vector(ax,
                        s.coord,
                        v,
                        color=style.color.sample,
                        lw=0.4,
                        scale=1.0,
                        alpha=0.5)  # style.alpha.sample)

    # draw sample average
    xs = []
    ys = []
    zs = []
    for X in avg_trace:
        xs.append(X[0] * 1.0001)
        ys.append(X[1] * 1.0001)
        zs.append(X[2] * 1.0001)
    ax.plot3D(xs, ys, zs=zs, color='black', linewidth=2.0, linestyle='--')

    # write all samples + symbol locations to file
    d = {
        'M_samples': M,
        'trajectory_length': len(ps[0]),
        'trajectory_data': [],
        'symbol_data': []
    }
    for m in range(M):
        td = []
        for n in range(len(ps[0])):
            td.append([
                float(ps[m][n].coord[0]),
                float(ps[m][n].coord[1]),
                float(ps[m][n].coord[2])
            ])
        d['trajectory_data'].append(td)

    for i in range(len(sym_xs)):
        d['symbol_data'].append(
            [float(sym_xs[i]),
             float(sym_ys[i]),
             float(sym_zs[i])])

    with open(trajectorysamples_json_path, 'w') as f:
        json.dump(d, f, indent=1)

    ax.set_xlabel('X')
    ax.set_ylabel('Y')
    ax.set_zlabel('Z')
    plt.show()
Esempio n. 3
0
def main(args) :
    # get a string for this simulation and generate the directory
    global DEMO_NAME

    # grid periods to use in this demo
    periods = [0.2]
    for i in range(1, args.nscales):
        periods.append(periods[-1] * np.sqrt(2))

    basename = os.path.basename(args.filename)
    dir_str = "{}/{}_{}.d".format(args.output_dir, DEMO_NAME, basename)
    if args.save_figures:
        print("Saving figures to directory {}".format(dir_str))
        if not os.path.exists(dir_str):
            os.mkdir(dir_str)

    # load HDF5
    print("Loading trajectory data from file '{}'".format(args.filename))
    cfg, Xs, Ys = utils.load_trajectory_hdf5(args.filename, verbose=False)

    # generate symbols, and select start and targets
    print("Generating symbols along trajectory.")
    symbols = generate_symbols_on_trajectory(cfg, Xs, Ys, args.mindist, args.nscales)

    global_start, _ = utils.get_closest_symbol(symbols, np.array([Xs[0], Ys[0]]))
    global_target, _ = utils.get_closest_symbol(symbols, np.array([Xs[-1], Ys[-1]]))


    # create transition layers and associate each with all available symbols
    print("Generating transition layers")
    z = 0
    layers = []
    for period in periods:
        print("Generating layer {} of {}".format(z+1, len(periods)))
        layers.append(modules.TransitionLayer(period, cfg.world_radius * 2.0, cfg.world_radius * 2.0, pointgen.hex))

        # this is required due to the circular world, centered at 0.0
        # shift all transitions
        for t in layers[-1].ts:
            t.coord -= cfg.world_radius
        # remove transitions outside of the environment
        ts = []
        for t in layers[-1].ts:
            dist = np.linalg.norm(t.coord)
            if dist <= (cfg.world_radius + 0.1):
                ts.append(t)
        layers[-1].ts = ts
        # compute neighborhood
        layers[-1].compute_neighborhoods()

        print("associating layer {}".format(z))
        layers[-1].associate(symbols, z)
        z += 1


    # plot that only shows the transition centers
    fig, axs = plotter.setup_watermaze(cfg, len(periods), ion=False)
    for scale in range(args.nscales):
        # exploit the symbol plotter here
        plotter.watermaze(axs[scale], cfg, Xs[0], Ys[0], plot_start_target=False)
        plotter.symbols(axs[scale], layers[scale].ts, range(len(layers[scale].ts)))
    if args.save_figures:
        fig.savefig("{}/transition_centers.svg".format(dir_str))
    plt.show()


    # result plotting
    fig, axs = plotter.setup_watermaze(cfg, len(periods), ion=False)

    for ax in axs:
        plotter.watermaze(ax, cfg, Xs[0], Ys[0])
        plotter.symbols(ax, symbols, [])
        plotter.trajectory(ax, Xs, Ys)
        plotter.start_target(ax, symbols, [global_start], [global_target])


    print("Running algorithm for each layer individually.")
    recorder = utils.Recorder(args.nscales)
    for scale in range(args.nscales):

        # reset the symbols for this scale
        for s in symbols:
            s.reset()

        #
        # Algorithm: expansion only, then backtracking during sample computation
        #
        hits = find_sequence_on_scale(layers, scale, symbols, global_start, global_target, args, recorder)
        print("Scale {}: Trajectory found.".format(scale))

        ts = []

        # Algorithm: compute M sample trajectories
        for i in range(args.M):
            # backtracking ala Dijkstra
            p = symbols[global_target]
            ts.append(layers[scale].ts[p.t[scale]])

            s = symbols[global_target]
            # TODO: is the following line required? I think not
            ts.append(layers[scale].ts[s.t[scale]])

            while not (s == symbols[global_start]):
                rnd_p = p.getRandomParent()

                p = symbols[rnd_p]

                ts.append(layers[scale].ts[p.t[scale]])
                plotter.sample_segment(axs[scale], s, p)

                s = p
                ts.append(layers[scale].ts[s.t[scale]])

        ts = list(set(ts))
        cols = utils.Config()
        cols.transition = 'gray'
        for t in ts:
            plotter.transition_domain(axs[scale], t, periods[scale])

        axs[scale].axis('off')

    if args.save_figures:
        fig.savefig("{}/results.svg".format(dir_str))
    plt.show()
def simulate_linear_track(symbols,
                          grid_period,
                          W,
                          H,
                          output_dir,
                          live_plot=False):
    """Simulate a linear track, on which the goal is to go from start to finish"""

    # color configuration
    colors = utils.Config()

    colors.symbol_hit = 'black'
    colors.symbol_hit_alpha = 0.6
    colors.symbol_miss = 'grey'
    colors.symbol_miss_alpha = 0.4

    colors.transition_hit = '#2882cd'
    colors.transition_hit_alpha = 0.6
    colors.transition_miss = 'grey'
    colors.transition_miss_alpha = 0.4

    # create transition layer and associate it with all available symbols
    layer = modules.TransitionLayer(grid_period, W, H, pointgen.flat)
    layer.associate(symbols)

    # select some random symbol and activate it as well as all others in the area
    current_symbols = layer.getClosestTransition(np.array((0, 0))).domain

    # select the rightmost symbols as final target location
    target_symbol, _ = utils.get_closest_symbol(symbols, np.array([W, 0.0]))

    # visualization setup
    fig = plt.figure(figsize=(20, 3))
    gs = gspec.GridSpec(1, 1)
    gs.update(left=0.05,
              right=0.95,
              top=0.95,
              bottom=0.05,
              wspace=0.025,
              hspace=0.05)
    ax = plt.subplot(gs[0])

    if live_plot:
        plt.ion()
        plt.show()

    # pure retrieval to target
    ticks = 0
    while not target_symbol in current_symbols:
        ax.clear()

        # update 'retrieval tick' -> this emulates refractory periods of place
        # cells, which this model predicts are significantly different than grid
        # cell refractory periods
        for s in current_symbols:
            symbols[s].retrieval_tick = ticks

        # plot all transitions for which the precondition is met
        ts = layer.getDefinedTransitions(current_symbols)
        layer.plot_with_highlight(ax,
                                  symbols,
                                  highlighted=ts,
                                  color=colors.transition_miss,
                                  color_highlight=colors.transition_hit,
                                  marker='o',
                                  markersize=10)

        # replot all symbols. currently active symbols will get a different color
        for i in range(len(symbols)):
            if i in current_symbols:
                ax.plot(symbols[i].coord[0],
                        symbols[i].coord[1],
                        '.',
                        color=colors.symbol_hit,
                        alpha=colors.symbol_hit_alpha)
            else:
                ax.plot(symbols[i].coord[0],
                        symbols[i].coord[1],
                        '.',
                        color=colors.symbol_miss,
                        alpha=colors.symbol_miss_alpha)

        # predict next batch of symbols, and remove currently active ones
        next_symbols = layer.expand(current_symbols, symbols, ticks)
        current_symbols = [
            s for s in next_symbols
            if s not in current_symbols and symbols[s].retrieval_tick < 0
        ]

        ax.set_xlim([-0.15, W + .15])
        ax.set_ylim([-0.1, 0.1])
        ax.set_aspect('equal')

        # drawing
        plt.title("tick %i" % (ticks))
        plt.draw()
        if live_plot:
            plt.pause(0.1)
        fig.savefig("{}/{:03}.svg".format(output_dir, ticks))

        # update tick counter
        ticks += 1

    # draw final state
    ax.clear()
    ts = layer.getDefinedTransitions(current_symbols)
    layer.plot_with_highlight(ax,
                              symbols,
                              highlighted=ts,
                              color=colors.transition_miss,
                              color_highlight=colors.transition_hit,
                              marker='o',
                              markersize=10)

    # replot all symbols. currently active symbols will get a different color
    for i in range(len(symbols)):
        if i in current_symbols:
            ax.plot(symbols[i].coord[0],
                    symbols[i].coord[1],
                    '.',
                    color=colors.symbol_hit,
                    alpha=colors.symbol_hit_alpha)
        else:
            ax.plot(symbols[i].coord[0],
                    symbols[i].coord[1],
                    '.',
                    color=colors.symbol_miss,
                    alpha=colors.symbol_miss_alpha)

    ax.set_xlim([-0.15, W + .15])
    ax.set_ylim([-0.1, 0.1])
    ax.set_aspect('equal')
    plt.title("tick %i" % (ticks))
    plt.draw()
    if live_plot:
        plt.pause(0.1)
    fig.savefig("{}/{:03}.svg".format(output_dir, ticks))
    if live_plot:
        plt.ioff()
        plt.show()

    return ticks
Esempio n. 5
0
def main(args):
    # get a string for this simulation and generate the directory
    global DEMO_NAME

    dir_str = "{}/{}_{}.d".format(args.output_dir, DEMO_NAME, args.pointgen)
    if args.save_figures:
        print("Saving figures to directory {}".format(dir_str))
        if not os.path.exists(dir_str):
            os.mkdir(dir_str)

    # grid periods to use in this demo
    periods = [0.2]
    for i in range(1, args.nscales):
        periods.append(periods[-1] * np.sqrt(2))

    # generate symbols
    print("Generating symbols.")
    nscales = len(periods)
    mindist = periods[0] / 4
    if args.pointgen == 'hammersley':
        symbols = utils.gen_symbols(args.W, args.H, args.N, nscales=nscales)
    else:
        symbols = utils.gen_symbols(args.W,
                                    args.H,
                                    N=args.N,
                                    nscales=nscales,
                                    method='rmind1',
                                    mindist=mindist)

    # create transition layers and associate each with all available symbols
    print("Generating transition layers")
    z = 0
    layers = []
    for period in periods:
        print("Generating layer {} of {}".format(z + 1, len(periods)))
        layers.append(
            modules.TransitionLayer(period, args.W, args.H, pointgen.hex))
        layers[-1].associate(symbols, len(layers) - 1)
        z += 1

    # select desired start and target symbols
    global_start, _ = utils.get_closest_symbol(
        symbols, np.array([args.startX, args.startY]))
    global_target, _ = utils.get_closest_symbol(
        symbols, np.array([args.targetX, args.targetY]))

    ##
    ## Algorithm start #################################################################
    ##
    print("Running algorithm.")
    recorder = utils.Recorder(nscales)
    find_sequence(layers, periods, symbols, global_start, global_target, args,
                  recorder)
    print("Done.")
    ##
    ##  Algorithm end ##################################################################
    ##

    # plot that only shows the transition centers
    fig, axs = plotter.setup(args, len(periods), ion=False)
    for scale in range(args.nscales):
        # exploit the symbol plotter here
        plotter.rectangular_scene(axs[scale], args.W, args.H)
        plotter.symbols(axs[scale], layers[scale].ts,
                        range(len(layers[scale].ts)))
    plt.draw()
    if args.save_figures:
        fig.savefig("{}/transition_centers.svg".format(dir_str))
    plt.show()

    # plotting
    fig, axs = plotter.setup(args, len(periods), ion=False)

    for ax in axs:
        plotter.rectangular_scene(ax, args.W, args.H)
        plotter.symbols(ax, symbols, [])

        # global start and target
        plotter.start_target(ax, symbols, [global_start], [global_target])

    scale = nscales - 1
    while scale >= 0:

        # select axes to plot to
        ax = axs[nscales - scale - 1]

        # subgoals
        plotter.subgoals(ax, symbols, recorder.searches[scale][-1].targets)

        ts = []
        for b in recorder.backtracks[scale]:
            # symbol's associated transition
            for s in b.ss:
                t = utils.get_transition_obj(layers, symbols, scale, s)
                ts.append(t)
        ts = list(set(ts))

        for t in ts:
            plotter.transition_domain(ax, t, periods[scale])

        # plot initial transition area
        ts = []
        b = recorder.backtracks[scale][-1]
        for s in b.ps:
            t = utils.get_transition_obj(layers, symbols, scale, s)
            ts.append(t)
        ts = list(set(ts))
        for t in ts:
            # tmp_colors = utils.Config()
            # tmp_colors.transition = 'green'
            plotter.transition_domain(ax, t, periods[scale])

        scale -= 1

    plt.draw()
    if args.save_figures:
        fig.savefig("{}/results.svg".format(dir_str))
    plt.show()
Esempio n. 6
0
def main(args):
    # get a string for this simulation and generate the directory
    global DEMO_NAME

    # grid periods to use in this demo
    periods = [0.2]
    for i in range(1, args.nscales):
        periods.append(periods[-1] * np.sqrt(2))

    dir_str = "{}/{}_{}.d".format(args.output_dir, DEMO_NAME, args.pointgen)
    if args.save_figures:
        print("Saving figures to directory {}".format(dir_str))
        if not os.path.exists(dir_str):
            os.mkdir(dir_str)

    # generate symbols
    print("Generating symbols.")
    nscales = len(periods)
    mindist = periods[0] / 4
    if args.pointgen == 'hammersley':
        symbols = utils.gen_symbols(args.W, args.H, args.N, nscales=nscales)
    else:
        symbols = utils.gen_symbols(args.W,
                                    args.H,
                                    N=args.N,
                                    nscales=nscales,
                                    method='rmind1',
                                    mindist=mindist)

    # create transition layers and associate each with all available symbols
    print("Generating transition layers")
    z = 0
    layers = []
    for period in periods:
        print("Generating layer {} of {}".format(z + 1, len(periods)))
        layers.append(
            modules.TransitionLayer(period, args.W, args.H, pointgen.hex))
        layers[-1].associate(symbols, len(layers) - 1)
        z += 1

    # select desired start and target symbols
    global_start, _ = utils.get_closest_symbol(
        symbols, np.array([args.startX, args.startY]))
    global_target, _ = utils.get_closest_symbol(
        symbols, np.array([args.targetX, args.targetY]))

    ##
    ## Algorithm start #################################################################
    ##
    print("Running algorithm.")
    recorder = utils.Recorder(nscales)
    find_sequence(layers, periods, symbols, global_start, global_target, args,
                  recorder)
    print("Done.")
    ##
    ##  Algorithm end ##################################################################
    ##

    # plot that only shows the transition centers
    fig, axs = plotter.setup(args, len(periods), ion=False)
    for scale in range(args.nscales):
        # exploit the symbol plotter here
        plotter.rectangular_scene(axs[scale], args.W, args.H)
        plotter.symbols(axs[scale], layers[scale].ts,
                        range(len(layers[scale].ts)))
    plt.draw()
    if args.save_figures:
        fig.savefig("{}/transition_centers.svg".format(dir_str))
    plt.show()

    # plotting results
    fig, axs = plotter.setup(args, len(periods), ion=False)

    for ax in axs:
        plotter.rectangular_scene(ax, args.W, args.H)
        plotter.symbols(ax, symbols, range(len(symbols)))

        # global start and target
        plotter.start_target(ax, symbols, [global_start], [global_target])

    scale = nscales - 1
    while scale >= 0:
        col_tmp = utils.Config()
        col_tmp.active = 'red'

        ts = []
        for e in recorder.expansions[scale]:
            plotter.symbols(axs[scale],
                            symbols,
                            e.active_symbols,
                            only_active=False)
            for s in e.active_symbols:
                ts.append(layers[scale].ts[symbols[s].t[scale]])

        ts = list(set(ts))
        for t in ts:
            plotter.transition_domain(axs[scale], t, periods[scale])

        scale -= 1

    # find a few samples
    # MonteCarloSamples = [list() for n in range(nscales)]
    print("Monte Carlo sampling.")
    for i in range(args.M):
        # backtracking ala Dijkstra
        p = symbols[global_target]
        s = symbols[global_target]

        while not (s == symbols[global_start]):
            p = symbols[p.getRandomParent()]
            plotter.sample_segment(axs[-1], s, p)
            s = p

    plt.draw()
    if args.save_figures:
        fig.savefig("{}/results.svg".format(dir_str))
    plt.show()
def main(args):
    global DEMO_NAME

    # get a string for this simulation and generate the directory
    dir_str = "{}/{}_{}_{:4.2f}.d".format(args.output_dir, DEMO_NAME,
                                          args.pointgen, args.period)
    if args.save_figures:
        print("Saving figures to directory {}".format(dir_str))
        if not os.path.exists(dir_str):
            os.mkdir(dir_str)

    # generate symbols
    print("Generating symbols.")
    mindist = 0.02
    if args.pointgen == 'hammersley':
        symbols = utils.gen_symbols(args.W, args.H, args.N)
    else:
        symbols = utils.gen_symbols(args.W,
                                    args.H,
                                    N=args.N,
                                    method='rmind1',
                                    mindist=mindist)

    # create transition layer and associate it with all available symbols
    print("Creating layer.")
    layers = []
    layers.append(
        modules.TransitionLayer(args.period, args.W, args.H, pointgen.hex))
    layers[0].associate(symbols)

    # select some random symbols
    start, _ = utils.get_closest_symbol(symbols,
                                        np.array([args.startX, args.startY]))
    target, _ = utils.get_closest_symbol(
        symbols, np.array([args.targetX, args.targetY]))

    # initialize the symbols
    current_symbols = [start]

    # plotting setup
    fig, ax = plotter.setup(args, 1, figsize=(4, 4))
    ax = ax[0]
    ax.axis('off')

    # pure retrieval to target
    target_found = False
    tick = 0
    print("Running algorithm.")
    while tick <= args.maxticks:
        ax.clear()
        ax.axis('off')

        # update 'retrieval tick' -> this emulates refractory periods of place
        # cells. This comes from marking symbols as "expanded"
        for s in current_symbols:
            symbols[s].retrieval_tick = tick

        # plotting
        plotter.everything(args, ax, symbols, current_symbols, start, target)
        if args.save_figures:
            fig.savefig("{}/{:03}.svg".format(dir_str, tick))

        # predict next batch of symbols, and remove currently active ones
        next_symbols = layers[0].expand(current_symbols, symbols, tick)
        current_symbols = [
            s for s in next_symbols
            if s not in current_symbols and symbols[s].retrieval_tick < 0
        ]

        # update time
        tick += 1

        # check to see if we reached the destination
        target_found = target in current_symbols
        if target_found:
            break

    print("Done.")
    if not target_found:
        print("EE: Target not found")

    plotter.everything(args, ax, symbols, current_symbols, start, target)
    plt.draw()

    if target_found:
        print("Generating Monte Carlo samples")
        # get some monte carlo samples
        for i in range(args.M):
            # backtracking ala Dijkstra
            p = symbols[target]
            s = symbols[target]

            while not (s == symbols[start]):
                p = symbols[p.getRandomParent()]
                plotter.sample_segment(ax, s, p)
                s = p

        # plot the transition regions using a backtracking sample ala Dijkstra
        ts = []
        p = symbols[target]
        s = symbols[target]
        ts.append(layers[0].ts[p.t[0]])
        while not (s == symbols[start]):
            p = symbols[p.getRandomParent()]
            ts.append(layers[0].ts[p.t[0]])
            s = p

        for t in ts:
            plotter.transition_domain(ax, t, args.period)

    plt.ioff()
    if args.save_figures:
        fig.savefig("{}/{:03}.svg".format(dir_str, tick))
    plt.show()