Priante/boids_algorithm_app
0
1#!/usr/bin/env python32# -*- coding: utf-8 -*-3"""4Created on Sun Aug 28 11:14:47 20225 6@author: francesca7http://www.vergenet.net/~conrad/boids/pseudocode.html8https://www.youtube.com/watch?v=XiYnZ6Dy4v89https://www.youtube.com/watch?v=VZ_tS4F6P2A10"""11 12# import random13# import matplotlib14import streamlit as st15import time16import numpy as np17from streamlit.hello.utils import show_code18 19from functions import move20 21 22 23def animation_demo():24 # %%25 L = 45026 tsteps = 50027 V0 = 20 # Initial velocity28 29 wall_repulsion = V0 # https://vanhunteradams.com/Pico/Animal_Movement/Boids-algorithm.html#Screen-edges30 # should be similar to max speed, otherwise they escape31 margin = 4032 max_speed = V033 34 # %%35 n = st.sidebar.slider("Number of birds", min_value= 2, max_value = 1000, value = 300, step =2)36 37 38 # Rule 139 # velocity to center contribution40 R = st.sidebar.slider("1. COHESION", 41 min_value=0., max_value=2., step = 0.05, value = 0.1)42 43 # Rule 244 bird_repulsion = st.sidebar.slider("2. SEPARATION", 45 min_value=0., max_value=10., step = 1., value = 7.) 46 # Rule 347 match_velocity = st.sidebar.slider("3. ALIGNMENT", 48 min_value=0., max_value=10., step = 0.5, value = 3.) 49 50 51 # Community distance (~ community size)52 neighbors_dist = st.sidebar.slider("Community distance i.e. distance of influence between birds (From spread to packed). Applied to rule 1 and rule 3)",53 min_value = 10, max_value=200, value = 70)54 55 privacy = st.sidebar.slider("Bird privacy (distance at which we apply rule 2)", 56 min_value=0, max_value=30, step = 1, value = 14)57 # low values make more "stains" of birds, nice visualization58 # When they see each other at this distance, 59 # they apply bird repulsion in the other direction60 61 progress_bar = st.sidebar.progress(0)62 63 frame_text = st.sidebar.empty()64 image = st.empty()65 66 67 68 69 70 # %% INITIALIZE71 x = np.zeros((n,tsteps))72 y = np.zeros((n,tsteps))73 74 x[:,0] = np.random.uniform(low=-L, high=L, size=(int(n),))75 y[:,0] = np.random.uniform(low=-L, high=L, size=(int(n),))76 77 x[:,1] = x[:,0] + np.random.uniform(low=-V0, high=V0, size=(int(n),))78 y[:,1] = y[:,0] + np.random.uniform(low=-V0, high=V0, size=(int(n),))79 80 81 y = y.astype(int)82 x = x.astype(int)83 84 # %% MOVE85 # ANIM = np.zeros((tsteps, L*2+margin, L*2+margin))86 N = np.zeros((L*2+margin, L*2+margin))87 last_col = np.shape(N)[0]-188 for t in range(1,tsteps-1):89 x[:, t+1],y[:, t+1] = move(x[:, t],y[:, t], x[:,t-1],y[:,t-1],90 n, neighbors_dist, R, privacy, bird_repulsion, match_velocity, L, margin, wall_repulsion, max_speed)91 92 y = y.astype(int)93 x = x.astype(int)94 N = np.zeros((L*2+margin, L*2+margin))95 # N[y[:,t]+L+10, x[:,t]+L+10] = 096 N[y[:,t+1]+L+round(margin/2), x[:,t+1]+L+round(margin/2)] = 197 98 99 # Increase the size of the points100 to_plot = N101 to_plot[1:last_col,:] = N[1:last_col,:] + N[0:(last_col-1),:] # right shift of the matrix102 to_plot[:,1:last_col] = N[:,1:last_col] + N[:,0:(last_col-1)] # upper shift of the matrix103 to_plot[0:(last_col-1),:] = N[0:(last_col-1),:] + to_plot[1:last_col,:] # left shift of the matrix104 to_plot[:,0:(last_col-1)] = N[:,0:(last_col-1)] + to_plot[:,1:last_col] # bottom shift of the matrix105 to_plot = np.ceil(to_plot/np.amax(to_plot))106 107 # matplotlib.use("agg") # https://discuss.streamlit.io/t/mediafilemanager-missing-file-when-try-to-plot-two-line-chart-o-the-same-figure/5735/8108 # _lock = RendererAgg.lock109 # with _lock:110 111 # ANIM[t] = to_plot112 image.image(to_plot, use_column_width=True)113 time.sleep(0.05)114 115 # for t in range(1,tsteps-1):116 # image.image(ANIM[t], use_column_width=True)117 # time.sleep(0.05)118 119 # We clear elements by calling empty on them.120 progress_bar.empty()121 frame_text.empty()122 123 # Streamlit widgets automatically run the script from top to bottom. Since124 # this button is not connected to any other logic, it just causes a plain125 # rerun.126 st.button("Re-run")127 128 129st.set_page_config(page_title="Flocks", page_icon="🐤") # 📹130st.markdown("# Flock Animation")131st.sidebar.header("Parameters")132st.markdown(133 """The animation shows a simulation of a flock of birds. 134Flocks of birds follows three rules simulataneously:1351. __Cohesion__ rule: a bird flies towards the center of mass of the nearest neighbors.136 1372. __Separation__ rule: a bird tries to avoid collisions with other birds.138 1393. __Alignment__ rule: a bird tries to match velocity with near birds.140 141You can change the intensity of these rules moving the sliders in the lateral bar.142 143More details in my github page [https://frapria.github.io/blog/flocks](https://frapria.github.io/blog/flocks)144"""145)146 147animation_demo()148 149 150show_code(animation_demo)