MEEP: How to make an array of flux detectors? - mit-scheme

I have been using MIT's MEEP for simulation of THz frequency light transmission in silicon photonics. I needed to make an array of flux detectors in MIT's MEEP so that I wouldn't have to write many (add-flux) blocks of code.
Scheme's map seemed like a good solution, yet, despite there being many people in many forums searching for a way to do this, an implementation of such code is sparse online. Thus, I wanted to share a way of doing it.
In the documentation on the MEEP wiki, adding flux detectors is done in the follow fashion:
(define-param fcen 0.25) ; pulse center frequency
(define-param df 0.4) ; pulse width (in frequency)
(define-param nfreq 4001) ; number of frequencies at which to compute flux
(define refl-det ; reflection detector
(add-flux freq_c pulse_width num_freqs
(make flux-region
(center some-x some-y)
(size 1 0))))
(define trans-det ; transmission detector
(add-flux freq_c pulse_width num_freqs
(make flux-region
(center some-other-x some-other-y)
(size 1 0))))
;;...;; code for running sources
(display-fluxes refl-det trans-det) ; MEEP's function for outputting flux for frequencies
So, if I want 20 transmission detectors and 20 reflection detectors, I would have to define 40 blocks by hard coding them...not good.

There are many variants which can be made on this code. The one presented below is for detectors in a straight line. It is also possible to implement one for detectors placed in a circular arrangement; however, that requires calculating your angles in another function and adding another variable to the detectors function.
; The following is a sample algorithm you can use to get the x values
(define det-sample-length 5)
(define det-start-x-position 25)
(define (refl-det-x-position n) (+ det-start-x-position (* n det-sample-length)))
; Here you use map to return a list of the x positions for the detectors
(define det-positions-x (map refl-det-x-position (list 1 2 3 4 5 6 7 8 9)))
; This is a function to make the array of detectors. It takes the x position as an argument.
(define (detectors det-position-x)
(add-flux freq_c pulse_width num_freqs
(make flux-region
(center det-position-x 0)
(size 0 1))))
; To return a list of detectors based on the above function, map it against the x position list.
(define my-refl-flux-list
(map detectors det-positions-x))
; If you need to put another detector not part of the above series, define it as a "list"
(define source-top-det
(list (add-flux freq_c pulse_width num_freqs
(make flux-region
(center some-x some-y)
(size 1 0)))))
; Here, again, you can make another detector as a list or another array of detectors.
(define source-bottom-det
(list (add-flux freq_c pulse_width num_freqs
(make flux-region
(center some-other-x some-other-y)
(size 1 0)))))
; Finally, before you use "display-fluxes", you must append the detectors into a list.
(define my-flux-list (append source-top-det source-bottom-det my-refl-flux-list))
; And last, but not least, use Scheme's "apply" on "display-fluxes" over "my-flux-list"
(apply display-fluxes my-flux-list)
The most important thing to remember is that the detectors must be contained in a list. Map by its nature makes a list, so this is why you don't define a list in the "detectors" function. Append just joins all of the lists into a bigger list. And you have to use "apply" for "display-fluxes" because you are using it on a list, not directly within the function. Hope this helps!

Related

How to get yDomain value in ReactVis

