-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSAMPL.nlogo
1923 lines (1592 loc) · 62.8 KB
/
SAMPL.nlogo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
extensions [GIS matrix table csv];
;variable that has the same value for all the agents in the model across all procedures
globals [
width-bw-transects ;width between transects
transects ;patches in a transect
#-of-mussels ;total number of mussels in the model
total-rare-mussels ;total number of rare mussels in model
total-med-rare-mussels ;total number of medium rare mussels in model
total-common-mussels ;total number of common mussels in model
clusters ;patches in an adaptive sampling cluster. If sampled it will be TRUE. else it will be 0
total-clusters ;number of patches where in an adaptive sampling cluster. cluster = True
color-list ;color list for clusters. The color-list is sampled without replacement for clusters, so color-list2 holds the original color list.
color-list2 ;saved copy of original color-list
adapt? ;a boolean variable that is TRUE when adaptive sampling should continue.
maxX maxY ;max x coordinate and max y coordinate
newPatchSize ;cell size
musselSize ;size of mussels dots in UI
output-file-mussels ;the filepath where results will be written. Partially defined by file-name input
total-mussels-sampled ;the number of mussels that are in patches where quadrat = TRUE. The number of mussels that are sampled
rare-mussels-sampled ;same but only counting rare mussels
common-mussels-sampled ;same but only counting common mussels
med-rare-mussels-sampled ;same but only counting medium rare mussels
total-mussels-detected ;number of mussels that are detected
rare-mussels-detected ;same but only counting rare mussels
common-mussels-detected ;same but with common-mussels
med-rare-mussels-detected ;same but with medium rare mussels
number-of-transects ;number of transects
mussel-group-sizes ;a list that holds all of the mussel group sizes
poisson-clump-sizes ;list to store output of clump-size function
timed-search-minute-counter ;keeps track or random walk time
person-hours ;number of person hours (calc depends on search method)
mussels-per-surveyor-list ;a list holding total mussels detected by each surveyor
total-num-quadrats ;the number of cells/patches where quadrat = TRUE
total-quadrats-surveyed ;the sum of the number of quadrats searched by each surveyor
estimated-mussel-density ;number of mussels detected/number of square meters sampled
sample-cv ;coefficient of variation for detected mussels
mussels-per-person-hour ;number of mussels detected/person hours searched
hh-estimated-density-m ;#hh estimation of true population mean
hh-estimated-total-pop ;hh estimate of total population
hh-estimated-density-var ;hh variance of estimated population mean
hh-estimated-pop-var ;hh variance of estimated total population
var-mean-ratio ;calculate the variance to mean ratio (using quadrat size)
]
;Attributes that are unique to the class patch
patches-own [
transect? ;True or False. If the patch is in a transect or not.
transect-ID ;The ID of the transect that the patch is in. If it’s zero, it’s not in a transect.
quadrat? ;True or False. If the patch is sampled
cluster? ;True or False. Is the patch in a cluster
cluster-ID ;The ID of the cluster that the patch is in.
cluster-ring ;What iteration of adaptive sampling is the patch in. If it is in initial random sample it is 0, if it is in the next iteration it is 1. etc.
cluster-edge? ;if the patch is at the edge of a cluster or not
parent-patch? ;True or False. If the patch is the center of a poisson cluster
ellipse-set ;set of patches that compose an ellipse
ellipse-center? ;True or False. Is the patch the center of an ellipse?
ellipse? ;Is the patch in an ellipse
major-axis ;half of the longest length in the ellipse. Formula changes based on custom matern size/locations (ie shore, center, etc)
minor-axis ;half the shorter length in the ellipse.
heading-ellipse ;ellipse orientation (variable is angle)
network-summary ;summary of type of mussels that were sampled.
mussels-on-patch ;the number of mussels on each patch
]
;Attributes that are unique to class turtle (mussels, surveyors)
turtles-own [
species ;What species is the mussel? Can be rare, med-rare, or common
quarter ;what quarter of the model space the agent is in. from left to right quarters are 1,2,3,4
detectability ;a random number between 0 and 1. If it is less than the detect-threshold it will be detected
detect-threshold ;a species specific number. If detectability < detect-threshold the mussel will be detected
detected? ;True or False. Was the mussel detected?
tick-detected ;the tick when the mussel was detected random walk search
detected-id ;the surveyor and detected step so we know when and by who mussel was detected
distance-from-parent-cell ;The distance from the patch that is the center of poisson clump
parent-patch ;identifies which patch is the parent patch (center of poisson distribution. Used to determine how far away
quadrats-searched ;the number of quadrats a surveyor has searched
mussels-found ;the number of mussels a surveyor detects
tick-since-last-find ;time since surveyor last found a mussel
search-mode ;if they surveyor is searching (T) or walking (F)
out-of-time? ;T/F, if the surveyor has used more than a x/4 time but has not reached x/4 distance through model (only applies to before reached destination)
destination ;where the surveyor is going (opposite side as where they started)
reached-destination-once? ;T/F, if the surveyor reached other side at least once
reached-destination? ;T/F, if the surveyor reached the destination
cornered? ;T/F, if the surveyor is in a corner
at-horizontal-edge? ;T/F, if the surveyor is at top bottom edge
at-vertical-edge? ;T/F, if the surveyor is at a left right edge
counter ;counts ticks to tell if surveyor is in search mode or not
]
;breed - defines plural and singular of breed
breed [mussels mussel]
breed [surveyors surveyor]
;initialize model
to initialize
no-display ;turns off display until display is called (so user does not see updates)
;random-seed 13 ;creates a repeatable series of random simulations
ca ct cp ;clears all variables (clear all, clear turtles, clear patches)
reset-ticks ;resets counter
set-world-size ;call to custom functionthat sets patch size, world size, etc
set color-list [15 25 35 45 55 65 75 85 115 125 135] ;creates a list of colors for adaptive clusters
set color-list2 color-list ;save a copy of color-list in color-list2
set adapt? TRUE ;variable for determining when to end adaptive clusters
set output-file-mussels (word "Results/" file-name ".csv" )
;initialized the habitat patches
ask patches [
set pcolor 103
set transect? FALSE
set cluster? FALSE
set cluster-ID -999
set cluster-ring -999
set ellipse? FALSE
set major-axis random max-pxcor / 4
set minor-axis random max-pycor / 4
set heading-ellipse util-random-range 255 300
]
set mussel-group-sizes []
add-mussels ;call to custom function that creates the mussels
mussel-attributes ;call to custom function that adds mussel attributes (i.e. size, shape, color in ui, detectability)
;parameterizes model based on sampling scheme
if sampling-method = "simple-random-sample" [set-srs]
if sampling-method = "transect" [set-transects]
if sampling-method = "adaptive-cluster" [create-clusters]
if sampling-method = "timed-search" [add-surveyors]
display ;turn on display
end
;function that determines patch size, max x and y values
to set-world-size
ifelse quadrat-size = 0.25
[set maxX 199 set maxY 39
set newPatchSize 5
set musselSize 0.6]
[ifelse quadrat-size = 0.5
[set maxX 99 set maxY 19
set newPatchSize 10
set musselSize 0.30]
[set maxX 49 set maxY 9
set newPatchSize 20
set musselSize 0.15]
]
resize-world 0 maxX 0 maxY
set-patch-size newPatchSize
end
;procedure to create and place mussels
to add-mussels
if mussels-per-meter = 0 [stop]
set #-of-mussels 500 * mussels-per-meter
;randomly distribute mussels
if spatial-distribution = "random" [
create-mussels #-of-mussels [
setxy random-xcor random-ycor
]
]
;clumped matern distribute mussels
if spatial-distribution = "Clumped-Matern" [
;random matern clumps
ifelse matern-clump-placement = "Randomly placed" [
ask n-of num-groups patches [
set ellipse-set create-ellipse pxcor pycor major-axis minor-axis heading-ellipse
ask ellipse-set [set ellipse? TRUE set pcolor pcolor + 1]]
]
;creates clump that runs lenght of shore
[
ask patch (max-pxcor / 2) 2 [
set major-axis max-pxcor / 2
set minor-axis 3
set ellipse-set create-ellipse pxcor pycor major-axis minor-axis 270
ask ellipse-set [set ellipse? TRUE set pcolor pcolor + 1]]
;creates circular clump in center
if matern-clump-placement = "One shore; one middle" or matern-clump-placement = "One shore; one middle; 2 additional" [
ask patch (max-pxcor / 2) (max-pycor / 2) [
set major-axis util-random-range 5 10
set minor-axis major-axis
set heading-ellipse util-random-range 255 300
set ellipse-set create-ellipse pxcor pycor major-axis minor-axis heading-ellipse
ask ellipse-set [set ellipse? TRUE set pcolor pcolor + 1]]]
;creates 2 random matern clumps
if matern-clump-placement = "One shore; one middle; 2 additional" or matern-clump-placement = "One shore; 2 additional" [
ask n-of 2 patches with [ellipse? = FALSE][
set major-axis util-random-range (max-pxcor * 0.05) (max-pxcor * 0.10)
set minor-axis util-random-range (max-pycor * 0.05) (max-pycor * 0.10)
set heading-ellipse util-random-range 255 300
set ellipse-set create-ellipse pxcor pycor major-axis minor-axis heading-ellipse
ask ellipse-set [set ellipse? TRUE set pcolor pcolor + 1]]
]
]
create-mussels #-of-mussels [
move-to one-of patches with [ellipse? = TRUE]]
]
if spatial-distribution = "Clumped-Poisson" [
set poisson-clump-sizes clump-size
let tmp6 0
ask n-of num-groups patches [
set parent-patch? TRUE
let mussel-clumps item tmp6 poisson-clump-sizes
set tmp6 tmp6 + 1
sprout-mussels mussel-clumps [
set parent-patch patch-here
set distance-from-parent-cell (random-poisson (poisson-mean-meters / quadrat-size))
ifelse any? patches in-radius distance-from-parent-cell
[move-to one-of patches in-radius distance-from-parent-cell]
[move-to one-of neighbors]
let xcor-tmp xcor + random-float 1
let ycor-tmp ycor + random-float 1
if xcor-tmp <= max-pxcor and ycor-tmp <= max-pycor [setxy xcor-tmp ycor-tmp]
set parent-patch tmp6 - 1
]
]
]
;count how many mussels are on each quadrat
ask patches [set mussels-on-patch count mussels-here]
;caclulate and store variance to mean ratio
if mussels-per-meter > 0 [
set var-mean-ratio var-to-mean-ratio
]
end
;function to add mussel aesthetics, rarity, detectability
to mussel-attributes
ask mussels [
set size musselSize
set shape "circle"
set color white
set detectability random-float 1
set detected? False
set quarter find-quarter
let tmp random-float 1
(ifelse
tmp <= freq-rare [
set species "rare"
;set color cyan
set detect-threshold detect-rare
]
tmp > freq-rare and tmp <= freq-med-rare [
set species "med-rare"
;set color violet
set detect-threshold detect-med-rare
]
[
set species "common"
;set color white
set detect-threshold detect-common
]
)
]
end
;reports the number of mussels in each clump (list with number per each clump
to-report clump-size
let rounded-group-size []
while [sum rounded-group-size != #-of-mussels] [
set rounded-group-size []
set mussel-group-sizes []
;generates list of random numbers between 0-1
repeat num-groups [
let tmp random-float 1 ;generate random number
set mussel-group-sizes lput tmp mussel-group-sizes ;add to mussel-group-sizes list
]
let tmp sum mussel-group-sizes ;sum all random numbers in the list
;create new list of where each value is random number/sum of random number list (will add up to one)
let tmp4 map [x -> x / tmp] mussel-group-sizes
;multiply proportion from tmp4 by total number of mussels
let tmp5 map [ x -> x * #-of-mussels] tmp4
;round so whole number of mussels
set rounded-group-size map round tmp5
]
report rounded-group-size
end
;procedure to create ellipse for matern clusters
to-report create-ellipse [x y a b head]
set ellipse-center? TRUE
let c 0
ifelse a >= b [
set c sqrt ( ( (a) ^ 2 ) - ( (b) ^ 2 ) )]
[set c sqrt ( ( (b) ^ 2 ) - ( (a) ^ 2 ) )]
let f1x ( x + ( c * sin head ) )
let f1y ( y + ( c * cos head ) )
let f2x ( x - ( c * sin head ) )
let f2y ( y - ( c * cos head ) )
report patches with [
( distancexy f1x f1y ) +
( distancexy f2x f2y ) <=
2 * ( sqrt ( ( b ^ 2 ) + ( c ^ 2 ) ) ) ]
end
to-report find-quarter
let q 0
(ifelse
xcor < (max-pxcor + 1) * 0.25 [set q 1]
xcor > (max-pxcor + 1) * 0.25 and xcor <= (max-pxcor + 1) * 0.5 [set q 2]
xcor > (max-pxcor + 1) * 0.5 and xcor <= (max-pxcor + 1) * 0.75 [set q 3]
xcor > (max-pxcor + 1) * 0.75 and xcor <= (max-pxcor + 1) [set q 4]
)
report q
end
;runs procedures after model is intialized
to go
(ifelse
;if adaptive clustering, build cluster until adapt? = FALSE
sampling-method = "adaptive-cluster"
[
;procedure to determine when to stop adaptive clusters
while [adapt-cluster? = TRUE] [
build-cluster tick] ;procedure to build clusters
stop
]
;if random walk, stop after time limit is reached
sampling-method = "timed-search"
[
while [(timed-search-minute-counter / 60) <= person-hours-to-search] [
timed-search tick] ;procedure to random walk
stop
]
;else for transects and simple random sampling exit the go loop
[stop]
)
end
;procedure to create simple random sample
to set-srs
ask n-of quadrats-to-sample patches [
set pcolor pink
set quadrat? TRUE
]
ask mussels-on patches with [quadrat? = TRUE][set detected? detect]
ask mussels with [detected? = TRUE] [set color red set pcolor green]
end
;procedure that initializes transects
to set-transects
let tmp 0
let tmp1 1
while [tmp <= max-pxcor] [
ask patches with [pxcor = tmp] [
set pcolor grey - 2
set transect? TRUE
set transect-ID tmp1]
set tmp tmp + transect-spacing + 1
set tmp1 tmp1 + 1
]
set transects patches with [transect-ID > 0]
set number-of-transects max [transect-ID] of patches with [transect? = TRUE]
let tmp2 1
while [tmp2 <= number-of-transects] [
ask n-of quadrats-on-transect patches with [transect-id = tmp2 ] [
set quadrat? TRUE set pcolor pink]
set tmp2 tmp2 + 1
]
ask mussels-on patches with [quadrat? = TRUE][set detected? detect]
ask mussels with [detected? = TRUE] [set color red set pcolor green]
end
;procedure to create initial clusers
to create-clusters
let tmp1 1
ask n-of num-initial-clusters patches [
set pcolor pop-color
set cluster? TRUE
set cluster-ID tmp1
set tmp1 tmp1 + 1
set cluster-ring 0
set quadrat? TRUE
]
ask mussels-on patches with [quadrat? = TRUE][set detected? detect]
ask mussels with [detected? = TRUE] [set color red]
set clusters patches with [cluster? = TRUE]
end
;procedure that determines when to stop adaptive clusters
to-report adapt-cluster?
set adapt? FALSE
if any? patches with [(cluster?) and (any? mussels-here with [detected? = true]) and (any? neighbors4 with [cluster? = FALSE])] [
set adapt? TRUE
]
if total-clusters >= max-clusters [set adapt? FALSE]
report adapt?
end
;procedure to expand clusers
to build-cluster
if adapt-cluster? = TRUE [
ask patches [
if any? mussels-here with [detected? = TRUE] and any? neighbors4 with [cluster? = FALSE] [
ask neighbors4 with [cluster? = FALSE] [
if total-clusters < max-clusters [
set cluster? TRUE
set quadrat? TRUE
ask mussels-here [set detected? detect]
ask mussels with [detected? = TRUE] [set color red]
set pcolor [pcolor] of myself + 0.3
set cluster-ID [cluster-ID] of myself
set cluster-ring ( [cluster-ring] of myself + 1 )
set total-clusters count patches with [cluster?]
if not any? mussels-here with [detected? = TRUE] [set cluster-edge? TRUE]
]
]
]
]]
end
;calculate Hansen-Herwitz estimators
to calc-hh-estimates
let network-avg-list []
let tmp 1
let L 50 ;length in m
let W 10 ;width in m
let num-cells (L * W) / (quadrat-size ^ 2) ;number of grid cells or patches in model
while [tmp <= num-initial-clusters][
let mussels-per-network count (mussels with [cluster-ID = tmp and detected? = TRUE])
let network-size count (patches with [cluster-ID = tmp and cluster-edge? = 0])
set tmp tmp + 1
let network-avg mussels-per-network / network-size
set network-avg-list lput network-avg network-avg-list
]
set hh-estimated-density-m (1 / num-initial-clusters * (sum network-avg-list)) / (quadrat-size ^ 2)
set hh-estimated-total-pop hh-estimated-density-m * (num-cells * (quadrat-size ^ 2))
set hh-estimated-density-var (1 / (num-initial-clusters * (num-initial-clusters - 1)) *
(sum (map [x -> (x - hh-estimated-density-m) ^ 2] network-avg-list))) / (quadrat-size ^ 2) ^ 2
set hh-estimated-pop-var ((num-cells * (quadrat-size ^ 2)) ^ 2) * hh-estimated-density-var
end
;procedure to determine colors of clusters
to-report pop-color
if empty? color-list [set color-list color-list2]
let $color first color-list
set color-list but-first color-list
report $color
end
;function to add surveyors
to add-surveyors
let xcord min-pxcor
let ycord-list []
let new-ycord 0
foreach [1 2 3] [
set new-ycord ((max-pycor ) / 4) + new-ycord
set ycord-list lput new-ycord ycord-list
]
foreach ycord-list [
x ->
create-surveyors 1 [
setxy xcord x
set size 4
set color yellow
set quadrats-searched 0
set mussels-found 0
set tick-since-last-find 999
set search-mode one-of [ true false ]
set counter 0
set destination max-pxcor
set reached-destination-once? False
set reached-destination? False
facexy max-pxcor ycor
pen-down
]
]
end
;procedure to move surveyors
to timed-search
;determine if search mode is T or F
ask surveyors[
ifelse variable-search-mode = True [
( ifelse
tick-since-last-find <= 20 [
set search-mode True]
ticks mod 10 = 0 [
set search-mode search-mode = False]
[])
]
[set search-mode True]
]
;check if surveyors reached destination
ask surveyors [
if pxcor = destination [
set reached-destination-once? true
set reached-destination? True
]
]
;check if surveyors are out of time
ask surveyors [
set out-of-time? False
set quarter find-quarter
if reached-destination-once? = False [
if (quarter = 1 and (timed-search-minute-counter / 60) > (person-hours-to-search * 0.25)) or
(quarter = 2 and (timed-search-minute-counter / 60) > (person-hours-to-search * 0.5)) or
(quarter = 3 and (timed-search-minute-counter / 60) > (person-hours-to-search * 0.75)) or
(quarter = 4 and (timed-search-minute-counter / 60) > (person-hours-to-search))
[
set out-of-time? True
set search-mode False
]
]
]
;check if surveyors are at edge or corner
ask surveyors [
;at an edge?
set at-vertical-edge?
([pxcor] of patch-ahead 0 >= max-pxcor and heading > 0 and heading < 180) or
([pxcor] of patch-ahead 0 <= min-pxcor and heading > 180)
set at-horizontal-edge?
([pycor] of patch-ahead 0 >= max-pycor and (heading > 270 or heading < 90)) or
([pycor] of patch-ahead 0 <= min-pycor and heading > 90 and heading < 270)
;at a corner?
set cornered?
(pxcor = min-pxcor and pycor = max-pycor) or
(pxcor = max-pxcor and pycor = max-pycor) or
(pxcor = min-pxcor and pycor = min-pycor) or
(pxcor = max-pxcor and pycor = min-pycor)
]
;procedure to determine which direction surveyors move
ask surveyors[
(ifelse
;if at corner spin until you get out
cornered?[
right (random 360)
]
;if at edge of world turn around
at-vertical-edge? [
if reached-destination? [
set reached-destination? False
ifelse destination = max-pxcor [set destination 0] [set destination max-pxcor]
]
set heading (- heading)
]
at-horizontal-edge? [
set heading (180 - heading)
]
;if out of time to search section, head towards next section
out-of-time? [
facexy destination ycor
right util-random-range -10 10
]
;avoid other surveyors
any? other surveyors in-cone (meters-to-quadrats 2) 90 [
right one-of (list 90 -90)
]
;if recently found mussel turn more sharply
tick-since-last-find <= 20 [
right util-random-range -90 90
]
;if a patch where something was recently found is near
any? other surveyors with [tick-since-last-find <= 20] and any? mussels with [(ticks - tick-detected) <= 20] in-radius meters-to-quadrats 5 [ ;WORKSHOP THIS NUMBER
right util-random-range -90 90
set search-mode True
]
;if other surveyors found something and you have not, face towards closest patch where something was recently found
any? mussels with [detected? = TRUE and ((ticks - tick-detected) <= 20) and (quarter = [quarter] of myself)] [
let closest min-one-of (mussels with [(ticks - tick-detected) <= 20 and quarter = [quarter] of myself]) [distance myself];
face closest ;if two others found something, face closest
right util-random-range -10 10]
;or else face more or less forward
[
facexy destination ycor
right util-random-range (0 - 45) 45
]
)
]
;Surveyors step forward
ask surveyors [fd 1]
;patch with surveyors on it becomes quadrat
ask surveyors [
ifelse search-mode = True [
set quadrats-searched quadrats-searched + 1
ask patch-here [set quadrat? TRUE]
ask mussels-here with [detected? = FALSE] [
set detected? detect
if detected? = TRUE [
set detected-id (word myself "-" ticks)
set tick-detected ticks
set color red
]
if detected? = FALSE [set detectability random-float 1]
]
set timed-search-minute-counter timed-search-minute-counter + ((quadrat-size ^ 2) * 2)
]
[
set timed-search-minute-counter timed-search-minute-counter + ((quadrat-size ^ 2) * 0.05)
]
]
;surveyor updates time since last tick and patch color
ask surveyors [
(ifelse
any? mussels-here with [detected? = TRUE and detected-id = (word myself "-" ticks) ]
[
set tick-since-last-find 0
set mussels-found mussels-found + count mussels-here with [detected? = TRUE and detected-id = (word myself "-" ticks)]
set pcolor green
]
search-mode = True
[set tick-since-last-find tick-since-last-find + 1
if pcolor != green [set pcolor pink]]
;else
[set tick-since-last-find tick-since-last-find + 1]
)
]
end
;function to calculate metrics after the model runs
to calculate-metrics
set total-rare-mussels count (mussels with [species = "rare"])
set total-common-mussels count(mussels with [species = "common"])
set total-med-rare-mussels count (mussels with [species = "med-rare"])
set total-mussels-sampled count mussels-on patches with [quadrat? = TRUE]
set rare-mussels-sampled count (mussels with [quadrat? = TRUE and species = "rare"])
set common-mussels-sampled count(mussels with [quadrat? = TRUE and species = "common"])
set med-rare-mussels-sampled count (mussels with [quadrat? = TRUE and species = "med-rare"])
set total-num-quadrats count patches with [quadrat? = TRUE]
set total-quadrats-surveyed sum [quadrats-searched] of surveyors
set total-mussels-detected count mussels with [detected? = TRUE]
set rare-mussels-detected count (mussels with [quadrat? = TRUE and species = "rare" and detected? = TRUE])
set common-mussels-detected count(mussels with [quadrat? = TRUE and species = "common" and detected? = TRUE])
set med-rare-mussels-detected count (mussels with [quadrat? = TRUE and species = "med-rare" and detected? = TRUE])
;create empty list to hold surveyor counts of mussels detected
set mussels-per-surveyor-list [0 0 0]
;if method is transect, calculate estimated density
if sampling-method = "transect" or sampling-method = "simple-random-sample"[
;estimated mussel density is the number of mussels found/quadrats samples
set estimated-mussel-density total-mussels-detected / quadrats-to-meters-sq total-num-quadrats
set sample-cv cv
output-print (word "estimated density (m^2): " estimated-mussel-density)
output-print (word "coefficient of variation: " sample-cv)
output-print (word "sq meters searched: " (total-num-quadrats * (quadrat-size ^ 2)) )
output-print (word "total mussels found: " total-mussels-detected)
]
ifelse sampling-method = "timed-search"
[
;timed search minute counter divided by 60
set person-hours timed-search-minute-counter / 60
]
[
;number of square meters searched x 2 minutes divided by 60
set person-hours ((quadrats-to-meters-sq total-num-quadrats) * 2) / 60
]
;if method is random walk, calculate mussels per person hour
if sampling-method = "timed-search" [
;create empty list to hold surveyor counts of mussels detected
set mussels-per-surveyor-list []
;ask surveyors to add mussels found to list
ask surveyors [
set mussels-per-surveyor-list fput mussels-found mussels-per-surveyor-list
]
;mussels per person hour is the number of mussels per each hour searching per each surveyor
set mussels-per-person-hour total-mussels-detected / (timed-search-minute-counter / 60)
set sample-cv "NA"
output-print (word "total person-hours: " (timed-search-minute-counter / 60))
output-print (word "sq meters searched: " (total-num-quadrats * (quadrat-size ^ 2)) )
output-print (word "total mussels found: " total-mussels-detected)
output-print (word "mussels per person hour: " mussels-per-person-hour)
]
;if the method is adapt, calculate hh metrics
if sampling-method = "adaptive-cluster" [
calc-hh-estimates
set sample-cv cv
output-print word "estimated density (HH): " hh-estimated-density-m
output-print word "estimated pop: " hh-estimated-total-pop
output-print word "estimated density var: " hh-estimated-density-var
output-print word "estimated pop var: " hh-estimated-pop-var
output-print (word "coefficient of variation: " sample-cv)
output-print (word "sq meters searched: " (total-num-quadrats * (quadrat-size ^ 2)) )
output-print (word "mussels found: " total-mussels-detected)
]
end
;function to create csv file and write column headings (will save over file if one exist with same name)
to initialize-file
set output-file-mussels (word "Results/" file-name ".csv" )
if(file-exists? output-file-mussels) [
carefully
[
file-close
file-delete output-file-mussels]
[print error-message]
]
if not file-exists? output-file-mussels [
file-open output-file-mussels
;write column headings
file-type "Rep,"
file-type "Quadrat Edge Length,"
file-type "Sampling Method,"
file-type "True Mussel Density,"
file-type "Total Mussels,"
file-type "Total Rare Mussels,"
file-type "Total Medium Mussels,"
file-type "Total Common Mussels,"
file-type "Detectability of Rare Mussels,"
file-type "Detectability of Medium-Rare Mussels,"
file-type "Detectability of Common Mussels,"
file-type "Spatial Distribution,"
file-type "Number of clumps,"
file-type "Poisson mean,"
file-type "Matern Clump Placement,"
file-type "Variance to Mean Ratio,"
file-type "SRS Num Quadrats,"
file-type "Number Transects,"
file-type "Number Quadrats Per Transect,"
file-type "ACS Num Quadrats,"
file-type "ACS Max Clusters,"
file-type "Timed Search variable Search mode,"
file-type "Timed Search max PH,"
file-type "Timed Search detect reduction,"
file-type "Total Quadrats Sampled,"
file-type "Total Mussels in Quadrats,"
file-type "Rare Mussels in Quadrats,"
file-type "Medium Rare Mussels in Quadrats,"
file-type "Common Mussels in Quadrats,"
file-type "Total Mussels Detected,"
file-type "Rare Mussels Detected,"
file-type "Medium Mussels Detected,"
file-type "Common Mussels Detected,"
file-type "Person Hours Searched,"
file-type "Sum of Quadrats per Surveyor,"
file-type "Mussels detected by Surveyor 1,"
file-type "Mussels detected by Surveyor 2,"
file-type "Mussels detected by Surveyor 3,"
file-type "Estimated Density,"
file-type "Sample CV,"
file-type "Mussels Per Person Hour,"
file-type "HH metric,"
file-print "HH Variance," ;last line must be file-print
file-close ;close file
]
end
;function to save metrics into output file
to save-results
calculate-metrics
if not file-exists? output-file-mussels [initialize-file]
file-open output-file-mussels
file-type (word behaviorspace-run-number ",")
file-type (word quadrat-size ",")
file-type (word sampling-method ",")
file-type (word mussels-per-meter ",")
file-type (word #-of-mussels ",")
file-type (word total-rare-mussels ",")
file-type (word total-med-rare-mussels ",")
file-type (word total-common-mussels ",")
file-type (word detect-rare ",")
file-type (word detect-med-rare ",")
file-type (word detect-common ",")
file-type (word spatial-distribution ",")
file-type (word num-groups ",")
file-type (word poisson-mean-meters ",")
file-type (word matern-clump-placement ",")
file-type (word var-mean-ratio ",")
file-type (word quadrats-to-sample ",")
file-type (word number-of-transects ",")
file-type (word quadrats-on-transect ",")
file-type (word num-initial-clusters ",")
file-type (word max-clusters ",")
file-type (word variable-search-mode ",")
file-type (word person-hours-to-search ",")
file-type (word detect-reduction ",")
file-type (word total-num-quadrats ",")
file-type (word total-mussels-sampled ",")
file-type (word rare-mussels-sampled ",")
file-type (word med-rare-mussels-sampled ",")
file-type (word common-mussels-sampled ",")
file-type (word total-mussels-detected ",")
file-type (word rare-mussels-detected ",")
file-type (word med-rare-mussels-detected ",")
file-type (word common-mussels-detected ",")
file-type (word person-hours ",")
file-type (word total-quadrats-surveyed ",")
file-type (word item 0 mussels-per-surveyor-list ",")
file-type (word item 1 mussels-per-surveyor-list ",")
file-type (word item 2 mussels-per-surveyor-list ",")
file-type (word estimated-mussel-density ",")
file-type (word sample-cv ",")
file-type (word mussels-per-person-hour ",")
file-type (word hh-estimated-density-m ",")
file-print (word hh-estimated-density-var ",")
file-close ;close file
end
;reports if mussel is detected or not (T/F)
to-report detect
(ifelse
sampling-method != "timed-search" [
ifelse detectability <= detect-threshold [report TRUE][report FALSE]
]
[
ifelse detectability <= detect-threshold - detect-reduction [report TRUE][report FALSE]
]
)
end
;reports the variance to mean ratio --sensitive to patch size
to-report var-to-mean-ratio
let n count patches
let mean-mussels-on-patches mean [mussels-on-patch] of patches
let patch-mussel-var ( sum [((mussels-on-patch - mean-mussels-on-patches) ^ 2)] of patches ) / n
report (patch-mussel-var / mean-mussels-on-patches)
end
to-report cv
let quadrats patches with [quadrat? = TRUE]
let mussels-per-quadrat-list []
ask quadrats [
let mussels-on-self mussels-on self
let detected-mussels-on-patch count mussels-on-self with [detected? = TRUE]
set mussels-per-quadrat-list fput detected-mussels-on-patch mussels-per-quadrat-list
]
let mean-count mean mussels-per-quadrat-list
let std-dev standard-deviation mussels-per-quadrat-list
let coef-var "NA"
if mean-count != 0
[set coef-var std-dev / mean-count]
report coef-var
end
;converts linear distance in meters to distance in patch size
to-report meters-to-quadrats [x-distance]
report x-distance / quadrat-size
end
;converts number of quadrats to square meters