To be able to edit code and run cells, you need to run the notebook yourself. Where would you like to run the notebook?

This notebook takes about 30 seconds to run.

In the cloud (experimental)

Binder is a free, open source service that runs scientific notebooks in the cloud! It will take a while, usually 2-7 minutes to get a session.

On your computer

(Recommended if you want to store your changes.)

  1. Copy the notebook URL:
  2. Run Pluto

    (Also see: How to install Julia and Pluto)

  3. Paste URL in the Open box

Frontmatter

If you are publishing this notebook on the web, you can set the parameters below to provide HTML metadata. This is useful for search engines and social media.

Author 1
👀 Reading hidden code
using Plots
3.4 s
👀 Reading hidden code
using PlutoUI
82.0 ms
👀 Reading hidden code
using Hyperscript
131 μs
👀 Reading hidden code
script = m(Hyperscript.NOESCAPE_HTMLSVG_CONTEXT, "script")
38.9 ms
👀 Reading hidden code
div = m("div")
14.9 μs
randid (generic function with 1 method)
👀 Reading hidden code
randid() = String(rand(('a':'z') ∪ ('A':'Z'), 12))
420 μs
clicktracker_js (generic function with 1 method)
👀 Reading hidden code
clicktracker_js(id) = """
const container = document.querySelector("#$(id)")
const graph = container.firstElementChild

const onclick = (e) => {
const svgrect = graph.getBoundingClientRect()
container.value = [
(e.clientX - svgrect.left) / svgrect.width,
(e.clientY - svgrect.top) / svgrect.height
]
container.dispatchEvent(new CustomEvent("input"), {})
}

graph.addEventListener("click", onclick)

invalidation.then(() => {
graph.removeEventListener("click", onclick)
})
"""
390 μs
clicktracker (generic function with 1 method)
clicktracker(x) = let
id = randid()
div(id=id, x, script(clicktracker_js(id)))
end
👀 Reading hidden code
641 μs
@bind qq clicktracker(p)
👀 Reading hidden code
496 ms
Error message

Another cell defining physical_coords contains errors.

Keep calm, you got this!
let
p = plot(1:10)
scatter!(p, plot_coords[1:1], plot_coords[2:2])
end
👀 Reading hidden code
---
Error message

MethodError: no method matching *(::Missing, ::Measures.AbsoluteLength)

Closest candidates are:

*(::Any, ::Any, ::Any, ::Any...) at /opt/hostedtoolcache/julia/1.7.3/x64/share/julia/base/operators.jl:655

*(::Measures.Length{:pct}, ::Measures.AbsoluteLength) at ~/.julia/packages/Plots/uiCPf/src/plotmeasures.jl:17

*(::ChainRulesCore.AbstractThunk, ::Any) at ~/.julia/packages/ChainRulesCore/U6wNx/src/tangent_arithmetic.jl:125

...

Stack trace

Here is what happened, the most recent locations are first:

  1. _broadcast_getindex_evalf
  2. _broadcast_getindex
  3. (::Base.Broadcast.var"#29#30"{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple}, Nothing, typeof(*), Tuple{Base.RefValue{Missing}, Tuple{Measures.AbsoluteLength, Measures.AbsoluteLength}}}})(k::Int64)
  4. ntuple
  5. materialize(bc::Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple}, Nothing, typeof(*), Tuple{Base.RefValue{Missing}, Tuple{Measures.AbsoluteLength, Measures.AbsoluteLength}}})
  6. image_coord_to_plot_coord(x::Missing, plt::Plots.Plot{Plots.GRBackend})
    	small = plotarea(p[1])		physical_coords = x .* big.a	fractional_plot_coords = (physical_coords .- small.x0) ./ small.a	plot_coords = let
  7. Show more...
image_coord_to_plot_coord(qq, p)
👀 Reading hidden code
---

👀 Reading hidden code
69.0 μs
image_coord_to_plot_coord (generic function with 1 method)
function image_coord_to_plot_coord(x, plt::Plots.Plot)
if length(plt) != 1
error("This does not work with subplots yet")
end
big = bbox(p.layout)
small = plotarea(p[1])
physical_coords = x .* big.a
fractional_plot_coords = (physical_coords .- small.x0) ./ small.a
plot_coords = let
xl = xlims(plt)
yl = ylims(plt)
[
fractional_plot_coords[1] * (xl[2] - xl[1]) + xl[1],
(1.0 - fractional_plot_coords[2]) * (yl[2] - yl[1]) + yl[1],
]
end
plot_coords
end
👀 Reading hidden code
1.4 ms
missing
qq
👀 Reading hidden code
8.1 μs
Error message

MethodError: no method matching *(::Missing, ::Measures.AbsoluteLength)

Closest candidates are:

