How do you control Z-order of entities in Seesaw(clojure)? - clojure

I have a window with an xyz-panel that holds a bunch of labels. Now some of them have to overlap and I can't figure out how to set the Z-order.
(defn- mk-smhi-frame
"create the frame"
[]
(sc/window
:width 1920
:height 1080
:content
(sc/xyz-panel :items [
; begin snip
(sc/label :id :clock
:bounds [1000 0 920 500]
:paint draw-clock)
;----------------------------------------------
; how do make :radar be on top of :clock?
;----------------------------------------------
(sc/label :id :radar
:bounds [1200 100 500 300]
:paint draw-radar)
; end snip
])))

Related

Converting agentset into list in NetLogo

I'm writing some code to vaccinate individuals in a population where flu is circulating. There are two kinds of vaccines (named HOV and HEV in the code); the HOV is already done. What I tried/wanted to do was convert the agentset of blue turtles into a list, that I could then iterate over one turtle at a time. I need to do this because the HEV condition has to give a slightly different vaccine to each blue turtle (i.e. the flu strain in each vaccine has to be slightly different). However, NetLogo is highlighting "foreach [vax-turtles]" with an error message that says "Expected a literal value."
My code is below, the "if vaccine = "HEV"" piece of code is what I need help with:
extensions [csv]
globals [strain_list_list epidemic-threshold cumulative-infections proportion-of-infection currently-infected peak-prevalence vax-strain]
turtles-own [infection-period infection-number tflu-strain immune-label ant-distance cross-immunity]
patches-own [fomite-age pflu-strain]
to setup
clear-all
setup-turtles
set strain_list_list (list t-sorted-strain-list)
print strain_list_list
reset-ticks
end
to-report t-sorted-strain-list
report map [i -> [tflu-strain] of i] sort turtles
end
to setup-turtles
create-turtles 100
ask turtles [setxy random-xcor random-ycor]
ask turtles [set color white set infection-number 0 set immune-label -999999999999 set tflu-strain -999999999999]
ask one-of turtles [set color red set infection-period 0 set infection-number 1 set immune-label 0 set tflu-strain 0]
if vaccine = "HOV" [
ifelse (one-of [1 2] = 1) [
set vax-strain (random ((2 * drift-size) + 1))]
[set vax-strain (-1 * random ((2 * drift-size) + 1))]
ask n-of prop-vax turtles with [color = white] [set color blue set immune-label vax-strain]
]
if vaccine = "HEV" [
let vax-turtles (list turtles with [color = blue])
ask n-of prop-vax turtles with [color = white] [set color blue]
foreach [vax-turtles] [
ifelse (one-of [1 2] = 1) [
set vax-strain (random ((2 * drift-size) + 1))]
[set vax-strain (-1 * random ((2 * drift-size) + 1))]
]
]
set epidemic-threshold "no"
set cumulative-infections 0
set peak-prevalence 0
end
to go
if ticks = flu-season-length [stop]
move-infecteds
move-uninfecteds
transmit
mutate
update-immunity
track-infecteds
set cumulative-infections (count turtles with [infection-period = 1] + cumulative-infections)
set proportion-of-infection (100 - (count turtles with [immune-label = -999999999999]))
set currently-infected (count turtles with [infection-period = 1])
csv:to-file "strains_each_tick.csv" strain_list_list
set strain_list_list lput t-sorted-strain-list strain_list_list
tick
end
to move-uninfecteds ;; uninfected turtles move faster than infected ones
ask turtles with [color = white or color = blue] [
right random 360
forward 5
]
end
to move-infecteds ;; infected turtles move slower than uninfected ones and always transmit infection to patches before they leave them
ask turtles with [color = red] [
if pcolor = black [
set pcolor red
set fomite-age 0
set pflu-strain tflu-strain]
right random 360
forward 3
]
end
to transmit ;; uninfected turtles are infected by fomites (red patches) with some probability. immune-labelling currently first infection
ask turtles with [color = white or color = blue and pcolor = red] [
if immune-label != pflu-strain [
set ant-distance (abs (immune-label - pflu-strain))
set cross-immunity (natural-immunity * (1 - (ant-distance / antigenic-distance-limit)))
if cross-immunity < 0 [set cross-immunity 0]
if random 100 < (((100 - cross-immunity) / 100) * probability-of-infection)
[set color red set infection-period 0 set infection-number infection-number + 1 set tflu-strain pflu-strain]
]
if immune-label = pflu-strain [
if random 100 < (((100 - natural-immunity) / 100) * probability-of-infection)
[set color red set infection-period 0 set infection-number infection-number + 1 set tflu-strain pflu-strain]
]
]
end
to mutate ;; some probability of mutation (change in strain label) when an individual receives infection from a patch
ifelse in-host [
ask turtles with [color = red] [
if random 100 < probability-of-mutation [
ifelse (one-of [1 2] = 1) [
set tflu-strain (tflu-strain + (random (drift-size + 1)))]
[set tflu-strain (tflu-strain - (random (drift-size + 1)))]
]
]
]
[ask turtles with [color = red and infection-period = 0] [
if random 100 < probability-of-mutation [
ifelse (one-of [1 2] = 1) [
set tflu-strain (tflu-strain + (random (drift-size + 1)))]
[set tflu-strain (tflu-strain - (random (drift-size + 1)))]
]
]
]
end
to update-immunity
ask turtles with [color = red and infection-period = 0] [
ifelse immune-labelling = "first-infection" [
if immune-label = -999999999999 [
set immune-label tflu-strain]]
[set immune-label tflu-strain]
]
end
to track-infecteds ;; turtles with given infection period should become uninfected
ask turtles with [color = red] [
set infection-period infection-period + 1
if infection-period = age-infection-max [
set color white set infection-period 0 set tflu-strain -999999999999
]
]
ask patches with [pcolor = red] [
set fomite-age fomite-age + 1
if fomite-age > max-fomite-persistence [
set pcolor black
]
]
end
Any advice would be greatly appreciated! Thanks
The problem is with the line
let vax-turtles (list turtles with [color = blue])
the list primitive creates a list, but not a list of turtles with [color = blue]. Rather it creates a list of its arguments, which in this case is a single angentset. You instead want a list of the agents in the agentset. The of reporter is the easiest way to get that as of always returns a list.
let vax-turtles [self] of turtles with [color = blue]
Alternatively, if you wanted the list to be sorted, you could use sort, which also always returns a list.
let vax-turtles sort turtles with [color = blue]
As for the problem you describe in the comment below, you need to ask each vax-turtle to set its own vax-strain (which I assume is a turtles-own variable). Assuming that you are using NetLogo 6.x,
if vaccine = "HEV" [
let vax-turtles [self] of turtles with [color = blue]
ask n-of prop-vax turtles with [color = white] [set color blue]
foreach [vax-turtles] [t ->
ifelse (one-of [1 2] = 1) [
ask t [set vax-strain (random ((2 * drift-size) + 1))]]
[ask t [set vax-strain (-1 * random ((2 * drift-size) + 1))]]
]
]
But if drift-size is the same for all vax-turtles, it would be pretty unlikely that, given random, JenB's solution below would give the same value for vax-strain for any two turtles, would it not?
Looking at your code, I can't see why you need to do the iteration rather than ask and it is much cleaner to stick with ask. So, try replacing:
if vaccine = "HEV" [
let vax-turtles (list turtles with [color = blue])
ask n-of prop-vax turtles with [color = white] [set color blue]
foreach [vax-turtles] [
ifelse (one-of [1 2] = 1) [
set vax-strain (random ((2 * drift-size) + 1))]
[set vax-strain (-1 * random ((2 * drift-size) + 1))]
]
]
with
if vaccine = "HEV" [
let vax-turtles turtles with [color = blue]
ask n-of prop-vax turtles with [color = white] [set color blue]
ask [vax-turtles] [
ifelse (one-of [1 2] = 1)
[ set vax-strain (random ((2 * drift-size) + 1)) ]
[ set vax-strain (-1 * random ((2 * drift-size) + 1)) ]
]
]
For that matter, I think the different values are simply different signs of the same value, so you could do:
if vaccine = "HEV" [
let vax-turtles turtles with [color = blue]
ask n-of prop-vax turtles with [color = white] [set color blue]
ask [vax-turtles] [
set vax-strain one-of [-1 1] * (random ((2 * drift-size) + 1))
]
]
Also, I am not sure if you are doing this intentionally, but you are changing the proportion to blue after creating the vax-turtles agentset. This means that the newly changed turtles will not be given a vax-strain until the next tick or whenever the code is next run. Furthermore, the code you have will assign a new vax-strain to all the blue turtles, even if they were made blue in a previous steps. If you actually want the vax-strain to be assigned once only and the turtle to change colour to show this, try:
if vaccine = "HEV" [
ask n-of prop-vax turtles with [color = white]
[ set color blue
set vax-strain one-of [-1 1] * (random ((2 * drift-size) + 1))
type "drift-size is " type drift-size type " and vax-strain is " print vax-strain ;; new line here for diagnostics
]
]
UPDATE: ask gives a new random number to each agent. You can see this by running the complete model:
turtles-own [testnum]
to setup
clear-all
create-turtles 10
[ set testnum random 5 ]
print [testnum] of turtles
end
I think
foreach sort-on [who] turtles with [color = blue]
will suffice.

