Работа с WorkspaceArray в Engee
Страница в процессе разработки. |
WorkspaceArray
— это специальный тип данных в среде моделирования Engee, предназначенный для хранения и обработки временных рядов. Он основан на интерфейсе AbstractArray
языка Julia, но в отличие от стандартных массивов, реализует ленивую загрузку (Lazy Loading) данных, что делает его ленивым массивом.
Ленивый массив (или лениво загружаемый массив) — это структура, которая не хранит данные целиком в оперативной памяти, а подгружает их по мере необходимости: например, при итерировании, обращении по индексу или преобразовании в таблицу. Это позволяет эффективно работать с очень большими наборами данных, которые не умещаются в память или поступают из внешних источников (например, из базы данных или файла).
WorkspaceArray
в Engee используется в следующих сценариях:
-
Как результат симуляции — для хранения записываемых сигналов. Например, в переменной
simout
(подробнее см. Программная обработка результатов симуляции в Engee); -
Для передачи данных между моделями через блоки В рабочую область и Из рабочей области;
-
Для импорта пользовательских временных рядов из CSV-файлов или таблиц (
DataFrame
), которые затем можно использовать в моделях Engee.
Так, WorkspaceArray
обеспечивает единый и удобный интерфейс доступа к временным данным на протяжении всего моделирования — от подготовки входных данных до анализа результатов.
Создание WorkspaceArray
Обычно WorkspaceArray
формируется автоматически в процессе симуляции — например, при записи сигналов через блок В рабочую область или при сохранении результатов в переменную simout.
Однако его также можно создать вручную — например, чтобы загрузить внешние данные или протестировать модель на заранее подготовленных входах. В этом случае WorkspaceArray
создается одним из следующих способов:
-
Из CSV-файла. Чтобы загрузить данные из CSV-файла, достаточно указать путь к файлу:
wa = WorkspaceArray("my_wa", "/user/path_to_csv.csv")
"my_wa"
— это имя, под которым массив будет сохранен в Окно переменныхEngee. Оно используется для последующей ссылки на массив в моделях, скриптах и других приложениях.
CSV-файл должен содержать два столбца: один обязательно с именем
time
, второй — со значениями сигнала. Пример структуры CSV-файла:time value 0.1 1 0.2 2 0.3 3
-
Из таблицы
DataFrame
. Если вы уже работаете с табличными данными в Julia, можно создатьWorkspaceArray
напрямую из объектаDataFrame
. Это особенно удобно при генерации входных сигналов программно, во время анализа или трансформации данных.DataFrame
— это табличная структура из пакетаDataFrames.jl
, аналогичная таблицам в Excel или DataFrame в Python (pandas). Каждая колонка имеет имя и тип, а данные хранятся по строкам. Пример создания:using DataFrames df = DataFrame(time = [0.1, 0.2, 0.3], value = [1, 2, 3]) wa = WorkspaceArray("my_wa", df)
Таблица должна содержать два столбца:
time
(типFloat64
) иvalue
(может быть скаляром, вектором или массивом чисел).
Работа с WorkspaceArray
WorkspaceArray
реализует интерфейс AbstractArray
, что позволяет обращаться к нему как к обычному массиву в Julia — индексировать, итерировать, выполнять срезы и т.д. Однако помимо базового поведения массивов, WorkspaceArray
содержит внутреннюю структуру и дополнительные поля, которые обеспечивают его связь с источниками данных, поддерживают ленивую загрузку и позволяют удобно работать с временными рядами.
Каждый WorkspaceArray
— это не просто набор чисел, а объект с «метаданными»: он знает, где лежат его данные, как они связаны со временем, откуда загружаются, и как были получены. Эти дополнительные свойства можно запросить напрямую, просто обращаясь к полям объекта через точку:
wa = WorkspaceArray("my_wa")
wa.time # доступ к временны́м меткам
wa.value # доступ к значениям
wa.type # узнаём, какой тип у массива — :pair, :time или :value
Доступны следующие поля:
-
time
— дочернийWorkspaceArray
, содержащий только временные метки. Имеет тип:time
; -
value
— дочернийWorkspaceArray
, содержащий значения сигнала. Имеет тип:value
; -
type
— тип текущего массива::time
,:value
или:pair
(временные метки + значения); -
parent
— ссылка на родительскийWorkspaceArray
, если текущий является результатом среза; -
range
— диапазон индексов, на основе которого был создан срез. Используется при ленивом срезе; -
dimension
— размерность данных в полеvalue
(например, скаляр, вектор, матрица); -
signal_id
— уникальный идентификатор источника данных в Engee.
Чаще всего при работе с WorkspaceArray напрямую используются поля time и value , особенно при необходимости получить данные по отдельности или преобразовать их в таблицу.
|
Повторное использование
После создания переменной, содержащей WorkspaceArray
(например с именем wa
), автоматически связывается с signal_id
(уникальным идентификатором) в Engee. Это позволяет ссылаться на нее по имени и повторно использовать в других частях проекта — например, в веб-приложениях на базе фреймворка Genie (подробнее см. Работа с Genie в Engee), в других моделях или в блоках с вложенностью, например Подсистема:
wa = WorkspaceArray("my_wa")
Такая запись создает новый WorkspaceArray
, ссылающийся на уже зарегистрированные данные под именем "my_wa"
.
Использование с моделями
Блоки В рабочую область и Из рабочей области предназначены для взаимодействия с WorkspaceArray
в модели:
Блок В рабочую область записывает данные из модели в переменную типа WorkspaceArray
в рабочей области Engee. Имя переменной задается параметром Variable name. Поддерживаются только числовые данные (скалярные и массивы).
Блок Из рабочей области считывает данные из рабочей области и подает их на вход модели. Используются только переменные типа WorkspaceArray
.
Блоки To Workspace и From Workspace работают только с типом WorkspaceArray .
|
Пример использования: From/To Workspace демо
Работа с CSV
Выгрузка данных
Полная выгрузка в DataFrame
Для полной выгрузки данных из WorkspaceArray
в DataFrame используйте collect
:
df = collect(wa) # получаем DataFrame с колонками time и value
Вы также можете получить отдельные колонки из WorkspaceArray
:
collect(wa.time) # только время
collect(wa.value) # только значения
Не рекомендуется использовать collect для очень больших данных — возможна перегрузка памяти.
|
Ленивые срезы
Одно из ключевых преимуществ WorkspaceArray
— поддержка ленивых срезов (Lazy Slices).
В отличие от обычных массивов Julia, где срез (wa[1:10]
) создает новый массив с копией данных, WorkspaceArray
работает иначе. При срезе создается представление (view), которое хранит только диапазон индексов (range
) и ссылку на исходный объект (parent
) — без фактической загрузки значений в память. Данные подгружаются из хранилища только при явном запросе, например, через collect
, при итерации или доступе по индексу.
Это особенно полезно для:
-
Экономии памяти — срезы не копируют данные, а лишь указывают на нужные элементы;
-
Быстродействия — можно работать только с нужными фрагментами данных;
-
Гибкости — ленивые срезы можно использовать в качестве входных данных моделей, в визуализациях или при экспорте.
Пример:
wa_slice = wa[1:2:end] # ленивое представление: каждый второй элемент
collect(wa_slice) # загружаем данные в память (в виде DataFrame)
Результат:
Row │ time value
│ Float64 Int64
────┼───────────────
1 │ 0.1 1
2 │ 0.3 3
3 │ 0.5 5
Кроме срезов, можно получить доступ к отдельному элементу по индексу:
wa[1] # доступ к первой записи, будет получено (0.1, 1)
Срезы по полям time
и value
В WorkspaceArray
доступны отдельные поля .time
и .value
, к которым также можно применять ленивые срезы:
wa_values = wa.value[2:end] # срез только по значениям
wa_times = wa.time[2:end] # срез только по временной шкале
Срез При необходимости данные можно загрузить в память:
|
Методы и интерфейс WorkspaceArray
WorkspaceArray
реализует стандартные интерфейсы Julia и дополняет их собственными методами. Ниже — краткий обзор наиболее полезных функций, которые можно использовать при работе с временными рядами:
-
wa[i]
— доступ к элементу по индексу, возвращает кортеж(time, value)
:wa[1] # будет получено (0.1, 42.0)
-
wa[start:stop]
— срез по диапазону, возвращает ленивое представление. Данные не копируются, а подгружаются по мере необходимости:wa_slice = wa[1:10] collect(wa_slice) # загружает только выбранный диапазон
-
wa[1:2:end]
— ленивый срез с шагом. -
wa.time
,wa.value
— доступ к дочернимWorkspaceArray
, содержащим отдельно время и значения. К ним тоже можно применять срезы:wa_times = wa.time[5:end] wa_values = wa.value[5:end]
-
collect(wa)
— преобразуетWorkspaceArray
вDataFrame
. Это основной способ получить данные в явном виде:df = collect(wa)
-
copy(wa)
/similar(wa)
— создают поверхностную копию объекта. В текущей реализации работают одинаково. -
wa1 == wa2
— сравнение двухWorkspaceArray
поsignal_id
и диапазону (range
).
Если вы работаете с временными рядами в Engee, то, скорее всего, вам хватит collect , срезов (wa[1:10] ) и iterrows для повседневных задач. Остальные методы пригодятся при оптимизации и тонкой настройке поведения.
|
Пример использования
Рассмотрим базовый пример работы с WorkspaceArray
— от создания до получения среза и выгрузки данных. Этот сценарий охватывает самые типовые сценарии использования WorkspaceArray
.
-
Для начала создайте таблицу (
DataFrame
), содержащую два столбца:time
иvalue
. Это обязательный формат для импорта данных вWorkspaceArray
:using DataFrames df = DataFrame(time = [0.1, 0.2, 0.3, 0.4, 0.5], value = [1, 2, 3, 4, 5])
-
time
— момент времени (в секундах); -
value
— значение сигнала в этот момент.
-
-
Преобразуйте таблицу в
WorkspaceArray
, указав имя, под которым массив будет доступен в Engee:wa = WorkspaceArray("myarr", df)
Здесь
"myarr"
— имя переменной, с которой можно будет работать в моделях и скриптах. -
WorkspaceArray
поддерживает доступ по индексу. Например, получите первую запись:println(wa[1])
Результат:
(0.1, 1)
Это кортеж: первый элемент — время, второй — значение сигнала.
Данные подгружаются только при обращении к ним. То есть даже при wa[1]
загружается только один элемент. -
Сделайте срез массива, получите каждый второй элемент
(1, 3, 5)
. Это создаст ленивое представление, а не копию:wa_slice = wa[1:2:end]
Чтобы получить данные в виде таблицы, используйте
collect
:println(collect(wa_slice))
Результат:
3×2 DataFrame Row │ time value │ Float64 Int64 ─────┼──────────────── 1 │ 0.1 1 2 │ 0.3 3 3 │ 0.5 5
Срез
wa[1:2:end]
не загружает данные сам по себе. Только приcollect
, итерации или обращении по индексу данные реально подгружаются из хранилища.