In React-vis, I display the cursor position of the mouse using a LineSeries. I would like it to extend along all the vertical extent of the FlexibleXYPlot in which it's included:
Image of the cursor on a ReactVis plot
¿How can I get the value of the yDomain of the plot?
Thank you!
Edit
I am using React-vis in clojurescript. I got the line seen in the first image with this code:
[:> rvis/LineSeries {:data [{:x #nearest-x :y y-min}{:x #nearest-x :y y-max}]
:strokeStyle "dashed" :color "black"
:opacity (if #button-pressed? .5 0)}]
And I needed to compute the value of y-min and y-max (that was the meaning of my question).
But then I realized that I can use the Crosshair facility:
[:> rvis/Crosshair {:values [{:x #nearest-x :y 0}]
:style {:line {:opacity (if #button-pressed? .5 0)}}}
[:div]]
Crosshair in React-vis
It's difficult to see (it's under the cursor), because I still can't manage to change its color. I thought that this would work:
[:> rvis/Crosshair {:values [{:x #nearest-x :y 0}]
:style {:line {:color "#000"
:opacity (if #button-pressed? .5 0)}}}
[:div]]
But it doesn't. I think this would be another question. :)
Edit 2
It was :background "black" instead of :color "black". I got it reading the file plot.scss. :)

rnd:weighted-one-of-list work doesn't return the distribution I think it should

I trying to use the rnd extension's function weighted-one-of-list.
My list looks like
observer>show female-yr-run-stats
observer: [[117 0.001169] [118 0.002684] [119 0.004697] [120 0.003368] [121 0.004871] [122 0.018738] [123 0.034986] [124 0.070616] [125 0.035608] [126 0.012939] [127 0.011883] [128 0.016594] [129 0.068837] [130 0.044391] [131 0.028422] [132 0.053251] [133 0.023741] [134 0.042111] [135 0.035811] [136 0.022447] [137 0.031563] [138 0.024253] [139 0.030213] [140 0.024372] [141 0.033266] [142 0.059869] [143 0.028711] [144 0.030863] [145 0.04043] [146 0.008819] [147 0.012308] [148 0.008638] [149 0.021345] [150 0.016176] [151 0.009815] [152 0.017242] [153 0.014362] [154 0.010717] [155 0.015868] [156 0.003865] [157 0.008441] [158 0.004358] [159 0.003113] [160 0.002464] [161 0.001768]]
The first item is day-of-the-year and the second is the probability (all sum to one).
I am using the code
repeat 50000[
let tempo first rnd:weighted-one-of-list female-yr-run-stats [ [p] -> last p ]
file-open "C://temp//check_wgt_random.csv"
file-print (word tempo)
file-close
]
to randomly select a day-of-the-year 50000 times to check that the rnd:weighted-one-of-list function is doing what I want it to do. From the results, I get a distribution of day-of-the-year. But when I compare the resulting distribution to the original probability distribution, they are quite different.
I am thinking that the rnd:weighted-one-of-list with my list would be equivalent to randomly drawing from a multinomial distribution like R's rmultinom function. Am I correct? Am I doing something wrong?
Any help would be appreciated.
The graph below shows the comparisons
The rnd:weighted-one-of-list primitive works the way (I think) you think it works. From your data, it draws the value 112 with probability 3.04E-4, value 113 with probability 0.001236 etc. The probabilities don't have to add to 1 (I have assumed that you are correct that yours do). I can't see anything wrong with your use of this primitive for your draws.
But I am not sure about the file construction. You have the file-open and file-close inside the repeat so the file is opened, the new data is appended, the file is closed. It is not clear whether you ever clear the dataset. So perhaps the problem is that you have some data left over from when you were building your code. Do you get the same problem if you clear out all the old data and start again?
Sorry to waste your time. I discovered what happened. I had two probabilities stream mixed up.

How to use add elements to a matrix?

I want to add multiple items from one list to another list, that is organized in one big list, like a matrix.
let targetlists (list firstlist seccondlist thirdlist)
So in my double while loop, I added this code;
set (item x targetlists) lput (item y sourcelist) (item x targetlists)
Sadly it gives me the following error:
This isn't something you can use "set" on.
I found out that it has to do with how I select the target list, as the following code does work, but doesn't do what I want:
set firstlist lput (item y sourcelist) firstlist
JenB is right that, in general, you use replace-item. However, replacing your while loops with map will be much more effective.
I'm not entirely sure what you're trying to do, but it looks like you're trying to put the elements of sourcelist onto the end of the lists in targetlists. Even if that's not what you're doing, this should point you in the right direction:
set targetlists (map [ [ source-item target-row ] ->
lput source-item target-row
] sourcelist targetlists)
This will iterate through the items of sourcelist and targetlists together, calling lput on the pairs.
Also, there's a handy shortcut where, if a reporter already does what you want, you can pass it directly to map. So you can condense this to:
set targetlists (map lput sourcelist targetlists)
Now, given that you mentioned nested whiles and you're indexing into the two lists with two different indices, you might be trying to put the entire contents of sourcelist onto the ends of each of the targetlists. If that's the case, you can just do
set targetlists map [ l -> (sentence l sourcelist) ] targetlists
If I'm totally off, and you're trying to do something completely different, just let me know in the comments and I'll update my answer.

How can I make an image blink in racket language using a frame counter?

The following procedure is in a racket radar simulator for a flight simulator it displays objects that are locking on your aircraft as an ellipse, we need to get the ellipse to blink (appear and reappear periodically). Using a frame counter, or not, how can this be scripted?
(define rwr-tracking
(let ([p (new dc-path%)])
(send p ellipse 0 0 400 400)
p)
)
Here is an example to get you started:
#lang racket
(define (redraw-radar)
(sleep 0.5) ; 0.5 seconds
(displayln "Drawing")
(flush-output)
(redraw-radar))
(thread redraw-radar)
A new thread is created to the redrawing.
The thread waits, redraws, and, loops.

NetLogo: procedure for performing an operation on one item in a list in a compact way?

New to NetLogo... wondering if there's a procedure that performs an operation on one item in a list in a compact way (like map but for one item).
For example, say I wanted to add 3 to the item at index i in list blah.
Right now I'm doing this like:
set blah replace-item i blah (item i blah + 3)
It seems a little clunky, and like there would be a procedure that does that, but I haven't been able to find one. Just wanted to make sure I wasn't missing something.
Thank you!
Taylor
There isn't something built in that does this. But you could define it yourself as a procedure that takes a task as input:
;; replace item i of xs with the result of applying fn to that item
to-report mapping-replace-item [i xs fn]
report replace-item i xs (runresult fn item i xs)
end
Sample usage:
observer> show mapping-replace-item 2 [10 20 30 40] task [? * ?]
observer: [10 20 900 40]