Exporting a list of patches to a shapefile in NetLogo - netlogo

I'm building an agent-based model in NetLogo where the agents walk to a target. I'm using the GIS Extension for NetLogo 6.3. At each tick they record the patch where they are currently standing on a list called "path".
I want to include a button to export this list to a shapefile, but I don't know how to do it. I believe I need to use the "gis:store-dataset" function. I'm using it like this:
to export-path
let file (word "path_output.shp")
if file-exists? file [file-delete file]
file-open file
let exported-path path
gis:store-dataset exported-path file
end
At the interface page I've set up a button calling the procedure with an ask turtles []. However I got the error message saying that this is not a dataset. Anyone can help me with this?
Thanks.

For computation and precision (depending on how big of an area your patches represent) I would suggest that instead of storing the patches in their lists, the turtles simply record their coordinates (using something like envelope-of) so that you can use your GIS to translate their coordinates into a shapefile with finer control:
extensions [ gis csv ]
turtles-own [ path ]
to setup
ca
reset-ticks
let shp_path "C:/gis_example/british_columbia_administrative.shp"
let prj_path "C:/gis_example/british_columbia_administrative.prj"
gis:load-coordinate-system prj_path
let shp gis:load-dataset shp_path
let base_envelope gis:envelope-of shp
gis:set-world-envelope-ds base_envelope
gis:set-drawing-color white
gis:draw shp 1
ask n-of 3 patches [
sprout 1 [
set path ( list self-ticks-coords )
show path
]
]
end
to-report self-ticks-coords
; Report the current ticks and then middle two 'envelope' values of the turtle
report sentence ticks (reduce sentence sublist gis:envelope-of self 1 3)
end
to go
ask turtles [
rt random 60 - 30
fd 1
set path lput self-ticks-coords path
]
tick
end
to go-10-then-export
repeat 10 [
go
]
let out-list reduce sentence [self-who-tick-coords] of turtles
set out-list fput [ "who" "tick" "x" "y" ] out-list
csv:to-file "C:/gis_example/example_coords.csv" out-list
end
to-report self-who-tick-coords
; Report a formatted list of who, tick, and coordinate vlaues
let who-tick-coord-list map [ i -> ( sentence who i ) ] path
report who-tick-coord-list
end
This exports a csv that stores the turtle identifier, the timestep, and coordinates (and flexibly can store whatever info you need) which I find more useful. My two cents!
Dataset downloaded from MapCruzin.com

Related

Netlogo - Iterating through patch list and writing each output to a row in a list

I have a list of cells destination_cells, and am trying to loop through each cell and count the number of turtles and the average weight of the turtles in each. For each cell, I want to write the cell's ID (which I am assuming is just destination_cells as coordinates) and the two variables to a list cell_list. I think my confusion stems from not understanding how to use anonymous reporters in foreach. If I replace 'next cell' with destination_cells in the foreach block, I get, for example, the same total_turtle_in_destination_cells value for every single cell in destination_cells. The same occurs with using next_cells in the block. Where am I making a mistake?
set destination_cells [self] of patches with [ any? turtles-here]
foreach destination_cells [next_cell -> ask next_cell
[
; Counts number of turtles in each cell
set total_turtle_in_destination count turtles-on destination_cells
; Finds average weight of turtles in each cell
set avg_weight_turtle_in_destination mean [mass] of turtles-on destination_cells
]
set cell_list lput (csv:to-row (list
destination_cells
total_turtle_in_destination
avg_weight_turtle_in_destination
)) cell_events_list
]
Here is an alternative that:
Makes a reporter to get the info desired (the patch info as patch x and y, the total turtles on a patch, the mean weight of present turtles) from whatever patch that calls the reporter
Updates the info list directly by querying the destination_cells
turtles-own [ weight ]
globals [ destination_cells cell_info_list]
to setup
ca
resize-world 0 5 0 5
set-patch-size 30
reset-ticks
crt 20 [
set weight random 10 + 1
move-to one-of patches
]
end
to-report report-self-info
let n_turtles_here count turtles-here
let mean_weight mean [weight] of turtles-here
report (list self n_turtles_here mean_weight)
end
to create-info-list
set destination_cells patches with [ any? turtles-here]
set cell_info_list [report-self-info] of destination_cells
print cell_info_list
end
In response to your question "how can the patch call the reporter? I tried ask destination_cell [report-self-info], but a command is expected":
When you make a to-report procedure with the structure like the above that uses self, it's somewhat like a turtles-own or patches-own variable. In this case, you can call it just as you would have a turtle variable like color or xcor or a patch variable like pcolor or pxcor- if you run something like:
ask one-of patches [ print report-self-info ]
You should get something like
[(patch 5 2) 2 7.5]
This is why the set cell_info_list [report-self-info] of destination_cells above works- because you could do something like set cell_info_list [pcolor] of destination_cells in a similar way.

