ROOT — платформа C++ для хранения петабайтных данных, статистического анализа и визуализации

Аннотация

ROOT — это объектно-ориентированная среда C++, созданная сообществом специалистов по физике высоких энергий (HEP) и предназначенная для эффективного хранения и анализа петабайт данных. Любой экземпляр класса C++ может быть сохранен в файле ROOT в машинно-независимом сжатом двоичном формате. В ROOT контейнер объектов TTree оптимизирован для статистического анализа очень больших наборов данных с использованием методов вертикального хранения данных. Эти контейнеры могут охватывать большое количество файлов на локальных дисках, в Интернете или в нескольких различных общих файловых системах. Для анализа этих данных пользователь может выбирать из широкого набора математических и статистических функций, включая классы линейной алгебры, численные алгоритмы, такие как интегрирование и минимизация, а также различные методы выполнения регрессионного анализа (подгонки). В частности, пакет RooFit позволяет пользователю выполнять сложное моделирование и подгонку данных, а библиотека RooStats предоставляет абстракции и реализации для расширенных статистических инструментов. Многомерные методы классификации, основанные на методах машинного обучения, доступны через пакет TMVA. Центральным элементом этих инструментов анализа являются классы гистограмм, обеспечивающие объединение одномерных и многомерных данных. Результаты можно сохранять в высококачественных графических форматах, таких как Postscript и PDF, или в растровых форматах, таких как JPG или GIF. Результат также может быть сохранен в макросах ROOT, что позволяет полностью воссоздать и переработать графику. Как правило, пользователи создают свои макросы анализа шаг за шагом, используя интерактивный интерпретатор C++ CINT, одновременно обрабатывая небольшие выборки данных. После завершения разработки они могут запускать эти макросы на полной скорости компиляции для больших наборов данных, используя компиляцию «на лету» или создавая автономную пакетную программу. Наконец, если доступны обрабатывающие фермы, пользователь может сократить время выполнения внутренне параллельных задач, например. интеллектуальный анализ данных в HEP — с помощью PROOF, который позаботится об оптимальном распределении работы по доступным ресурсам прозрачным способом.

1. Введение

ROOT — это кроссплатформенный C++ фреймворк для обработки данных, созданный в CERN (Европейская организация ядерных исследований, Женева, Швейцария). Каждый день тысячи физиков используют приложения на основе ROOT для анализа и визуализации своих данных.

Проект ROOT был запущен в 1995 году Рене Брюном и Фонсом Радемакерсом. Он начинался как частный проект и превратился в официально поддерживаемый инструментарий анализа LHC. В настоящее время он разрабатывается небольшой командой из нескольких лабораторий. ROOT извлекает выгоду из значительного количества вкладов пользователей, как внутри, так и за пределами науки. В этой статье основное внимание уделяется текущему состоянию ROOT по состоянию на версию 5.24.00.

Типичное приложение, разработанное для исследования ВЭП (более подробно в разделе 1.2 и рис. 2), используется для обработки как реальных, так и смоделированных данных, состоящих из множества событий, имеющих одинаковую структуру данных и предполагаемых статистически независимыми (такая независимость очень важна от вычислительной точки зрения, так как позволяет получить максимальное ускорение за счет распределения подмножеств данных по параллельным узлам анализа). Кроме того, для анализа данных также необходима дополнительная информация, например, параметры детектора (геометрия, питание и конфигурация считывания, карты магнитного поля и т. д.) или входные настройки механизмов моделирования. Такие значения не меняются в масштабе события. Скорее, они имеют более медленную эволюцию, которая определяет гораздо более грубую степень детализации: прогон определяется набором событий с постоянными настройками (4). меньшие блоки, занимающие промежуточное положение между масштабом событий и степенью детализации запуска).

1.1. Обнаружение ROOT

Чтобы познакомиться с инфраструктурой ROOT, можно следовать типичному подходу новых пользователей и его большому набору библиотек и инструментов с помощью эскиза на рис. 1. Подробное описание функций ROOT см. в Руководстве пользователя [2].

Новички часто начинают со своей собственной программы анализа, просматривая свои данные (обычно хранящиеся в формате ASCII или доступ к которым осуществляется через механизм реляционной базы данных). Они просто ищут библиотеку для создания графиков для визуализации своих гистограмм. Они начинают с игры с корневым классом TGraph, который можно использовать для отображения набора точек (x, y), включая ошибки.

Следующим шагом будет использование гистограмм ROOT (базовым классом которых является TH1; дополнительные сведения см. в разделе 2.3) и создание графиков методом TH1::Draw(). Гистограммы ROOT можно использовать для бинирования набора данных и оценки его плотности. У них есть ряд полезных свойств, позволяющих пользователю манипулировать ими, получать статистическую информацию о базовых данных и выполнять подгонку, не заботясь о графиках — они будут перерисовываться всякий раз, когда применяются изменения.

Особенно на ранних этапах, когда программа анализа данных меняется довольно часто, пользователи могут найти интерактивный интерпретатор C++ CINT, встроенный в ROOT, очень полезным. Разработка программ с помощью интерпретатора ускоряет типичный итеративный подход к анализу данных, удаляя дополнительные этапы компиляции и компоновки. Конечно, если логика приложения уже хорошо известна, можно предпочесть разработать программу более структурированным образом, полагаясь на компилятор обычным образом.

Наиболее распространенной задачей доступа к данным в HEP является выборочное разреженное сканирование данных. Традиционное горизонтальное разбиение данных, подобное РСУБД, не обеспечивает эффективного разреженного чтения, за исключением индексов. Вместо этого ROOT использует вертикальное разделение данных произвольных определяемых пользователем объектов, реализованное в его классе TTree.

