Movies API Reference
Functions for assembling an animation from a sequence of simulation outputs.
The workflow separates the expensive part from the cheap part on purpose: getmovie reads the outputs and produces frames, savemovie stores them, and moviefromframes encodes frames that already exist. Rendering a second version therefore does not re-read the simulation.
getmovie varies time: one frame per snapshot. To vary the angle instead, sweeping the camera around a single snapshot with a frame that cannot drift, use rotation_sequence. To vary both, getmovie takes angles (a full turn at each snapshot) or sweep (one moving angle across the series).
For a frame getmovie cannot produce, such as a cutting plane, timeseries reduces each snapshot to whatever you like, including a slice, and the resulting vector of maps goes straight into a MeraMovie for savemovie.
Mera.getmovie — Function
getmovie(path, quantity; unit=:standard, datatype=:hydro, outputs=:all, mera_files=false,
direction=:z, los=nothing, up=nothing, theta=nothing, phi=nothing,
inclination=nothing, azimuth=nothing, position_angle=nothing, axis=nothing,
angle_unit=:deg, center=[:boxcenter], range_unit=:standard,
xrange=[missing,missing], yrange=[missing,missing], zrange=[missing,missing],
res=nothing, lmax=nothing, pxsize=nothing, weighting=nothing,
fov=nothing, fov_unit=nothing, aperture=nothing, binning=nothing, nmax=nothing,
angles=nothing, sweep=nothing, angle_var=:azimuth,
time_unit=:Myr, verbose=true) -> MeraMovieProject quantity for every output of a simulation and collect the maps into a MeraMovie — the frames of a movie of the run evolving. Like timeseries it loads one snapshot at a time (RAM-safe) and discovers outputs the same way (RAMSES or mera_files).
Axis-aligned by default (direction=:z); for an off-axis movie use any of projection's view controls — a los/up (e.g. from face_on/edge_on), the angles inclination/azimuth (or theta/phi, position_angle, with angle_unit), or axis=:angmom to auto-orient face-on. res/pxsize/lmax and the region keywords cut cost per frame.
Hold the frame still. Without fov an off-axis projection auto-fits its window to the rotated data, which differs from snapshot to snapshot: the object appears to zoom, only the first frame's extent is recorded, and a size change between snapshots stops the encode. Pass fov/fov_unit (with aperture=:circle|:square) to select a fixed sphere about center, exactly as rotation_sequence does, so every frame shares one window.
Moving the camera — two different movies, and neither invents a frame; every one is a real projection from a real viewpoint:
anglessweeps that whole list at every snapshot, givingoutputs x anglesframes: orbit, then step time. The snapshot stays resident while its angles render, trading the one-snapshot-at-a-time memory profile for the extra viewpoints.sweepadvances one angle across the series: one frame per snapshot, each a different time and angle, orbit while time passes. Give one value per output, or a(lo, hi)pair to spread linearly over them. Memory profile unchanged.
angle_var picks which angle they drive: :azimuth (default), :inclination or :position_angle. Setting that same angle explicitly as well is an error, not a silent override.
datatype=:particles works and takes a Symbol weighting; the hydro [quantity, unit] spelling is accepted too. Gravity and clumps cannot be projected alone and are refused with a message naming the alternative.
m = getmovie("/data/sim", :sd) # face-up density movie, all outputs
fr = face_on(gethydro(getinfo(1, "/data/sim"))) # a fixed orientation …
m = getmovie("/data/sim", :sd; los=fr.los, up=fr.up, center=fr.center)
# a steady off-axis movie: one fixed camera frame for every snapshot
m = getmovie("/data/sim", :sd; inclination=60, axis=:angmom,
fov=15, fov_unit=:kpc, aperture=:square, pxsize=[0.5, :kpc])
m = getmovie("/data/sim", :sd; angles=0:5:355, fov=15, fov_unit=:kpc) # a turn at each snapshot
m = getmovie("/data/sim", :sd; sweep=(0, 180), fov=15, fov_unit=:kpc) # turning as it evolves
m = getmovie("/data/sim", :sd; datatype=:particles, fov=15, fov_unit=:kpc) # stars, not gas
savemovie(m, "density.gif")Returns a MeraMovie; m.frames[k] is the 2D map of output m.outputs[k] at time m.times[k]. See savemovie to write a GIF.
Mera.savemovie — Function
savemovie(m::MeraMovie, file="movie.gif"; colormap=:fire, log=true, colorrange=:global,
clip=(0.0, 1.0), fps=10, tags=nothing, annotate=true, save_frames=nothing,
verbose=true) -> fileWrite a MeraMovie to an animated GIF (file), using the bundled FileIO/Images (no extra package needed). Each frame is normalised over a colour range and mapped through a colormap.
colormap—:fire(default) or:gray, or a functiont∈[0,1] -> (r,g,b).log— maplog10of the (positive) values (default; good for density).colorrange—:global(one range across all frames — steady brightness),:perframe, or an explicit(lo, hi)(already in log space whenlog=true).clip— drop this lower/upper quantile fraction when auto-computing the range.fps— playback frame rate of the GIF.
Tags (per-frame labels). Pass tags to label each frame:
:time→"t=<time> <unit>",:output→"output 00001";- a vector of strings (one per frame); or a function
k -> String; - a tuple of any of the above stacks multiple lines, e.g.
tags=(:output, :time).
The labels are printed (when verbose) and, when annotate=true, burned onto the frames with a built-in bitmap font (no font dependency). Control the look:
tag_scale— font size::auto(default, scales with the frame) or an integer.tag_position—:topleft(default),:topright,:bottomleft,:bottomright, or an explicit(row, col)pixel.tag_color—:white(default),:yellow,:red,:cyan,:green,:black, anRGB, or an(r,g,b)tuple.
Scratch frames. Set save_frames to a directory to also write each rendered frame as frame_00001.png, … in it (the directory is created). Those PNGs can be re-assembled later with moviefromframes — or fed to ffmpeg for an MP4.
Persisting the movie object. A file ending in .jld2 stores the whole MeraMovie (the numeric frames + metadata) to a JLD2 file instead of encoding a GIF — reload it with loadmovie. Same Julia-native way savemap persists a map; nothing is re-rendered, so it round-trips exactly.
savemovie(m, "density.gif"; tags=:time, fps=12)
savemovie(m, "density.gif"; tags=(:output, :time), tag_position=:bottomright, tag_color=:yellow)
savemovie(m, "density.gif"; tags=:output, tag_scale=3, save_frames="frames/")
savemovie(m, "density.jld2") # persist the MeraMovie object (→ loadmovie)Mera.loadmovie — Function
Mera.moviefromframes — Function
moviefromframes(dir, file="movie.gif"; pattern=r"\.png$"i, fps=10, verbose=true) -> fileAssemble an animated GIF from existing image files in dir (e.g. PNG frames you rendered yourself, or wrote earlier with savemovie(...; save_frames=dir)). Files matching pattern are sorted by name and stacked in that order. The complement to savemovie's save_frames.
moviefromframes("frames/", "movie.gif"; fps=12)Mera.makethumb — Function
makethumb(source, out; width=800, height=450, mode=:fit, anchor=:center,
frame=0.4, background=:auto) -> StringMake a fixed-size preview image from a figure or an animation, and return the path written.
source is a saved picture (PNG, JPEG, and anything else FileIO reads) or an animated GIF. out is the file to write, a PNG. Both sizes default to the 800 by 450 used by the cards in the Gallery.
Two ways to deal with a picture whose shape does not match the card:
mode=:fit(the default) scales the whole picture in and pads the rest, so nothing is lost. A wide multi-panel figure keeps its outer panels.mode=:cropfills the card and cuts off the overflow. Right only when the subject is centred and the edges carry nothing.anchorpicks what survives::center,:top,:bottom,:leftor:right.
background is the colour the padding uses. The default :auto takes it from the picture's own corners, so padding a figure drawn on black stays black instead of putting a bright border round every card. Pass any Colorant to choose it yourself.
frame selects where in an animation to take the picture, as a position from 0.0 to 1.0. The default of 0.4 is deliberate: an animation that opens on a static pose makes a dull preview from its first frame. It is ignored for a still picture.
A movie (MP4 and friends) is not read here, because decoding video would add a large binary dependency to every install for a job that is done once. Save a frame from the code that made the movie, or point this at the preview GIF.
makethumb("media/density.png", "media/my_recipe_thumb.png")
makethumb("media/preview.gif", "media/my_recipe_thumb.png"; frame=0.25)
makethumb("media/wide_strip.png", "card.png"; mode=:crop, anchor=:top)See also Gallery and shared workflows for how these are used, and savefits for exporting the data rather than a picture.