How to extract the path taken by each turtle in the world and save it in a .csv file?

I'm still trying to extract the coordinates of the path taken by every turtle in the world. For example, I would like to know the path taken by turtle 0 was patch 00 patch 0 5 patch 0 2 and patch 1 4 and save this information in a .csv file. In this way, I would like to extract the coordinates of the path taken by all the turtles in the world. I'm thinking about creating a list that gives me this information and then saving it.
The problem is that I cannot create an empty list for each turtle created and then, before every move, add the current patch location to the lists. And finally, generate the file of this information in .csv
That is, when inspecting the turtle I don't see the list and when creating the file in .csv it is not generated. Can anyone help me with the code?
Thanks in advance
turtles-own [ mypathx mypathy mytimer]
to setup
ca
reset-ticks
crt 5
ask turtles [
setxy random-xcor random-ycor
let i [ ]
pen-down
]
end
to go
move
let n count turtles
if n = 0 and output? = true [output] ;; ouput? is an switch on interface
if n = 0 [ stop ]
tick
end
to move
ask turtles [
rt random 360
fd 1
if ticks >= 10
[
die
]
]
end
To output
file-open "test.txt"
ask turtles [
set mypathx lput pxcor mypathx
set mypathy lput pycor mypathy
let maxer length mypathx
let i 0
repeat maxer
[
file-print (word item i mypathx " " item i mypathy " " item i mytimer)
let x ( i + 1 )
]
]
file-close
end
There are a number of things to note here, so I hope I understood what you inteded to do.
First of all, note that your code goes to output only after all the turtles died (that is infact one of the conditions to go to output: if n = 0). Therefore, it is normal that there is no data to be exported: in output you ask turtles, but when output is executed all turtles already left the simulation.
However, there is also something that Filip rightly noticed in the comment to the question: it seems logical to ask turtles to save the coordinates of their journey as they move - as opposed to asking them to do so at the end of the simulation.
Based on the current code, turtles simply move in the simulation, and only at the end (e.g. when output is called) they are are asked to save their current location. It would be ideal to include a piece of code where you ask turtles, after each move, to record their location in the list.
To combine this point and the previous one, I would do something like:
to setup
clear-all
reset-ticks
create-turtles 5 [
; I talk about this piece in point 3.
]
end
to go
move
tick
end
to move
ask turtles [
right random 360
forward 1
register-coordinates
]
end
to register-coordinates
set mypathx lput pxcor mypathx
set mypathy lput pycor mypathy
set mytimer lput ticks mytimer ; This is what I assumed you want mytimer to do.
end
And here comes the other problem. You are not initiating the turtles-own variables as lists.
If you run your piece of code now, nothing happens because all turtles are dead by the time you ask them to output. But if you just remove the die command, or if you ask turtles to output before they die, you would get an error - saying that lput expected a list but got something else instead.
From the NetLogo Dictionary you can see that the list primitive is used to create a list with two values.
If you want to create a list containing any other amount of values, you have to use (list ...). This includes the case in which you want to create an empty list. To do that, I would therefore do:
create-turtles 5 [
setxy random-xcor random-ycor
set mypathx (list)
set mypathy (list)
set mytimer (list)
pen-down
]
Now, mypathx, mypathy and mytimer are legal inputs to the lput procedure.
Finally, you can include the output at the end of your simulation (note how I changed go compared to the previous code example):
to go
if ticks = 11 [
ask turtles [output]
stop
]
move
tick
end
...
to output
file-open "test.csv"
file-print (word who "," mypathx "," mypathy "," mytimer)
file-close
end
So, overall, improtant adjustments are: initiate variables as lists if you want to treat them as such; ask your turtles to save their coordinates at every step in their turtles-own list variables; only at the end, ask them to write their list variables in the output file; do not kill your turtles before you ask them to output information.
Integrating all of the above, the code would look like:
turtles-own [mypathx mypathy mytimer]
to setup
clear-all
reset-ticks
create-turtles 5 [
setxy random-xcor random-ycor
set mypathx (list)
set mypathy (list)
set mytimer (list)
pen-down
]
end
to go
if ticks = 11 [
ask turtles [output]
stop
]
move
tick
end
to move
ask turtles [
right random 360
forward 1
register-coordinates
]
end
to register-coordinates
set mypathx lput pxcor mypathx
set mypathy lput pycor mypathy
set mytimer lput ticks mytimer
end
to output
file-open "test.csv"
file-print (word who "," mypathx "," mypathy "," mytimer)
file-close
end
Final notes on the code above:
I am not sure which exact format you want your output to be, but this example code works fine in saving the lists in the .csv file - so you can take it from there and play around to make it fit your needs.
I removed the pcolor part because it seemed unnecessary for the purpose of the question.
I am not sure what you wanted i to do in setup, but it seemed unnecessary for the purpose of the question so I removed that too from my exemplar code. Be careful at how you use item: I don't know what you wanted to do, but the way you included it in your question was often giving runtime errors.
I created a .csv as per the title of the question, instead of a .txt as per the code you provided.

