Zeyi Jiang
Data Mining the City
12 min readDec 10, 2018

--

Simulation & Visualization of Birds Migration

— — An algorithm providing guidelines for habitats protection

simulation of birds migration 1
simulation of birds migration 2
  • · Team: Jianqi Li(jl5212), Junyu Cao(jc5040),Zeyi Jiang(zj2243)
  • · Conference: SIMULTECH 2019
  • · Paper Submission Requirement: http://www.simultech.org/Guidelines.aspx
  • It is recommended that Regular Papers are submitted for review with around 8 to 10 pages, with the appropriate font size and page format, including references, tables, graphs, images and appendices. Submissions with less than 4 pages or more than 13 pages will be automatically rejected. Each paper should clearly indicate the nature of its technical/scientific contribution, and the problems, domains or environments to which it is applicable.

Simulation & Visualization of Birds Migration

— — An algorithm providing guidelines for habitats protection

1. Background Introduction

The sustainability of ecosystem and biodiversity is essential to both human’s life and our planet. Birds’ migration is one of important part of our ecosystem. However, because of recent urban sprawl, the birds’ migration are threatened a lot by habitat fragmentation, human activities, decline of food resources. In-between habitats should be protected and proposed for migrating birds to rest on and find food. Basically, we want to utilize the simulation model to simulate the migratory pathways and living environment of birds and find the reference for urban design and natural environmental protection.

2. Thesis

We chose the Arctic Tern as our research object. By simulating the migration path of Arctic terns, we can test the importance of several factors affecting bird migration, including habitat size and access, food resources and the maximum distance they can fly at once. Based on that we can find the best path for birds and create a guideline of how to protect existing habitats and which should be protected urgently at first.

3. Research of migration birds

— key aspects that influence their behaviors

Arctic tern is species which is strongly migratory, seeing two summers each year as it migrates along a convoluted route from its northern breeding grounds to the Antarctic coast for the southern summer and back again about six months later, which is the longest migration route among known animals.

The food of Arctic terns varies by region and time, but they are usually carnivorous. Fish play a very important role in their food. On their migration path, they need water to find food to replenish energy. Basically, the scale of habitats influence their migration route because larger habitat can provide more water and food resources to replenish their energy.

In addition to food, wind power is also an important factor affecting their migration. In order to conserve the wind and save energy, the Arctic terns of generations will choose a very tortuous migration route, which makes them fly twice a year more than the straight distance between north and south poles.

4. Programming model

We assume that each bird consume energy when flying, there are several parameters that can influence the energy consumption, such as the airflow, food resource and vegetation types. We take size of in-between habitats, flying distance into consideration this time.

We also assume that the birds will make clever choice based on their total energy consumption from start point to end point, so the outcome of visualization will show the most probable area of bird migration, which can be a reference for natural environmental protection and boundaries of urban development.

parameters of programming model

A. Individuals:

migration birds, habitats

B. Parameters:

Location of habitats; size of habitat (related to amount of food resources and water , which can supplement bird’s energy); flying distance between two habitats of migrating bird; flying direction (related to the location of habitats)

C. High dimensional parameters:

Establish a negative correlation function between energy consumption and possibility of each flying route. So the visualization of migration can show the most popular route and habitats.

D. Input:

The starting and ending point of migration bird. The location and the size of habitats.

E. Output:

the birds’ migration simulation

5. Logic of algorithm

Basically, our model chooses better migration paths by calculating and comparing the energy loss of migratory birds during different migration paths. When birds are migrating, they will lose energy based on the distance of their flight. And when they arrived at a habitat, they will supplement energy based on the scale of that habitat. So, when calculating their consumption and supplement of energy during each migration path, we can find out which path has the least energy consumption, which will be the best path for birds.

A. Establish habitats and connect different habitats

B. Filter out the paths connecting habitats which are too long and select all the others feasible paths.

C. Energy consumption rules

The energy consumed per unit of flight distance is constant. At the same time, birds can replenish energy while they reach their habitat. So the equation of energy consumption is:

Energy = int (distance*j-habitat _energy)