TTree разделены на ветви. Во время чтения каждая ветвь может быть доступна независимо. TBranch хранит последовательные объекты или члены данных класса или других TBranch. По умолчанию все ветки, хранящиеся в TTree, записываются в отдельные буферы в файле, поэтому для повторения данных, хранящихся в ветке, требуется только чтение этих связанных буферов. TTrees может охватывать несколько файлов ROOT. Файл ROOT очень похож на файловую систему, что позволяет дополнительную внутреннюю организацию с использованием каталогов. Например, основной набор данных может храниться в одном TTree, тогда как сводная информация (в виде гистограмм) находится в отдельных каталогах того же TFile.

Если объем данных растет, пользователь может разделить экземпляр TTree на несколько экземпляров TFile. Позже, при доступе к данным, все они могут быть объединены в единую логическую сущность, TChain, что делает доступ к нескольким файлам практически прозрачным. Поскольку TChain наследуется от TTree, он обеспечивает те же преимущества с точки зрения оптимизированного доступа к данным, даже если данные распределены по разным файлам.

Самый быстрый способ разработки пользовательской программы анализа — это пошаговое создание макросов ROOT с помощью CINT. Как только фаза разработки завершена, производительность становится первостепенной. Первым очевидным шагом оптимизации является преобразование приложения в скомпилированную программу. Тем не менее, не нужно отказываться от использования интерпретатора: наиболее эффективный способ работы с ROOT — рассматривать интерпретатор как «клей», который связывает воедино скомпилированные фрагменты кода, выполняющие большую часть интенсивных вычислений. На самом деле это не так сложно, как кажется: макросы CINT могут быть скомпилированы ACLiC во время интерактивного сеанса (раздел 2.6.2), чтобы получить полную скорость скомпилированного кода и надежность полного компилятора C++ (CINT, например, имеет ограниченную поддержку шаблонов C++). В общем, интерпретируемый код может вызывать скомпилированный код и наоборот (подробнее в Разделе 2.6). Наконец, если доступна многоядерная машина или вычислительная ферма, PROOF (раздел 2.7) предоставляет способ в полной мере использовать параллелизм событий, присущий независимым событиям HEP, позаботившись о распределении анализа по всем доступным ЦП и дискам в прозрачным способом.

1.1. Типичное использование ROOT

На рис. 2 показано большинство функций, которыми может обладать приложение ROOT. Конечно, одно приложение редко имеет их все: например, его внимание может быть сосредоточено на моделировании детектора или на анализе данных, но не на том и другом одновременно.

ROOT предоставляет интерфейс Virtual Monte Carlo (VMC) (раздел 2.5) для наиболее важных механизмов моделирования HEP, таких как Geant4 [3] (C++), Geant3 [4], Fluka [5] (FORTRAN), для моделирования прохождения частиц. через вещество и их распространение в магнитном поле. Интерфейс VMC позволяет пользователю создать приложение, моделирующее поведение детектора частиц, со свободой переключения между различными модулями моделирования. Сравнение результатов различных механизмов моделирования позволяет оценить систематические неопределенности моделирования.

Обычно большинство пользователей ROOT разрабатывают программы для выполнения статистического анализа данных (см. также раздел 2.2) группированных (гистограммы) или небинированных данных (переменные TTree). Пакет TMVA5 (раздел 2.2) можно использовать для классификации событий, чтобы различать сигнал и фон. Существуют различные методы для наилучшего соответствия выбранных данных теоретическим моделям.

