Tutorial 6: Taming the Elements
Introduction
The world is built up of tiny tiny building blocks known as atoms. ⚛️ These atoms come in many different sizes and each has different properties. Let's visualize these atoms and show their uniqueness!
Learning Outcomes 📚
In this tutorial you'll learn:
How to use
change
to change a variable inside of an animation.To use
Javis.jl
to interact with the following Julia packages:Ways of creating educational gifs
By the end of this tutorial, you will have made the following animation:
PeriodicTable.jl
and Unitful.jl
As normal with our tutorials, we need to import first the packages we will be using. In this tutorial, we are introducing two new packages:
PeriodicTable.jl
- Periodic table render in JuliaUnitful.jl
- Physical quantities with arbitrary units
These are straightforward to add to your Julia installation by executing the following in your Julia REPL:
julia> ] add Unitful, PeriodicTable
You might be wondering what these packages do. Let's dive into them then!
PeriodicTable.jl
enables one to look at information quickly related to the periodic table of elements. One can even print out such a table in their Julia REPL by doing the following:
julia> using PeriodicTable
julia> elements
Elements(…119 elements…):
H He
Li Be B C N O F Ne
Na Mg Al Si P S Cl Ar
K Ca Sc Ti V Cr Mn Fe Co Ni Cu Zn Ga Ge As Se Br Kr
Rb Sr Y Zr Nb Mo Tc Ru Rh Pd Ag Cd In Sn Sb Te I Xe
Cs Ba Hf Ta W Re Os Ir Pt Au Hg Tl Pb Bi Po At Rn
Fr Ra Rf Db Sg Bh Hs Mt Ds Rg Cn Nh Fl Mc Lv Ts Og
Uue
La Ce Pr Nd Pm Sm Eu Gd Tb Dy Ho Er Tm Yb Lu
Ac Th Pa U Np Pu Am Cm Bk Cf Es Fm Md No Lr
As the famous Mythbuster, Adam Savage once said, "IT'S SCIENTIFIC!" 🧪 🤓 One can even query PeriodicTable
to find out information on specific elements. Let's look up Oxygen (O) here!
julia> elements[8]
Oxygen (O), number 8:
category: diatomic nonmetal
atomic mass: 15.999 u
density: 1.429 g/cm³
melting point: 54.36 K
boiling point: 90.188 K
phase: Gas
shells: [2, 6]
e⁻-configuration: 1s² 2s² 2p⁴
summary: Oxygen is a chemical element with symbol O and atomic number 8. It is a member of the chalcogen group on the periodic table and is a highly reactive nonmetal and oxidizing agent that readily forms compounds (notably oxides) with most elements. By mass, oxygen is the third-most abundant element in the universe, after hydrogen and helium.
discovered by: Carl Wilhelm Scheele
named by: Antoine Lavoisier
source: https://en.wikipedia.org/wiki/Oxygen
spectral image: https://en.wikipedia.org/wiki/File:Oxygen_spectre.jpg
As fellow Julian, Johann-Tobias Schäg, said, one should learn Unitful.jl
if they want to interact with the real world. Unitful.jl
handles physical quantities such as pounds, meters, mols, etc. with minimal overhead in Julia. Further, it helps one to keep track of units and easily convert between different measurement systems.
Setting Up Our Animation
As always, let's import our needed packages:
using Animations
using Javis
using PeriodicTable
using Unitful
NOTE: For this tutorial, we will also use
Animations.jl
to provide what are called "easing functions".
These are used to control the speed at which an animation is drawn. This is further explained in Tutorial 7 so for now, don't worry too much about what we are doing with it.
And let's define our background function. This background function will also write the current frame being drawn:
function ground(video, action, frame)
background("white")
sethue("black")
end
Finally, let's get started with creating our render
function:
demo = Video(500, 500)
Background(1:550, ground)
render(demo, pathname="tutorial5.gif", framerate = 10)
As you can see, the animation we are creating is going to have many frames! This is the longest animation we have made so far. Why? Not only are we going to examine many different elements, this tutorial also serves to illustrate how one can make longer animations to convey ideas. Think of it as your directoral debut! 🎬 🎥
Taming the Elements!
Each element has a different atomic mass. This atomic mass is measured in the unit called a "Dalton" (symbol: u) which is equivalent to 1/12 of the mass of a stationary carbon-12 atom. We can use the change
functionality that Javis.jl
provides to visualize different elements!
To accomplish this, we need to make a function that shows our currently viewed element:
function element(; radius = 1, color = "black")
sethue(color)
circle(O, radius + 4, :fill) # The 4 is to make the circle not so small
end
Essentially, all the element
function does is create a circle in the middle of the frame with a radius of 5.
From there, we need to define one Object
for our animation to display the element we are viewing and scaling:
...
atom = Object(1:550, (args...; radius = 1) -> element(; radius = radius, color = "black"))
act!(
atom,
[
Action(101:140, change(:radius, 1 => 12)),
Action(241:280, change(:radius, 12 => 20)),
Action(381:420, change(:radius, 20 => 7)),
Action(521:550, change(:radius, 7 => 1)),
],
)
...
change
is used here to change the given radius of the circle in element
from 1
to 12
, from 12
to 20
, 20
to 7
, and finally 7
to 1
. This updates the circle being drawn and gives a growing or shrinking effect. change
interpolates the values in between what we want to change the value from to what the value we want to change to. It can be additionally used to simply set a value without interpolation (since v0.3.3).
That scaling looks like this:
Staring at this somewhat makes me think of a black hole... ⚫ But great! The only question now is... What are we looking at? Let's add some more information to this animation! 📝
How Much Does an Atom Weigh? ⚖️
To get the information about an element that we are currently previewing, we need to get information about our element. So, how do we do that?
To identify the element and display its information properly, let's create an info box similar to what we made in Tutorial 3! We do this by creating an info_box
function that takes in an element:
function info_box(; element = elements[1])
fontsize(12)
box(140, -210, 170, 40, :stroke)
box(0, 175, 450, 100, :stroke)
text("Element name: $(element.name)", 140, -220, valign = :middle, halign = :center)
text(
"Atomic Mass: $(round(ustrip(element.atomic_mass)))",
140,
-200,
valign = :middle,
halign = :center,
)
textwrap("Description: $(element.summary)", 400, Point(-200, 125))
end
To pass the element into the info_box
function, we need to define an Object
command to create our boxes. Then, we can change the element being passed in:
...
info = Object(1:550, (args...; elem = 1) -> info_box(element = elements[round(Int, elem)]))
act!(info, Action(1:30, sineio(), appear(:fade)))
act!(info, Action(71:100, sineio(), disappear(:fade)))
act!(info, Action(101:101, change(:elem, 1 => 12)))
act!(info, Action(140:170, sineio(), appear(:fade)))
act!(info, Action(210:241, sineio(), disappear(:fade)))
act!(info, Action(280:280, change(:elem, 12 => 20)))
act!(info, Action(280:310, sineio(), appear(:fade)))
act!(info, Action(350:381, sineio(), disappear(:fade)))
act!(info, Action(381:420, change(:elem, 20 => 7)))
act!(info, Action(420:450, sineio(), appear(:fade)))
act!(info, Action(490:521, sineio(), disappear(:fade)))
act!(info, Action(520:550, change(:elem, 7 => 1)))
...
Here, change
is being used to change the element, elem
, being queried from PeriodicTable.jl
over one frame. This gives us the updated information about each atom! Furthermore, using the method appear(:fade)
and disappear(:fade)
and sineio()
, we get a nice fading effect to easily transition between each element.
NOTE:
sineio()
comes fromAnimations.jl
and is an easing function.
More on this in Tutorial 6.
Now, let's look at that gif shall we?
Hooray! 🎉🎉🎉 We now have a very educational gif that tells us all about the elements we are viewing. We are basically physicists at this point. 😉
Conclusion
Great work getting through this tutorial! This tutorial was a little more complicated as you learned the following:
- Using
Javis.jl
tochange
animations in progress - Having
Javis.jl
interact with other Julia packages - Creating extended animations for use in education
Our hope with this tutorial is that it inspires you to create more comprehensive and informative animations with Javis.jl
Good luck and have fun making more animations!
Full Code
using Animations
using Javis
using PeriodicTable
using Unitful
function ground(video, action, frame)
background("white")
sethue("black")
end
function element(; radius = 1, color = "black")
sethue(color)
circle(O, radius + 4, :fill)
end
function info_box(; element = elements[1])
fontsize(12)
box(140, -210, 170, 40, :stroke)
box(0, 175, 450, 100, :stroke)
text("Element name: $(element.name)", 140, -220, valign = :middle, halign = :center)
text(
"Atomic Mass: $(round(ustrip(element.atomic_mass)))",
140,
-200,
valign = :middle,
halign = :center,
)
textwrap("Description: $(element.summary)", 400, Point(-200, 125))
end
demo = Video(500, 500)
Background(1:550, ground)
atom = Object(1:550, (args...; radius = 1) -> element(; radius = radius, color = "black"))
act!(
atom,
[
Action(101:140, change(:radius, 1 => 12)),
Action(241:280, change(:radius, 12 => 20)),
Action(381:420, change(:radius, 20 => 7)),
Action(521:550, change(:radius, 7 => 1)),
],
)
info = Object(1:550, (args...; elem = 1) -> info_box(element = elements[round(Int, elem)]))
act!(info, Action(1:30, sineio(), appear(:fade)))
act!(info, Action(71:100, sineio(), disappear(:fade)))
act!(info, Action(101:101, change(:elem, 1 => 12)))
act!(info, Action(140:170, sineio(), appear(:fade)))
act!(info, Action(210:241, sineio(), disappear(:fade)))
act!(info, Action(280:280, change(:elem, 12 => 20)))
act!(info, Action(280:310, sineio(), appear(:fade)))
act!(info, Action(350:381, sineio(), disappear(:fade)))
act!(info, Action(381:420, change(:elem, 20 => 7)))
act!(info, Action(420:450, sineio(), appear(:fade)))
act!(info, Action(490:521, sineio(), disappear(:fade)))
act!(info, Action(520:550, change(:elem, 7 => 1)))
render(demo, pathname="tutorial5.gif", framerate = 10)
Author(s): Jacob Zelko
Date: September 10, 2020
Tag(s): change, atoms, elements, appear, disappear, fade, unitful, periodictable