*(::Any, ::Any, ::Any, ::Any...) at /opt/hostedtoolcache/julia/1.7.3/x64/share/julia/base/operators.jl:655

*(::Measures.Length{:pct}, ::Measures.AbsoluteLength) at ~/.julia/packages/Plots/uiCPf/src/plotmeasures.jl:17

*(::ChainRulesCore.AbstractThunk, ::Any) at ~/.julia/packages/ChainRulesCore/U6wNx/src/tangent_arithmetic.jl:125

...

Stack trace

Here is what happened, the most recent locations are first:

  1. _broadcast_getindex_evalf
  2. _broadcast_getindex
  3. (::Base.Broadcast.var"#29#30"{Base.Broadcast.Broadcasted{Base.Broadcast.Style{Tuple}, Nothing, typeof(*), Tuple{Base.RefValue{Missing}, Tuple{Measures.AbsoluteLength, Measures.AbsoluteLength}}}})(k::Int64)
  4. ntuple
  5. materialize
  6. physical_coords = qq .* big.a
physical_coords = qq .* big.a
👀 Reading hidden code
---
Error message

Another cell defining physical_coords contains errors.

¯\_(ツ)_/¯
fractional_plot_coords = (physical_coords .- small.x0) ./ small.a
👀 Reading hidden code
---
Error message

Another cell defining physical_coords contains errors.

plot_coords = let
xl = xlims(p)
yl = ylims(p)
[
fractional_plot_coords[1] * (xl[2] - xl[1]) + xl[1],
(1.0 - fractional_plot_coords[2]) * (yl[2] - yl[1]) + yl[1],
]
end
👀 Reading hidden code
---
ylims(p)
👀 Reading hidden code
851 μs
small.a
👀 Reading hidden code
12.4 μs
small.x0
👀 Reading hidden code
11.7 μs
p = plot(1:10)
👀 Reading hidden code
3.0 s
Plots.GridLayout(1, 1)
p.layout
👀 Reading hidden code
12.5 μs
BBox{l,t,r,b,w,h = 0.0mm,0.0mm, 152.4mm,101.6mm, 152.4mm,101.6mm}
big = bbox(p.layout)
👀 Reading hidden code
800 μs
big.a
👀 Reading hidden code
12.2 μs
big.x0
👀 Reading hidden code
11.6 μs
Subplot{1}
p[1]
👀 Reading hidden code
10.0 μs
BBox{l,t,r,b,w,h = 8.8239244474213mm,3.0mm, 149.4mm,94.38944mm, 140.57607555257871mm,91.38944mm}
small = plotarea(p[1])
👀 Reading hidden code
15.6 μs
small.a
👀 Reading hidden code
10.9 μs
using Plots.Measures
👀 Reading hidden code
139 μs
1.0mm
1mm
👀 Reading hidden code
14.7 μs
begin
struct BondDefault
element
default
end
Base.show(io::IO, m::MIME"text/html", bd::BondDefault) = Base.show(io, m, bd.element)
Base.get(bd::BondDefault) = bd.default
end
👀 Reading hidden code
4.1 ms
let
if !@isdefined(x0_img_coords)
global x0_img_coords = [0,0]
end
p = plot(1:10)
x0 = image_coord_to_plot_coord(x0_img_coords, p)

scatter!(p, x0[1:1], x0[2:2])
@bind x0_img_coords BondDefault(clicktracker(p), x0_img_coords)
end
👀 Reading hidden code
459 ms

Scaling directly inside JS

👀 Reading hidden code
193 μs
Error message

syntax: unexpected "="

((x * big.a[1] - small.x0[1]) / small.a[1]) * (xl[2] - xl[1]) + xl[1]

=

x * (big.a[1] / small.a[1]) * (xl[2] - xl[1]) + xl[1] - (xl[2] - xl[1]) * small.x0[1] / small.a[1]
👀 Reading hidden code
---
Error message

MethodError: no method matching getindex(::Missing, ::Int64)

Stack trace

Here is what happened, the most recent locations are first:

  1. [qq[1] * r.x_scale + r.x_offset, qq[2] * r.y_scale + r.y_offset]
Be patient :)
[qq[1] * r.x_scale + r.x_offset, qq[2] * r.y_scale + r.y_offset]
👀 Reading hidden code
---
r = let
xl = xlims(p)
yl = ylims(p)
(
x_offset = xl[1] - (xl[2] - xl[1]) * small.x0[1] / small.a[1],
x_scale = (big.a[1] / small.a[1]) * (xl[2] - xl[1]),
y_offset = (yl[2] - yl[1]) + (small.x0[2] / small.a[2]) * (yl[2] - yl[1]) + yl[1],
y_scale = -(big.a[2]/ small.a[2]) * (yl[2] - yl[1])
)
end
👀 Reading hidden code
4.4 ms
Error message