Netlogo list updated in time

I'm writing up a code in Netlogo that basically should do the following:
Amongst directed links, interact and seek out their cooperative behavior (coop_b).
Store coop_b in a list variable together with the time of the interaction (reputation_now)
Every interaction, add the reputation_now to a bigger list, reputation_h (reputation history)
Now, add a time-weight to the reputation, so that the more recently had interactions weigh more in the total reputation. I do this by dividing the encounter time of an interaction by the current time tick, then multiplying that with the coop_b to retrieve a weighted reputation for each interaction. This is stored in the list reputation_h_w (historic reputations weighted). The thing is, this list should be updated every time the members interact, so that earlier additions to the list are now updated to the new time tick. My hunch is this is where my code goes in the mist (problems depicted below the code section).
My code:
to horizontal_interact
ask members [
;set random example variable for coop_b
set coop_b random-float 5 ; coop-b stands for cooperation behavior
if ticks > 0 [
ask my-out-links [ ;there are directed links between all members
set reputation_now (list [coop_b] of end2 ticks) ;list of coop_b and encounter time
set reputation_h lput reputation_now reputation_h ; history of reputations, a list of all reputation_now recorded
foreach reputation_h [ x ->
let cooperative_behavior item 0 x
let encounter_time item 1 x
let reputation_now_w (list cooperative_behavior encounter_time (encounter_time / ticks ))
]
]
]
]
end
If I test the content of reputation_h and reputation_h_w with 2 members, I get:
reputation_h is the coop_b variable of the member and the tick of encounter
links> show reputation_h
(link 1 0):
[[4.0900840358972825 1]
[0.8885953841506328 2]
[0.47017368072392984 3]]
(link 0 1): [[3.6805257472366164 1]
[3.6805257472366164 2]
[3.4201458793705326 3]]
reputation_h_w (containing the member's coop_b variable, the encounter time and the encounter time divided by the ticks):
links> show reputation_h_w
(link 0 1): [[3.6805257472366164 1 1]
[3.6805257472366164 1 0.5]
[3.6805257472366164 2 1]
[3.6805257472366164 1 0.3333333333333333]
[3.6805257472366164 2 0.6666666666666666]
[3.4201458793705326 3 1]]
(link 1 0): [[4.0900840358972825 1 1]
[4.0900840358972825 1 0.5]
[0.8885953841506328 2 1]
[4.0900840358972825 1 0.3333333333333333]
[0.8885953841506328 2 0.6666666666666666]
[0.47017368072392984 3 1]]
The problem is that reputation_h_w doesn't make sense to me - firstly there's six inputs instead of three, and secondly, the encounter time (item 1) and the encounter time/ticks (item 2) is off.
What am I doing wrong here?
Not sure where you update reputation_h_w in your code, but I'm guessing that you are not resetting it to a blank list before running your foreach loop again. So, it's lput-ing the values at the end of the list, which is not blank anymore.
Example setup:
breed [ as a ]
as-own [ coop_b ]
links-own [ reputation_now reputation_history reputation_history_w]
to setup
ca
create-as 2 [
set coop_b who + 1
setxy random-pxcor random-pycor
]
while [ any? as with [ not any? my-in-links ] ] [
ask one-of as with [ not any? my-out-links ] [
create-link-to one-of other as with [ not any? my-in-links ] [
set reputation_now []
set reputation_history []
]
]
]
reset-ticks
end
Note that here I will set reputation_history [] right before the foreach chunk runs:
to interact
if ticks > 0 [
ask links [
set reputation_now ( list [coop_b] of end2 ticks )
set reputation_history lput reputation_now reputation_history
; reset reputation history to a blank list, as you are
; recalculating the weighted value at each tick
set reputation_history_w []
foreach reputation_history [ x ->
let behavior item 0 x
let encounter_time item 1 x
let fraction encounter_time / ticks
set reputation_history_w lput (
list behavior encounter_time fraction ) reputation_history_w
]
show ( word "Current reputation: " reputation_now )
show ( word "Reputation history: " reputation_history )
show ( word "Weighted history rep list: " reputation_history_w )
]
]
tick
end
As far as why your ticks are off, I'd guess it's because you are calling tick after you run your horizontal_interact procedure. With the example above, my output looks like:
(link 0 1): "Current reputation: [2 2]"
(link 0 1): "Reputation history: [[2 1] [2 2]]"
(link 0 1): "Weighted history rep list: [[2 1 0.5] [2 2 1]]"
(link 1 0): "Current reputation: [1 2]"
(link 1 0): "Reputation history: [[1 1] [1 2]]"
(link 1 0): "Weighted history rep list: [[1 1 0.5] [1 2 1]]"
even though the ticks read 3. If you run it with tick at the start of the procedure, that might sort out your expected output.

How to make turtles move along a list of locations in order

My objective is to have an agentset (named ships) hatch at another agentset (named ports and listed in index) containing 2 locations representing the start and end of a pathway. To go- start moving ships/ heading towards a third agentset (called waypoints and listed in index1) in their given order.
However, if a port is closer to the current waypoint than another waypoint- move to port instead. Once the ships have reached the other port, I would also like them to stop.
Currently I have the model working with only two agentsets (ships and ports) however I would like to include a third set(called waypoints) to prevent ships from hatching at all locations(ports and waypoints) and to have the ships move in a sequential order by traveling along the waypoints (like stepping stones) before reaching the beginning or the end (ports).
Here is an example of my code:
breed [ships ship]
breed [ports port]
breed [waypoints waypoint]
ships-own [target-port
current-port]
to setup
ca
let index 0
create-ports 2
[ let loc item index [ [0 -32] [32 0] ]
setxy (item 0 loc) (item 1 loc)
set index index + 1
set shape "circle"
set size 2
set color red - 1]
let index1 0
create-waypoints 2
[let loc item index1 [[12 -3] [14 -26]]
setxy (item 0 loc) (item 1 loc)
set index1 index1 + 1
set shape "circle"
set size 1
set color red - 1]
ask ports
[ let s who
hatch-ships 1
[ set current-port s
set size 1
set color red
pen-down
set pen-size 1
set target-port min-one-of ports with [ who != s] [distance myself]
set heading towards target-port
]
]
reset-ticks
end
to go
;(obey-elevation)
ask ships
[ if (distance target-port = 0)
[ let other_ports no-turtles
ask target-port [set other_ports (other ports)]
set target-port min-one-of other_ports [distance myself]
face target-port
]
ifelse (distance target-port < 1)
[ move-to target-port
]
[fd 1
]
]
tick
end
Any help would be greatly appreciated.

Maps and keywords in clojure

So I do my query on my posts for their eid and I get a list:
(map :eid (get-all-posts))
(17592186045421 17592186045438 17592186045440 17592186045540
17592186045545 17592186045550 17592186045588 17592186045590
17592186045592 17592186045594 17592186045597 17592186045608
17592186045616 17592186045721 17592186045866 17592186046045
17592186046047 17592186046075 17592186046077 17592186046079
17592186046081 17592186046083 17592186046085 17592186046088
17592186046149 17592186046158 17592186046170 17592186046174
17592186046292 17592186046352 17592186046362 17592186047146
17592186047211)
Every post can have many :ratings,
(get-all-ratings 17592186047211)
({:rating "positive",
:rid 17592186047652,
:email "vaso#ph"}
{:rating "positive",
:rid 17592186047756,
:email "sova.kua#gmcom"}
{:rating "meh",
:rid 17592186047725,
:email "badger#ton"})
Would like to combine the maps so I can `(count) the number of ratings per post.
(count (get-all-ratings 17592186047211)
3
But trying something like
(count (map get-all-ratings (map :eid (get-all-posts)))
simply returns the number of posts... it's a big list like
(({:rating "plus", :rid 7175 ..}
{:rating "plus" :rid 7374})
({:rating "whatever", :rid 7535})
()
() <some have no ratings
({:rating "green", :rid 7152}))
How can I tally up the number of times :rating shows up in a list of listed maps like above?
>(map :rating (map first (map get-all-ratings (map :eid (get-all-posts)))))
is something I've been playing with, and it returns a list, but as you can probably tell, it just returns one :rating field from each post's expanded ratings map.
Edit:
I noticed just now that something like
({:rating 5}
{:rating 3}
{:rating 7})
just becomes
{:rating 7}
...disregarding other entries in the list. How come?

How to idiomatically print currency in Clojure?

I'm using the following:
(defn dollars [input] (str "$" (format "%.2f" input)))
(which doesn't do the commas)
But I think there must be a method using pprint/cl-format.
My question is: How to idiomatically print currency in Clojure?
If you have more to work with money, than just formatting it, you might consider using https://github.com/clojurewerkz/money (see the section Formatting), which wrapps joda-money. This not only covers formatting, but also other common problems like rounding.
user=> (mf/format (ma/amount-of mc/USD 10000))
"$10,000.00"
user=> (mf/format (ma/amount-of mc/USD 10000) java.util.Locale/GERMANY)
"USD10.000,00"
edit
You can pass the amount-of means of rounding. E.g.
user=> (mf/format (ma/amount-of mc/USD 10.111111111111111))
ArithmeticException Scale of amount 10.11111111111111 is greater than the scale of the currency USD org.joda.money.Money.of (Money.java:74)
user=> (mf/format (ma/amount-of mc/USD 10.111111111111111 (java.math.RoundingMode/HALF_DOWN)))
"$10.11"
See also Bankster: https://github.com/randomseed-io/bankster
(money/of :EUR 25)
; => #money[25.00 EUR]
(money/of 25 :EUR)
; => #money[25.00 EUR]
(money/of crypto/BTC 10.1)
; => #money/crypto[10.10000000 BTC]
(money/of BTC 10.1)
; => #money/crypto[10.10000000 BTC]
#money EUR
; => #money[0.00 EUR]
#money/crypto ETH
; => #money/crypto[0.000000000000000000 ETH]
#money[PLN 2.50]
; => #money[2.50 PLN]
#currency USD
; => #currency{:id :USD, :domain :ISO-4217, :kind :FIAT, :numeric 840, :scale 2}
(currency/symbol :USD)
; => "USD"
(currency/symbol :USD :en_US)
; => "$"
(currency/symbol :USDT)
; => "₮"
(currency/name :USDT)
; => "Tether"
(money/format #money[10 EUR])
; => "10,00 €"
(money/format #money[10 EUR] :en_US)
; => "€10.00"
(money/format #money[10 EUR] :pl {:currency-symbol-fn currency/name})
; => "10,00 euro"