Skip to content

Commit

Permalink
Brand new logo (#245)
Browse files Browse the repository at this point in the history
* add text (Montsserrat) for logo

* [wip] logo: integration and backwards time works

todo: slowdown!

* yeahhhhh slowdown is done, logo looks SICK!!!!

* Logo is FINISHED!!!

* add final logo :)

* bump version
  • Loading branch information
Datseris authored Oct 31, 2024
1 parent b254477 commit 061b628
Show file tree
Hide file tree
Showing 11 changed files with 338 additions and 38 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,5 @@ Manifest.toml
*.css
*style.jl
*.png
*.mp4
*.mp4
*.gif
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "DynamicalSystems"
uuid = "61744808-ddfa-5f27-97ff-6e42cc95d634"
repo = "https://github.com/JuliaDynamics/DynamicalSystems.jl.git"
version = "3.3.22"
version = "3.3.23"

[deps]
Attractors = "f3fd9213-ca85-4dba-9dfd-7fc91308fec7"
Expand Down
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
![DynamicalSystems.jl logo: The Double Pendulum](https://i.imgur.com/nFQFdB0.gif)
![DynamicalSystems.jl logo: The Double Pendulum](https://github.com/JuliaDynamics/JuliaDynamics/blob/master/videos/dynamicalsystems/juliadynamics_logo_anim_dark.gif?raw=true)

[![](https://img.shields.io/badge/docs-online-blue.svg)](https://juliadynamics.github.io/DynamicalSystemsDocs.jl/dynamicalsystems/dev/)
[![DocBuild](https://github.com/juliadynamics/DynamicalSystems.jl/workflows/CI/badge.svg)](https://github.com/JuliaDynamics/DynamicalSystems.jl/actions)
[![DOI](http://joss.theoj.org/papers/10.21105/joss.00598/status.svg)](https://doi.org/10.21105/joss.00598)
[![Textbook](https://img.shields.io/badge/Textbook-10.1007%2F978--3--030--91032--7-purple)](https://link.springer.com/book/10.1007/978-3-030-91032-7)
[![Package Downloads](https://img.shields.io/badge/dynamic/json?url=http%3A%2F%2Fjuliapkgstats.com%2Fapi%2Fv1%2Ftotal_downloads%2FDynamicalSystems&query=total_requests&label=Downloads)](http://juliapkgstats.com/pkg/DynamicalSystems)


**DynamicalSystems.jl** is an [award-winning](https://dsweb.siam.org/The-Magazine/Article/winners-of-the-dsweb-2018-software-contest) Julia software library for nonlinear dynamics and nonlinear timeseries analysis.
**DynamicalSystems.jl** is an [award-winning](https://dsweb.siam.org/The-Magazine/Article/winners-of-the-dsweb-2018-software-contest) Julia-based general-purpose software library for the whole of nonlinear dynamics and nonlinear timeseries analysis.

To install **DynamicalSystems.jl**, run `import Pkg; Pkg.add("DynamicalSystems")` as a Julia language command.
To learn how to use it and see its contents visit the documentation, which you can either find [online](https://juliadynamics.github.io/DynamicalSystems.jl/dev/) or build locally by running the `docs/make.jl` file.
Expand All @@ -23,8 +22,8 @@ Aspects of **DynamicalSystems.jl** that make it stand out among other codebases
- **Open source community project**. Built from the ground up entirely on GitHub, **DynamicalSystems.jl** is 100% open source and based on community contributions. Anyone can be a developer of the library. Everyone is welcomed.
- **Extensive content**. It aims to cover the entire field of nonlinear dynamics and nonlinear timeseries analysis. It has functionality for complexity measures, delay embeddings, periodic orbits, nonlocal stability analysis, continuation, chaos, fractal dimensions, surrogate testing, recurrence quantification analysis, and much more. Furthermore, all algorithms are "general" and work for any dynamical system applicable. Missing functionality that falls under this wide category of content is welcomed to be part of the library!
- **Well tested**. All implemented functionality is extensively tested. Each time any change in the code base is done, the extensive test suite is run and checked before merging the change in.
- **Extendable**. **DynamicalSystems.jl** is a living, evolving project. New contributions can become part of the library and be accessed by all users in the next release. Most importantly, all parts of the library follow professional standards in software design and implement extendable interfaces so that it is easy to contribute new functionality.
- **Active development**. Since the start of the project (May 2017) there has been activity every month: new features, bugfixes, and the developer team answers users questions on official Julia language forums.
- **Extendable**. New contributions can become part of the library and be accessed by all users in the next release. Most importantly, all parts of the library follow professional standards in software design and implement extendable interfaces so that it is easy to contribute new functionality.
- **Active development**. It is a living, evolving project. Since its beginning in May 2017, **DynamicalSystems.jl** has had some activity every single month: new features, bugfixes. The developer team routinely answers users questions on official Julia language forums.
- **Performant**. Written entirely in Julia, heavily optimized and parallelized, and taking advantage of some of the best packages within the language, **DynamicalSystems.jl** is _really fast_.

## Goals
Expand Down
185 changes: 155 additions & 30 deletions docs/logo.jl → docs/logo/logo.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using DynamicalSystems
using OrdinaryDiffEq
using OrdinaryDiffEqVerner
using CairoMakie
using DataStructures: CircularBuffer
desktop() = joinpath(homedir(), "Desktop")
desktop(args...) = joinpath(desktop(), args...)
desktop() = @__DIR__

# double pendulum dynamical system
@inbounds function doublependulum_rule(u, p, t)
Expand Down Expand Up @@ -61,7 +62,8 @@ ax = Axis(fig[1,1]; backgroundcolor = :transparent, aspect = DataAspect() )
# this is maximum possible limits:
# ax.limits = ((-L1-L2-0.1, L1 + L2+0.1), (-L1-L2-0.1, L1 + L2 + 0.1))
# this is reduced size in height:
ax.limits = ((-L1-L2-0.1, L1 + L2+0.1), (-L1-L2-0.1, (L1 + L2 + 0.1)/2))
lima = 0.1
ax.limits = ((-L1-L2-lima, L1 + L2+lima), (-L1-L2-lima, (L1 + L2 + lima)/2))
ylims!(-0.8660254037844386/2 - 2.1, -0.8660254037844386/2 + 2.1) # center y of axis for equal aspect ratio
# ax.aspect = 1
hidedecorations!(ax)
Expand Down Expand Up @@ -106,21 +108,26 @@ trajline = lines!(ax, traj; color = tailcoltransp, linewidth = 4)
# rods that connect the pendulum
rodlines = lines!(ax, balls; linewidth = 12, color = :black)

scatter!(ax, balls; marker = :circle, strokewidth = 10,
juliaballs = scatter!(ax, balls; marker = :circle, strokewidth = 10,
strokecolor = [julia_green, julia_red, julia_purple],
color = [lighter_green, lighter_red, lighter_purple],
markersize = 160,
)

function animstep!(dp)
step!(dp)
x1,x2,y1,y2 = xycoords(current_state(dp))
update!(current_state(dp))
end

function update!(u)
x1,x2,y1,y2 = xycoords(u)
rod[] = [Point2f(0, 0), Point2f(x1, y1), Point2f(x2, y2)]
balls[] = [Point2f(0, 0), Point2f(x1, y1), Point2f(x2, y2)]
push!(traj[], Point2f(x2, y2))
notify(traj)
end
function animstep!(dp, t)

function animstep!(dp::DynamicalSystem, t)
t0 = current_time(dp)
while current_time(dp) < t0 + t
animstep!(dp)
Expand All @@ -132,7 +139,7 @@ fig

# %% find initial condition that leads to nice Julia logo:
using DynamicalSystems.StateSpaceSets.Distances
u0 =/2 + 0.1, +2.03, 0.3, +5.412]
u0 = SVector{4}(/2 + 0.1, +2.03, 0.3, +5.412])
reinit!(dp, u0)


Expand All @@ -159,58 +166,176 @@ end

d
tf = current_time(dp)
uf = current_state(dp)

# reported final time of evolution from given initial condition:
# 168.38499999991936

# okay, save high quality version:
# Final state
# 5.757958811321035
# -5.924686393536801
# 58.11993236370379
# -2.839077350331716

fig


# %% okay, save high quality version:
ax.backgroundcolor = :transparent
CairoMakie.save(desktop("juliadynamics_logo.png"), fig; px_per_unit = 4)
# and one without tail
trajline.visible = false
save(desktop("juliadynamics_logo_no_tail.png"), fig; px_per_unit = 4)
trajline.visible = true
fig.scene.backgroundcolor = to_color(:transparent)
CairoMakie.save(desktop("juliadynamics_logo_light_transparent.png"), fig; px_per_unit = 4)
# and one more with white background
ax.backgroundcolor = :white
fig.scene.backgroundcolor = to_color(:white)
CairoMakie.save(desktop("juliadynamics_logo_white.png"), fig; px_per_unit = 4)
CairoMakie.save(desktop("juliadynamics_logo_light.png"), fig; px_per_unit = 4)
# and a dark background
rodlines.color = :white
trajline.color = tailcoltransplight
ax.backgroundcolor = "#1e1e20"
fig.scene.backgroundcolor = to_color("#1e1e20")
CairoMakie.save(desktop("juliadynamics_logo_dark.png"), fig; px_per_unit = 4)
# and transparent dark version
ax.backgroundcolor = :transparent
fig.scene.backgroundcolor = to_color(:transparent)
CairoMakie.save(desktop("juliadynamics_logo_dark_transparent.png"), fig; px_per_unit = 4)

# %% add text axis
texax = Axis(fig[:, 0]; backgroundcolor = "#1e1e20")

resize!(fig, 1600, 600)

lima = 0.1
ax.limits = ((-L1-L2-lima, L1 + L2+lima), (-L1-L2-lima, (L1 + L2 + lima)/2))

fig

# %% Add DynamicalSystems.jl font
font = "Montserrat-Medium"
empty!(texax)
hidedecorations!(texax)
hidespines!(texax)

dstext = text!(texax, 1.0, 0.5;
text = "Dynamical\nSystems.jl", font = joinpath(@__DIR__, "montserrat", "$(font).ttf"),
align = (:right, :center), justification = :right, space = :relative,
color = :white, fontsize = 130, offset = (-35.0, 0),
)

# Julia dots over i/j
scatter!(
[0.69, 0.885], [0.725, 0.445]; markersize = 40,
color = julia_blue
)

# add vertical line
vertline = lines!(texax, [0.99, 0.99], [0.1, 0.9]; color = :white, linewidth = 10,)
texax.limits = ((0, 1), (0, 1))
fig


# %% save full logo!
# dark version - solid
trajline.color = tailcoltransplight
ax.backgroundcolor = "#1e1e20"
texax.backgroundcolor = "#1e1e20"
fig.scene.backgroundcolor = to_color("#1e1e20")
rodlines.color = :white
CairoMakie.save(desktop("juliadynamics_full_logo_dark.png"), fig; px_per_unit = 4)

# dark version - transparent
texax.backgroundcolor = :transparent
ax.backgroundcolor = :transparent
fig.scene.backgroundcolor = to_color(:transparent)
CairoMakie.save(desktop("juliadynamics_logo_dark_transp.png"), fig; px_per_unit = 4)
# reset back to standard

CairoMakie.save(desktop("juliadynamics_full_logo_dark_transparent.png"), fig; px_per_unit = 4)

# light version - transparent
trajline.color = tailcoltransp
rodlines.color = :black
dstext.color = :black
vertline.color = :black

CairoMakie.save(desktop("juliadynamics_full_logo_light_transparent.png"), fig; px_per_unit = 4)

# light version - solid
texax.backgroundcolor = :white
ax.backgroundcolor = :white
fig.scene.backgroundcolor = to_color(:white)

CairoMakie.save(desktop("juliadynamics_full_logo_light.png"), fig; px_per_unit = 4)

fig

# %% perform video animation animate from some t start to tf
# %% reset back to solid dark for animation, modify accordingly for light
# don't use transparent background, it doesn't work well with videos!!!
rodlines.color = :white
trajline.color = tailcoltransplight
dstext.color = :white
vertline.color = :white

ax.backgroundcolor = "#1e1e20"
texax.backgroundcolor = "#1e1e20"
fig.scene.backgroundcolor = to_color("#1e1e20")

reinit!(dp, u0)
resize!(fig, 800, 800)
fig

# %% perform video animation animate from some t start to tf
# What I want to do here is the following:
# animate the pendulum motion so that it slows down as it reaches the final
# state, and it stops once it reaches the final state.

# For this, it is better to have a full ODE solution backwards in time,
# it is so much simpler for adjusting time
prob = ODEProblem((u,p,t) -> -doublependulum_rule(u,p,t), uf, (0.0, 100.0), p0)

sol = solve(prob; alg = Vern9(), dt, dense = true, adaptive = false)

# %%
# We need to adjust limits of the pendulum axis and ball size because
# the pendulum goes outside the axis range
lima = 0.25
ax.limits = ((-L1-L2-lima, L1 + L2+lima), (-L1-L2-lima, (L1 + L2 + lima)/2))
juliaballs.markersize = 140

# time
ts1 = 12.0 # time when animation starts
ts2 = 2.0 # time when slowdown function is applied
tf = 0 # final time must be 0 by definition
dtmin = dt/40 # minimum possible slowdown

# we must update a full span first before recording for a smooth tail
span = tail*dt
ts = tf - span
# ts += 20dt # for whatever reason we have to do this correction
animstep!(dp, ts) # initial state

# fig.scene.backgroundcolor = :
dtrecord = dt*10
frames = 1:(Int(span ÷ dtrecord) - 10)
@show length(frames)

record(fig, desktop("juliadynamics_logo_anim.mp4"), frames; framerate = 30) do i # i = frame number
animstep!(dp, dtrecord)
fig
before = (ts1 + span):-dt:ts1
for t in before
update!(sol(t))
end

# now we make the time vector populated more densely at the end
# we just need a function that returns `dt` when `t=ts2` and `dtmin`
# when `t = tf`; it doesn't matter the function.

# linear
decay(t) = dt + (t - ts2)*(dtmin - dt)/(tf - ts2)
# nonlinear 1, extreme slowdown at the end
decay(t) = dtmin + (dt - dtmin)*(t/(ts2 - tf))^(1/2)

# now make the non-equi spaced vector
newtimes = collect(ts1:-dt:ts2)
while newtimes[end] > tf
x = decay(newtimes[end])
push!(newtimes, newtimes[end] - x)
end
pop!(newtimes)

framerate = 30
freq = 10 # this is the animation speed at normal `dt`, decrease it to slow down
@time record(fig, desktop("juliadynamics_logo_anim_dark.gif"); framerate) do io
for (i, t) in enumerate(newtimes)
update!(sol(t))
i % freq == 0 && recordframe!(io)
end
# add a couple of seconds of stillness at the end
for _ in 1:3framerate; recordframe!(io); end
end

fig
Binary file added docs/logo/montserrat/Montserrat-Bold.ttf
Binary file not shown.
Binary file added docs/logo/montserrat/Montserrat-Medium.ttf
Binary file not shown.
Binary file added docs/logo/montserrat/Montserrat-Regular.ttf
Binary file not shown.
Binary file added docs/logo/montserrat/Montserrat-SemiBold.ttf
Binary file not shown.
Loading

0 comments on commit 061b628

Please sign in to comment.