syntax: unexpected "="

C'est la vie !
(1.0 - (y * big.a[2] - small.x0[2]) / small.a[2]) * (yl[2] - yl[1]) + yl[1]

=
(1.0 - (y * big.a[2]/ small.a[2] - small.x0[2] / small.a[2]))
* (yl[2] - yl[1])

+ yl[1]

=

(yl[2] - yl[1]) -
(y * big.a[2]/ small.a[2] - small.x0[2] / small.a[2])
* (yl[2] - yl[1])

+ yl[1]

=

(yl[2] - yl[1]) +
-(y * big.a[2]/ small.a[2])
* (yl[2] - yl[1])
+
(small.x0[2] / small.a[2])
* (yl[2] - yl[1])
+ yl[1]
👀 Reading hidden code
---
plotclicktracker_js (generic function with 1 method)
plotclicktracker_js(id, r) = """
const container = document.querySelector("#$(id)")
const graph = container.firstElementChild

const onclick = (e) => {
const svgrect = graph.getBoundingClientRect()
const f = [
(e.clientX - svgrect.left) / svgrect.width,
(e.clientY - svgrect.top) / svgrect.height
]
container.value = [
f[0] * $(r.x_scale) + $(r.x_offset),
f[1] * $(r.y_scale) + $(r.y_offset),
]
console.log(container.value)
container.dispatchEvent(new CustomEvent("input"), {})
}

graph.addEventListener("click", onclick)

invalidation.then(() => {
graph.removeEventListener("click", onclick)
})
"""
👀 Reading hidden code
498 μs
plotclicktracker (generic function with 1 method)
plotclicktracker(p::Plots.Plot) = let
id = randid()
# we need to render the plot before its dimensions are available:
plot_render = repr(MIME"text/html"(), p)
big = bbox(p.layout)
small = plotarea(p[1])
xl = xlims(p)
yl = ylims(p)
r = (
x_offset = xl[1] - (xl[2] - xl[1]) * small.x0[1] / small.a[1],
x_scale = (big.a[1] / small.a[1]) * (xl[2] - xl[1]),
y_offset = (yl[2] - yl[1]) + (small.x0[2] / small.a[2]) * (yl[2] - yl[1]) + yl[1],
y_scale = -(big.a[2]/ small.a[2]) * (yl[2] - yl[1])
)
@info r xl yl big small
div(id=id, HTML(plot_render), script(plotclicktracker_js(id, r)))
end
👀 Reading hidden code
9.1 ms
missing
rar
👀 Reading hidden code
9.9 μs
@bind rar plotclicktracker(p)
👀 Reading hidden code
xlylbig
BBox{l,t,r,b,w,h = 0.0mm,0.0mm, 152.4mm,101.6mm, 152.4mm,101.6mm}
small
BBox{l,t,r,b,w,h = 8.8239244474213mm,3.0mm, 149.4mm,94.38944mm, 140.57607555257871mm,91.38944mm}
482 ms
let
# STEP 1: replace q0 with your variable name in 5 places
if !@isdefined(q0)
# STEP 2: set the initial 'click' location:
global q0 = [5,5]
end
# STEP 3: in another cell, write a function that takes the click position as
# argument returning a plot. REPLACE `hello` with the name of your function.
p = linepoint(q0)
@bind q0 BondDefault(plotclicktracker(p), q0)
end
👀 Reading hidden code
xlylbig
BBox{l,t,r,b,w,h = 0.0mm,0.0mm, 152.4mm,101.6mm, 152.4mm,101.6mm}
small
BBox{l,t,r,b,w,h = 8.8239244474213mm,3.0mm, 149.4mm,94.38944mm, 140.57607555257871mm,91.38944mm}
57.3 ms
linepoint (generic function with 1 method)
function linepoint(q0)
p = plot(1:10)
scatter!(p, q0[1:1], q0[2:2])
end
👀 Reading hidden code
551 μs
Error message

UndefVarError: COOL_PLOT not defined

Stack trace

Here is what happened, the most recent locations are first:

  1. 	# argument returning a plot. REPLACE `COOL_PLOT` with the name of your function.	p = COOL_PLOT( 👀👀👀 )	
Everything is going to be okay!
let
# STEP 1: REPLACE 👀👀👀 with your variable name in 5 places (double click)
if !@isdefined( 👀👀👀 )
# STEP 2: set the initial 'click' location:
global 👀👀👀 = [5,5]
end
# STEP 3: in another cell, write a function that takes the click position as
# argument returning a plot. REPLACE `COOL_PLOT` with the name of your function.
p = COOL_PLOT( 👀👀👀 )
@bind 👀👀👀 BondDefault(plotclicktracker(p), 👀👀👀 )
end
👀 Reading hidden code
---