diff --git a/docs/make.jl b/docs/make.jl index 94d6f42..95e5f6a 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -9,13 +9,14 @@ GENERATED = joinpath(@__DIR__, "..", "examples") OUTDIR = joinpath(@__DIR__, "src", "examples") blacklist = ["gpu", "JuKeBOX", "Krang_logo", "enzyme"] -SOURCE_FILES = filter(x-> all(i->!occursin(i, x), blacklist), Glob.glob("*.jl", GENERATED)) -foreach(fn -> Literate.markdown(fn, OUTDIR, documenter=true), SOURCE_FILES) +SOURCE_FILES = + filter(x -> all(i -> !occursin(i, x), blacklist), Glob.glob("*.jl", GENERATED)) +foreach(fn -> Literate.markdown(fn, OUTDIR, documenter = true), SOURCE_FILES) MD_FILES = [joinpath("examples", file) for file in readdir(OUTDIR)] -Documenter.DocMeta.setdocmeta!(Krang, :DocTestSetup, :(using Krang); recursive=true) +Documenter.DocMeta.setdocmeta!(Krang, :DocTestSetup, :(using Krang); recursive = true) -format=DocumenterVitepress.MarkdownVitepress( +format = DocumenterVitepress.MarkdownVitepress( repo = "https://github.com/dominic-chang/Krang.jl", # this must be the full URL! devbranch = "main", devurl = "dev", @@ -24,35 +25,29 @@ format=DocumenterVitepress.MarkdownVitepress( ) makedocs(; - sitename="Krang.jl", - authors="Dominic and contributors", - modules=[Krang], - repo="https://github.com/dominic-chang/Krang.jl/blob/{commit}{path}#{line}", - format=format, + sitename = "Krang.jl", + authors = "Dominic and contributors", + modules = [Krang], + repo = "https://github.com/dominic-chang/Krang.jl/blob/{commit}{path}#{line}", + format = format, draft = false, source = "src", build = "build", - pages=[ + pages = [ "Home" => "index.md", "Getting Started" => "getting_started.md", "Examples" => MD_FILES, "Theory" => [ - "Raytracing" => [ - "kerr_geodesic_summary.md", - "time_regularization.md", - ], - "Polarization" => [ - "newmann_penrose.md", - "polarization.md", - ] + "Raytracing" => ["kerr_geodesic_summary.md", "time_regularization.md"], + "Polarization" => ["newmann_penrose.md", "polarization.md"], ], "api.md", ], ) deploydocs(; - repo="github.com/dominic-chang/Krang.jl", + repo = "github.com/dominic-chang/Krang.jl", target = "build", # this is where Vitepress stores its output - devbranch="main", - push_preview=true, + devbranch = "main", + push_preview = true, ) diff --git a/examples/coordinate-example.jl b/examples/coordinate-example.jl index 287f34b..46477d1 100644 --- a/examples/coordinate-example.jl +++ b/examples/coordinate-example.jl @@ -11,15 +11,13 @@ using CairoMakie curr_theme = Theme( Axis = ( - xticksvisible = false, + xticksvisible = false, xticklabelsvisible = false, yticksvisible = false, yticklabelsvisible = false, - aspect=1 - ), - Heatmap = ( - rasterize=true, - ) + aspect = 1, + ), + Heatmap = (rasterize = true,), ) set_theme!(merge!(curr_theme, theme_latexfonts())) @@ -35,7 +33,7 @@ rmax = 10.0; # maximum radius to be ray traced ρmax = 15.0; # horizontal and vertical limits of the screen # Initialize Camera and pre-allocate memory for data to be plotted -coordinates = (zeros(sze, sze) for _ in 1:3) +coordinates = (zeros(sze, sze) for _ = 1:3) camera = Krang.SlowLightIntensityCamera(metric, θo, -ρmax, ρmax, -ρmax, ρmax, sze); colormaps = (:afmhot, :afmhot, :hsv) colorrange = ((-20, 20), (0, rmax), (0, 2π)) @@ -46,32 +44,35 @@ colorrange = ((-20, 20), (0, rmax), (0, 2π)) # coordiante information for a sub-image `n` associated with the ray at the pixel `pixel` which intersects a cone with opening angle `θs`. # We will define a function which introduces some basic occlusion effects by checking if the ray has intersected with the cone on # the 'far-side' or the 'near-side' from the obsever. -function coordinate_point(pix::Krang.AbstractPixel, geometry::Krang.ConeGeometry{T,A}) where {T, A} +function coordinate_point( + pix::Krang.AbstractPixel, + geometry::Krang.ConeGeometry{T,A}, +) where {T,A} n, rmin, rmax = geometry.attributes θs = geometry.opening_angle coords = ntuple(j -> zero(T), Val(4)) - isindir = false - for _ in 1:2 # Looping over isindir this way is needed to get Metal.jl to work + isindir = false + for _ = 1:2 # Looping over isindir this way is needed to get Metal.jl to work isindir ⊻= true - ts, rs, ϕs = emission_coordinates(pix, geometry.opening_angle, isindir, n) + ts, rs, ϕs = emission_coordinates(pix, geometry.opening_angle, isindir, n) if rs ≤ rmin || rs ≥ rmax continue end - coords = isnan(rs) ? observation : (ts, rs, θs, ϕs) + coords = isnan(rs) ? observation : (ts, rs, θs, ϕs) end - return coords + return coords end # ## Drawing coordinate points # This function plots the coordinates associated with the n=0,1,2 subimages of a cone with opening angle θs. function draw!(axes_list, camera, coordinates, rmin, rmax, θs) - times, radii, azimuths = coordinates + times, radii, azimuths = coordinates map(axes -> empty!.(axes), axes_list) - geometries = (Krang.ConeGeometry(θs, (i, rmin, rmax)) for i in 0:2) - + geometries = (Krang.ConeGeometry(θs, (i, rmin, rmax)) for i = 0:2) + for (i, geometry) in enumerate(geometries) rendered_scene = coordinate_point.(camera.screen.pixels, Ref(geometry)) for I in CartesianIndices(rendered_scene) @@ -79,25 +80,41 @@ function draw!(axes_list, camera, coordinates, rmin, rmax, θs) radii[I] = rendered_scene[I][2] azimuths[I] = rendered_scene[I][4] end - coordinates = (times, radii, mod2pi.(azimuths )) - for j in 1:3 - heatmap!(axes_list[i][j], coordinates[j], colormap = colormaps[j], colorrange=colorrange[j]) + coordinates = (times, radii, mod2pi.(azimuths)) + for j = 1:3 + heatmap!( + axes_list[i][j], + coordinates[j], + colormap = colormaps[j], + colorrange = colorrange[j], + ) end end end # Create Figure -fig = Figure(resolution=(700, 700)); +fig = Figure(resolution = (700, 700)); axes_list = [ [ - Axis(fig[i, 1], title=(i==1 ? "Regularized Time" : ""), titlesize=20, ylabel=(i==1 ? L"n=0" : i==2 ? L"n=1" : L"n=2"), ylabelsize=20), - Axis(fig[i, 2], title=(i==1 ? "Radius" : ""), titlesize=20), - Axis(fig[i, 3], title=(i==1 ? "Azimuth" : ""), titlesize=20), - ] for i in 1:3 + Axis( + fig[i, 1], + title = (i == 1 ? "Regularized Time" : ""), + titlesize = 20, + ylabel = (i == 1 ? L"n=0" : i == 2 ? L"n=1" : L"n=2"), + ylabelsize = 20, + ), + Axis(fig[i, 2], title = (i == 1 ? "Radius" : ""), titlesize = 20), + Axis(fig[i, 3], title = (i == 1 ? "Azimuth" : ""), titlesize = 20), + ] for i = 1:3 ] # Create the animation of Cone of Emission Coordinates -recording = CairoMakie.record(fig, "coordinate.gif", range(0.0, π, length=180), framerate=12) do θs +recording = CairoMakie.record( + fig, + "coordinate.gif", + range(0.0, π, length = 180), + framerate = 12, +) do θs draw!(axes_list, camera, coordinates, rmin, rmax, θs) end diff --git a/examples/custom-material-example.jl b/examples/custom-material-example.jl index 75dde79..13ff177 100644 --- a/examples/custom-material-example.jl +++ b/examples/custom-material-example.jl @@ -18,9 +18,12 @@ end # This functor will take in a pixel and a geometry and return the redshift associated with a given sub image. # You must include the relevant physics in the functor definition. # Here we will include redshift effects associated with a zero angular momentum observer (ZAMO). -function (m::ZAMORedshifts)(pix::Krang.AbstractPixel{T}, intersection::Krang.Intersection) where {T} +function (m::ZAMORedshifts)( + pix::Krang.AbstractPixel{T}, + intersection::Krang.Intersection, +) where {T} (; rs, θs, νr, νθ) = intersection - α,β=Krang.screen_coordinate(pix) + α, β = Krang.screen_coordinate(pix) ηtemp = η(metric, α, β, θo) λtemp = λ(metric, α, θo) @@ -34,7 +37,7 @@ function (m::ZAMORedshifts)(pix::Krang.AbstractPixel{T}, intersection::Krang.Int end # We need to define the return type or the material for ray tracing. This can be things like a `Float` of a `StokesParams`. Let's use a float for this case. -function Krang.yield(::ZAMORedshifts{T}) where T +function Krang.yield(::ZAMORedshifts{T}) where {T} return zero(T) end @@ -61,23 +64,23 @@ import CairoMakie as CMk theme = CMk.Theme( Axis = ( - xticksvisible = false, + xticksvisible = false, xticklabelsvisible = false, yticksvisible = false, yticklabelsvisible = false, - ), + ), ) CMk.set_theme!(CMk.merge!(theme, CMk.theme_latexfonts())) -fig = CMk.Figure(resolution=(700, 700)); -ax = CMk.Axis(fig[1, 1], title="Redshifts", titlesize=20, aspect=1) -hm = CMk.heatmap!(ax, redshifts, colormap=:afmhot) -CMk.Colorbar(fig[1, 2], hm, label="Redshifts", labelsize=20) +fig = CMk.Figure(resolution = (700, 700)); +ax = CMk.Axis(fig[1, 1], title = "Redshifts", titlesize = 20, aspect = 1) +hm = CMk.heatmap!(ax, redshifts, colormap = :afmhot) +CMk.Colorbar(fig[1, 2], hm, label = "Redshifts", labelsize = 20) CMk.save("redshifts.png", fig) # ![redshifts](redshifts.png) # Saving the redshifts to a .npy file using NPZ -npzwrite("redshifts_n1.npy", redshifts) \ No newline at end of file +npzwrite("redshifts_n1.npy", redshifts) diff --git a/examples/mino-time-example.jl b/examples/mino-time-example.jl index 5a56ec1..126010b 100644 --- a/examples/mino-time-example.jl +++ b/examples/mino-time-example.jl @@ -11,17 +11,17 @@ import GLMakie as GLMk GLMk.Makie.inline!(true) curr_theme = GLMk.Theme(# Makie theme - fontsize=20, - Axis=( - xticksvisible=false, - xticklabelsvisible=false, - yticksvisible=false, - yticklabelsvisible=false, - leftspinevisible=false, - rightspinevisible=false, - topspinevisible=false, - bottomspinevisible=false, - titlefontsize=30, + fontsize = 20, + Axis = ( + xticksvisible = false, + xticklabelsvisible = false, + yticksvisible = false, + yticklabelsvisible = false, + leftspinevisible = false, + rightspinevisible = false, + topspinevisible = false, + bottomspinevisible = false, + titlefontsize = 30, ), ) @@ -45,41 +45,56 @@ camera = Krang.SlowLightIntensityCamera(metric, θo, -ρmax, ρmax, -ρmax, ρma # We will create a loop to plot the emission coordinates for each `τ` using the `emission_coordinates!` function. # Let us now create a figure to plot the emission coordinates on. -fig = GLMk.Figure(resolution=(500, 600)); +fig = GLMk.Figure(resolution = (500, 600)); -recording = GLMk.record(fig, "raytrace.gif", range(0.1, 3, length=290), framerate=15) do τ - GLMk.empty!(fig) +recording = + GLMk.record(fig, "raytrace.gif", range(0.1, 3, length = 290), framerate = 15) do τ + GLMk.empty!(fig) - coordinates = zeros(4, size(camera.screen.pixels)...) # Pre allocated array to store coordinates - emission_coordinates!(coordinates, camera, τ) - time = coordinates[1,:,:] - radius = coordinates[2,:,:] - inclination = coordinates[3,:,:] - azimuth = mod2pi.(coordinates[4,:,:]) + coordinates = zeros(4, size(camera.screen.pixels)...) # Pre allocated array to store coordinates + emission_coordinates!(coordinates, camera, τ) + time = coordinates[1, :, :] + radius = coordinates[2, :, :] + inclination = coordinates[3, :, :] + azimuth = mod2pi.(coordinates[4, :, :]) - data = (time, radius, inclination, azimuth) - titles = (GLMk.L"\text{Regularized Time }(t_s)", GLMk.L"\text{Radius }(r_s)", GLMk.L"\text{Inclination }(\theta_s)", GLMk.L"\text{Azimuth } (\phi_s)") - colormaps = (:afmhot, :afmhot, :afmhot, :hsv) - colorrange = ((-20, 20), (0, 10.0), (0,π), (0, 2π)) - indices = ((1,1), ()) - - for i in 1:4 - hm = GLMk.heatmap!( - GLMk.Axis(getindex(fig, (i > 2 ? 2 : 1), (iszero(i%2) ? 3 : 1)); aspect=1, title=titles[i]), - data[i], - colormap=colormaps[i], - colorrange=colorrange[i] + data = (time, radius, inclination, azimuth) + titles = ( + GLMk.L"\text{Regularized Time }(t_s)", + GLMk.L"\text{Radius }(r_s)", + GLMk.L"\text{Inclination }(\theta_s)", + GLMk.L"\text{Azimuth } (\phi_s)", ) - cb = GLMk.Colorbar(fig[(i > 2 ? 2 : 1), (iszero(i%2) ? 3 : 1)+1], hm; labelsize=30, ticklabelsize=20) + colormaps = (:afmhot, :afmhot, :afmhot, :hsv) + colorrange = ((-20, 20), (0, 10.0), (0, π), (0, 2π)) + indices = ((1, 1), ()) + + for i = 1:4 + hm = GLMk.heatmap!( + GLMk.Axis( + getindex(fig, (i > 2 ? 2 : 1), (iszero(i % 2) ? 3 : 1)); + aspect = 1, + title = titles[i], + ), + data[i], + colormap = colormaps[i], + colorrange = colorrange[i], + ) + cb = GLMk.Colorbar( + fig[(i > 2 ? 2 : 1), (iszero(i % 2) ? 3 : 1)+1], + hm; + labelsize = 30, + ticklabelsize = 20, + ) + end + + ax = GLMk.Axis(fig[3, 1:3], height = 60) + GLMk.hidedecorations!(ax) + GLMk.text!(ax, 0, 100; text = GLMk.L"θ_o=%$(Int(floor(θo*180/π)))^\circ") + GLMk.rowgap!(fig.layout, 1, GLMk.Fixed(0)) end - ax = GLMk.Axis(fig[3, 1:3], height=60) - GLMk.hidedecorations!(ax) - GLMk.text!(ax,0,100; text=GLMk.L"θ_o=%$(Int(floor(θo*180/π)))^\circ") - GLMk.rowgap!(fig.layout, 1, GLMk.Fixed(0)) -end - # ![image](raytrace.gif) # ## Plotting rays @@ -90,26 +105,26 @@ end camera = Krang.SlowLightIntensityCamera(metric, θo, -3, 3, -3, 3, 4); fig = GLMk.Figure() -ax = GLMk.Axis3(fig[1,1], aspect=(1,1,1)) -GLMk.xlims!(ax, (-3, 3)) -GLMk.ylims!(ax, (-3, 3)) -GLMk.zlims!(ax, (-3, 3)) +ax = GLMk.Axis3(fig[1, 1], aspect = (1, 1, 1)) +GLMk.xlims!(ax, (-3, 3)) +GLMk.ylims!(ax, (-3, 3)) +GLMk.zlims!(ax, (-3, 3)) lines_to_plot = [] lines_to_plot = Krang.generate_ray.(camera.screen.pixels, 5_000) -sphere = GLMk.Sphere(GLMk.Point(0.0,0.0,0.0), horizon(metric)) -GLMk.mesh!(ax, sphere, color=:black) # Sphere to represent black hole +sphere = GLMk.Sphere(GLMk.Point(0.0, 0.0, 0.0), horizon(metric)) +GLMk.mesh!(ax, sphere, color = :black) # Sphere to represent black hole -for i in lines_to_plot; - ray = map(x-> begin - (;rs, θs, ϕs) = x - [rs*sin(θs)*cos(ϕs), rs*sin(θs)*sin(ϕs), rs*cos(θs)] +for i in lines_to_plot + ray = map(x -> begin + (; rs, θs, ϕs) = x + [rs * sin(θs) * cos(ϕs), rs * sin(θs) * sin(ϕs), rs * cos(θs)] end, i) ray = hcat(ray...) - GLMk.lines!(ax, ray) + GLMk.lines!(ax, ray) end fig GLMk.save("mino_time_rays.png", fig) -# ![Photons trajectories around Kerr black hole in Boyer-Lindquist Coordinates](mino_time_rays.png) \ No newline at end of file +# ![Photons trajectories around Kerr black hole in Boyer-Lindquist Coordinates](mino_time_rays.png) diff --git a/examples/neural-net-example.jl b/examples/neural-net-example.jl index ec8922c..b609ec8 100644 --- a/examples/neural-net-example.jl +++ b/examples/neural-net-example.jl @@ -18,7 +18,7 @@ rng = Random.GLOBAL_RNG # Lets define an `ImageModel` which will be comprised of an emission layer that we will raytrace. # We will do this by first creating a struct to represent our image model that will store our emission model as a layer. -struct ImageModel{T <: Chain} +struct ImageModel{T<:Chain} emission_layer::T end @@ -27,44 +27,45 @@ end # We will assume that the emission is coming from emission that originates in the equatorial plane. function (m::ImageModel)(x, ps, st) metric = Krang.Kerr(0.99e0) - θo = Float64(20/180*π) - pixels = Krang.IntensityPixel.(Ref(metric), x[1,:], x[2,:], θo) + θo = Float64(20 / 180 * π) + pixels = Krang.IntensityPixel.(Ref(metric), x[1, :], x[2, :], θo) sze = unsafe_trunc(Int, sqrt(size(x)[2])) - coords = zeros(Float64, 2,sze*sze) - emission_vals = zeros(Float64, 1, sze*sze) - for n in 0:1 - for i in 1:sze - Threads.@threads for j in 1:sze + coords = zeros(Float64, 2, sze * sze) + emission_vals = zeros(Float64, 1, sze * sze) + for n = 0:1 + for i = 1:sze + Threads.@threads for j = 1:sze pix = pixels[i+(j-1)*sze] α, β = Krang.screen_coordinate(pix) T = typeof(α) - rs, ϕs = Krang.emission_coordinates_fast_light(pix, Float64(π/2), β > 0, n)[1:3] + rs, ϕs = + Krang.emission_coordinates_fast_light(pix, Float64(π / 2), β > 0, n)[1:3] xs = rs * cos(ϕs) ys = rs * sin(ϕs) if hypot(xs, ys) ≤ Krang.horizon(metric) - coords[1,i+(j-1)*sze] = zero(T) - coords[2,i+(j-1)*sze] = zero(T) + coords[1, i+(j-1)*sze] = zero(T) + coords[2, i+(j-1)*sze] = zero(T) else - coords[1,i+(j-1)*sze] = xs - coords[2,i+(j-1)*sze] = ys + coords[1, i+(j-1)*sze] = xs + coords[2, i+(j-1)*sze] = ys end end end emission_vals .+= m.emission_layer(coords, ps, st)[1] end - emission_vals,st + emission_vals, st end # Lets define an emisison layer for our model as a simple fully connected neural network with 2 hidden layers. # The emission layer will take in 2D coordinates on an equatorial disk in the bulk spacetime and return a scalar intensity value. emission_model = Chain( - Dense(2 => 20, Lux.sigmoid), + Dense(2 => 20, Lux.sigmoid), Dense(20 => 20, Lux.sigmoid), - Dense(20 => 1, Lux.sigmoid) - ) + Dense(20 => 1, Lux.sigmoid), +) ps, st = Lux.setup(rng, emission_model); # Get the emission model parameters and state @@ -74,22 +75,27 @@ image_model = ImageModel(emission_model) ## Plotting the model # Lets create an 20x20 pixel image of the `image_model` with a field of view of $10 MG/c^2$. - + sze = 20 ρmax = 10e0 -pixels = zeros(Float64, 2, sze*sze) +pixels = zeros(Float64, 2, sze * sze) for (iiter, i) in enumerate(range(-ρmax, ρmax, sze)) for (jiter, j) in enumerate(range(-ρmax, ρmax, sze)) - pixels[1,iiter+(jiter-1)*sze] = Float64(i) - pixels[2,iiter+(jiter-1)*sze] = Float64(j) + pixels[1, iiter+(jiter-1)*sze] = Float64(i) + pixels[2, iiter+(jiter-1)*sze] = Float64(j) end end # We can see the effects of raytracing on emission in the bulk spacetime by plotting an image of the emission model and the image model. using CairoMakie curr_theme = Theme( - Axis = (xticksvisible=false, xticklabelsvisible=false, yticksvisible=false, yticklabelsvisible=false,), - Heatmap =(colormap=:afmhot, ), + Axis = ( + xticksvisible = false, + xticklabelsvisible = false, + yticksvisible = false, + yticklabelsvisible = false, + ), + Heatmap = (colormap = :afmhot,), ) set_theme!(merge(curr_theme, theme_latexfonts())) @@ -97,8 +103,11 @@ emitted_intensity = reshape(emission_model(pixels, ps, st)[1], sze, sze) received_intensity = reshape(image_model(pixels, ps, st)[1], sze, sze) fig = Figure(); -heatmap!(Axis(fig[1,1], aspect=1, title="Emission Model"), emitted_intensity) -heatmap!(Axis(fig[1,2], aspect=1, title="Image Model (Lensed Emission Model)"), received_intensity) +heatmap!(Axis(fig[1, 1], aspect = 1, title = "Emission Model"), emitted_intensity) +heatmap!( + Axis(fig[1, 2], aspect = 1, title = "Image Model (Lensed Emission Model)"), + received_intensity, +) save("emission_model_and_target_model.png", fig) # ![image](emission_model_and_target_model.png) @@ -106,18 +115,18 @@ save("emission_model_and_target_model.png", fig) # ## Fitting the NeRF model # This will be a toy example showing the mechanics of fitting our ImageModel to a target image using the normalized cross correlation as a kernel for our loss function. # This will be the image we will try to fit our model to. -target_img = reshape(received_intensity, 1, sze*sze); +target_img = reshape(received_intensity, 1, sze * sze); # Lets fit our model using the normalized cross correlation as a kernel for our loss function. using Enzyme -using Optimization +using Optimization using OptimizationOptimisers using StatsBase using ComponentArrays -function mse(img1::Matrix{T}, img2::Matrix{T}) where T - mean(((img1 ./ sum(img1)) .- (img2 ./ sum(img2))) .^ 2) +function mse(img1::Matrix{T}, img2::Matrix{T}) where {T} + mean(((img1 ./ sum(img1)) .- (img2 ./ sum(img2))) .^ 2) end function loss_function(pixels, y, ps, st) @@ -135,21 +144,29 @@ received_intensity = reshape(image_model(pixels, ps, st)[1], sze, sze) loss_function(pixels, target_img, ps, st) fig = Figure(); -heatmap!(Axis(fig[1,1], aspect=1, title="Emission Model"), emitted_intensity, colormap=:afmhot) -heatmap!(Axis(fig[1,2], aspect=1, title="Imgage Model (Lensed Emission Model)"), received_intensity, colormap=:afmhot) +heatmap!( + Axis(fig[1, 1], aspect = 1, title = "Emission Model"), + emitted_intensity, + colormap = :afmhot, +) +heatmap!( + Axis(fig[1, 2], aspect = 1, title = "Imgage Model (Lensed Emission Model)"), + received_intensity, + colormap = :afmhot, +) save("emission_model_and_image_model.png", fig) # ![image](emission_model_and_image_model.png) # Lets define callback function to print the loss as we optimize our model. -mutable struct Callback +mutable struct Callback counter::Int stride::Int const f::Function end Callback(stride, f) = Callback(0, stride, f) function (c::Callback)(state, loss, others...) - c.counter += 1 + c.counter += 1 if c.counter % c.stride == 0 @info "On step $(c.counter) loss = $(loss)" return false @@ -159,40 +176,58 @@ function (c::Callback)(state, loss, others...) end # We can now optimize our model using the ADAM optimizer. -ps_trained, st_trained = let st=Ref(st), x=pixels, y=reshape(target_img, 1, sze*sze) - +ps_trained, st_trained = let st = Ref(st), x = pixels, y = reshape(target_img, 1, sze * sze) + optprob = Optimization.OptimizationProblem( Optimization.OptimizationFunction( - function(ps, constants) + function (ps, constants) loss, st[] = loss_function(x, y, ps, st[]) loss end, - Optimization.AutoEnzyme() + Optimization.AutoEnzyme(), ), - ComponentArrays.ComponentVector{Float64}(ps) + ComponentArrays.ComponentVector{Float64}(ps), ) - + solution = Optimization.solve( optprob, OptimizationOptimisers.Adam(), - maxiters = 5_000, - callback=Callback(100,()->nothing) + maxiters = 5_000, + callback = Callback(100, () -> nothing), ) - + solution.u, st[] end # Let's plot the results of our optimization. and compare it to the target image. -received_intensity, st = ((x) -> (reshape(x[1], sze, sze), x[2]))(image_model(pixels, ps_trained, st_trained)) +received_intensity, st = + ((x) -> (reshape(x[1], sze, sze), x[2]))(image_model(pixels, ps_trained, st_trained)) acc_intensity, st = ((x) -> (reshape(x[1], sze, sze), x[2]))(image_model(pixels, ps, st)) loss_function(pixels, target_img, ps, st) loss_function(pixels, target_img, ps_trained, st_trained) using Printf -begin - fig = Figure(size=(700, 300)); - heatmap!(Axis(fig[1,1], aspect=1, title="Target Image"), reshape(target_img, sze, sze)) - heatmap!(Axis(fig[1,2], aspect=1, title="Starting State (loss=$(@sprintf("%0.2e", loss_function(pixels, target_img, ps, st)[1])))"), acc_intensity) - heatmap!(Axis(fig[1,3], aspect=1, title="Fitted State (loss=$(@sprintf("%0.2e", loss_function(pixels, target_img, ps_trained, st_trained)[1])))"), received_intensity) +begin + fig = Figure(size = (700, 300)) + heatmap!( + Axis(fig[1, 1], aspect = 1, title = "Target Image"), + reshape(target_img, sze, sze), + ) + heatmap!( + Axis( + fig[1, 2], + aspect = 1, + title = "Starting State (loss=$(@sprintf("%0.2e", loss_function(pixels, target_img, ps, st)[1])))", + ), + acc_intensity, + ) + heatmap!( + Axis( + fig[1, 3], + aspect = 1, + title = "Fitted State (loss=$(@sprintf("%0.2e", loss_function(pixels, target_img, ps_trained, st_trained)[1])))", + ), + received_intensity, + ) save("neural_net_results.png", fig) end diff --git a/examples/polarization-example.jl b/examples/polarization-example.jl index 5bfd39a..6f8c2de 100644 --- a/examples/polarization-example.jl +++ b/examples/polarization-example.jl @@ -7,15 +7,15 @@ # # First, let's import Krang and CairoMakie for plotting. using Krang -using CairoMakie +using CairoMakie curr_theme = Theme( Axis = ( - xticksvisible = false, + xticksvisible = false, xticklabelsvisible = false, yticksvisible = false, yticklabelsvisible = false, - ), + ), ) set_theme!(merge!(curr_theme, theme_latexfonts())) @@ -38,13 +38,13 @@ camera = Krang.IntensityCamera(metric, θo, -ρmax, ρmax, -ρmax, ρmax, 400); βv = 0.8776461626924748 σ = 0.7335172899224874 η1 = 2.6444786738735804 -η2 = π-η1 +η2 = π - η1 # These will be used to define the magnetic field and fluid velocity. -magfield1 = Krang.SVector(sin(ι)*cos(η1), sin(ι)*sin(η1), cos(ι)); -magfield2 = Krang.SVector(sin(ι)*cos(η2), sin(ι)*sin(η2), cos(ι)); -vel = Krang.SVector(βv, (π/2), χ); +magfield1 = Krang.SVector(sin(ι) * cos(η1), sin(ι) * sin(η1), cos(ι)); +magfield2 = Krang.SVector(sin(ι) * cos(η2), sin(ι) * sin(η2), cos(ι)); +vel = Krang.SVector(βv, (π / 2), χ); R = 3.3266154761905455 p1 = 4.05269835622511 p2 = 4.411852974336667 @@ -54,10 +54,26 @@ p2 = 4.411852974336667 # This includes the sub-images to ray trace, which in our case will be the n=0 and n=1 sub-images. θs = (75 * π / 180) -material1 = Krang.ElectronSynchrotronPowerLawPolarization(magfield1..., vel..., σ, R, p1, p2, (0,1,)); +material1 = Krang.ElectronSynchrotronPowerLawPolarization( + magfield1..., + vel..., + σ, + R, + p1, + p2, + (0, 1), +); geometry1 = Krang.ConeGeometry((θs)) -material2 = Krang.ElectronSynchrotronPowerLawPolarization(magfield2..., vel..., σ, R, p1, p2, (0,1,)); -geometry2 = Krang.ConeGeometry((π-θs)) +material2 = Krang.ElectronSynchrotronPowerLawPolarization( + magfield2..., + vel..., + σ, + R, + p1, + p2, + (0, 1), +); +geometry2 = Krang.ConeGeometry((π - θs)) # We will create two meshes, one for each geometry anc create a scene with both meshes. @@ -69,16 +85,25 @@ mesh2 = Krang.Mesh(geometry2, material2) scene = Krang.Scene((mesh1, mesh2)) stokesvals = render(camera, scene) -fig = Figure(resolution=(700, 700)); -ax1 = Axis(fig[1, 1], aspect=1, title="I") -ax2 = Axis(fig[1, 2], aspect=1, title="Q") -ax3 = Axis(fig[2, 1], aspect=1, title="U") -ax4 = Axis(fig[2, 2], aspect=1, title="V") +fig = Figure(resolution = (700, 700)); +ax1 = Axis(fig[1, 1], aspect = 1, title = "I") +ax2 = Axis(fig[1, 2], aspect = 1, title = "Q") +ax3 = Axis(fig[2, 1], aspect = 1, title = "U") +ax4 = Axis(fig[2, 2], aspect = 1, title = "V") colormaps = [:afmhot, :redsblues, :redsblues, :redsblues] -zip([ax1, ax2, ax3, ax4], [getproperty.(stokesvals,:I), getproperty.(stokesvals,:Q), getproperty.(stokesvals,:U), getproperty.(stokesvals,:V)], colormaps) .|> x->heatmap!(x[1], x[2], colormap=x[3]) +zip( + [ax1, ax2, ax3, ax4], + [ + getproperty.(stokesvals, :I), + getproperty.(stokesvals, :Q), + getproperty.(stokesvals, :U), + getproperty.(stokesvals, :V), + ], + colormaps, +) .|> x -> heatmap!(x[1], x[2], colormap = x[3]) fig save("polarization_example.png", fig) -# ![polarization of emission model](polarization_example.png) \ No newline at end of file +# ![polarization of emission model](polarization_example.png) diff --git a/examples/raytracing-mesh-example.jl b/examples/raytracing-mesh-example.jl index 9bea3e2..5df1451 100644 --- a/examples/raytracing-mesh-example.jl +++ b/examples/raytracing-mesh-example.jl @@ -5,7 +5,7 @@ using GeometryBasics using FileIO metric = Krang.Kerr(0.99) # Kerr metric with a spin of 0.99 -θo = 90/180*π # Inclination angle of the observer +θo = 90 / 180 * π # Inclination angle of the observer ρmax = 12.0 # Horizontal and Vertical extent of the screen sze = 100 # Resolution of the screen is sze x sze @@ -15,9 +15,22 @@ camera = Krang.SlowLightIntensityCamera(metric, θo, -ρmax, ρmax, -ρmax, ρma bunny_mesh = translate( rotate( scale( - load(download("https://graphics.stanford.edu/~mdfisher/Data/Meshes/bunny.obj", "bunny.obj")), 100 - ),π/2, 1.0, 0.0, 0.0 - ), 2.0,7.0,-10.0 + load( + download( + "https://graphics.stanford.edu/~mdfisher/Data/Meshes/bunny.obj", + "bunny.obj", + ), + ), + 100, + ), + π / 2, + 1.0, + 0.0, + 0.0, + ), + 2.0, + 7.0, + -10.0, ); # Ray trace the mesh embedded in the Kerr space time. The emission picked up by a ray will be the sum of all the intersections of the ray with the mesh @@ -31,8 +44,8 @@ intersections = raytrace(camera, bunny_mesh); # And plot the image with GLMakie, fig = GLMk.Figure() -ax = GLMk.Axis(fig[1,1], aspect=1) -GLMk.heatmap!(ax, intersections, colormap=:afmhot); +ax = GLMk.Axis(fig[1, 1], aspect = 1) +GLMk.heatmap!(ax, intersections, colormap = :afmhot); save("mesh_geometry_example.png", fig); @@ -41,26 +54,38 @@ save("mesh_geometry_example.png", fig); # Below is a short plotting routine that generates a video showing the scene from three different perspectives, and live renders the image. fig = GLMk.Figure() -ax1 = GLMk.Axis3(fig[1,1], aspect=(1,1,1), title="Top view of scene", elevation = π/2, azimuth = π) -ax2 = GLMk.Axis3(fig[1,2], aspect=(1,1,1), title="Side view of scene", elevation = 0.0, azimuth = 3π/2) -ax3 = GLMk.Axis3(fig[2,1], aspect=(1,1,1), title="Isometric view of scene") - -ax = GLMk.Axis(fig[2,2], aspect=1, title="Heatmap of ray intersections with mesh") +ax1 = GLMk.Axis3( + fig[1, 1], + aspect = (1, 1, 1), + title = "Top view of scene", + elevation = π / 2, + azimuth = π, +) +ax2 = GLMk.Axis3( + fig[1, 2], + aspect = (1, 1, 1), + title = "Side view of scene", + elevation = 0.0, + azimuth = 3π / 2, +) +ax3 = GLMk.Axis3(fig[2, 1], aspect = (1, 1, 1), title = "Isometric view of scene") + +ax = GLMk.Axis(fig[2, 2], aspect = 1, title = "Heatmap of ray intersections with mesh") for a in [ax1, ax2, ax3] - GLMk.xlims!(a, (-10, 10)) - GLMk.ylims!(a, (-10, 10)) - GLMk.zlims!(a, (-10, 10)) + GLMk.xlims!(a, (-10, 10)) + GLMk.ylims!(a, (-10, 10)) + GLMk.zlims!(a, (-10, 10)) GLMk.hidedecorations!(a) end GLMk.hidedecorations!(ax) -sphere = GLMk.Sphere(GLMk.Point(0.0,0.0,0.0), horizon(metric)) # Sphere to represent black hole +sphere = GLMk.Sphere(GLMk.Point(0.0, 0.0, 0.0), horizon(metric)) # Sphere to represent black hole lines_to_plot = Krang.generate_ray.(camera.screen.pixels, 100) # 100 is the number of steps to take along the ray img = zeros(sze, sze) -recording = GLMk.record(fig, "mesh.mp4", 1:sze*sze, framerate=120) do i - line = lines_to_plot[i] +recording = GLMk.record(fig, "mesh.mp4", 1:sze*sze, framerate = 120) do i + line = lines_to_plot[i] img[i] = intersections[i] @@ -70,15 +95,26 @@ recording = GLMk.record(fig, "mesh.mp4", 1:sze*sze, framerate=120) do i GLMk.empty!(ax3) for a in [ax1, ax2, ax3] - GLMk.mesh!(a, bunny_mesh, color=[parse(GLMk.Colorant, "rgba(0%, 50%, 70%,1.0)") for tri in bunny_mesh.position], colormap = :blues, transparency=true) - GLMk.mesh!(a, sphere, color=:black) + GLMk.mesh!( + a, + bunny_mesh, + color = [ + parse(GLMk.Colorant, "rgba(0%, 50%, 70%,1.0)") for + tri in bunny_mesh.position + ], + colormap = :blues, + transparency = true, + ) + GLMk.mesh!(a, sphere, color = :black) end - cart_line = map(x->(x.rs*sin(x.θs)*cos(x.ϕs), x.rs*sin(x.θs)*sin(x.ϕs), x.rs*cos(x.θs)), line) - GLMk.lines!(ax3, cart_line, color=:red) - GLMk.heatmap!(ax, img, colormap=:afmhot, colorrange=(0, 8)) + cart_line = map( + x -> (x.rs * sin(x.θs) * cos(x.ϕs), x.rs * sin(x.θs) * sin(x.ϕs), x.rs * cos(x.θs)), + line, + ) + GLMk.lines!(ax3, cart_line, color = :red) + GLMk.heatmap!(ax, img, colormap = :afmhot, colorrange = (0, 8)) end # ```@raw html #