ROOT также можно использовать для разработки отображения событий (раздел 2.4). Отображение событий — это приложение, обеспечивающее визуализацию геометрии детектора, отображение попаданий (6. На жаргоне HEP «удар» — это локальное выделение энергии, которое обнаруживается считывающей электроникой) и кластеров совпадений, используемых для создания струй калориметра. (Струя — это трехмерное распределение выделения энергии, которое обычно хорошо сдерживается конусом (представьте себе очень большую вытянутую каплю воды, чтобы визуализировать ее) и физическими векторами (4-импульс (четыре-импульс — это вектор пространство-время, чья времениподобная составляющая (пропорциональна) энергии частицы, а пространственноподобная составляющая представляет собой трехмерный импульс)) Кроме того, кластеры и физические векторы используются для построения треков, которые визуализируют путь частиц через детектор.

2. Описание ROOT framework

Фреймворк ROOT содержит около 3000 классов, сгруппированных примерно в 110 пакетов и плагинов. Кроме того, последние сгруппированы в категории верхнего уровня, которым посвящен данный раздел.

2.1. Ввод, вывод

В настоящее время ROOT используется для хранения до 50 петабайт данных по последним оценкам (согласно опросу ряда координаторов вычислительных экспериментов). Уровень ввода-вывода хранит объекты C++ в системах хранения, будь то файловые системы, базы данных, общие протоколы к элементам хранения, см. рис. 3.

1.1.1. Описание объектов C++

Для сохранения объекты C++ должны быть описаны: ввод-вывод должен знать, что хранить. ROOT предоставляет это описание (называемое словарем) для всех своих классов, и пользователи могут создавать словари для своих собственных классов. Данные описания (обычно называемые отражением) предоставляются CINT или комбинацией GCCXML [7] и Reflex, библиотеки отражения C++, которая является частью ROOT. На основе этой информации ROOT знает, где в памяти находятся элементы данных объекта, каков их размер и как их хранить. КОРНЕВОЙ ввод/вывод поддерживает (раз)развертку указателей, преобразование указателей в индексы в выходном буфере. Он может работать даже с графом объектов с циклическими ссылками (следя за тем, чтобы каждый объект передавался в буфер только один раз), и способен корректно восстанавливать его при чтении.

Поскольку описание всех соответствующих классов хранится вместе с данными, поддерживаются изменения определения класса объектов, сохраненных с помощью ROOT I/O. При чтении сравниваются описания из постоянного слоя и версии в памяти: если обнаружены различия, ROOT во многих случаях автоматически переводит из старого в новый формат (эволюция схемы). Также доступна полная структура для произвольных преобразований, контролируемых пользователем [8].

1.1.2. T-файл

Файл ROOT читается и записывается классом TFile и предназначен для однократной записи, многократного чтения (при поддержке удаления и повторного использования содержащихся данных).

Содержимое файла ROOT представляет собой простой двоичный поток, структура которого описана в документации класса TFile [9]. Все данные, кроме заголовка, обычно сжимаются, чтобы уменьшить пространство для хранения и использование полосы пропускания ввода-вывода для файлов за счет небольшого увеличения времени ЦП при чтении и записи файлов. Файл состоит из указателя содержимого, списка описаний типов, относящихся к файлу, и фактических данных. Каждый фрагмент данных имеет имя, и его можно получить по имени. TFile также поддерживает иерархическое хранение во вложенных каталогах.

Типичные размеры файлов варьируются от нескольких килобайт до нескольких гигабайт. Файлы можно объединять в новые файлы большего размера; это можно сделать рекурсивно, т. е. объединить также сами коллекции, содержащиеся в файле, если они имеют одинаковое имя и относятся к одному типу. Коллекции файлов также могут быть объединены в заархивированный контейнер; ROOT поддерживает прозрачную распаковку и навигацию в этой коллекции файлов.

Описание классов, хранящееся в файле (раздел 2.1.1), можно использовать для чтения данных даже без определения класса C++.

Таким образом, можно записывать объекты C++, используя определение из пользовательской библиотеки, и считывать их без использования пользовательской библиотеки. Любые доступные данные отражения используются для интерактивного просмотра ROOT-файла с помощью TBrowser, который также может расширять и просматривать содержимое всех объектов C++, либо из ROOT, либо из STL, либо определенных пользователем.

Файлы ROOT можно открывать по протоколу HTTP без каких-либо специальных требований к серверу. ROOT запрашивает только те части файла (используя HTTP-запросы диапазона содержимого), которые действительно необходимы. Это позволяет удаленно просматривать файлы ROOT с малой задержкой.

1.1.3. TTree и ввод-вывод

TTree — это контейнер, оптимизированный для ввода-вывода и использования памяти. TTree состоит из ветвей, ветви могут содержать полные объекты данного класса или быть разделены на подветви, содержащие отдельные элементы данных исходного объекта. Это называется разделением и может выполняться рекурсивно до тех пор, пока все подобъекты не будут разделены на ветви, содержащие только отдельные элементы данных. Разделение может даже преобразовывать контейнеры в ветви элементов данных контейнера, группируя их, как показано на рис. 4. Разделение может быть выполнено автоматически с использованием словарной информации класса. Каждая ветвь хранит свои данные в одном или нескольких связанных буферах на диске. Желаемый уровень разделения зависит от типичных шаблонов доступа к дереву в будущем. Если во время анализа будут доступны все элементы данных объекта, то разбиение не потребуется. Типичные анализы имеют доступ только к нескольким элементам данных; в этом случае расщепление очень выгодно.

Хранилище на основе ветвей называется вертикальным или столбцовым хранилищем (CWS; рис. 5), в отличие от горизонтального или построчного хранилища (RWS), которое обычно встречается в базах данных RDBMS. В CWS, так же как и в RWS, предполагается набор ("таблица") подобных объектов ("строк"). Однако в RWS всегда считываются все элементы данных объекта, тогда как в CWS считываются только необходимые буферы (например, элементы данных). Разделение — это автоматизированный способ создания этих столбцов.

CWS сокращает количество операций ввода-вывода и объем передаваемых данных, поскольку считывает только необходимые части каждого объекта. Все остальные члены объекта сохраняют значения, определенные конструктором класса по умолчанию. При итерации по коллекции элементы данных, которые необходимо прочитать, расположены последовательно на носителе данных в случае CWS. Это позволяет считывать данные по блокам для нескольких записей (строк) за один раз, что широко используется всеми современными операционными системами и носителями. Еще одно преимущество связано с тем, что ROOT сжимает буферы данных, используя кодировку Хаффмана [10], которая выигрывает от того, что чаще встречается один и тот же шаблон байтов, потому что один и тот же элемент данных обычно имеет схожие значения (например, идентификатор типа частицы).

Поскольку TTree описывает содержащиеся в нем объекты, можно читать объекты из TTree даже без определения исходного класса. TTree может даже генерировать заголовочный файл C++, представляющий структуру данных объекта, хранящихся в TTree. В сочетании с мощью интерпретатора и ACLiC (раздел 2.6.2) это обеспечивает плавный переход от хранимых двоичных данных к объектам C++ даже без библиотек C++. TTrees также может автоматически генерировать скелет TSelector (раздел 2.7.4) для анализа данных.

Учитывая огромное количество данных, обычно обрабатываемых пользователями ROOT, TTrees часто не помещаются в один файл или файл увеличивается до непрактичных размеров. Кроме того, в (параллельных) пакетных системных анализах разделение TT-деревьев на несколько файлов облегчает распределение данных. ROOT поддерживает это с помощью TChain, реализуя набор TFiles, каждый из которых содержит часть одного и того же12 TTree. TChain наследуется от TTree, поэтому для пользователя не имеет значения, хранится ли TTree в одном или нескольких физических файлах.

Анализы обычно обращаются к одной и той же части TTree для всех его записей. ROOT реализует автоадаптивный механизм предварительной выборки, считывающий следующую запись, в то время как предыдущая запись все еще обрабатывается. Это резко снижает влияние сетей с высокой задержкой: анализы разумного размера становятся жизнеспособными даже через ADSL. На рис. 6 показана продолжительность примера анализа данных. Файл данных размером 280 МБ размещен в ЦЕРНе при сетевом соединении со скоростью 100 Мбит/с; анализ показывает 6,6 МБ. Показанная пропускная способность — это наименьшая пропускная способность, обнаруженная на пути подключения. Очевидно, что для низкозагруженного соединения пропускная способность не является ограничивающим фактором.

1.1.4. форматы ввода/вывода

ROOT может хранить через свой интерфейс ввода-вывода любые объекты C++ в двоичных файлах ROOT. Он также поддерживает представление XML, хотя в основном в дидактических целях (этот формат изначально был реализован как формат обмена с приложениями, не основанными на ROOT, но только несколько приложений использовали его). производительность (из-за представления XML на основе ASCII) и использование диска (из-за подробных метаданных XML) запрещают его использование в качестве производственного формата хранения.

Данные также можно хранить в таблицах базы данных через уровень абстракции; описание объектов и их элементов переводится в таблицы и их столбцы.

1.2. Математические и статистические инструменты

Может потребоваться манипулировать данными различными способами. Поскольку ROOT — это среда C++, доступны все стандартные функции C и C++. Кроме того, ROOT предоставляет ряд передовых математических и статистических функций, хорошо интегрированных в структуру, которые позволяют выполнять практически все возможные операции с помощью нескольких простых команд.

Минимальный набор инструментов, необходимых для численных вычислений, предоставляется библиотекой MathCore. Он состоит из следующих компонентов.

• Часто используемые математические функции, такие как специальные функции, еще не предусмотренные стандартом C++, и функции статистического распределения. Для каждого статистического распределения приведены плотность вероятности, кумулятивная и обратная к ней функции. Эти функции представлены в пространствах имен ROOT::Math и TMath.

• Классы для генерации случайных чисел (классы TRandom). Генератор псевдослучайных чисел по умолчанию — это генератор Мерсенна и Твистера (класс TRandom3) [11].

• Базовая реализация и интерфейсы численных алгоритмов, таких как интегрирование, вывод или простая (одномерная) минимизация.

• Классы и интерфейсы, необходимые для установки всех объектов данных ROOT.

• Абстрактные интерфейсы и классы адаптеров для оценки функций в одном или нескольких измерениях.

Библиотека MathMore дополняет MathCore, предоставляя дополнительные математические функции. Он основан на научной библиотеке GNU (GSL) [12], которая используется как внешняя библиотека. MathMore реализует дополнительные специальные функции, такие как функции Бесселя различных типов и дробного порядка, эллиптические интегралы, многочлены Лагерра и Лежандра, гипергеометрические функции. MathMore содержит дополнительные реализации числовых алгоритмов и дополнительные генераторы случайных чисел, присутствующие в GSL.

Существуют различные библиотеки для численной минимизации и подгонки. Эти библиотеки включают в себя численные методы решения задачи подбора путем нахождения минимума многомерных функций. В MathCore существует общий интерфейс (класс ROOT::Math::Minimizer) для многомерной числовой минимизации. Несколько реализаций этого интерфейса присутствуют в ROOT:

• Minuit предоставляет реализацию популярного пакета минимизации MINUIT [13]. Это прямой перевод исходного кода Fortran на C++ и предоставляет очень похожий API.

• Minuit2 — совершенно новая объектно-ориентированная реализация MINUIT [14]. Присутствуют те же алгоритмы минимизации, что и Migrad и Simplex, но с новыми объектно-ориентированными интерфейсами. Кроме того, он обеспечивает реализацию специализированного метода нахождения минимума стандартных функций наименьших квадратов или правдоподобия путем линеаризации матрицы Гессе. Этот алгоритм называется в ROOT Fumili2.

• Fumili: библиотека, обеспечивающая реализацию алгоритма подгонки Fumili [15], еще одного специализированного метода минимизации для функций наименьших квадратов или функций правдоподобия.

• MathMore предлагает минимизаторы на основе GSL. К ним относятся различные методы минимизации, основанные на алгоритмах сопряженных градиентов, алгоритм Левенберга-Марквардта [16] для нелинейной аппроксимации методом наименьших квадратов и стохастический метод минимизации, основанный на имитации отжига.

• Класс TLinearFitter реализует линейную аппроксимацию методом наименьших квадратов с возможностью использования надежной аппроксимации.

ROOT содержит две библиотеки, предоставляющие классы матриц и векторов, а также операции линейной алгебры:

• Matrix: общий матричный пакет, включающий матричные классы TMatrix и векторные TVector, а также полную среду для выполнения вычислений линейной алгебры, таких как решение уравнений и разложение собственных значений.

• SMatrix: пакет, оптимизированный для высокопроизводительных матричных и векторных вычислений небольшого и фиксированного размера. Он основан на шаблонах выражений для достижения оптимизации высокого уровня и минимизации выделения памяти при матричных операциях. Он происходит от пакета, изначально разработанного для HeraB [17]. Исследования производительности матричных пакетов в эталонных приложениях, используемых в HEP, были показаны в другом месте [18].

В ROOT также существуют две библиотеки для описания векторов физики в 2, 3 и 4 измерениях (релятивистские векторы) с алгоритмами вращения и преобразования:

• Physics: библиотека с классами TVector3 и TLorentzVector.

• GenVector: пакет с общими шаблонами классов для моделирования геометрических векторов в 2-х и 3-х измерениях и векторов Лоренца. Пользователь может управлять внутренним представлением вектора, выбирая систему координат и базовый скалярный тип.

Другие математические и статистические пакеты в ROOT:

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

• Пена: многомерный генератор событий Монте-Карло общего назначения (и интегратор). Он случайным образом генерирует точки (векторы) в соответствии с произвольным распределением вероятностей в n измерениях [19].

• FFTW: библиотека с реализацией быстрого преобразования Фурье (БПФ) с использованием пакета FFTW.15 Требуется предварительная установка FFTW.

• MLP: библиотека с классом нейронной сети TMultiLayerPerceptron на основе алгоритма NN из пакета mlpfit16.

• Quadp: библиотека оптимизации с линейными и квадратичными методами программирования. Он основан на пакете Matrix.

• Статистические классы для вычисления пределов и доверительных уровней. Некоторые из этих классов в настоящее время предоставляются libPhysics.

• TMVA: набор инструментов для многомерного анализа данных, предоставляющий среду машинного обучения для обработки и параллельной оценки сложных методов многомерной классификации. Хотя он специально разработан для нужд приложений физики высоких энергий, он предлагает общие методы, которые можно использовать и в других областях [20].

• RooFit: набор инструментов для моделирования статистических распределений (особенно тех, которые используются в физическом анализе). Модели можно использовать для подбора правдоподобия, построения графиков и создания «игрушечных выборок Монте-Карло» для различных исследований [21].

  • RooStats: пакет, предоставляющий необходимые передовые статистические инструменты, необходимые экспериментам LHC для окончательного анализа их данных с целью расчета доверительных интервалов, проверки гипотез и комбинаций различных каналов анализа. Он предоставляет общие интерфейсы для основных инструментов с реализациями, основанными на различных статистических методах, которые были одобрены статистическими комитетами эксперимента. Он основан на классах RooFit для описания функций плотности вероятности или функций правдоподобия.

1.3. Гистограммы

Имея дело со многими событиями, обычно применяют статистические методы для их анализа. Возможны два различных подхода: статистический анализ объединенных в ячейки данных или несвязанных данных. Наиболее часто используемый подход включает в себя бинированные данные в форме гистограмм, тогда как небинированные данные сохраняются в экземплярах класса TTree (см. Раздел 2.1.3).

В ROOT одномерные гистограммы определяются базовым классом TH1: фактические классы наследуются от TH1 с типом счетчика ячеек (char, float, double, …), определенным производным классом. TH1 также является базовым классом для 2D- и 3D-гистограмм (опять же, с поддержкой различных типов записей) и для гистограмм профиля (TProfile, TProfile2D и TProfile3D). Гистограммы профиля используются для отображения среднего значения переменной и ее стандартного отклонения в каждом интервале другой зависимой переменной (или переменных в случае многомерных гистограмм профиля). Классы гистограмм также можно использовать для анализа взвешенных наборов данных.

Гистограммы ROOT внутренне содержат пару (значение, неопределенность) для каждого бина, а также количество записей, выходящих за его пределы (как переполнение, так и недополнение). Также сохраняется дополнительная информация, такая как общее количество записей и интеграл гистограммы. Можно получить статистическую информацию, такую ​​как среднее значение и стандартное отклонение по оси гистограммы. Биннинг может быть определен с постоянным или переменным размером шага, а многомерные гистограммы поддерживают проецирование и нарезку. Гистограммы также могут быть оснащены пользовательской функцией.

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

Гистограммы можно строить, вызывая метод Draw(), а результатом можно интерактивно манипулировать (см. Раздел 2.4). Метки могут быть числовыми или текстовыми, и пользователь может определить заголовки17 для гистограммы и каждой оси.

Наборы данных (x, y) или (x, y, z) могут отображаться и анализироваться в ROOT с использованием классов TGraph или TGraph2D. Ошибки данных также можно отображать с помощью производных классов TGraphErrors и TGraphAsymErrors. В дополнение к подгонке классы TGraph предоставляют функциональные возможности для интерполяции точек данных с использованием различных методов, таких как кубические сплайны и сглаживание.

ROOT позволяет пользователю сопоставлять как объединенные, так и несвязанные данные с параметрическими функциями, которые могут отображаться вместе с данными. Графические функции представлены классами TF1, TF2 или TF3 в зависимости от размерности. Их можно создать либо из предварительно скомпилированного пользовательского кода, используя глобальные функции или функции-члены класса, либо из математических выражений, которые обрабатываются классом TFormula. TFormula умеет разбирать выражения, содержащие математические функции, в том числе в TMath, и используя специальный синтаксис для определения параметров. Для облегчения использования также доступны предопределенные выражения, представляющие такие функции, как полиномиальная, гауссовская, экспоненциальная или Ландау.

Помимо вызова метода Fit() из макроса, пользователь также может использовать графический интерфейс, предоставляемый панелью подгонки (рис. 7), во время интерактивных сеансов. Его можно открыть непосредственно из меню ROOT TCanvas или через контекстное меню любого ROOT-объекта, подходящего для подгонки, доступного после щелчка правой кнопкой мыши по объекту. С помощью панели подгонки пользователь может выбрать функцию подгонки, установить начальный параметр и управлять всеми доступными опциями подгонки. Он также предлагает возможность рисовать графики сканирования и контурные графики подобранных параметров.

2.4. Графика и пользовательский интерфейс

Всякий раз, когда ROOT рисует объект, он помещает его в экземпляр TCanvas, представляя область, сопоставленную с окном, непосредственно находящимся под управлением диспетчера отображения. Можно сохранить TCanvas в нескольких возможных форматах: для стандартных графических форматов качество публикации достигается с помощью векторной графики, такой как PostScript или PDF, но растровая графика обычно является лучшим выбором для изображений, которые будут включены в веб-страницы. Его также можно сохранить как макрос C++, где операторы C++ воспроизводят состояние TCanvas и его содержимое. Это позволяет полностью воспроизвести из ROOT. Все классы ROOT, наследуемые от TObject, могут отображаться на панели с помощью метода Draw(). Размеры графических объектов обычно выражаются в пользовательских координатах. Например, после построения гистограммы или графика пользовательские координаты совпадают с координатами, заданными осями графика. Положение контактной площадки в родительской контактной площадке выражается в нормализованных координатах, в которых контактная площадка отображается в единичный прямоугольник. TCanvas требует, чтобы размеры в пикселях располагались на рабочем столе. В ROOT метод Draw на самом деле не рисует сам объект. Вместо этого он добавляет объект в список отображения панели (чтобы он рисовался каждый раз, когда панель перерисовывается) и вызывает метод Paint, который рисует фактические графические примитивы. ROOT автоматически управляет перерисовкой TCanvas, когда объект обновляется или требует операционная система.

2.4.1. 2D графика

2D-графика включает в себя все, что мы можем отобразить на мониторе или распечатать на бумаге. ROOT должен быть связан с графическим движком операционной системы, чтобы иметь возможность отображать окна, содержащие какой-либо сюжет. ROOT также может загружать растровые изображения и манипулировать ими. Этот пакет также позволяет создавать растровые выходные файлы во всех распространенных форматах, таких как GIF, PNG, JPEG и т. д.

2.4.2. 3D графика

Существует несколько способов рендеринга 3D-графики в ROOT, предпочтительным является использование графической библиотеки OpenGL, которая используется в ROOT для отображения данных с использованием лего и поверхностных графиков, а также для рендеринга геометрии детектора.

2.4.3. Отображение геометрии и событий

Геометрия в трехмерном пространстве описывается в ROOT с помощью базовых тел, которые можно соединять, пересекать или вычитать для создания более сложных форм. ROOT реализует собственную библиотеку управления графом сцены и механизм рендеринга, который обеспечивает расширенные функции визуализации и анимацию в реальном времени. Программы отображения событий являются важным применением 3D-визуализации. EVE, среда визуализации событий ROOT, широко использует свои интерфейсы обработки данных, GUI и OpenGL. EVE может служить в качестве основы для управления объектами, предлагая иерархическую организацию данных, взаимодействие объектов и визуализацию с помощью графического пользовательского интерфейса и представлений OpenGL, а также автоматическое создание 2D-проекций. С другой стороны, он может служить набором инструментов, удовлетворяющих большинству требований HEP, позволяя визуализировать геометрию, смоделированные и реконструированные данные, такие как совпадения, кластеры, треки и калориметрическая информация.

2.4.4. Графический пользовательский интерфейс

Графический интерфейс пользователя (GUI) ROOT объединяет типичные функции GUI с функциями ROOT, такими как сохранение GUI в качестве источника C++, интерпретация GUI через CINT и связь сигнала/слота на основе CINT. Результатом стал гибкий набор инструментов с графическим интерфейсом, богатый функциональными возможностями и предлагающий все виджеты, которые предоставляются другими наборами инструментов, включая конструктор графического интерфейса. (Потребовалась разработка специального ROOT GUI, поскольку в начале проекта не было хорошего кросс-платформенного инструментария; Qt существовал, но имел проблемы с лицензией.)

2.5. Моделирование

TVirtualMC предоставляет виртуальный интерфейс для приложений Монте-Карло, позволяя пользователю создавать симуляцию независимо от какой-либо реальной базовой реализации Монте-Карло. Пользователь должен будет реализовать класс, производный от абстрактного класса приложения Монте-Карло, и предоставить такие функции, как ConstructGeometry(), BeginEvent(), FinishEvent(), …. Конкретная реализация методом Монте-Карло (Geant3, Geant4, Fluka) выбирается во время выполнения — при обработке макроса ROOT, в котором создается экземпляр конкретного объекта Монте-Карло. Это позволяет сравнивать различные механизмы (часто используемые для оценки систематических погрешностей моделирования) с использованием одного приложения. Таким образом, ROOT предлагает единый интерфейс, общий для всех наиболее распространенных механизмов моделирования; он предлагает централизованно управляемую, производительную геометрическую систему C++ вместо множества различных, часто несовместимых и слишком специализированных геометрических систем, предоставляемых механизмами моделирования. Его система геометрии предлагает возможности ввода-вывода и интерфейс для отображения событий ROOT.

Моделирование Монте-Карло всегда должно описывать входные частицы вместе с их взаимодействием и детектором (геометрия, материалы и считывающая электроника). Определение частиц, доступных взаимодействий и детектора выполняется на этапе инициализации. Затем основной частью приложения является цикл по всем частицам, которые отслеживаются во всех материалах до тех пор, пока они не исчезнут, не остановятся или не исчезнут (путем распада или аннигиляции). Трассировка ведется дискретно: на каждом шаге находится детекторный объем, в котором находится частица, и псевдослучайными числами «рисуется» один из возможно нескольких физических процессов, моделируется взаимодействие частицы с причина. Если происходит взаимодействие, вычисляется потеря энергии частицей (опять же, обычно это случайный процесс) и вычитается из ее кинетической энергии. Когда последний достигает нуля, частица останавливается, в противном случае выполняется новый шаг. При моделировании любого детектора особое значение имеет определение его геометрии. Пакет геометрии ROOT — это инструмент для создания, просмотра и визуализации геометрии детектора. Он не зависит от какого-либо механизма моделирования Монте-Карло, хотя он был разработан для оптимизации переноса частиц в сочетании с пакетами моделирования, такими как Geant3, Geant4 и Fluka.

Сложная геометрия может быть построена иерархически с помощью концепции вмещения: нужно определить и расположить одни объемы внутри других. Позиционирование осуществляется с помощью пространственных преобразований относительно «материнской системы отсчета» (т. е. системы, определяемой содержащим объемом). Сложные объемы строятся с использованием основных или примитивных форм, уже определенных ROOT (например, коробка, труба, конус и т. д.), с помощью таких операций, как соединение или вычитание.

Наконец, заданный объем можно позиционировать в геометрии несколько раз или его можно разделить в соответствии с заданными пользователем шаблонами, автоматически определяя новые содержащиеся объемы. После создания геометрии ее можно сохранить в ROOT-файл или в виде макроса C++ с помощью метода Export() TGeoManager. Загрузка геометрии выполняется с помощью метода Import(). Кроме того, отдельные тома также могут быть сохранены в файле ROOT. Наконец, ROOT предоставляет графический пользовательский интерфейс для редактирования или построения геометрии. Редактор можно открыть с помощью метода Edit() TGeoManager. Определив геометрию детектора, необходимо отслеживать частицы внутри всех объемов и моделировать их взаимодействие. Приложение может использовать пакет геометрии ROOT для создания детектора и виртуальный интерфейс Монте-Карло для доступа к одному или нескольким механизмам моделирования. ROOT также позволяет хранить и визуализировать треки, как это делается внутри пакета рисования с помощью класса TGeoTrack.

2.6. Переводчики

CINT — почти полностью совместимый с ANSI интерпретатор C/C++. Он служит неграфическим пользовательским интерфейсом ROOT как для интерактивного использования (через приглашение CINT), так и в безголовом «пакетном» режиме, когда CINT обрабатывает код C++ без отображения графики. CINT позволяет интерпретируемому и скомпилированному коду взаимодействовать: он может вызывать скомпилированный код так же, как он может быть вызван из скомпилированного кода, с повторным входом. При этом такой код, как histogram-›Draw(), можно интерпретировать, в результате чего вызывается функция TH1::Draw() в одной из библиотек ROOT. С другой стороны, скомпилированный код может содержать оператор gROOT->ProcessLine("myobj->Go()"), который может выполнять интерпретируемую функцию MyObj::Go(). Переход цепочки вызовов от интерпретируемого к компилируемому коду происходит через заглушки; CINT хранит указатель на функцию-заглушку для каждой функции, которую можно вызвать из интерпретатора.

2.6.1. Варианты использования интерпретатора

Хотя варианты использования интерпретаторов практически не ограничены, уже есть несколько ключевых примеров использования в контексте ROOT. Графический пользовательский интерфейс реализует механизм слота сигнала через интерпретатор: сигнал выдается в виде строк, интерпретируемых интерпретатором, которые оцениваются динамически. Это позволяет использовать мощные выражения и слабую связь между вызывающим и вызываемым, поскольку вызываемую функцию не нужно разрешать во время компоновки. OOT даже полагается на CINT для некоторых частей инфраструктуры ввода-вывода: интерпретатор позволяет ROOT вызывать вспомогательную функцию для объекта, зная только его адрес в памяти и имя типа. Это тоже идеальный вариант использования интерпретатора.

2.6.2. Автоматические сборки библиотек

Интерпретация кода всегда медленнее, чем скомпилированный код. Таким образом, после разработки кода его следует «переместить в скомпилированный мир», и переход кода должен быть плавным. Но это не так: код нужно скомпилировать, слинковать и загрузить. Платформа сериализации ROOT и интерпретатор требуют дополнительного шага сборки. ROOT полностью устраняет это препятствие, полностью скрывая сложность от пользователя. Чтобы загрузить исходный файл myCode.cxx в интерпретатор, обычно вызывали

.L мой код.cxx

Затем функции и типы этого файла доступны для интерпретации. Чтобы вместо этого загрузить файл как разделяемую библиотеку и, при необходимости, создать его на лету, пользователи вводят следующую команду:

.L мой код.cxx+

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

2.7. Параллельная обработка с использованием PROOF

Средство Parallel ROOT, PROOF [25], представляет собой расширение ROOT, позволяющее проводить интерактивный анализ больших наборов файлов ROOT параллельно на кластерах компьютеров или многоядерных машинах. В более общем плане PROOF может распараллелить класс задач, решения для которых можно сформулировать как набор независимых подзадач (неудобно или идеально параллельных).

Основными целями разработки системы PROOF являются:

• Прозрачность: должно быть как можно меньше различий между локальным сеансом анализа на основе ROOT и удаленным параллельным сеансом PROOF. Обычно макросы анализа должны работать без изменений.

• Масштабируемость: базовая архитектура не должна налагать неявных ограничений на количество компьютеров, которые можно использовать параллельно.

• Адаптивность: система должна быть способна адаптироваться к изменениям в удаленной среде (изменение нагрузки на узлы кластера, сбои в сети и т. д.).

PROOF в первую очередь предназначен для использования в качестве альтернативы периодическим системам для центральных аналитических центров и ведомственных рабочих групп (уровня 2 и уровня 3 [26]) в экспериментах по физике элементарных частиц. Однако благодаря многоуровневой архитектуре, допускающей несколько уровней мастеров, его можно легко адаптировать к широкому спектру виртуальных кластеров, распределенных по географически разделенным доменам и гетерогенным машинам (GRID).

2.7.1. ДОКАЗАТЕЛЬНАЯ архитектура

Система PROOF реализована с использованием многоуровневой архитектуры. Клиент — это пользователь, который хочет использовать ресурсы для выполнения задачи. Мастер — это точка входа в вычислительный комплекс: он анализирует клиентские запросы, распределяет работу между рабочими, собирает и объединяет результаты. Основной уровень может быть многоуровневым. Это позволяет, например, объединять географически разделенные кластеры, оптимизируя доступ к вспомогательным ресурсам, таким как системы хранения данных (MSS). Это также позволяет распределять работу по распределению и слиянию, которая в противном случае могла бы стать узким местом в случае многих работников. PROOF-Lite, версия PROOF, предназначенная для многоядерных рабочих столов, реализует двухуровневую архитектуру, в которой мастер объединен с клиентом, а последний находится под непосредственным контролем рабочих.

2.7.2. Параллелизм на уровне событий

Одна из идей, лежащих в основе PROOF, состоит в том, чтобы свести к минимуму время выполнения за счет того, что все задействованные работники одновременно завершают назначенные им задачи. Это достигается за счет использования мелкозернистого распределения работы, при котором объем работы, назначенный работнику, динамически адаптируется в соответствии с производительностью каждого работника в реальном времени. В принципе, пакет может быть таким же маленьким, как основная единица — событие.

2.7.3. Пакетайзер

Пакетизатор отвечает за балансировку нагрузки задания между назначенными ему работниками. Он решает, где должна быть обработана каждая часть работы, называемая пакетом. Экземпляр пакетизатора создается на главном узле. В случае конфигурации с несколькими мастерами для каждого субмастера создается один пакетизатор. Производительность рабочих может значительно различаться, как и скорость передачи файловых данных (локальные или удаленные файлы). Чтобы динамически сбалансировать распределение работы, PROOF использует «архитектуру вытягивания»: когда рабочие процессы готовы к дальнейшей обработке, они запрашивают у пакетизатора следующий пакет. Пакетизатор использует скорость обработки рабочего процесса, чтобы определить размер следующего пакета для этого рабочего процесса. Пакетизатор пытается определить размер всех пакетов таким образом, чтобы все рабочие процессы завершались примерно в одно и то же время. В начале запроса пакеты будут небольшими, чтобы быстро получить представление о производительности воркеров. Затем размер пакета будет увеличен, чтобы обеспечить оптимальные шаблоны доступа к диску (избегая небольших чтений) и наилучшим образом удовлетворить производительность процессора рабочих.

2.7.4. Структура селектора

Чтобы иметь возможность выполнять параллелизм на уровне событий, PROOF должен отвечать за цикл событий, то есть поток выполнения, управляющий заданием. Это требует, чтобы исполняемый код имел предопределенную, хотя и гибкую структуру. В ROOT это обеспечивается платформой Selector, определенной абстрактным классом TSelector, который определяет три логических шага:

(1) Начало, где дано определение задания (параметры, входные данные, выходы); выполняется на клиенте и рабочих;

(2) Процесс, в котором выполняется фактическая работа; призывал к каждому событию, к рабочим;

(3) завершение, когда результаты окончательно обрабатываются (подгоняются, визуализируются и т. д.); вызвал клиента и рабочих. Процесс — это та часть, которую можно распараллелить для класса задач, решаемых PROOF.

2.7.5. Совокупность результатов

PROOF имеет мощную функцию, дополняющую использование TSelector framework. После того, как каждый рабочий процесс выполнил описанный выше метод Terminate, он отправляет набор именованных результатов обратно своему мастеру. Мастер собирает эти промежуточные результаты и агрегирует их в зависимости от их типа. Для нескольких распространенных типов, таких как, например, гистограммы, существует естественный способ объединения этих результатов. Гистограмма, полученная путем сложения всех промежуточных гистограмм, идентична той, которая была бы получена в результате обработки всех событий одним рабочим процессом. Точно так же списки событий могут быть агрегированы и т. д. PROOF использует четко определенный API для этого процесса, позволяющий определенным пользователем классам использовать эту функцию. Промежуточные результаты, которые нельзя объединить, возвращаются «как есть» в единой коллекции для каждого результирующего объекта.

2.7.6. Мониторинг в реальном времени и обратная связь

Пользователь может отслеживать ход выполнения запроса или задания PROOF различными способами. Виджет показывает количество обработанных событий и файлов, процент завершения и расчетное время до завершения. Эта обратная связь полезна для получения общего представления о поведении и производительности системы PROOF и ее базовых компонентов.

Если пользователь зарегистрировал гистограммы в методе Begin класса TSelector, PROOF может отображать эти гистограммы, динамически обновляемые во время выполнения запроса. Эта функция позволяет детально отслеживать ход выполнения запроса, особенно если обрабатывается очень большой набор данных. Динамически обновляемый дисплей также очень эффективен в образовательных и демонстрационных целях.

3. Инструкции по установке

ROOT можно собрать из исходного кода на всех поддерживаемых платформах, используя хорошо известные инструменты с открытым исходным кодом, такие как Subversion, configure и make.

3.1. Получение источника

Исходный ROOT-архив распространяется Программной библиотекой CPC как aefa_v1_0.tar.gz. Распакуйте файл tar и извлеките его содержимое, например. с помощью команд UNIX,

gzip -dc aefa.tar.gz | смола -xf-

3.2. Компиляция

Компиляция ROOT — это всего лишь вопрос:

$ ./настроить

$ сделать

Сценарий ./configure обнаружит платформу и проверит наличие сторонних библиотек, необходимых для ряда дополнительных плагинов. Чтобы увидеть все доступные варианты, выполните:

$ ./настроить -помощь

Полное описание процедуры сборки см. на веб-сайте ROOT.

4. Описание тестового прогона

После установки ROOT можно найти большой набор тестовых программ в учебниках и тестовых каталогах. Все тестовые программы в каталоге tutorials представлены в виде макросов, которые можно запускать через интерпретатор CINT или компилировать через ACLiC. Стандартный тестовый макрос — Benchets.C, который можно запустить с помощью:

$ компакт-диск учебники

$ корень

корень [0] .x тесты.C

корень [1].q

Если ROOT установлен правильно, этот макрос должен завершиться без ошибок и сообщить число ROOTMARKS:

****************************************************

* Ваша машина оценена в 1120.18 ROOTMARKS *

****************************************************

Все программы в тестовом каталоге являются автономными программами, которые создаются с помощью команды make, например:

$ компакт-диск тест

$ сделать

Это скомпилирует ряд «демонстрационных» программ, таких как guitest, threads и т. д., и «стрессовых» программ, например, stress, stressGeometry, stressGraphics и т. д. Все «стрессовые» программы также вернут число ROOTMARKS производительности, например:

$ ./стресс -b 30

****************************************************

* КОРЕНЬ************************************************