Просмотр скомпилированной Vega из Vega-Lite

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


Процесс трансляции Vega-Lite → Vega

Vega-Lite не выполняется напрямую движком Vega. Перед рендерингом происходит компиляция:

  • вход: декларативная спецификация Vega-Lite
  • выход: полная спецификация Vega

Компилятор выполняет несколько преобразований:

  • разворачивание сокращённых описаний mark-конструкций
  • генерация scales, axes, legends
  • построение dataflow-графа Vega
  • создание signal-системы для интерактивности
  • нормализация трансформаций данных (filter, aggregate, bin, stack)

Результатом является полноценный JSON-объект Vega, пригодный для исполнения движком vega.View.


Компиляция через библиотеку vega-lite

В JavaScript среде компиляция осуществляется через пакет vega-lite.

Базовая компиляция спецификации

import vegaLite from 'vega-lite';

const vlSpec = {
  data: { values: [1, 2, 3, 4, 5] },
  mark: "bar",
  encoding: {
    x: { field: "data", type: "quantitative", aggregate: "count" }
  }
};

const compiled = vegaLite.compile(vlSpec);

const vgSpec = compiled.spec;

Результатом является объект Vega-спецификации, содержащий:

  • раздел data с трансформированными источниками
  • marks с развернутыми примитивами
  • scales, axes, legends
  • signals для взаимодействий

Структура скомпилированной Vega-спецификации

Скомпилированная Vega-структура значительно более многословна, чем исходный Vega-Lite:

Dataflow

Vega превращает все преобразования данных в последовательность узлов:

  • source_0 — исходные данные
  • data_0_transform — агрегирование, фильтрация
  • data_1 — промежуточные наборы

Каждый этап становится отдельным объектом в data[].


Scales и domain/range

Vega-Lite задаёт масштаб декларативно:

"x": { "type": "quantitative" }

Vega-компилятор разворачивает это в:

  • domain (вычисленный из данных)
  • range (обычно пиксельные координаты)
  • nice, zero, clamp параметры

Marks

Простой mark Vega-Lite:

"mark": "bar"

Превращается в структуру Vega:

  • type: "rect"
  • набор выражений для координат
  • привязка к scale через encode

Просмотр через Vega View API

Для рендеринга используется vega пакет.

Создание представления

import { View, parse } from 'vega';

const runtime = parse(vgSpec);

const view = new View(runtime)
  .renderer('canvas')
  .initialize('#vis');

view.runAsync();

Здесь происходит:

  • парсинг JSON в runtime-граф
  • построение вычислительного конвейера
  • запуск layout и рендеринга

Отображение компилированной спецификации в браузере

Отдельный сценарий — визуализация именно результата компиляции Vega-Lite, а не исходного уровня.

Полный цикл компиляции и отображения

import vegaLite from 'vega-lite';
import * as vega from 'vega';

const vlSpec = {
  data: { values: [10, 20, 30, 40] },
  mark: "line",
  encoding: {
    x: { field: "x", type: "quantitative" },
    y: { field: "y", type: "quantitative" }
  }
};

// Компиляция
const vgSpec = vegaLite.compile(vlSpec).spec;

// Рендеринг Vega
const runtime = vega.parse(vgSpec);

new vega.View(runtime)
  .renderer('canvas')
  .initialize(document.body)
  .run();

Использование Vega Embed для инспекции компиляции

Библиотека vega-embed поддерживает автоматическую компиляцию Vega-Lite и возможность доступа к результату Vega.

import embed from 'vega-embed';

const vlSpec = {
  mark: "area",
  encoding: {
    x: { field: "year", type: "temporal" },
    y: { field: "value", type: "quantitative" }
  },
  data: { values: [] }
};

embed('#vis', vlSpec, {
  mode: 'vega-lite'
}).then(result => {
  const compiledVegaSpec = result.spec;
});

В объекте result содержится:

  • view — экземпляр Vega View
  • spec — итоговая Vega-спецификация
  • vgSpec или аналогичные поля (в зависимости от версии)

Отладка скомпилированной Vega

Просмотр итогового Vega JSON используется для анализа:

Типичные задачи

  • проверка правильности агрегаций
  • анализ генерации scale-domain
  • исследование signal dependencies
  • оптимизация больших визуализаций
  • диагностика неожиданных transform-цепочек

Сравнение уровней абстракции

Vega-Lite

  • компактное описание
  • декларативная семантика
  • автоматическая генерация осей и масштабов
  • ограниченная, но удобная выразительность

Vega

  • полный контроль над dataflow
  • явные сигналы и события
  • детализированное описание рендеринга
  • высокая сложность и гибкость

Извлечение и сериализация результата компиляции

Скомпилированная Vega-спецификация является обычным JSON и может быть сериализована:

const json = JSON.stringify(vgSpec, null, 2);

Такой JSON часто сохраняется для:

  • офлайн-рендеринга
  • серверного исполнения Vega
  • кэширования сложных визуализаций
  • интеграции в аналитические пайплайны

Взаимодействие с runtime Vega

После компиляции Vega-спецификация становится входом для runtime:

  • parse() создаёт внутреннее представление
  • View управляет состоянием исполнения
  • изменения сигналов приводят к реактивному пересчёту
  • dataflow обновляется инкрементально

Особенности компиляции интерактивных элементов

Интерактивность Vega-Lite (selection, hover, brush) трансформируется в Vega следующим образом:

  • selection → signals
  • encodings → signal-driven predicates
  • bind → input elements + signal updates

Пример:

"selection": {
  "brush": { "type": "interval" }
}

Компилятор генерирует:

  • signal для хранения диапазона
  • event listeners (drag, mouseup)
  • фильтрующие выражения в transforms

Структурные отличия результата компиляции

Скомпилированная Vega-спецификация обычно:

  • в 3–10 раз больше исходной Vega-Lite
  • содержит явные идентификаторы всех узлов
  • включает внутренние transforms (formula, collect, project)
  • имеет развернутые выражения Vega Expression Language

Использование с Node.js средой

Компиляция и просмотр Vega возможны вне браузера:

import vegaLite from 'vega-lite';
import vega from 'vega';
import fs from 'fs';

const vgSpec = vegaLite.compile(vlSpec).spec;

const view = new vega.View(vega.parse(vgSpec));

view.toImageURL('png').then(url => {
  const base64 = url;
});

Это позволяет:

  • генерацию изображений на сервере
  • пакетную обработку графиков
  • интеграцию в отчётные системы

Значение просмотра промежуточной Vega-спецификации

Промежуточный результат компиляции служит связующим звеном между:

  • декларативной моделью Vega-Lite
  • исполнительной моделью Vega

Анализ этого слоя позволяет точно понимать:

  • как агрегируются данные
  • как распределяются координаты
  • как строится реактивная модель взаимодействий
  • какие оптимизации применяются компилятором