The energy comsumption of each path = Energy loss based on the distance of flight between habitats + Energy supplement based on the scale of habitats which birds arrive at.

D. Calculate the energy consumption

Calculate the energy consumption of all possible paths from the start point to the end point by algorithm.

E. Get birds density of each routes

Get the number of birds flying on each route through an inverse ratio equation:

birdsamount= int(birdsamountfactor/energy)

The birds amount of each route= a predetermined parameter/ energy consumption of each route.

For example, in the case of sample 1, we calculate all the energy consumption through all the routes birds migrate to get a total consumption, which is -38. Then we calculate all the energy supplement from the habitats they pass by, which will be +10. Then the total energy loss is -28. Based on the same reason, we can calculate the other three samples.

Weight the number of birds appearing on different paths according to the inverse ratio of the energy consumption value, and get the probability of birds flying on each path. Assume that birdsamountfactor=3000, so:

Birdsamount1= int(3000/28)=107

Birdsamount2= int(3000/22)=136

Birdsamount3= int(3000/20)=150

Birdsamount4= int(3000/31)=97

6. Interaction and visualization

In our simulation model, we also want to have the interaction with users. Users can add some spots of habitats of different scale based on different site contexts. Through our simulation model, users can find the best migration route of birds according to the habitats they put in and find the best intervention spot which has the biggest impact to the whole migration network.

Interactive process:

1. Import map and set the starting point and destination.

2. Place habitats which you can define as large habitat, medium habitat and small habitat according to its range. (Different levels of habitat represent for different level of energy supplement)

3. Birds begin to migrate, each bird’s energy will reduce during its flight, different amount of birds will show up in each route based on its energy loss. The route with less energy loss will show up more birds.

4. Based on the consumption and supplement of the energy, birds finally reach the destination. When birds reach to destination, they will restart from the start point again. So there would be countless birds flying on route, which could illustrate clearly that which route and habitats is more popular and need to be protected.

7. Contribution of our model

Our simulation model can help people find out the guidelines for protecting birds’ migration habitat, which we think have meanings from three aspects: urban design practice, educational significance for society and ecosystem.

For urban design practice, we can apply our projects to an exact rural-urban area. Through learning from the most beneficial routes for birds migration, we can define the boundary of ecological safety area and urban develop boundary for reserving essential habitats for birds migrating. And we can also acknowledge the weight of key elements that impact the birds migration. Most importantly, we can find the most probable route for birds’ migration to avoid the influence of urban development to natural environment as well as guide our urban design.

For society, through the process of interaction, people will realize the significance of protecting bird habitats for the harmonious development of human and nature. This also have an educational function for children’s awareness of bird’s habitats’ importance.

For ecosystem, by finding the most likely place for birds to survive. we can establish protected area to provide habitats for birds. Birds are also important pollinators of nature, by protecting birds, more species including trees and plants will be saved to increase the biodiversity of our ecosystem.

8. Conclusion

Through the coding and visualization of bird migration, we find out several surprising outcome and summarized some unexpected experience.

The first thing is that we can use some easy equation to replace some complex relationship when we translate our logic of project to code. For example, when we want to express the negative relationship between possibility and energy consumption of each routes, we first try to use the equation:

The Ex means the expectation(possibility) of one bird flying in one route.

When we want to use code to solute this equation, we find it is difficult because it is a multiple equations, which need a tool not existed in processing. So we try to use another easy equation to figure out this relationship:

birdsamountroute= birdsamountfactor/ |△Eroute|

so we keep the negative relationship between possibility of each routes and energy consumption, and we get rid of the problem of solving a multiple equation.

The second thing is that we find out that most of time there are not only one best route but several similar good solutions. More obvious is that some habitats are passed through by huge amount of birds. So maybe we can acknowledge more information about which habitat are more important on the process of bird migration. Based on this we can strategically choose the most valuable habitats to protect for resilience of urban development.

9. References

[1] Kurt D. Reed. Birds, Migration and Emerging Zoonoses: West Nile Virus, Lyme Disease, Influenza A and Enteropathogens. Clin Med Res, January 1, no. 1(2003): 5–12