Selecting an item from a list in Netlogo

I'd need to pick an object in a bag containing 20 elements with attributes c (color) and s (size). Both color and size are numbers (e.g. c= {red = 256, black = 0, ... } = {256, 0, ...}).
As in Python I'd use random.choice in numpy library, I found on the web that the corresponding function in Netlogo is the extension rnd.
Struggling along a possible solution, I did
Edited:
breed[people person]
people-own
[
ball
size
color
bag
]
to setup
create-people 5
[ set color gray
setxy random-xcor random-ycor
]
ask people[
set bag [ ] ; 0 items
]
end
To create the balls:
to create-balls
set color random 300 ; color
set size random-float 5 ; size
let this-ball self
ask one-of people [ ; ask one of people to put the ball created into the bag
set bag fput this-ball bag ; add ball to the bag
]
end
The code below should include the part of drawing:
to draw
ask one-of people [
rnd:weighted-one-of bag [ ] ; I do not know what I'd write in the brackets
]
end
As you can easily see, I've many doubts about how to implement the code.
How can I select one item from the bag depending on its size (or color)?
Can you please help me out with it?
Here is a complete model that creates people and balls as turtle agents and has 30 of the balls get chosen weighted by their size. It then opens an inspect window for the person who has chosen the most balls.
extensions [rnd]
breed [people person]
people-own [ my-balls ]
breed [balls ball]
balls-own [ chosen? ]
to setup
clear-all
create-people 20
[ setxy random-xcor random-ycor
set my-balls (turtle-set nobody)
]
create-balls 50
[ hide-turtle
set size one-of [1 2 3 4 5]
set color one-of [red white blue yellow]
set chosen? false
]
repeat 30 [draw-ball]
inspect max-one-of people [count my-balls]
end
to draw-ball
ask one-of people
[ let bag-of-balls balls with [not chosen?]
let choice rnd:weighted-one-of bag-of-balls [size]
ask choice [set chosen? true]
set my-balls (turtle-set my-balls choice)
]
end
Some things to notice:
There are NO lists in this code. There are situations where you should use lists. Common uses include memory where the order is important (eg you only want to keep track of the last 5 other people seen) or where the same agent can appear multiple times. And the list commands are very powerful. However, unless you need a list then you should use agentsets.
Each person has their own bag called 'my-balls' that contains the balls they select. That is initialised as a turtle-list as part of the setup.
I used a variable called 'chosen?' that is owned by each ball to track whether it is still in the bag for the next person to choose. Then the bag-of-balls is created only as all the balls not yet chosen.
The code for weighted random choice (when choosing from agentsets) simply has the name of the variable holding the weight as the reporter, but you could use some function such as rnd:weighted-one-of bag-of-balls [size ^ 2] if you wanted a more complicated weighting scheme.

