Объединение компонентов

Здесь мы рассмотрим, как объединить линии и макет для создания графика.

Мы также обсудим интеграцию с различными фронтендами.

Plot

Напомним, что определение объекта Plot имеет следующий вид:

mutable struct Plot{TT<:AbstractVector{<:AbstractTrace},TL<:AbstractLayout,TF<:AbstractVector{<:PlotlyFrame}}
    data::TT
    layout::TL
    frames::TF
    divid::UUID
    config::PlotConfig
end

Получив одну или несколько линий AbstractTrace и, по желанию, макет (Layout), мы строим объект Plot с помощью любого из следующих конструкторов:

# Чистый холст без линий и макета
Plot()

# Вектор линий и макет
Plot{T<:AbstractTrace}(data::AbstractVector{T}, layout::AbstractLayout)

# Вектор линий — предоставляется макет по умолчанию
Plot{T<:AbstractTrace}(data::AbstractVector{T})

# Одна линия: будет помещена в вектор — предоставляется макет по умолчанию
Plot(data::AbstractTrace)

# Одна линия и макет (линия помещается в вектор)
Plot(data::AbstractTrace, layout::AbstractLayout)

Обратите внимание, что ни в одном из рекомендуемых конструкторов не требуется передавать поле divid вручную. Это внутреннее поле, используемое для отображения и уникальной идентификации нескольких графиков на одной веб-странице.

Вспомогательные методы

Существует также ряд вспомогательных методов для функции Plot, которые попытаются построить линии. Они имеют следующие сигнатуры.

# PlotlyBase.PlotType

Plot(x, y)
Plot(x, y, l; kind, config, kwargs...)

Строит график с одной линией типа kind и задает для x x, а для y — y. Все именованные аргументы передаются напрямую как именованные аргументы в создаваемую линию.

ПРИМЕЧАНИЕ. Если y является матрицей, для каждого столбца y строится одна линия.

ПРИМЕЧАНИЕ. Если x и y являются матрицами, они должны иметь одинаковое количество столбцов (например, N). Затем создаются линии N, где i-й столбец x сопряжен с i-м столбцом y.

Plot(y)
Plot(y, l; kwargs...)

Строит график рассеяния и задает для y y. Все именованные аргументы передаются напрямую как именованные аргументы в создаваемый график.

Plot(f, x0, x1)
Plot(f, x0, x1, l; config, kwargs...)

Строит график f от x0 до x1 с помощью макета l. Все именованные аргументы применяются к создаваемой линии.

Plot(fs, x0, x1)
Plot(fs, x0, x1, l; config, kwargs...)

Для каждой функции в f в fs создает линию рассеяния, которая строит график f от x0 до x1 с помощью макета l. Именованные аргументы применяются ко всем создаваемым линиям.

Именованный аргумент group особенно удобен при вызове Plot(::AbstractDataFrame, ... ; ...). Ниже приведен пример.

using RDatasets
iris = RDatasets.dataset("datasets", "iris");
p = Plot(iris, x=:SepalLength, y=:SepalWidth, mode="markers", marker_size=8, group=:Species)
syncplots1

Объекты SyncPlot

Plot — это чистый объект Julia, который сам по себе не взаимодействует с plotly.js. Это означает, что невозможно просмотреть реальную фигуру plotly, которую представляют данные.

Для этого необходимо связать объект Plot с одним или несколькими фронтендами отображения.

Для реального подключения к фронтендам отображения используется пакет WebIO.jl. Взаимодействие с WebIO заключено в тип SyncPlot, который определяется следующим образом.

mutable struct SyncPlot
    plot::PlotlyBase.Plot
    scope::Scope
    window::Union{Nothing,Blink.Window}
end

Как следует из названия, SyncPlot будет поддерживать представление Julia графика (экземпляр Plot) в синхронизации с графиком с фронтендом.

Функция Plot создаст объект Plot, а функция plot создаст объект SyncPlot. Функция plot передает все аргументы для построения Plot, а затем настраивает отображение. Все методы Plot также определены для plot.

Используя WebIO.jl, можно отрисовывать фигуры в любом месте, где это может сделать WebIO. На момент написания этого документа этими местами являются интерактивный скрипт Jupyter, Jupyterlab, веб-приложения Mux.jl, среда Juno Julia в текстовом редакторе Atom и окна Electron из Blink.jl. Дополнительную (и актуальную) информацию можно найти в файле сведений WebIO.jl.

При использовании PlotlyJS.jl в REPL Julia график автоматически отображается в окне Electron. Это выделенное окно браузера, которое мы полностью контролируем. Чтобы увидеть график p, достаточно ввести p в REPL и выполнить строку. Или можно вызвать display(p).

Помимо того, что графики можно просматривать во многих интерфейсных средах, WebIO также обеспечивает двустороннее взаимодействие между javascript и Julia. Фактически, при построении SyncPlot мы автоматически получаем прослушиватели для всех событий plotly.js javascript. Более того, при активации этих событий можно подключать функции Julia в качестве обратных вызовов. В выдуманном примере, приведенном ниже, Julia выводит подробную информацию о точках на графике, когда пользователь наводит на них курсор мыши:

using WebIO
p = plot(rand(10, 4));
display(p)  # обычно необязательно

on(p["hover"]) do data
    println("\nYou hovered over", data)
end

В следующем примере при щелчке точки символ маркера изменяется на звезду, а цвет маркера — на золотой:

using WebIO
colors = (fill("red", 10), fill("blue", 10))
symbols = (fill("circle", 10), fill("circle", 10))
ys = (rand(10), rand(10))
p = plot(
    [scatter(y=y, marker=attr(color=c, symbol=s, size=15), line_color=c[1])
    for (y, c, s) in zip(ys, colors, symbols)]
)
display(p)  # обычно необязательно

on(p["click"]) do data
    colors = (fill("red", 10), fill("blue", 10))
    symbols = (fill("circle", 10), fill("circle", 10))
    for point in data["points"]
        colors[point["curveNumber"] + 1][point["pointIndex"] + 1] = "gold"
        symbols[point["curveNumber"] + 1][point["pointIndex"] + 1] = "star"
    end
    restyle!(p, marker_color=colors, marker_symbol=symbols)
end

Хотя эти примеры совершенно бессмысленны, хотелось бы надеяться, что они демонстрируют возможность создания полнофункциональных, интерактивных веб-приложений для визуализации данных с бизнес-логикой, реализованной полностью на Julia.

Конфигурация отображения

Новая возможность в PlotlyBase версии 0.6.4 (PlotlyJS версии 0.16.3)

При вызове plot или Plot можно указать несколько параметров конфигурации с помощью именованного аргумента config.

Аргумент config должен быть экземпляром PlotConfig, который должен быть построен с использованием именованных аргументов.

Например, при выполнении следующего кода вместо интерактивного графика мы увидим статичный график (без вывода информации при наведении курсора или возможности масштабирования/панорамирования) с четырьмя линиями:

`example plot_config Plot(rand(10, 4), config=PlotConfig(staticPlot=true)) `

Полный список параметров см. в документации по API для PlotConfig.