[2] Carsten Egevang, Iain J. Stenhouse, Richard A. Phillips, Aevar Petersen, James W. Fox, and Janet R. D. Silk. Tracking of Arctic terns Sterna paradisaea reveals longest animal migration. PNAS, February 2, no. 107(2010): 2078–2081

[3] Thomas Alerstam, Anders Hedenström, Susanne Åkesson. Long‐distance migration: evolution and determinants. OIKOS, October 17, no. 103(2003): 247–260

Code:

final_birds_simulation

from habitat import Habitat
from startend import Startend
from calculation import Calculation
from visualizationlink import Visualizationlink
from mover import Mover
def setup():
global a,hcolour,simulate,smallhabitat,mediumhabitat,largehabitat,startpoint,endpoint,clearhabitat,endpoint,\
init_smallbx,init_smallby,init_mediumbx,init_mediumby,\
init_largebx,init_largeby,init_stbx,init_stby,init_endbx,init_endby,clearbx,clearby,\
ssize,msize,lsize, st_size,startcolour,starttext,endtext,largehabitatpoint,lenergy,senergy,menergy,\
simulatebx,simulateby,maxdist,swich,bg

bg = loadImage("map.png")

rectMode(RADIUS)
size(1600, 900)
swich = False
maxdist=600

hcolour=255
#small habitat button setup
ssize=7
init_smallbx = width / 20
init_smallby = height / 10
smallhabitat=[Habitat(init_smallbx, init_smallby,ssize,hcolour)]
senergy=50

#medium habitat button setup
msize=12
init_mediumbx = width / 20
init_mediumby = height / 6
mediumhabitat=[Habitat(init_mediumbx, init_mediumby,msize,hcolour)]
menergy=200

#large habitat button setup
lsize=16
init_largebx = width / 20
init_largeby = height / 4
largehabitat=[Habitat(init_largebx, init_largeby,lsize,hcolour)]
largehabitatpoint=[]
lenergy=100

#startpoint button setup
startcolour = 255
st_size=12
init_stbx = width / 20
init_stby = height/3
starttext = "S"
startpoint = [Startend(init_stbx,init_stby,st_size,startcolour,starttext)]

#endpoint button setup

init_endbx = width / 20
init_endby = height/2.5
endtext = "E"
endpoint = [Startend(init_endbx,init_endby,st_size,startcolour,endtext)]


#clear habitat button setup
clearcolour= 0
clearsize=16
clearbx = width / 20
clearby = height / 1.8
clearhabitat=Habitat(clearbx, clearby,clearsize,clearcolour)



#simulate button
simulatecolour= 0
simulatesize=25
simulatebx = width / 20
simulateby = height / 1.5
simulate=Habitat(simulatebx, simulateby,simulatesize,simulatecolour)
def mousePressed():
global a,hcolour,simulate,smallhabitat,mediumhabitat,largehabitat,startpoint,endpoint,clearhabitat,endpoint,\
init_smallbx,init_smallby,init_mediumbx,init_mediumby,\
init_largebx,init_largeby,init_stbx,init_stby,init_endbx,init_endby,clearbx,clearby,\
ssize,msize,lsize, st_size,startcolour,starttext,endtext,largehabitatpoint,lenergy,senergy,menergy,\
simulatebx,simulateby,maxdist,link,swich,tmpbird

