Cоздание сложных компоновок графиков с помощью Makie¶
В данном примере демонстрируются инструменты библиотеки Makie для создания профессиональных научных визуализаций через объединение графиков разных типов (диаграммы рассеяния, контурные графики, 3D-модели и временные ряды) в единую сложную компоновку с использованием вложенных GridLayout, связанных осей, пользовательских легенд и цветовых шкал, а также продвинутых техник позиционирования элементов и управления пространством для создания информативных и красочных иллюстраций.
1. Установка пакетов и подготовка данных¶
Pkg.add("Makie")
Pkg.add("CairoMakie")
Подготовка данных для первого графика:
seconds = 0:0.1:2
measurements = [8.2, 8.4, 6.3, 9.5, 9.1, 10.5, 8.6, 8.2, 10.5, 8.5, 7.2,
8.8, 9.7, 10.8, 12.5, 11.6, 12.1, 12.1, 15.1, 14.7, 13.1]
using CairoMakie
2. Создание базового графика¶
Начнем с простой визуализации экспериментальных данных и экспоненциальной модели.
Основные компоненты:
Figure()
создает контейнер для графиковAxis()
определяет систему координат с подписямиscatter!()
добавляет точки измеренийlines!()
рисует линию моделиaxislegend()
создает легенду
Отображение графика с экспериментальными данными и экспоненциальной моделью:
f = Figure()
ax = Axis(f[1, 1],
title = "Experimental data and exponential fit",
xlabel = "Time (seconds)",
ylabel = "Value",
)
CairoMakie.scatter!(
ax,
seconds,
measurements,
color = :tomato,
label = "Measurements"
)
lines!(
ax,
seconds,
exp.(seconds) .+ 7,
color = :tomato,
linestyle = :dash,
label = "f(x) = exp(x) + 7",
)
# Добавление легенды в правый нижний угол
axislegend(position = :rb)
# Отображение фигуры
f
3. Формирование сложной компоновки¶
Создаем сложный графический объект (фигуру) с несколькими областями для построения графиков:
- Используем
GridLayout
для организации вложенных сеток - Определяем 4 основные области (A, B, C, D)
- Настраиваем фон и размер фигуры
- Связываем оси для синхронизации масштабов
using CairoMakie
using Makie.FileIO # Для работы с файлами
# Активация бэкенда и создание фигуры
CairoMakie.activate!()
f = Figure(
backgroundcolor = RGBf(0.98, 0.98, 0.98),
size = (1000, 700)
)
# Создание вложенных сеток
ga = f[1, 1] = GridLayout() # Область A
gb = f[2, 1] = GridLayout() # Область B
gcd = f[1:2, 2] = GridLayout() # Контейнер для C и D
gc = gcd[1, 1] = GridLayout() # Область C (3D мозг)
gd = gcd[2, 1] = GridLayout() # Область D (EEG сигналы)
# Создание связанных осей для Область A
axtop = Axis(ga[1, 1]) # Верхнее распределение
axmain = Axis(ga[2, 1], # Основной график
xlabel = "before",
ylabel = "after")
axright = Axis(ga[2, 2]) # Правое распределение
# Связывание осей для синхронизации
linkyaxes!(axmain, axright) # Общая шкала Y
linkxaxes!(axmain, axtop) # Общая шкала X
f
4. Область A: Диаграммы рассеяния и распределения¶
Область A демонстрирует:
- Группировку данных через цветовое кодирование
- Связанные оси с общими масштабами
- Распределения на краях основного графика
- Автоматическое размещение легенды
- Точную настройку отступов между элементами
# Генерация тестовых данных для трех групп
labels = ["treatment", "placebo", "control"]
data = randn(3, 100, 2) .+ [1, 3, 5] # 3 группы × 100 точек × 2 измерения
# Визуализация каждой группы
for (label, col) in zip(labels, eachslice(data, dims = 1))
CairoMakie.scatter!(axmain, col, label = label)
CairoMakie.density!(axtop, col[:, 1]) # Распределение сверху
CairoMakie.density!(axright, col[:, 2], direction = :y) # Распределение справа
end
# Настройка границ осей
CairoMakie.ylims!(axtop, low = 0)
CairoMakie.xlims!(axright, low = 0)
# Установка меток на осях
axmain.xticks = 0:3:9
axtop.xticks = 0:3:9
# Добавление легенды и скрытие лишних элементов
leg = Legend(ga[1, 2], axmain)
hidedecorations!(axtop, grid = false)
hidedecorations!(axright, grid = false)
leg.tellheight = true # Фиксируем высоту легенды
# Добавление заголовка области
Label(ga[1, 1:2, Top()], "Stimulus ratings", valign = :bottom,
font = :bold,
padding = (0, 0, 5, 0))
# Настройка расстояний между элементами
colgap!(ga, 10)
rowgap!(ga, 10)
f
5. Область B: Контурные графики¶
Область B показывает:
- Контурные графики для визуализации 2D данных
- Иерархию графиков: contourf + contour
- Кастомную цветовую шкалу с биновой маркировкой
- Выравнивание элементов через
Mixed
alignmode - Точный контроль над расстояниями между графиками
# Подготовка данных для контурных графиков
xs = LinRange(0.5, 6, 50)
ys = LinRange(0.5, 6, 50)
data1 = [sin(x^1.5) * cos(y^0.5) for x in xs, y in ys] .+ 0.1 .* randn.()
data2 = [sin(x^0.8) * cos(y^1.5) for x in xs, y in ys] .+ 0.1 .* randn.()
# Построение контурных графиков
ax1, hm = CairoMakie.contourf(gb[1, 1], xs, ys, data1, levels = 6)
ax1.title = "Histological analysis"
CairoMakie.contour!(ax1, xs, ys, data1, levels = 5, color = :black)
hidexdecorations!(ax1) # Скрываем метки на оси X
ax2, hm2 = CairoMakie.contourf(gb[2, 1], xs, ys, data2, levels = 6)
CairoMakie.contour!(ax2, xs, ys, data2, levels = 5, color = :black)
# Настройка цветовой шкалы
cb = CairoMakie.Colorbar(gb[1:2, 2], hm, label = "cell group")
low, high = CairoMakie.extrema(data1)
edges = range(low, high, length = 7)
centers = (edges[1:6] .+ edges[2:7]) .* 0.5
cb.ticks = (centers, string.(1:6)) # Кастомные метки
# Оптимизация выравнивания
cb.alignmode = Mixed(right = 0)
# Настройка расстояний
colgap!(gb, 10)
rowgap!(gb, 10)
f
6. Область C: 3D визуализация мозга¶
Область C демонстрирует:
- Загрузку и визуализацию 3D моделей (формат STL)
- Использование
Axis3
для 3D графиков - Цветовое кодирование на основе координат Y
- Инвертированную цветовую карту для лучшего восприятия
- Интеграцию 3D визуализации в общую компоновку
# Загрузка и визуализация 3D модели мозга
brain = load(assetpath("brain.stl"))
ax3d = Axis3(gc[1, 1], title = "Brain activation")
m = mesh!(
ax3d,
brain,
color = [tri[1][2] for tri in brain for i in 1:3],
colormap = Reverse(:magma), # Инвертированная цветовая карта
)
Colorbar(gc[1, 2], m, label = "BOLD level") # Цветовая шкала
f
7. Область D: ЭЭГ сигналы¶
Область D показывает:
- Массивы осей для группировки графиков
- Генерацию искусственных ЭЭГ сигналов
- Динамическое масштабирование осей по количеству точек
- Повёрнутые метки для экономии пространства
- Автоматическое выравнивание размеров колонок
# Создание сетки осей для сигналов ЭЭГ
axs = [Axis(gd[row, col]) for row in 1:3, col in 1:2]
hidedecorations!.(axs, grid = false, label = false) # Упрощаем оформление
# Генерация и визуализация ЭЭГ сигналов
for row in 1:3, col in 1:2
xrange = col == 1 ? (0:0.1:6pi) : (0:0.1:10pi) # Разные диапазоны
eeg = [sum(sin(pi * rand() + k * x) / k for k in 1:10)
for x in xrange] .+ 0.1 .* randn.()
lines!(axs[row, col], eeg, color = (:black, 0.5)) # Полупрозрачные линии
end
# Подписи осей и заголовок
axs[3, 1].xlabel = "Day 1"
axs[3, 2].xlabel = "Day 2"
Label(gd[1, :, Top()], "EEG traces", valign = :bottom,
font = :bold,
padding = (0, 0, 5, 0))
# Добавление повернутых меток
for (i, label) in enumerate(["sleep", "awake", "test"])
Box(gd[i, 3], color = :gray90) # Фон метки
Label(gd[i, 3], label, rotation = pi/2, tellheight = false) # Вертикальный текст
end
# Автомасштабирование по количеству точек
n_day_1 = length(0:0.1:6pi)
n_day_2 = length(0:0.1:10pi)
colsize!(gd, 1, Auto(n_day_1))
colsize!(gd, 2, Auto(n_day_2))
# Настройка расстояний
rowgap!(gd, 10)
colgap!(gd, 10)
colgap!(gd, 2, 0) # Убираем отступ у колонки с метками
f
8. Финальные настройки и метки¶
Дополнительные настройки:
- Добавление меток A/B/C/D
- Точная настройка пропорций колонок
- Балансировка высоты строк
- Оптимизация общего расположения элементов
# Добавление меток областей
for (label, layout) in zip(["A", "B", "C", "D"], [ga, gb, gc, gd])
Label(layout[1, 1, TopLeft()], label,
fontsize = 26,
font = :bold,
padding = (0, 5, 5, 0),
halign = :right)
end
# Настройка пропорций
colsize!(f.layout, 1, Auto(0.5)) # Уменьшаем ширину первой колонки
rowsize!(gcd, 1, Auto(1.5)) # Увеличиваем высоту 3D визуализации
# Отображение финального результата
f