datashader
|
Страница в процессе перевода. |
#
Makie.datashader — Function
datashader(points::AbstractVector{<: Point})
|
Warning Эта возможность может меняться вне критических выпусков, так как API еще не доработан. Если наблюдаются необычные проявления в работе, это может быть следствием ошибок в реализации. Также можно ознакомиться с открытыми проблемами. |
Аргументом points может быть массив любого типа, поддерживающий итерацию и функцию getindex, включая размещенные в памяти массивы. Если у вас отдельные массивы для координат x и y и вы хотите избежать конвертации и копирования, можно поступить так:
using Makie.StructArrays
points = StructArray{Point2f}((x, y))
datashader(points)
Однако обратите внимание, что если для x и y не реализована быстрая итерация и getindex, такой подход может оказаться медленнее, чем простое копирование данных в новый массив.
Для повышения производительности используйте method=Makie.AggThreads() и обязательно запускайте Julia с параметром julia -tauto либо присвойте переменной среды JULIA_NUM_THREADS имеющееся количество ядер.
Тип графика
Псевдоним типа графика для функции datashader — DataShader.
Примеры
Аэропорты
using GLMakie
using DelimitedFiles
airports = Point2f.(eachrow(readdlm(assetpath("airportlocations.csv"))))
fig, ax, ds = datashader(airports,
colormap=[:white, :black],
# для вывода документации мы не должны вычислять изображение асинхронно,
# так как не сможем дождаться окончания отрисовки и встроить пустое изображение
async = false,
figure = (; figure_padding=0, size=(360*2, 160*2))
)
Colorbar(fig[1, 2], ds, label="Number of airports")
hidedecorations!(ax); hidespines!(ax)
fig
Агрегирование среднего значения
Для типа агрегирования AggMean требуется Point3, где среднее значение берется по значениям z всех точек, которые попадают в один и тот же столбец x/y.
using GLMakie
with_z(p2) = Point3f(p2..., cos(p2[1]) * sin(p2[2]))
points = randn(Point2f, 100_000)
points_with_z = map(with_z, points)
f = Figure()
ax = Axis(f[1, 1], title = "AggMean")
datashader!(ax, points_with_z, agg = Makie.AggMean(), operation = identity)
ax2 = Axis(f[1, 2], title = "AggMean binsize = 3")
datashader!(ax2, points_with_z, agg = Makie.AggMean(), operation = identity, binsize = 3)
f
Странные аттракторы
using GLMakie
# Взято из статьи Beautiful Maki Лазаро Алонсо (Lazaro Alonso):
# https://beautiful.makie.org/dev/examples/generated/2d/datavis/strange_attractors/?h=cliffo#trajectory
Clifford((x, y), a, b, c, d) = Point2f(sin(a * y) + c * cos(a * x), sin(b * x) + d * cos(b * y))
function trajectory(fn, x0, y0, kargs...; n=1000) # kargs = a, b, c, d
xy = zeros(Point2f, n + 1)
xy[1] = Point2f(x0, y0)
@inbounds for i in 1:n
xy[i+1] = fn(xy[i], kargs...)
end
return xy
end
cargs = [[0, 0, -1.3, -1.3, -1.8, -1.9],
[0, 0, -1.4, 1.6, 1.0, 0.7],
[0, 0, 1.7, 1.7, 0.6, 1.2],
[0, 0, 1.7, 0.7, 1.4, 2.0],
[0, 0, -1.7, 1.8, -1.9, -0.4],
[0, 0, 1.1, -1.32, -1.03, 1.54],
[0, 0, 0.77, 1.99, -1.31, -1.45],
[0, 0, -1.9, -1.9, -1.9, -1.0],
[0, 0, 0.75, 1.34, -1.93, 1.0],
[0, 0, -1.32, -1.65, 0.74, 1.81],
[0, 0, -1.6, 1.6, 0.7, -1.0],
[0, 0, -1.7, 1.5, -0.5, 0.7]
]
fig = Figure(size=(1000, 1000))
fig_grid = CartesianIndices((3, 4))
cmap = to_colormap(:BuPu_9)
cmap[1] = RGBAf(1, 1, 1, 1) # Убедитесь, что фон локально белый,
let
# можно получить неплохие результаты с n_points.
# Например, 4*(10^7), но нам не нужно слишком сильное замедление docbuild.
n_points = 10^6
for (i, arg) in enumerate(cargs)
points = trajectory(Clifford, arg...; n=n_points)
r, c = Tuple(fig_grid[i])
ax, plot = datashader(fig[r, c], points;
colormap=cmap,
async=false,
axis=(; title=join(string.(arg), ", ")))
hidedecorations!(ax)
hidespines!(ax)
end
end
rowgap!(fig.layout,5)
colgap!(fig.layout,1)
fig
Более крупные примеры
Временные показатели в комментариях приведены для ноутбука Ryzen 5800H с 32 ГБ памяти. Оба примера еще не полностью оптимизированы и используют только необработанные, неотсортированные, размещенные в памяти массивы Point2f. В будущем мы сможем добавить структуры ускорения, чтобы оптимизировать доступ к подобластям.
Набор данных о такси Нью-Йорка с 14 миллионами точек
using GLMakie, Downloads, Parquet2
bucket = "https://ursa-labs-taxi-data.s3.us-east-2.amazonaws.com"
year = 2009
month = "01"
filename = join([year, month, "data.parquet"], "/")
out = joinpath("$year-$month-data.parquet")
url = bucket * "/" * filename
Downloads.download(url, out)
# Загрузка ~1,5 с
@time begin
ds = Parquet2.Dataset(out)
dlat = Parquet2.load(ds, "dropoff_latitude")
dlon = Parquet2.load(ds, "dropoff_longitude")
# Здесь можно было бы использовать массив структуры, но dlon/dlat являются
# пользовательским типом массива из Parquet2, поддерживающего отсутствующие и некоторые другие функции, которые замедляют работу.
# points = StructArray{Point2f}((dlon, dlat))
points = Point2f.(dlon, dlat)
groups = Parquet2.load(ds, "vendor_id")
end
# ~0,06 с
@time begin
f, ax, dsplot = datashader(points;
colormap=:fire,
axis=(; type=Axis, autolimitaspect = 1),
figure=(;figure_padding=0, size=(1200, 600))
)
# Увеличим масштаб фрагмента изображения
limits!(ax, Rect2f(-74.175, 40.619, 0.5, 0.25))
# сделаем так, чтобы изображение заполняло весь экран
hidedecorations!(ax)
hidespines!(ax)
display(f)
end
2,7 миллиарда GPS-точек OSM
Скачаем данные из GPS-точек OSM и используем обновленный скрипт отсюда, чтобы преобразовать CSV в двоичный BLOB-объект, который можно разместить в памяти.
using GLMakie, Mmap
path = "gpspoints.bin"
points = Mmap.mmap(open(path, "r"), Vector{Point2f});
# ~ 26 с
@time begin
f, ax, pl = datashader(
points;
# Интересно посмотреть, сколько времени занимает каждое агрегирование в большом наборе данных.
show_timings = true,
# Используем локальную операцию, которая быстрее вычисляется и неплохо выглядит.
local_operation=x-> log10(x + 1),
#=
in the code we used to save the binary, we had the points in the wrong order.
A good chance to demonstrate the `point_transform` argument,
Which gets applied to every point before aggregating it
=#
point_transform=reverse,
axis=(; type=Axis, autolimitaspect = 1),
figure=(;figure_padding=0, size=(1200, 600))
)
hidedecorations!(ax)
hidespines!(ax)
display(f)
end
aggregation took 1.395s aggregation took 1.176s aggregation took 0.81s aggregation took 0.791s aggregation took 0.729s aggregation took 1.272s aggregation took 1.117s aggregation took 0.866s aggregation took 0.724s
Категориальные данные
В настоящее время существует два способа построения графика на основе категориальных данных.
datashader(one_category_per_point, points)
datashader(Dict(:category_a => all_points_a, :category_b => all_points_b))
Тип категории не имеет значения, но внутренне она будет преобразована в строку, чтобы корректно отображаться в условных обозначениях. Сейчас категории объединяются в один холст для каждой категории, а затем накладываются друг на друга с помощью альфа-смешивания.
using GLMakie
normaldist = randn(Point2f, 1_000_000)
ds1 = normaldist .+ (Point2f(-1, 0),)
ds2 = normaldist .+ (Point2f(1, 0),)
fig, ax, pl = datashader(Dict("a" => ds1, "b" => ds2); async = false)
hidedecorations!(ax)
fig
Также можно повторно использовать предыдущий пример с такси Нью-Йорка для построения категориального графика.
@time begin
f = Figure(figure_padding=0, size=(1200, 600))
ax = Axis(
f[1, 1],
autolimitaspect=1,
limits=(-74.022, -73.827, 40.696, 40.793),
backgroundcolor=:black
)
datashader!(ax, groups, points)
hidedecorations!(ax)
hidespines!(ax)
# Создадим стилизованные условные обозначения
axislegend("Vendor ID"; titlecolor=:white, framecolor=:grey, polystrokewidth=2, polystrokecolor=(:white, 0.5), rowgap=10, backgroundcolor=:black, labelcolor=:white)
display(f)
end
Расширенный API
Шаблон datashader позволяет легко начать работу, он также имеет оптимальную реализацию, поэтому при большинстве изменений, таких как f, ax, pl = datashader(...); pl.colorrange=new_range; pl.operation=log10, не нужно повторно выполнять агрегирование. Но если вам все еще требуется большой объем управления вручную, можно также использовать базовый API Canvas напрямую.
Атрибуты
agg
Значение по умолчанию: AggCount{Float32}()
Может быть AggCount(), AggAny() или AggMean(). Убедитесь, что используется правильный тип элемента, например AggCount{Float32}(), который должен соответствовать выводимым данным local_operation. Расширяемый пользователем путем перегрузки:
struct MyAgg{T} <: Makie.AggOp end
MyAgg() = MyAgg{Float64}()
Makie.Aggregation.null(::MyAgg{T}) where {T} = zero(T)
Makie.Aggregation.embed(::MyAgg{T}, x) where {T} = convert(T, x)
Makie.Aggregation.merge(::MyAgg{T}, x::T, y::T) where {T} = x + y
Makie.Aggregation.value(::MyAgg{T}, x::T) where {T} = x
alpha
Значение по умолчанию: 1.0
Альфа-значение цветовой карты или атрибута color. Несколько букв, таких как в plot(alpha=0.2, color=(:red, 0.5), будут умножены.
async
Значение по умолчанию: true
Будет вычислять get_aggregation в задаче и пропускать любые обновления масштабирования / панорамирования во время работы. Отлично подходит для взаимодействия, но должен быть отключен для сохранения, например, в формате png или при встраивании в Documenter.
binsize
Значение по умолчанию: 1
Коэффициент, определяющий, сколько ячеек требуется для каждого пикселя экрана. Установите значение n > 1, если вы хотите получить более грубое изображение.
clip_planes
Значение по умолчанию: automatic
Плоскости отсечения позволяют выполнять отсечение в трехмерном пространстве. Вы можете задать вектор длиной до 8 Plane3f здесь плоскости, за которыми участки будут обрезаны (т.е. станут невидимыми). По умолчанию плоскости клипа наследуются от родительского графика или сцены. Вы можете удалить родительский элемент clip_planes проходя мимо Plane3f[].
colormap
Значение по умолчанию: @inherit colormap :viridis
Устанавливает цветовую схему, которая выбирается для числовых значений. colors. PlotUtils.cgrad(...), Makie.Reverse(any_colormap) также можно использовать любой символ из ColorBrewer или PlotUtils. Чтобы просмотреть все доступные цветовые градиенты, вы можете позвонить по телефону Makie.available_gradients().
colorrange
Значение по умолчанию: automatic
Значения, представляющие начальную и конечную точки colormap.
colorscale
Значение по умолчанию: identity
Функция преобразования цвета. Может быть любой функцией, но хорошо работает только в сочетании с Colorbar для identity, log, log2, log10, sqrt, logit, Makie.pseudolog10 и Makie.Symlog10.
depth_shift
Значение по умолчанию: 0.0
настраивает значение глубины участка после всех других преобразований, т.е. в пространстве клипа, где 0 <= depth <= 1. This only applies to GLMakie and WGLMakie and can be used to adjust render order (like a tunable overdraw).
fxaa
Значение по умолчанию: true
Регулирует, будет ли график отображаться с использованием fxaa (сглаживание, только GLMakie).
inspectable
Значение по умолчанию: @inherit inspectable
Определяет, должен ли этот сюжет отображаться пользователем DataInspector. Значение по умолчанию зависит от темы родительской сцены.
inspector_clear
Значение по умолчанию: automatic
Устанавливает функцию обратного вызова (inspector, plot) -> ...</span> для очистки пользовательских индикаторов в DataInspector.
inspector_hover
Значение по умолчанию: automatic
Устанавливает функцию обратного вызова (inspector, plot, index) -> ... которая заменяет функцию по умолчанию show_data методы.
inspector_label
Значение по умолчанию: automatic
Устанавливает функцию обратного вызова (plot, index, position) -> string , которая заменяет метку по умолчанию, сгенерированную DataInspector.
interpolate
Значение по умолчанию: false
Если результирующее изображение должно быть отображено с интерполяцией. Обратите внимание, что интерполяция может привести к тому, что NaN-смежные ячейки также будут NaN в некоторых серверных системах, например, из-за схем интерполяции, используемых в аппаратном обеспечении GPU. Это может создать впечатление, что NaN-ячеек больше, чем есть на самом деле.
local_operation
Значение по умолчанию: identity
Функция, которая вызывается для каждого элемента после агрегации (map!(x-> local_operation(x), final_aggregation_result)).
method
Значение по умолчанию: AggThreads()
Может быть AggThreads() или AggSerial() для потоковой и последовательной агрегации.
model
Значение по умолчанию: automatic
Задает матрицу модели для построения графика. Это отменяет корректировки, сделанные с помощью translate!, rotate! и scale!.
operation
Значение по умолчанию: automatic
Значение по умолчанию: Makie.equalize_histogram функция, которая вызывается для всего массива get_aggregation перед отображением (operation(final_aggregation_result)).
overdraw
Значение по умолчанию: false
Определяет, будет ли график отображаться поверх других графиков. В частности, это означает игнорирование проверок глубины в GL-интерфейсах
point_transform
Значение по умолчанию: identity
Функция, которая применяется к каждой точке перед ее агрегированием.
show_timings
Значение по умолчанию: false
Установлен в true чтобы показать, сколько времени требуется для агрегирования каждого кадра.
space
Значение по умолчанию: :data
задает область преобразования для прямоугольника, охватывающего участок. Видеть Makie.spaces() для получения возможных вводных данных.
ssao
Значение по умолчанию: false
Определяет, будет ли график отображаться с помощью ssao (screen space ambient occlusion). Обратите внимание, что это имеет смысл только для 3D-графиков и применимо только к fxaa = true.