FishCensus
Model was written in NetLogo
6.0
•
Viewed 316 times
•
Downloaded 23 times
•
Run 0 times
Do you have questions or comments about this model? Ask them here! (You'll first need to log in.)
Info tab cannot be displayed because of an encoding error
Comments and Questions
Please start the discussion about this model!
(You'll first need to log in.)
Click to Run Model
extensions [ csv ; used to import species parameters through a csv file rnd ; used by fishes to calculate next behavior with a weighted random pick ] ;Global variables not represented on the interface tab globals[ world.area species.data ; imported input data from the csv file nr.species ; number of species in the csv file. Variable updated by the go procedure total.density wat.dens.value ; just a step to calculate drag.formula for each species when fish are created numb.fishes timed.transect.diver.mean.speed distance.transect.diver.mean.speed transect.time.secs stationary.time.secs roving.time.secs roving.diver.mean.speed sampling.area persons ; an agentset of diver and buddy hours ; variables for the model clock minutes seconds real.densities snapshot.estimates density.estimates bias.estimates output.real ; outputs for behaviorspace experiments (only works with 1st species in input file) output.estimated output.difference output.inaccuracy output.bias output.instantaneous ] ;Agent types breed [fishes fish] breed [divers diver] breed [buddies buddy] ;Agent variables fishes-own [ ; fish variables drag.formula ; the coefficient used to calculate drag, given speed and fish size current.behavior ; picked from behavior.list behavior.set? ; boolean that tells if fish has set its behavior this turn schoolmates ; for schooling species, agentset of nearby fishes velocity ; vector with x and y components determined by the previous velocity and the current acceleration at each step acceleration ; vector with x and y components, determined by the sum of all urges species ; this separates the different types within the fish breed. This is the variable recorded by divers while counting prey.type ; "benthic" or "fish". Defines the type of feeding behavior (gather around a patch or chase prey) detectability ; probability of being missed (if = 1 fish is always counted if within id.distance) visible? ; boolean variable that is set by detectability every second id.distance ; maximum distance from diver at which it is still possible to identify the species (and count the fish) approach.dist ; minimum distance from diver that the fish tolerate behavior.list ; list of up to 4 distinct behaviors behavior.freqs ; frequency of each behavior behavior.params ; a list of lists with constants for the movement model per behavior picked.patch ; patch picked by the school to feed on (if prey is benthic) picked.patch.dist ; maximum distance from the feeding patch patch.gathering.w ; weighs the urge to gather at a feeding patch perception.dist ; fish perception distance perception.angle ; fish perception angle (360 for full directional awareness) max.sustained.speed ; maximum attainable velocity with low energy consumption (cruise) burst.speed ; maximum attainable velocity with high energy consumption (chase and escape) max.acceleration ; maximum attainable acceleration diver.avoidance.w ; weighs the urge to avoid divers. If negative, fish are attracted to divers predator.avoidance.w ; weighs the urge to avoid fish with prey.type = "fish" prey.chasing.w ; weighs the urge to chase other fish schoolmate.dist ; distance among schoolmates in a school (in body lengths) align.w ; weighs the urge to match school direction center.w ; weighs the urge to stand between nearby schoolmates spacing.w ; weighs the urge to maintain crusing.distance from schoolmates wander.w ; weighs the urge to wander around randomly rest.w ; weighs the urge to stop and rest cruise.w ; wighs the urge to keep a constant speed and heading schooling? ; boolean variable that determines if fish exhibit schooling behavior ] divers-own [ ; distance transect diver variables counted.fishes snapshot.fishes speed memory viewangle initial.ycor ; for distance transects final.ycor ; for distance transects finished? ] ;Interface procedures to startup set file.name "example" set override.density 0 end to setup ca stop-inspecting-dead-agents ; clears diver detail windows from previous simulation runs output-print "Importing species data..." let full.file.name word file.name ".csv" carefully [set species.data (csv:from-file full.file.name file.delimiter)] ; import csv file into a list of lists [user-message (word "File " file.name " not found in model folder. Import the example.csv file or create one using the FishCensus species creator.") stop] ; ERROR MESSAGE if species.data = 0 [user-message "You need to import a dataset. Import the example.csv file or create one using the FishCensus species creator." stop] ; ERROR MESSAGE if length species.data < 2 [user-message "ERROR: input file has only 1 row or is empty. Check if input file has a header plus 1 line per species." stop] ; ERROR MESSAGE if length item 0 species.data != 82 [user-message "ERROR: unable to separate parameters in the file. Ensure the correct file delimiter was picked." stop] ; ERROR MESSAGE set nr.species length species.data - 1 ; all filled lines minus the header set real.densities [] ; establishes real.densities as a list foreach n-values nr.species [[x] -> x + 1] [ ; Fills real densities with data from file UPDATED TO NEW CODE SYNTAX FOR NETLOGO 6.0 [n] -> let sp.param item n species.data let real.dens.pair list item 0 sp.param item 4 sp.param set real.densities lput real.dens.pair real.densities ] if fixed.seed? [random-seed seed] output-print "Painting floor tiles..." ask patches with [pycor mod 2 = 0 and pxcor mod 2 = 0] [set pcolor 103] ask patches with [pycor mod 2 = 1 and pxcor mod 2 = 1] [set pcolor 103] ask patches with [pcolor = black] [set pcolor 105] set world.area world-height * world-width set transect.time.secs transect.time * 60 ; convert survey times from minutes to seconds set stationary.time.secs stationary.time * 60 set roving.time.secs roving.time * 60 set timed.transect.diver.mean.speed (timed.transect.diver.speed / 60) ; these lines just convert interface speeds (in m/min) to m/s set distance.transect.diver.mean.speed (distance.transect.diver.speed / 60) set roving.diver.mean.speed (roving.diver.speed / 60) set density.estimates [] ; establish diver record lists set snapshot.estimates [] set bias.estimates [] set persons no-turtles ; resets the "persons" agentset (otherwise it would be set to 0 and generate errors during setup) ; for the timed transect, the sampled area is distance * width plus max visibility * width at the end (an approximation that ignores the fact that visibility is the radius of a circle). if sampling.method = "Fixed time transect" [ set sampling.area timed.transect.width * (timed.transect.diver.mean.speed * transect.time.secs) + (timed.transect.width * max.visibility) ] ; for the distance transect, the sampled area is only distance * width if sampling.method = "Fixed distance transect" [ set sampling.area distance.transect.width * transect.distance ] ; for the stationary diver, it is the area of the circle around the diver if sampling.method = "Stationary point count" [ set sampling.area pi * stationary.radius ^ 2 ] ; the roving diver only records counts, so sampling area can be set to 1 if sampling.method = "Random path" [ set sampling.area 1 ] ; read the information stored in species.data to place fishes output-print "Placing fishes..." foreach n-values nr.species [[x] -> x + 1] [ ; loop that creates fish for each species and sets all fish variables [n] -> let sp.param item n species.data ifelse override.density = 0 [set total.density item 4 sp.param] [set total.density override.density] create-fishes (total.density * world.area) [ setxy random-xcor random-ycor set velocity [0 0] set acceleration [0 0] set picked.patch false set schoolmates no-turtles ; sets schoolmates as an empty agentset set species item 0 sp.param if length sp.param != 82 [user-message (word "ERROR: species number " n " '" species "' has a parameter list that is incomplete or too long. Check file.") stop] ; ERROR MESSAGE set shape item 1 sp.param set size item 2 sp.param ifelse item 17 sp.param = "Seawater - 1027 Kg/m3" [set wat.dens.value 1027] [set wat.dens.value 1000] set drag.formula ((0.5 * (item 14 sp.param) * wat.dens.value * (((item 13 sp.param) * ((size * 100) ^ 2)) * 0.0001))/(((item 15 sp.param) * ((size * 100) ^ (item 16 sp.param))) * 0.001)) ; formula to calculate k in order to calculate the deceleration due to drag in the form of a = kv^2 (v for velocity). set color item 3 sp.param set id.distance item 5 sp.param set approach.dist item 6 sp.param set perception.dist item 7 sp.param set perception.angle item 8 sp.param set prey.type item 9 sp.param set max.acceleration item 10 sp.param set max.sustained.speed item 11 sp.param set burst.speed item 12 sp.param set behavior.list (list item 18 sp.param item 34 sp.param item 50 sp.param item 66 sp.param) set behavior.freqs (list item 19 sp.param item 35 sp.param item 51 sp.param item 67 sp.param) if reduce + behavior.freqs != 1 [ user-message (word "ERROR! Behavior frequencies for " species " do not add up to 1.") stop] ; ERROR MESSAGE set behavior.params (list ; lists parameter values for all 4 behaviors sublist sp.param 18 34 sublist sp.param 34 50 sublist sp.param 50 66 sublist sp.param 66 82) set visible? true set behavior.set? false set.first.behavior ; fish procedure that picks the first behavior in behavior.list as the starting behavior and fills in parameters (this sets "visible?" depending on detectability of first behavior) ] ] set total.density (count fishes / world.area) ; this takes into account the actual number of fishes in the area, and not the original input number. set numb.fishes count fishes output-print (word "Imported " count fishes " fishes belonging to " nr.species " species,") output-print (word "with a total density of " total.density " fish per square meter.") output-print (word "Stabilizing fish movement for " initial.time.to.stabilize.movement " model seconds...") ask fishes [repeat movement.time.step * initial.time.to.stabilize.movement [do.fish.movement]] ; lets the fish movement model stabilize for a pre-determined amount of model seconds (20 by default). output-print "Placing diver..." if sampling.method = "Fixed time transect" [ ;timed transect diver setup create-divers 1 [ set heading 0 set shape "diver" set color cyan set size 2 setxy (world-width / 2) 5 if show.paths? = true [pen-down] ;this shows the path of the diver set speed timed.transect.diver.mean.speed set viewangle transect.viewangle set counted.fishes [] ; sets counted.fishes as an empty list set snapshot.fishes ([species] of (fishes with [(xcor >= (world-width / 2) - timed.transect.width) and (xcor <= (world-width / 2) + timed.transect.width) and (ycor >= (world-height / 4)) and (ycor <= ((world-height / 4) + (transect.time * timed.transect.diver.speed)))])) ] if buddy? [ create-buddies 1 [ set heading 0 set shape "diver" set color cyan set size 2 setxy ([xcor] of one-of divers + 1) ([ycor] of one-of divers - 1) ] ] ] if sampling.method = "Fixed distance transect" [ ;distance transect diver setup create-divers 1 [ set heading 0 set shape "diver" set color green set size 2 setxy (world-width / 2) 5 if show.paths? = true [pen-down] ;this shows the path of the diver set speed distance.transect.diver.mean.speed set viewangle transect.viewangle set initial.ycor ycor ; fixed distance transect divers record their start and end points as given by "transect.distance" initially set final.ycor ycor + transect.distance ; because coordinates are in meters set counted.fishes [] ; sets counted.fishes as an empty list set snapshot.fishes ([species] of (fishes with [(xcor >= (world-width / 2) - distance.transect.width) and (xcor <= (world-width / 2) + distance.transect.width) and (ycor >= (world-height / 4)) and (ycor <= ((world-height / 4) + (transect.distance)))])) ] if buddy? [ create-buddies 1 [ set heading 0 set shape "diver" set color green set size 2 setxy ([xcor] of one-of divers + 1) ([ycor] of one-of divers - 1) ] ] ] if sampling.method = "Stationary point count" [ ;stationary diver setup create-divers 1 [ set heading 0 set shape "diver" set color red set size 2 setxy (world-width / 2) (world-height / 2) set viewangle stationary.viewangle set counted.fishes [] ; sets counted.fishes as an empty list set snapshot.fishes ([species] of (fishes in-radius stationary.radius)) ] if buddy? [ create-buddies 1 [ set heading 0 set shape "diver" set color red set size 2 setxy ([xcor] of one-of divers + 1) ([ycor] of one-of divers - 1) ] ] ] if sampling.method = "Random path" [ ;roving diver setup create-divers 1 [ set heading 0 set shape "diver" set color magenta set size 2 setxy (world-width / 2) 5 if show.paths? = true [pen-down] ;this shows the path of the diver set speed roving.diver.mean.speed set viewangle rpath.viewangle set counted.fishes [] ; sets counted.fishes as an empty list set snapshot.fishes [] ; sets snapshot.fishes as an empty list (no snapshot possible for roving divers, as their path is random) ] if buddy? [ create-buddies 1 [ set heading 0 set shape "diver" set color magenta set size 2 setxy ([xcor] of one-of divers + 1) ([ycor] of one-of divers - 1) ] ] ] set persons (turtle-set divers buddies) ; creates the agentset containing divers and buddies ask divers [ set finished? false ; reset the "finished?" variable set memory [] ; reset the memory list ] output-print "Setup complete. Press GO to run the model" reset-ticks ; open diver detail window if show.diver.detail.window? = true [inspect one-of divers] end ;of setup procedure to go if count divers = count divers with [finished?] [ ; do.outputs and stop if diver is finished do.outputs stop] if sampling.method = "Stationary point count" and stationary.radius > max.visibility [ user-message "ERROR: stationary.radius is greater than max.visibility. Diver will not be able to see the sample area." ; if the stationary radius is higher than visibility, stop and output an error description« stop ] if sampling.method = "Fixed distance transect" [ask divers [ ; divers count the fishes and then check if finishing conditions are met d.count.fishes set finished? ycor > final.ycor ] ] if sampling.method = "Fixed time transect" [ask divers [ t.count.fishes set finished? ticks > transect.time.secs ] ] if sampling.method = "Stationary point count" [ask divers [ s.count.fishes set finished? ticks > stationary.time.secs ] ] if sampling.method = "Random path" [ask divers [ r.count.fishes set finished? ticks > roving.time.secs ] ] repeat movement.time.step [ if sampling.method = "Fixed distance transect" [ask divers [do.ddiver.movement]] ; move the diver if sampling.method = "Fixed time transect" [ask divers [do.tdiver.movement]] if sampling.method = "Stationary point count" [ask divers [do.stdiver.movement]] if sampling.method = "Random path" [ask divers [do.rdiver.movement]] ask buddies [ ; move the buddy move-to one-of divers set heading [heading] of one-of divers rt 135 fd sqrt 2 ; keep 1m behind and 1m to the right of the diver set heading [heading] of one-of divers ] ask fishes [ ; move the fishes do.fish.movement ] if smooth.animation? [display] ] ; closes repeat movement.time.step if sampling.method = "Random path" and ticks mod 2 = 0 [ ask divers[set heading heading + random-float-between (- roving.diver.turning.angle) roving.diver.turning.angle]] ;random path turning happens every 2 seconds (must be out of the "repeat" cycle) if not super.memory? [ask divers [forget.fishes]] ; if super memory is disabled, divers forget fishes they no longer see if ticks mod behavior.change.interval = 0 [ ask fishes [ set behavior.set? false set.behavior ] ; fishes set a new behavior in the end of the go procedure, every x seconds (determined by behavior.change.interval) ] advance-clock tick end ; of go procedure to advance-clock set seconds seconds + 1 if seconds = 60 [set minutes minutes + 1 set seconds 0] if minutes = 60 and seconds = 0 [set hours hours + 1 set minutes 0] end ;OBSERVER PROCEDURES to do.outputs ask divers [ output-print "Density estimates:" foreach n-values nr.species [[x] -> x + 1] [ [n] -> let sp.param item n species.data let name item 0 sp.param let sp.dens.pair list name precision (occurrences name counted.fishes / sampling.area) 3 set density.estimates lput sp.dens.pair density.estimates output-print (word first sp.dens.pair ": " last sp.dens.pair) ] output-print "Bias due to non-instantaneous sampling:" foreach n-values nr.species [[x] -> x + 1] [ [n] -> let sp.param item n species.data let name item 0 sp.param let snapshot.dens.pair list name precision (occurrences name snapshot.fishes / sampling.area) 3 set snapshot.estimates lput snapshot.dens.pair snapshot.estimates ; this just stores snapshot densities in a variable ifelse last snapshot.dens.pair = 0 [ let bias.pair list name "n/a" ; if snapshot.density is 0, do not calculate bias due to non-instantaneous sampling set bias.estimates lput bias.pair bias.estimates ; this just stores bias estimates in a variable output-print (word first bias.pair ": " last bias.pair) ] [ let bias.pair list name precision ((((last item (n - 1) density.estimates)) - (last snapshot.dens.pair)) / (last snapshot.dens.pair)) 3 ; bias is calculated as (counted density - snapshot density) / snapshot density set bias.estimates lput bias.pair bias.estimates ; this just stores bias estimates in a variable output-print (word first bias.pair ": " last bias.pair) ] ] set output.real total.density ; fill output variables for BehaviourSpace (if more than 1 species, these outputs only apply to the 1st) set output.estimated last first density.estimates set output.difference output.estimated - output.real set output.inaccuracy output.difference / output.real set output.instantaneous last first snapshot.estimates set output.bias last first bias.estimates ] end ; of do.outputs ;FISH PROCEDURES ;fish movement submodel to do.fish.movement if schooling? [set schoolmates other fishes in-cone perception.dist perception.angle with [species = [species] of myself]] ; if schooling is true,look for conspecifics in my vicinity set acceleration (list 0 0) ; acceleration at each step is determined entirely by the urges ;check if weights are not 0 (to prevent useless calculations) and calculate all urge vectors if patch.gathering.w != 0 [add-urge patch-center-urge patch.gathering.w] ; check if weights are not 0 (to prevent useless calculations) and calculate all urge vectors if wander.w != 0 [add-urge wander-urge wander.w] if predator.avoidance.w != 0 [add-urge avoid-predator-urge predator.avoidance.w] if diver.avoidance.w != 0 [add-urge avoid-diver-urge diver.avoidance.w] if rest.w != 0 [add-urge rest-urge rest.w] if cruise.w != 0 [add-urge cruise-urge cruise.w] if count schoolmates > 0 and schooling? ; if I'm not in a school ignore the school related urges. If schooling is disabled, ignore them as well [ add-urge spacing-urge spacing.w add-urge center-urge center.w add-urge align-urge align.w ] let deceleration (scale ((drag.formula * ((magnitude velocity) ^ 2))) (subtract (list 0 0) (normalize velocity))) ; subtract the deceleration due to drag from the acceleration vector set acceleration (add acceleration deceleration) if magnitude acceleration > max.acceleration ; keep the acceleration within the accepted range. It is important that this is done after accounting for drag, so that max.acceleration can be reached. [ set acceleration (scale max.acceleration normalize acceleration) ] set velocity (add velocity acceleration) ; the new velocity of the fish is sum of the acceleration and the old velocity. ;keep velocity within accepted range. When near threats, use burst.speed as limit, but only if avoidance urge weight is greater than 0 ifelse ((any? (fishes with [prey.type = "fish"]) in-cone approach.dist perception.angle) and (predator.avoidance.w > 0)) or ((any? divers in-cone approach.dist perception.angle) and (diver.avoidance.w > 0)) [ if magnitude velocity > burst.speed [ set velocity (scale burst.speed normalize velocity) ] ] [ if magnitude velocity > max.sustained.speed [ set velocity (scale max.sustained.speed normalize velocity) ] ] let nxcor xcor + ( first velocity ) let nycor ycor + ( last velocity ) if magnitude velocity > 0.2 [ ; minimum velocity that triggers movement. This is to prevent erratic movement when stopped. facexy nxcor nycor fd (magnitude velocity) / movement.time.step] end ;of do.fish.movement to add-urge [urge factor] ;fish procedure set acceleration add acceleration scale factor normalize urge end to pick.patch ;fish procedure if picked.patch = false [ let chosen.patch patch-ahead 2 ; second patch ahead of the fish if [pxcor] of chosen.patch > (world-width - (picked.patch.dist + 1)) [ ; create a (picked.patch.dist + 1) -wide buffer so that picked patches are not too close to the edges let new.chosen.patch patch ([pxcor] of chosen.patch - (picked.patch.dist + 1)) ([pycor] of chosen.patch) set chosen.patch new.chosen.patch ] if [pxcor] of chosen.patch < (picked.patch.dist + 1) [ let new.chosen.patch patch ([pxcor] of chosen.patch + (picked.patch.dist + 1)) ([pycor] of chosen.patch) set chosen.patch new.chosen.patch ] if [pycor] of chosen.patch > (world-height - (picked.patch.dist + 1)) [ let new.chosen.patch patch ([pxcor] of chosen.patch) ([pycor] of chosen.patch - (picked.patch.dist + 1)) set chosen.patch new.chosen.patch ] if [pycor] of chosen.patch < (picked.patch.dist + 1) [ let new.chosen.patch patch ([pxcor] of chosen.patch) ([pycor] of chosen.patch + (picked.patch.dist + 1)) set chosen.patch new.chosen.patch ] set picked.patch chosen.patch if any? schoolmates [ ask schoolmates [ set picked.patch chosen.patch ] ]] end ;procedure that selects a new behavior and fills in behavior parameters to set.behavior ; fish procedure if not behavior.set? [ let pairs (map list behavior.list behavior.freqs) ; pairs behavior names with probabilities as lists within a list, to work better with the rnd extension: [[b1 0.2] [b2 0.3] [b3 0.5]] set current.behavior first rnd:weighted-one-of-list pairs [[p] -> last p] ; pick a random behavior from behavior list, using a weighted random pick let param.pos position current.behavior behavior.list ; check which behavior was picked (1, 2, 3 or 4) let params item param.pos behavior.params ; retreive list of parameters from the correct position in behavior.params set detectability item 2 params set schooling? item 3 params set schoolmate.dist item 4 params set align.w item 5 params set center.w item 6 params set spacing.w item 7 params set wander.w item 8 params set rest.w item 9 params set cruise.w item 10 params set picked.patch.dist item 11 params set patch.gathering.w item 12 params set predator.avoidance.w item 13 params set prey.chasing.w item 14 params set diver.avoidance.w item 15 params ifelse detectability < 1 [ set visible? random-bernoulli detectability ; visibility of individual fish is set when behavior changes, using a Bernoulli trial ] [ set visible? true ] set behavior.set? true if any? schoolmates [ ask schoolmates [ set current.behavior [current.behavior] of myself set detectability item 2 params set schooling? item 3 params set schoolmate.dist item 4 params set align.w item 5 params set center.w item 6 params set spacing.w item 7 params set wander.w item 8 params set rest.w item 9 params set cruise.w item 10 params set picked.patch.dist item 11 params set patch.gathering.w item 12 params set predator.avoidance.w item 13 params set prey.chasing.w item 14 params set diver.avoidance.w item 15 params ifelse detectability < 1 [ set visible? random-bernoulli detectability ; visibility of schoolmates is set independently ] [ set visible? true ] set behavior.set? true ] ] ifelse patch.gathering.w > 0 [ ; if selected behavior has patch gathering urge, pick a patch. If in a school, ask schoolmates to pick a patch collectively. pick.patch] [set picked.patch false] ; if patch gathering urge has zero weight, variable picked.patch is set to false (important for pick.patch procedure). ] end to set.first.behavior ; fish procedure set current.behavior first behavior.list ; set behavior to first in the list (this should be the most frequent and/or the most typical for the species) let params first behavior.params ; retreive list of parameters from the first position in behavior.params set detectability item 2 params set schooling? item 3 params set schoolmate.dist item 4 params set align.w item 5 params set center.w item 6 params set spacing.w item 7 params set wander.w item 8 params set rest.w item 9 params set cruise.w item 10 params set picked.patch.dist item 11 params set patch.gathering.w item 12 params set predator.avoidance.w item 13 params set prey.chasing.w item 14 params set diver.avoidance.w item 15 params ifelse detectability < 1 [ set visible? random-bernoulli detectability ; visibility of individual fish is set when behavior changes, using a Bernoulli trial ] [ set visible? true ] set behavior.set? true ifelse patch.gathering.w > 0 [ ; if selected behavior has patch gathering urge, pick a patch. If in a school, ask schoolmates to pick a patch collectively. pick.patch] [set picked.patch false] ; if patch gathering urge has zero weight, variable picked.patch is set to false (important for pick.patch procedure). end ; fish urges to-report patch-center-urge ; a vector directed at the center of the picked patch ifelse picked.patch != false [ let patch-x [pxcor] of picked.patch let patch-y [pycor] of picked.patch ifelse distancexy patch-x patch-y > picked.patch.dist ; distance to picked patch [ report (list (patch-x - xcor) (patch-y - ycor)) ] ; number of coordinate units (vertical and horizontal) needed to get to picked.patch [ report (list 0 0) ] ] [ report (list 0 0) ] end to-report center-urge ; a vector directed at the average location of my schoolmates if count schoolmates = 0 or center.w = 0 [ report (list 0 0) ] report (map - (list mean [ xcor ] of schoolmates mean [ ycor ] of schoolmates) (list xcor ycor) ) end to-report align-urge ; a vector obtained by averaging the velocity of schoolmates if count schoolmates = 0 or align.w = 0 [ report (list 0 0) ] report (map - (list mean [ first velocity ] of schoolmates ; x component mean [ last velocity ] of schoolmates ; y component ) velocity ) end to-report rest-urge ;a vector opposite to current velocity (counters current movement) report subtract [0 0] velocity end to-report cruise-urge ; a vector that simply reinforces the current velocity report normalize velocity end to-report wander-urge ; reports 2 random numbers between -1 and 1, leading to a vector with random direction report n-values 2 [ (random-float 2) - 1 ] end to-report spacing-urge let urge [ 0 0 ] ;; report the sum of the distances to fishes ;; in my school that are closer to me than ;; schoolmate.dist (in body lengths) ask schoolmates with [ distance myself < (schoolmate.dist * size) ] [ set urge add urge (subtract (list [xcor] of myself [ycor] of myself) (list xcor ycor)) ] report urge end to-report avoid-predator-urge ; a normalized vector that is opposite to the position of the closest predator let urge (list 0 0) if predator.avoidance.w = 0 [ report urge ] let predators fishes in-cone approach.dist perception.angle with [species != [species] of myself and prey.type = "fish"] if any? predators [ask min-one-of predators [distance myself] [set urge normalize (add urge subtract (list [xcor] of myself [ycor] of myself) (list xcor ycor)) ]] report urge end to-report avoid-diver-urge ; a normalized vector that is opposite to the position of the closest person let urge (list 0 0) if diver.avoidance.w = 0 [ report urge ] let threats persons in-cone approach.dist perception.angle ; persons is an agenteset that includes divers and buddies if any? threats [ask min-one-of threats [distance myself] [set urge normalize (add urge subtract (list [xcor] of myself [ycor] of myself) (list xcor ycor)) ]] report urge end ;VECTOR OPERATIONS to-report add [ v1 v2 ] report (map + v1 v2) end to-report subtract [ v1 v2 ] report (map - v1 v2) end to-report scale [ scalar vector ] report map [ [v] -> scalar * v ] vector end to-report magnitude [ vector ] report sqrt sum map [ [v] -> v * v ] vector end to-report normalize [ vector ] let m magnitude vector if m = 0 [ report vector ] report map [ [v] -> v / m ] vector end ;DIVER PROCEDURES ;movement to do.ddiver.movement ; fixed distance transect diver movement fd speed / movement.time.step ; each step is a second, so the speed is basically the distance divided by the movement.time.step end to do.tdiver.movement ; fixed time transect diver movement fd speed / movement.time.step ; each step is a second, so the speed is basically the distance divided by the movement.time.step end to do.stdiver.movement ; stationary point count diver movement set heading heading + (stationary.turning.angle / movement.time.step) ; turns clockwise at a constant speed (in degrees per second) end to do.rdiver.movement ; roving diver movement NOTE: turning happens every two seconds, so this part is coded separately in the go procedure fd speed / movement.time.step ; each step is a second, so the speed is basically the distance divided by the movement.time.step end ;count procedures to d.count.fishes ; for fixed distance transects, there is a limit to the y coordinate (the diver does not count beyond the end mark of the transect) let myxcor xcor let my.final.ycor final.ycor let seen.fishes fishes in-cone max.visibility viewangle let eligible.fishes seen.fishes with [(xcor > myxcor - (distance.transect.width / 2)) and (xcor < myxcor + (distance.transect.width / 2)) and (ycor < my.final.ycor)] ; distance transects have a limit in ycor as well let identifiable.fishes eligible.fishes with [id.distance >= distance myself and visible?] ; only fish that within their id.distance and are visible are counted let diver.memory memory let new.fishes (identifiable.fishes with [not member? who diver.memory]) ; only fishes that are not remembered are counted ifelse count new.fishes > count.saturation [ ; even if there are more, only the max number of fishes per second is counted (count.saturation) let new.records ([species] of min-n-of count.saturation new.fishes [distance myself]) ; priority is given to closest fishes set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ] [ if any? new.fishes [ ; if there are new fishes, but they do not exceed count.saturation, just count them let new.records ([species] of new.fishes) set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ]] end to t.count.fishes let myxcor xcor let seen.fishes fishes in-cone max.visibility viewangle let eligible.fishes seen.fishes with [(xcor >= myxcor - (timed.transect.width / 2)) and (xcor <= myxcor + (timed.transect.width / 2))] ; this only works for transects heading north, of course let identifiable.fishes eligible.fishes with [id.distance >= distance myself and visible?] let diver.memory memory let new.fishes identifiable.fishes with [not member? who diver.memory] ; only fishes that are not remembered are counted ifelse count new.fishes > count.saturation [ ; even if there are more, only the max number of fishes per second is counted (count.saturation) let new.records ([species] of min-n-of count.saturation new.fishes [distance myself]) ; priority is given to closest fishes set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ] [ if any? new.fishes [ ; if there are new fishes, but they do not exceed count.saturation, just count them let new.records ([species] of new.fishes) set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ]] end to s.count.fishes let eligible.fishes fishes in-cone stationary.radius viewangle let identifiable.fishes eligible.fishes with [id.distance >= distance myself and visible?] let diver.memory memory let new.fishes identifiable.fishes with [not member? who diver.memory] ; only fishes that are not remembered are counted ifelse count new.fishes > count.saturation [ ; even if there are more, only the max number of fishes per second is counted (count.saturation) let new.records ([species] of min-n-of count.saturation new.fishes [distance myself]) ; priority is given to closest fishes set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ] [ if any? new.fishes [ ; if there are new fishes, but they do not exceed count.saturation, just count them let new.records ([species] of new.fishes) set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ]] end to r.count.fishes let eligible.fishes fishes in-cone max.visibility viewangle let identifiable.fishes eligible.fishes with [id.distance >= distance myself and visible?] let diver.memory memory let new.fishes identifiable.fishes with [not member? who diver.memory] ; only fishes that were not previously counted are counted ifelse count new.fishes > count.saturation [ ; even if there are more, only the max number of fishes per second is counted (count.saturation) let new.records ([species] of min-n-of count.saturation new.fishes [distance myself]) ; priority is given to closest fishes set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ] [ if any? new.fishes [ ; if there are new fishes, but they do not exceed count.saturation, just count them let new.records ([species] of new.fishes) set counted.fishes sentence counted.fishes new.records set memory sentence memory [who] of new.fishes ]] end ;forget fishes to forget.fishes ; runs if super memory is off let seen.fish.id [who] of fishes in-cone max.visibility viewangle let diver.memory memory set memory filter [[id] -> member? id seen.fish.id] diver.memory end ; USEFUL REPORTERS to-report random-bernoulli [probability-true] if probability-true < 0.0 or probability-true > 1.0 [user-message "WARNING: probability outside 0-1 range in random-bernoulli."] report random-float 1.0 < probability-true end to-report random-float-between [a b] ; generate a random float between two numbers report random-float a + (b - a) end to-report occurrences [x the-list] ; count the number of occurrences of an item in a list (useful for summarizing species lists) report reduce [[occurrence-count next-item] -> ifelse-value (next-item = x) [occurrence-count + 1] [occurrence-count]] (fput 0 the-list) end
There are 2 versions of this model.
Attached files
File | Type | Description | Last updated | |
---|---|---|---|---|
FishCensus.png | preview | Preview for 'FishCensus' | about 8 years ago, by Miguel Pais | Download |
This model does not have any ancestors.
This model does not have any descendants.