How to adjust files to export data in NetLogo 6.2? - netlogo

I am trying to export a file in NetLogo 6.2. But I'm having 2 difficulties:
put only 1 header in the output. It only comes out with multiple headers or without header (see figures below)
multiple headers:
without header:
and I would like it to look like this (below). Is it possible?
close the file so that multiple results are not written to the same file. When I use the command "carefully" and "file-delete" and "[]" only the result of a turtle appears:
if I remove the commands "carefully" and "file-delete" and "[]" the result of all turtles appears. However, if I run the model several times, the results will be saved on top. How is it possible to close the file without changing the result?
The code:
globals [ outifile ]
turtles-own [ my-xcor my-ycor my-timer ]
to output
; carefully ;; using this command to close the file only saves the path of the last turtle
; [ file-delete ( word outfile name ".csv" ) ] ;; using this command to close the file only saves the path of the last turtle
; [ ] ;; using this command to close the file only saves the path of the last turtle
file-open ( word outifile ".csv" )
file-print ( word "id;my_xcor;my_ycor;my_timer" ) ;; when removing this line, there is no header
file-print ( word self " ; " my-xcor " ; " my-ycor " ; " my-timer )
file-close
end

The two issues have the same cause and same solution.
For point 1
This is because apparently to output is executed by every turtle, which means that every turtle will first print the headers and then print the values. Note that this is exactly what you're asking them to do, having both of the following lines of code being executed by each turtle:
file-print ( word "id;my_xcor;my_ycor;my_timer" )
file-print ( word self " ; " my-xcor " ; " my-ycor " ; " my-timer )
Therefore, you have to print the headers first, before asking turtles to do anything (i.e. the observer is the one who has to print the headers, and then has to ask turtles to print values).
For point 2
This issue too comes from the fact that you have every turtle executing the whole to output procedure. In this case, this means that every turtle will run
carefully
[file-delete (word outfile name ".csv")]
[]
Hence, every turtle will make sure that the file has been deleted (or that it doesn't exist) before writing their output.
Again, this is something that the observer should do, because it needs to be done only once.
Fix
To solve these things, you have two absolutely equivalent options:
Option 1
Leave to output a turtle-context procedure (i.e. a procedure executed by turtles) and place the observer's tasks somewhere else in your code, where you know that they will be executed only once - for example in setup or some equivalent place:
to setup
; Here you have your normal 'setup' code, plus:
prepare-output
end
to prepare-output
carefully
[file-delete (word outfile name ".csv")]
[]
file-open (word outifile ".csv")
file-print (word "id;my_xcor;my_ycor;my_timer")
file-close
end
So the observer will take care of cleaning the file and creating headers, and when turtles will run to output they will only need to print their values.
Option 2
Change to output from a procedure that is executed by turtles, to a procedure that is executed by the observer. In this case, at the beginning of the procedure the observer will do once its observer's things, and only then ask all turtles to print their values. Once the turtles are done, the observer closes the file. For example:
to go
; Here you have your normal 'go' code, plus something like:
if (stop-condition-reached?) [
output
stop
]
end
to output
carefully
[file-delete (word outfile name ".csv")]
[]
file-open (word outifile ".csv")
file-print (word "id;my_xcor;my_ycor;my_timer")
ask turtles [
file-print (word self " ; " my-xcor " ; " my-ycor " ; " my-timer)
]
file-close
end
The logic behind both options is exactly the same: the observer does its things once (deleting the old file and creating a new one with headers), then each turtle prints its values.
The difference between the two options is only in how the code is organised - i.e. is to output a procedure executed by turtles, or by the observer (who then asks turtles to print)?
In general it is important to keep track of who is executing what.
For this reason, in my code I always comment the declaration of each procedure with a note stating what context such procedure is being executed from (e.g. observer context, turtle context, patch context, link context).

Related

Problems to use csv: to-file in NetLogo 6.2

I have a question about using the csv extension in NetLogo. I would like to export a .csv file using the csv extension. However, my output is per tick and when using csv: to-file it only writes the last tick. It's like csv:to-file would delete previous ticks. I looked for ways not to delete and couldn't find a solution. Does anyone know if it is possible to use csv: to-file per tick, without erasing previous ticks? I need to use csv because I am working with lists. OBS.: It is not possible to accumulate the values ​​generated at each iteration, because the list would be large and ended up having a memory problem
Thanks in advance
Below is a code showing that csv: to-file deletes the previous information (only the values ​​5,6 and 7,8 appear in the file)
to test
csv:to-file (" test-1.csv" ) [ [1 2] [ 3 4 ] ]
csv:to-file (" test-1.csv" ) [ [5 6] [ 7 8 ] ]
end
yes, csv:to-file is for writing a whole file at a time. To write one line each tick, you need csv:to-row, which converts a list to a line of csv output:
file-open "The-file-name.csv"
file-print csv:to-row (list output-1 output-2 output-3 ...)
file-close
(This is quite fast and will not slow your code down unless your model is extremely simple. Unfortunately there is not an example of it in the Models Library's csv code example.)

file-write output without quotation marks

I want to write an output file with some information in Netlogo. It works fine so far but i wonder if i can write strings without quotation marks. It would help me alot in analysing my data. I could use another programm to delete the quotation marks but i would like to generate the file without them if its possible.
For example: i want to generate the output:
2_100_1 / 0.05081157374735357
3_100_1 / 0.09989594172736732
but i get the output
"2_100_1 / 0.05081157374735357"
"3_100_1 / 0.09989594172736732"
The problem seems to be that i use word, but i have no idea how i can fix this.
Any help is appreciated
file-write (word frequenz "_" transferrate "_" dangerradius " / " (overall-wait / ticks))
You can use file-print instead.
From the Netlogo Dictionary:
file-write outputs quotes around strings.
file-write value This command will output value, which can be a number,
string, list, boolean, or nobody to an opened file, not followed by a
carriage return (unlike file-print and file-show).
This agent is not printed before the value, unlike file-show. Its
output also includes quotes around strings and is prepended with a
space. It will output the value in such a manner that file-read will
be able to interpret it.
Note that this command is the file i/o equivalent of write, and
file-open needs to be called before this command can be used.
file-print:
file-print value Prints value to an opened file, followed by a
carriage return.
This agent is not printed before the value, unlike file-show.
Note that this command is the file i/o equivalent of print, and
file-open needs to be called before this command can be used.
See also file-show, file-type, file-write, and Output (programming
guide).

Iterating through every record in a field and trimming white space

I'm trying to use the following script to replace each value in a field with the Trimmed version of itself. The script runs fine, but I export all records afterwards and I still see white space - am I missing something?
Go to Record/Request/Page [First]
Loop
Exit Loop If [Let($c=$c+1;$c>Get(FoundCount))]
Set Field [MyDataBase::MyField; Trim ( MyDataBase::MyField )]
Commit Records/Requests [With dialog:On]
End Loop
No need for a loop script for such an operation. FileMaker has a function for this exact purpose.
Replace Field Contents [MyDataBase::MyField; Trim ( MyDataBase::MyField )]
Figured it out - I was missing a Go to Record/Request/Page [ Next ] inside my loop. Final working code is:
Go to Record/Request/Page [First]
Loop
Exit Loop If [Let($c=$c+1;$c>Get(FoundCount))]
Set Field [MyDataBase::MyField; Trim ( MyDataBase::MyField )]
Commit Records/Requests [With dialog:On]
Go to Record/Request/Page [ Next ]
End Loop

Extract date from date-and-time in netlogo

I want to use the system date to name my output files, I have created a variable to do that but I find it to be "unclean". How can I create a reporter procedure to create a variable that is just the current system date, say 18Feb2016, without removing items individually. Currently I am using
globals [
time
filename
]
to setup
ca
set time (remove-item 6(remove-item 7(remove-item 8 (remove "-"(remove " "(remove "."
(remove ":" date-and-time)))))))
set filename (word "test-" time ".csv"
if file-exists? filename
[file-close
file-delete filename
]
file-open filename
end
You could definitely reduce your code by using the substring primitive.
set date (remove "-" (substring date-and-time 16 27))
set time (remove "." remove ":" remove " " (substring date-and-time 0 15))
However, I don`t know if there is a more elegant way to access the system date and time in NetLogo without the need of string reconstruction.

Two Element Lists with Table Extension

I'm trying to use the table extension for my model. My code includes the table:from-list command to generate the table. However I am getting an error saying **"Extension exception: expected a two-element list". I generate the list from a txt file that is two columns of numerical data. Apparently this is not the correct format to create a two-element list, but I can't find any documentation describing the appropriate format. How can a two-element list be generated?
Also, is it possible to build a table with more than two elements? Time is serving as the key in my table, but I would like to build a table such that this key would update three different variables (hence a four column table: ticks variable1 variable2 variable3)
Any good resources for learning my way around the tables and arrays extensions is also welcomed (I've already checked out the extensions guide but don't have the hang of it yet).
extensions [table]
Globals
[
list-O2
table-O2
]
to setup
make-lsolutes ; loads lists for solute data (based on node 96)
make-tsolutes
to go
if table:has-key? table-O2 ticks
[ update-from-FEM]
tick
end
to make-lsolutes
ifelse ( file-exists? "96O214day.txt" )
[
set list-O2 []
file-open "96O214day.txt"
while [ not file-at-end? ] [set list-O2 lput file-read list-O2]
file-close
]
[ user-message "There is no 96O214day.txt file in current directory!" ]
end
to make-tsolutes
set table-O2 table:from-list list-O2
end
to update-from-FEM
ask insulation
[ set O2 table:get table-O2 ticks]
end
The txt files to make the solute lists have two columns. Left column is time, and the right column is O2 concentration. Columns are separated by spaces.
A two-element list would look like this:
[[key1 val1][key2 val2][keyn valn]]
I would use the file-open, file-read-line, and while [not file-at-end?] primitives to iterate over your input and use the String primitives to create the pair-lists from your input file. Something like:
let the-list []
file-open filename.txt
while [not file-at-end?][
let input file-read-line
;; find the start and end position/index of key and value (X,Y,O,P) using the position primitive on your delimiter
let key substring input X Y
let value substring input O P
let the-pair (list key value)
set the-list lput the-pair the-list
]
You can embed tables inside tables. So if you want several values as key value, just create a table for each entry and put them in your main table.