Netlogo: Making a turtle interact with anotherone after evaluating similarity in a given variable

I have several turtles each with three variables opinion1, opinion2 and opinion3. I need them to:
identify which of these three variables has the highest value
find another turtle in their network with a value at least as high
as the one found in 1.
update its own value found in 1. with
respect to that of the turtle found in 2.
What I have done doesn't really work because it only updates looking at o1 without really having a look at which of the tree (opinion1, opinion2 or opinion3) is the highest and THEN looking for a neighbour.
to update-opinion
ask turtles [
let my-nearby-turtles nw:turtles-in-radius 1
let my-opinion1 opinion1
set neighbour one-of my-nearby-turtles with [ opinion1 > my-opinion1 ]
if neighbour != nobody [
let opinion_n [opinion1] of neighbour
set opinion1 ((opinion1 + opinion_n) / (2))
]
]
end
I don't know a simple way to do this with unique variables like opinion1 etc, but maybe having a list of opinions instead of individual variables for each opinion will work. For example, with this setup:
extensions [ nw ]
turtles-own [
opinions
]
to setup
ca
resize-world -5 5 -5 5
set-patch-size 30
crt 30 [
set shape "dot"
set opinions n-values 3 [ precision random-float 10 2]
set color scale-color blue sum opinions -5 35
while [ any? other turtles-here ] [
move-to one-of neighbors4
]
]
ask turtles [
create-links-with turtles-on neighbors4
]
reset-ticks
end
You get something like this:
Where each turtle has an opinions list variable that is three items long. Now, you can have each turtle determine its highest opinion value using max, get that maximum values index position in the list using position, and then query that turtle's neighbors to see if any of them have a higher value in the same index position. If they do, modify your asking turtles opinions list using replace-item to be the average of the two values:
to go
ask turtles [
; Get adjacent turtles
let my-nearby-turtles nw:turtles-in-radius 1
; Identify the highest highest value variable of
; the current turtle, and get its list position
let my-opinion max opinions
let my-op-ind position my-opinion opinions
; Pick one of the turtles whose value in the same indexed
; position is higher than my-opinion
let influence one-of my-nearby-turtles with [
item my-op-ind opinions > my-opinion
]
; If that turtle exists, update my own opinions list as appropriate
if influence != nobody [
let new-opinion precision (
( [ item my-op-ind opinions ] of influence + my-opinion ) / 2
) 2
set opinions replace-item my-op-ind opinions new-opinion
]
set color scale-color blue sum opinions -5 35
]
tick
end
Hopefully that is sort of on the right track, not sure if a list will work for what you need. If you must have the variables as standalone values at each tick, I suppose you could convert them to a list then follow the procedure above. If you only need them for output, you could just update your unique variables as needed based on the values in the list (as long as you are consistent with the order).

Netlogo: Set specific setxy patern with set number of turtles?

Is it possible to create a set number of turtles, from a file, to have their own patches? Like always be in the same location?
I've got 106 turtles I'm reading in from a file and I was hoping to have them be created on their own patches, like a square latice kind of thing. I want to be able to look at the model world and easily identify a turtle.
file-open "turtledata_A.txt"
show file-read-line
while [not file-at-end?]
[
set param read-from-string (word "[" file-read-line "]")
create-turtles 1 [setxy ??]
]
file-close
]
Probably easiest to use the csv extension and just add xy data to the file you're reading in. For example, if you have a turtle_data.csv file that looks like:
param-to-read,x,y
John,-10,10
Billy,-5,5
Bob,0,0
Simon,5,-5
Michael,10,-10
You can do:
extensions [ csv ]
turtles-own [ param ]
to setup
ca
reset-ticks
file-close-all
file-open "turtle_data.csv"
;; read the headings line in to skip it for data extraction
let headings csv:from-row file-read-line
while [ not file-at-end? ] [
let data csv:from-row file-read-line
create-turtles 1 [
set param item 0 data
setxy item 1 data item 2 data
]
]
file-close-all
end
which would give you something like:
Then you can modify the x and y values in your .csv file to place your turtles where you want them. Would that work?
Of course, you can add other columns in the .csv file (like color, size, shape, etc) that will help you identify turtles at a glance.