Read a file one line per tick - netlogo

I model archaeological settlement distributions and dynamics.
I want to annually update the number of houses at the settlement sites using a .csv file similar to this one:
Settlement 1
0
1
5
...
I have two questions on that:
1) I do not succeed with the procedure as proposed in the Netlogo manual. There it reads
"to go
if file-at-end? [ stop ]
set data csv:from-row file-read-line
tick
end"
BUT csv:from-row results in an error message ("nothing named... is defined"). How do I do this?
2)
I have more than just one site. Is there a way to use only one .csv - file such as
Settlement 1,Settlement 2,Settlement 3
0,0,0
1,0,0
5,0,1
...
and make sure that Settlement 1 updates houses according to column 1, Settlement 2 according to column 2 etc?
Thank you for your help!
Til

extensions [csv]
globals [settlements-list] ;;to keep them in order
breed [settlements settlement]
settlements-own [n-houses]
to setup
file-close-all
ca
create-settlements 3 ;;3 settlements, to match your example
set settlements-list [self] of settlements ;;or sort if you wish
file-open "c:/temp/temp.csv"
let _trash file-read-line ;;discard headers
end
to go
file-open "c:/temp/temp.csv"
if file-at-end? [ stop ] ;;or at least, stop reading data!
let _data csv:from-row file-read-line ;;get data as list
foreach n-values length settlements-list [?] [
ask (item ? settlements-list) [set n-houses item ? _data]
]
ask settlements [
show n-houses
]
end

Related

Exporting a list of patches to a shapefile in 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

Netlogo: How to subset with row and column indexes

Could someone help me out with the code on reading in data in Netlogo? I am trying to choose one element in multiple lists to assign it to the turtle as a variable (I have the data in a rectangular table read from a csv file).
In my current code, it reads as I want but the problem is it is reading only elements of one last row instead of iteratively reading elements (across columns) of all rows. What I need is to read one element of each row at a time.
here are some rows of my data
Here is what I have tried so far:
let residents-file "mock-data.csv"
let residents-list []
set residents-list csv:from-file residents-file
foreach residents-list [ ?1 ->
let hh-col ?1row
let residents-to-create 1
create-residents residents-to-create [ setxy random-xcor random-ycor ]
ask residents [
set shape "person"
set color 9
set ID item 0 hh-col
set occupancy item 1 hh-col]]
It looks like the issue is that you are using create-residents to create n residents, but then asking all residents to do something. In other words, no matter which row is currently being processed, all of the existing residents (whether created in this iteration or created in previous iterations) are being asked to pull the values from the row that is being processed on the current iteration.
The easiest way to fix this is probably just to have each resident pull the values as it's being created.
With this toy version of your dataset:
id occupancy
1 owner
2 renter
3 owner
4 renter
5 owner
Here is a simplified example:
breed [ residents resident ]
residents-own [ id occupancy ]
extensions [csv]
to setup
ca
let residents-file "mock-data.csv"
let residents-list but-first csv:from-file residents-file
foreach residents-list [ cur-row ->
create-residents 1 [
set id item 0 cur-row
set occupancy item 1 cur-row
]
]
ask residents [
print ( word "My who is " who ", my id is " id ", and my occupancy is " occupancy )
]
reset-ticks
end
Output should look something like:

Different results of reporters turtles/turtle x

I have created an opinion dynamics model, that works just fine. But now I wanted to see, how the opinion of all of my turtles changes. So I created the reporter "report [opinion] of turtles". When I put this in behaviorspace I get wildly jumping results that do not correspond with what I observe. If I test this with individual turtles like "report [opinion] of turtle 0", I get the smooth curve progression that I expected to see.
Does anyone know why this is happening? I would find it rather unwieldy, if I had to put every turtle individually in my behaviorspace, because I have sliding Agentsnumbers.
You can let each turtle have a list variable, at the beginning of which each turtle will record its ID. At every step, each turtle will append its opinion value.
Then you can have a global variable, which you will use as a list of lists, to which at the end of the simulation each turtle will append its own list.
In BheaviorSpace, you will only need to use one reporter (the list of lists) at the end of each experiment's run.
See below for a working example:
globals [
results
]
turtles-own [
opinion
my-list
]
to setup
clear-all
reset-ticks
set results (list)
create-turtles 3 [
set opinion random 10
set my-list list self opinion
]
end
to go
if (ticks = 5) [
ask turtles [
set results lput my-list results
]
stop
]
ask turtles [
set opinion opinion + 1
set my-list lput opinion my-list
]
tick
end
At the end of each run, the results reporter will look like:
[[(turtle 2) 3 4 5 6 7 8] [(turtle 0) 0 1 2 3 4 5] [(turtle 1) 5 6 7 8 9 10]]
Note that, this way, the lists in results will always be in random order.
If you're interested in having them ordered according to some criterion, you can do it.
The example below changes the if (ticks = 5) statement to order results according to turtles' ID, but you can just use sort on whatever characteristic you're interested in.
if (ticks = 5) [
let sorted-turtles sort turtles
foreach sorted-turtles [this-turtle -> ask this-turtle [set results lput my-list results]]
stop
]

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.