#smallhabitat button click
for i in smallhabitat:
i.mousePressed()
if init_smallbx - i.boxSize < mouseX < init_smallbx + i.boxSize and \
init_smallby - i.boxSize < mouseY < init_smallby + i.boxSize:
tmp = []
tmp.append(Habitat(i.bx, i.by,ssize,hcolour))
smallhabitat += tmp
#mediumhabitat button click
for i in mediumhabitat:
i.mousePressed()
if init_mediumbx - i.boxSize < mouseX < init_mediumbx + i.boxSize and \
init_mediumby - i.boxSize < mouseY < init_mediumby + i.boxSize:
tmp = []
tmp.append(Habitat(i.bx, i.by,msize,hcolour))
mediumhabitat += tmp
#largehabitat button click
for i in largehabitat:
i.mousePressed()
if init_largebx - i.boxSize < mouseX < init_largebx + i.boxSize and \
init_largeby - i.boxSize < mouseY < init_largeby + i.boxSize:
tmp = []
tmp.append(Habitat(i.bx, i.by,lsize,hcolour))
largehabitat += tmp
#startpoint button click
for i in startpoint:
i.mousePressed()
if len(startpoint)<>2:
if init_stbx - i.boxSize < mouseX < init_stbx + i.boxSize and \
init_stby - i.boxSize < mouseY < init_stby + i.boxSize:
tmp = []
tmp.append(Startend(i.bx, i.by,st_size,startcolour,starttext))
startpoint += tmp
#endpoint button click
for i in endpoint:
i.mousePressed()
if len(endpoint)<>2:
if init_endbx - i.boxSize < mouseX < init_endbx + i.boxSize and \
init_endby - i.boxSize < mouseY < init_endby + i.boxSize:
tmp = []
tmp.append(Startend(i.bx, i.by,st_size,startcolour,endtext))
endpoint += tmp
#clear button click
if clearbx - clearhabitat.boxSize < mouseX < clearbx + clearhabitat.boxSize and \
clearby - clearhabitat.boxSize < mouseY < clearby + clearhabitat.boxSize:
smallhabitat=[Habitat(init_smallbx, init_smallby,ssize,hcolour)]
mediumhabitat=[Habitat(init_mediumbx, init_mediumby,msize,hcolour)]
largehabitat=[Habitat(init_largebx, init_largeby,lsize,hcolour)]
startpoint = [Startend(init_stbx,init_stby,st_size,startcolour,starttext)]
endpoint = [Startend(init_endbx,init_endby,st_size,startcolour,endtext)]
swich= False


#simlate button click
if simulatebx - simulate.boxSize < mouseX < simulatebx + simulate.boxSize and \
simulateby - simulate.boxSize < mouseY < simulateby + simulate.boxSize:
swich = True

habitatpoint=set()
energydict={}
energydict.clear()

#generate the haitatpoint:((LoactionX1,LocationY1),(LoactionX2,LocationY2)....))
# and energydic:{(LoactionX1,LocationY1):energy,.....},energy is the energy each haitatpoint that can supply to the bird
for n in range(len(largehabitat)):
habitatpoint.add((largehabitat[n].bx,largehabitat[n].by))
energydict[(largehabitat[n].bx,largehabitat[n].by)]= lenergy

if (init_largebx,init_largeby) in habitatpoint:
habitatpoint.remove((init_largebx,init_largeby))

for n in range(len(mediumhabitat)):
habitatpoint.add((mediumhabitat[n].bx,mediumhabitat[n].by))
energydict[(mediumhabitat[n].bx,mediumhabitat[n].by)]= menergy

if (init_mediumbx,init_mediumby) in habitatpoint:
habitatpoint.remove((init_mediumbx,init_mediumby))

for n in range(len(smallhabitat)):
habitatpoint.add((smallhabitat[n].bx,smallhabitat[n].by))
energydict[(smallhabitat[n].bx,smallhabitat[n].by)]= senergy

if (init_smallbx,init_smallby) in habitatpoint:
habitatpoint.remove((init_smallbx,init_smallby))

if len(startpoint)==2:
habitatpoint.add((startpoint[0].bx,startpoint[0].by))
energydict[(startpoint[0].bx,startpoint[0].by)]= 0

if len(endpoint)==2:
habitatpoint.add((endpoint[0].bx,endpoint[0].by))
energydict[(endpoint[0].bx,endpoint[0].by)]= 0

#imput habitatpoint and energydict to calculation
tempcal=Calculation((startpoint[0].bx,startpoint[0].by),(endpoint[0].bx,endpoint[0].by),habitatpoint,energydict,maxdist)

#possible routes visualization
link = Visualizationlink(maxdist,habitatpoint)

#bird visualization
birdsamountfactor=3000
tmpbird=[]
for energy in tempcal.route_energy_use:
birdsamount= int(birdsamountfactor/energy)
for i in range(birdsamount):
tmpbird.append(Mover(tempcal.route_energydict_use[energy],2+0.1*i,0.4))






