Эта заметка содержит черновое описание API для анализа событий в экспериментальной физике. Планируется, что часть её я потом переведу на английский и размещу во внутренних Doxygen/(T)Wiki. API реализовано в библиотеке StromaV.
В этом посте рассматривается короткая спецификация AnalysisPipeline
для анализа данных на C++, а так же даётся краткое практическое описание
утилиты afpipe
использующий функциональность AnalysisPipeline
наиболее
наглядным образом.
AnalysisPipeline
в C++На наиболее базововм концептуальном уровне AnalysisPipeline
представляет
собой список обработчиков (реализующих iEventProcessor
) которые
последовательно применяются к множеству событий выраженному в виде
экземпляра класса реализующего интерфейс iEventSequence
.
Следующий сниппет отвечает случаю, когда чтение событий реализовано в
классе MyEventSequence
, а список обработчиков представлен экземплярами
классов MyProcessingClass1
, MyProcessingClass2
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | AnalysisPipeline pipe;
// Set the events source:
iEventSequence * source = new MyEventSequence();
// Set the processor handlers in order:
pipe.push_back_processor( new MyProcessingClass1() );
pipe.push_back_processor( new MyProcessingClass2() );
pipe.push_back_processor( new MyProcessingClass1() );
// ...
// Process the events using assembled processing sequence:
for( auto event = source->initialize_reading();
source->is_good();
source->next_event( event ) ) {
pipe.process( event );
}
source->finalize_reading();
|
Такой фрагмент был принят в качестве базовой спецификации при проектировании, и преследовал цель обеспечить наибольшую простоту пользовательского кода. При этом достаточно очевидна гибкость такой простой концепции:
iEventSequence
.Поскольку потребность в итерировании событий посредством for(...){...}
в строках 13-18 возникает довольно часто, класс AnalysisPipeline
содержит
вспомогательный метод process( iEventSequence * )
, реализующий такое
поведение. Строки 13-18 можно заменить вызовом
pipe.process( source );
Кроме того, нередко возникает надобность изнутри обработчиков каким‐то образом отслеживать источник данных и текущий состав списка обработчиков. Поскольку такая информация нередко оказывается нужна в силу применения различных пользовательских библиотек с неизменяемым API, а так же для извлечения метаинформации.
Экземпляр AnalysisPipeline
может ссылаться на экземпляр iEventSequence
(ассоциация). После введения защищённого атрибута указывающего на
экземпляр источника данных и методов для работы с ним первоначальный
сниппет можно упростить до следующего:
1 2 3 4 5 6 7 8 9 10 11 12 | AnalysisPipeline pipe;
// Set the events source:
pipe.event_sequence( new MyEventSequence() );
// Set the processor handlers in order:
pipe.push_back_processor( new MyProcessingClass1() );
pipe.push_back_processor( new MyProcessingClass2() );
pipe.push_back_processor( new MyProcessingClass1() );
// ...
pipe.process( source );
|
Наиболее важный практический сценарий использования класса AnalysisPipeline
—
применение конвейера обработчиков для задачи непосредственного анализа данных.
afpipe
StromaV предоставляет утилиту afpipe
, использующую AnalysisPipeline
прямолинейным образом: источник данных и набор процессоров
задаются и параметризуются из командной строки (или конфигурационных
файлов), после чего приложение производит обработку заданного числа
событий (или всех доступных в источнике) последовательно извлекая их
по мере обработки.
Хотя код самого приложения чрезвычайно прост, для понимания он требует
предварительного описания пары служебных компонент StromaV, включя классы
приложений, логику конфигурирования и словарь IndexOfConstructables
(шаблонная фабрика). Эти описания будут даны в соответствующих разделах, а
пока целесообразно рассказать о паре практически‐важных примеров использования
этого приложения.
Справка об аргументах командной строки может быть получена по стандартному
ключу -h,--help
:
$ install/bin/afpipe --help
Из представленных ключей, практический интерес для обработки данных управляемой командной строкой наиболее важны следующие:
-l,--load-module
— параметр, задающий подгружаемые модули. Эти модули
представленные обычной разделяемой библиотекой (shared object file) содержат
реализации iEventSequence
и iEventProcessor
специфичные для конкретного
эксперимента.-i,--input-file
— параметр, задающий источник данных: файл, или
дескриптор сетевого подключения которым инициализируется выбранный подкласс
iEventSequence
.-F,--input-format
— парамтер, задающий формат источника входных данных.
Фактически, это должно быть имя по которому был зарегистрирован подкласс
iEventSequence
отвечающий формату входных данных.--list-src-formats
— флаг, предписывающий afpipe
напечатать список
зарегистрированных форматов входных данных после базовой инициализации и
завершиться.-p,--processor
— параметр, задающий обработчик данных. Фактически
соответствует имени с которым зарегистрирован нужный подкласс
iEventProcessor
. Может быть указан несколько раз — в этом случае обработчики
будут добавлены в цепочку по порядку упоминания.--list-processors
— флаг, предписывающий afpipe
напечатать список
зарегистрированных обработчиков данных после базовой инициализации и
завершиться.Так, например, чтобы увидеть список доступных форматов входных данных для
сборки afpipe
безо всяких расширений:
$ install/bin/afpipe --list-src-formats
* "svb"
╟─ progressbar, type=`b', flag, value set: "False" Displays simple ...
╟─ listeningPort, type=`i', value set: "23011" Network port for ...
╙─ recvBufferSize_kB, type=`m', value set: "256" Size of recieving ...
В таком виде, справка будет содержать, помимо имени формата, ASCII-дерево
отражающее его локальный конфигурационный словарь, что бывает полезно при
построении обработчика из командной строки или интерактивной сессии
CLING/Python. "svbp"
— это штатный формат обмена данными о физических
событиях в StromaV, не зависящий от конкретного эксперимента.
Практически, пользователя обычно интересует список доступных форматов или обработчиков включающий, помимо штатного набора StromaV и те что были предоставлены расширением. Например, для пакета расширений afNA64 для эксперимента NA64 (CERN, SPS):
$ install/bin/afpipe -linstall/lib/na64/libafNA64-rdbg.so --list-src-formats
* "svb"
...
* "ddd"
...
Появившийся формат "ddd"
реализован в библиотеке libafNA64-rdbg.so.1.0 и
представляет собой класс реализующий методы iEventSequence
StromaV для данных
представленных в формате .raw
, базовый кодек которых предоставлен библиотекой
DaqDataDecoding пакета CORAL.
В тех нередких случаях, когда внутренний формат данных статистики эксперимента предполагает дорогое (сравнительно с «svb») декодирование1) оказывается целесообразным сохранить статистику в файл для последующего использования:
$ install/bin/afpipe -A -linstall/lib/na64/libafNA64-rdbg.so \
-Fddd -i/data/cdr01001-2543.dat \
-p eventsStore \
-o /tmp/run-2543-chunk-1.svb
Приведённая команда осуществит вычитку всех событий из файла
/data/cdr01001-2543.dat
и сохранит их в формате «svb»
в файл /tmp/run-2543-chunk-1.svb
.
Практическое мспользование afpipe
без каких‐либо модулей расширения можно
продемонстрировать на следующем
простейшем примере: имеется файл /tmp/sV_latest.svbs
содержащий наборы
событий в формате «svb», первые 2500 событий из которого необходимо переслать
по сетевому соединению на некоторый удалённый хост (скажем, идентифицируемый IP
10.0.0.2) и сохранить применяя
компрессию LZMA.
В этом случае достаточно запустить на удалённом хосте процесс afpipe
с
источником данных в формате «svb» сконфигурированном в режиме сервера
принимающего входящие TCP соединения с единственным обработчиком «eventsStore»
(см. справку по соответствующим аргументам):
$ install/bin/afpipe -Fsvb -i@ -peventsStore \
-Oanalysis.processors.store.compression=lzma
На локальном хосте afpipe
запускается в режиме чтения из файла с единственным
обработчиком осуществляющим пересылку прочитанных из файла событий:
$ install/bin/afpipe-rdbg -Fsvb -peventsSend \
-i/tmp/sV_latest.buckets.raw -n2500 \
-Oanalysis.processors.send.destination=10.0.0.2
AnalysisPipeline
из C++ достаточно просто, чтобы
пользовательский код мог определять простейшие конвейеры динамически, в
несколько строк.afpipe
как самостоятельного инструмента для общих
операция чтения‐записи, не касающихся внутренней структуры данных.AnalysisPipeline
и операциям с виртуальными
конструкторами, оказывается возможно реализовать обёртки и биндинги для
интерактивных сред: ROOT CLING/IPython, etc.1. Эти случаи нередки по той причине, что формат кодирования экспериментальных данных создаётся обычно с требованием минимизировать время записи данных. DAQ‐системы должны обеспечивать максимальное время отклика. «svb» представляет собой эффективный для представления сложноструктурированных данных, эффективный в равной мере для чтения и записи. В плане реализации он представляет собой сериализацию сообщений Google Protocol Buffers, которые зарекомендовали себя как сравнительно эффектиное средство.