NetLogo : what is a good way for Storing link values and deducting the dead link values without calling links more than 1 time?

I am sorry to keep asking about links, but one of the features that I am going to add to my model is considering collective mutual relationship of people of different villages in village's future relationships,
I have a few thousand links and it's not efficient to call links and get their value whenever the village wants to make a decision (the decision is made every 48 ticks at clock 0)
Agents own belongs_to which is one one "Village1" Village2" Village3" or "Village4"
Links have a Value of Relationship.
This is the function I used to update links value:
to Update_link_Values [Other_Agent Value]
if self != Other_Agent
[
ifelse out-link-neighbor? Other_Agent
[
ask out-link-to Other_Agent
[
set Value-Of-The-Relationship Value-Of-The-Relationship + Value
set-List-of-Mutual-Obligations
]
]
[
create-link-to Other_Agent
[
set Value-Of-The-Relationship Value-Of-The-Relationship + Value
set-List-of-Mutual-Obligations
]
]
]
end
if I use following formula to store sum of relationship values for different villages it takes 0.003 MS to calculate all mutual relationship values
if [belongs_to] of end1 = "Village1" and [belongs_to] of end2 = "Village2"
[
set List-of-Mutual-Obligations replace-item 0 List-of-Mutual-Obligations (item 0 List-of-Mutual-Obligations + Value-Of-The-Relationship)
]
While this one takes 1.002 MS to execute,
if [belongs_to] of end1 = "Village1" and [belongs_to] of end2 = "Village2"
[
set List-of-Mutual-Obligations replace-item 0 List-of-Mutual-Obligations sum [Value-Of-The-Relationship] of links with [[Belongs_to] of end1 = "Village1" and [Belongs_to] of end2 = "Village2"]
]
my problem with first version is that it adds the value of each link to sum of all values of previous links in that group and does not consider if a link is dead or not, but second one is more accurate.
Since Value of relationship is link property I don't want to ask links more than once in the code and I update the sum values whenever a link is being changed or created.
I thought it might be better to update the values every 48 ticks , since many agents might call this function every tick, but for doing that I have to call links and I am not sure which way is better?
Update:
I have changed my code so I will calculate the links I need whenever a decision is made:
to-report Value-of-Mutual-Obligations [Village1 Village2]
report sum [Value-Of-The-Relationship] of links with [[Belongs_to] of end1 = Village1 and [Belongs_to] of end2 = Village2]
end
Another way of thinking of it.
Create a breed for the Villages.
breed [ villages village ]
Create new link breeds, one for the villages, and one for people. (you can't use the built-in links breed when you have any custom links breed):
directed-link-breed [ village-links village-link ]
directed-link-breed [ person-links person-link ]
give village-links a variable VALUE-OF-MUTUAL-OBLIGATIONS
give the villages a variable VALUE-OF-SELF-OBLIGATIONS -- this is to handle cases where both persons are from the same village -- sadly, netlogo does not allow self-links.
Create a village turtle for each village. They can be hidden. You can apply the name of the village ("Village 1") to the label of the village.
Link all the villages to each other, in both directions.
A person's belongs-to contains a village turtle.
e.g. to randomly assign a village:
set belongs-to one-of villages
So, now, rather than having to calculate the value of mutual obligations wholesale, you can alter it directly, as it changes.
Whenever you change the value of a link, you can also change the VOMO variable for the village link. You use the who numbers of the villages to figure out the link ID, or to use the SELF-OBLIGATIONS version in that special case.
to update-relationship-value [ #value ] ;; run by the person's LINK
set value-of-the-relationship value-of-the-relationship + #value
let from-village [ belongs-to ] of end1
let to-village [ belongs-to ] of end2
ifelse from-village != to-village
[ ask village-link ([who] of from-village ) ([who] of to-village)
[ set value-of-mutual-obligations value-of-mutual-obligations + #value
]
]
[ ask from-village ;; update self-obligation value
[ set value-of-self-obligations value-of-self-obligations + #value
]
]
end
So, you only touch the value of mutual obligations once, when you update the relationship value.
You could probably make this slightly more efficient by extracting the village link update code so that it's run by the turtle, not by the link, so that you don't have the extra "[stuff] of end1" stuff.