def draw():
global a,hcolour,simulate,smallhabitat,mediumhabitat,largehabitat,startpoint,endpoint,clearhabitat,endpoint,\
init_smallbx,init_smallby,init_mediumbx,init_mediumby,\
init_largebx,init_largeby,init_stbx,init_stby,init_endbx,init_endby,clearbx,clearby,\
ssize,msize,lsize, st_size,startcolour,starttext,endtext,largehabitatpoint,lenergy,senergy,menergy,\
simulatebx,simulateby,link,swich,tmpbird,bg
background(bg)

if swich == True:
background(bg)

for bird in tmpbird:
bird.update()
bird.display()
link.display()


for i in smallhabitat:
i.display()

for i in mediumhabitat:
i.display()

for i in largehabitat:
i.display()

for i in startpoint:
i.display()

for i in endpoint:
i.display()




clearhabitat.display()
fill(255)
textSize(30)
text("c",clearbx-8,clearby+8)

simulate.display()
fill(255)
textSize(10)
text("SIMULATE",simulatebx-23,simulateby+4)
def mouseDragged():
global a,hcolour,smallhabitat,mediumhabitat,largehabitat,startpoint,endpoint,clearhabitat,endpoint,\
init_smallbx,init_smallby,init_mediumbx,init_mediumby,\
init_largebx,init_largeby,init_stbx,init_stby,init_endbx,init_endby,clearbx,clearby,\
ssize,msize,lsize, st_size,startcolour,starttext,endtext
for i in smallhabitat:
i.mouseDragged()
for i in mediumhabitat:
i.mouseDragged()
for i in largehabitat:
i.mouseDragged()
if len(startpoint)==2:
startpoint[0].mouseDragged()
if len(endpoint)==2:
endpoint[0].mouseDragged()

caculation:

#Routes energy consumption calculation
import itertools
import math
class Calculation(object):
def __init__(self, startpoint, endpoint, habitatpoint,energydict,maxdist):
j= 0.8
listpoint=[]
listdistance=[]
t2=0
t3=0
seen=set()
tempseen=set()
seen.add(startpoint)
queue=[]
queue.append(startpoint)
possibleroute=[]
queue2=[]
queue2.append([startpoint])
possibleroutedistance=[]
route_energy=[]
route_energydict={}

#calculate the distance between two different points
def euclid(pair):
return int(math.sqrt((pair[0][0] - pair[1][0]) ** 2 + (pair[0][1] - pair[1][1]) ** 2))

#select the possible route, generate the graphy
def gen_dist_dict(habitatpoint, maxdist):
dist_dict = dict()
for pair in itertools.permutations(habitatpoint, 2):
d = euclid(pair)
if d > maxdist:
continue
if pair[0] not in dist_dict:
dist_dict[pair[0]] = dict()

dist_dict[pair[0]][pair[1]] = euclid(pair)

return dist_dict

habitatpoint_dict = gen_dist_dict(habitatpoint, maxdist)
#Import the graphy get above, Find all the possible routes and collect them into the list possibleroute
while (len(queue)>0):
vertex= queue.pop(0)
t= queue2.pop(0)
t2=t3
t3=len(t)
if t3>t2:
seen=seen|tempseen
nodes=habitatpoint_dict[vertex]
tempseen.add(vertex)
if endpoint in t:
possibleroute.append(t)

for w in nodes:
if w not in seen:
if endpoint not in t:
queue.append(w)
f = list(t)
f.append(w)
queue2.append(f)


#calculate the energy consumption of each routes(considering distance and the size of the habitat)
for route in possibleroute:

distance=0
for n in range(len(route)-1):
distance = distance + habitatpoint_dict[route[n]][route[n+1]]
habitat_energy = 0
for h in route:
habitat_energy = habitat_energy + energydict[h]

energy= int(distance*j-habitat_energy)
route_energydict[energy] = route
route_energy.append(energy)


#output
route_energy.sort()
self.possibleroute_use= possibleroute
self.route_energy_use = route_energy
self.network = habitatpoint_dict
self.route_energydict_use=route_energydict

--

--