LXF83:ROOT
Heeppy (обсуждение | вклад) |
Yaleks (обсуждение | вклад) м (оформление) |
||
(не показаны 6 промежуточных версий 4 участников) | |||
Строка 1: | Строка 1: | ||
+ | {{Цикл/PAW ROOT}} | ||
+ | |||
== Продолжая традиции: ROOT == | == Продолжая традиции: ROOT == | ||
'' '''Часть 3''' Данные мало получить – надо ещё понять, а есть ли от них польза. '''Евгений Балдин''' представляет вашему вниманию «новинку» среди приложений для анализа данных.'' | '' '''Часть 3''' Данные мало получить – надо ещё понять, а есть ли от них польза. '''Евгений Балдин''' представляет вашему вниманию «новинку» среди приложений для анализа данных.'' | ||
Строка 4: | Строка 6: | ||
Даже если данных много – их надо как-то проанализировать. Это может сделать только человек. Компьютер в этом деле только помощник. Выбор инструмента очень важен. ROOT – хороший инструмент. У него был достойный предок и он мог бы быть гораздо лучше. Но здесь и сейчас надо анализировать данные, фиксируя недостатки, дабы исправить их в будущем. Это возможно, потому что ROOT – это свободный продукт. | Даже если данных много – их надо как-то проанализировать. Это может сделать только человек. Компьютер в этом деле только помощник. Выбор инструмента очень важен. ROOT – хороший инструмент. У него был достойный предок и он мог бы быть гораздо лучше. Но здесь и сейчас надо анализировать данные, фиксируя недостатки, дабы исправить их в будущем. Это возможно, потому что ROOT – это свободный продукт. | ||
− | Примерно через десять лет после возникновения команде PAW (Physics Analysis Workstation) стало скучно, и ее лидер PAW Рене Брюн (Ren Brun) сотоварищи начал новый проект ROOT – | + | Примерно через десять лет после возникновения команде PAW (Physics Analysis Workstation) стало скучно, и ее лидер PAW Рене Брюн (Ren Brun) сотоварищи начал новый проект ROOT – An Object Oriented Data Analysis Framework <ref>Почему ROOT так называется? У меня есть только догадки: OO — видимо, Object Oriented, а сам ROOT от английского «корень» или «источник» (root). Предполагается, что ROOT — это база для разработок, а не просто система анализа, то есть корень всех …</ref>. |
− | Компьютеры стали много мощнее, но и поток данных увеличился. ROOT стал разрабатываться в рамках эксперимента NA49, где поток данных за один заход мог превышает <ref> | + | Компьютеры стали много мощнее, но и поток данных увеличился. ROOT стал разрабатываться в рамках эксперимента NA49, где поток данных за один заход мог превышает 10 Тб <ref>Таких заходов было чуть меньше 5 тысяч. Грубо, <math>1</math>Тб=<math>10^3</math>Гб=<math>10^6</math>Мб.</ref>. |
С начала 2006 года ROOT ([http://root.cern.ch/ http://root.cern.ch/]) стал выпускаться под лицензией GNU, и, возможно, скоро попадёт во все основные дис трибутивы GNU/Linux. | С начала 2006 года ROOT ([http://root.cern.ch/ http://root.cern.ch/]) стал выпускаться под лицензией GNU, и, возможно, скоро попадёт во все основные дис трибутивы GNU/Linux. | ||
Строка 15: | Строка 17: | ||
Почему PAW? Если в вашем проекте PAW уже используется, особых причин для смены инструмента нет. Для стандартных операций анализа ROOT использовать значительно сложнее, чем PAW. Это плата за попытку объять необъятное. | Почему PAW? Если в вашем проекте PAW уже используется, особых причин для смены инструмента нет. Для стандартных операций анализа ROOT использовать значительно сложнее, чем PAW. Это плата за попытку объять необъятное. | ||
− | <ref> | + | Почему ROOT? <ref>Я слышал такой вариант ответа: «потому что, в отличие от PAW, в графическом окне ROOT можно мышкой подправить экспериментальные данные» – очень надеюсь, что это была шутка.</ref> С++ популярнее FORTRAN и KUIP. С++ привычнее и с его помощью проще решать задачи, которые являются вспомогательными к анализу – для всего используется один инструмент. ROOT активно поддерживается и развивается. У ROOT есть довольно мощное сообщество. На сайте [http://root.cern.ch http://root.cern.ch] можно найти ответ почти на все вопросы, касающиеся пакета, в RootTalk (там же) можно задать вопрос любой сложности, на который вам с очень большой вероятностью ответят. |
<center>'''Сравнение PAW и ROOT (IMHO)'''</center> | <center>'''Сравнение PAW и ROOT (IMHO)'''</center> | ||
Строка 73: | Строка 75: | ||
=== Запускаем ROOT === | === Запускаем ROOT === | ||
− | [[Изображение: | + | [[Изображение:Img 83 92 1.png|thumb|200px|ROOT в действии – демонстрация.]] |
Так как ROOT получил лицензию LGPL совсем недавно, то, скорее всего, в вашем настольном дистрибутиве его нет. Поэтому запуск придётся отложить «на потом» после сборки и установки. | Так как ROOT получил лицензию LGPL совсем недавно, то, скорее всего, в вашем настольном дистрибутиве его нет. Поэтому запуск придётся отложить «на потом» после сборки и установки. | ||
Строка 117: | Строка 119: | ||
</pre> | </pre> | ||
− | Получив приглашение, можно приступать к работе. Сказать | + | Получив приглашение, можно приступать к работе. Сказать "Hello World" из ROOT можно следующим образом: |
− | root [0] cout << | + | root [0] cout << "Hello World" << endl; |
Hello World | Hello World | ||
− | При запуске ROOT считывается файл настроек .rootrc сначала в текущей директории, а, если здесь его нет, то в домашней; затем берётся системный файл /etc/root/system.rootrc. От версии к версии эта последовательность может <ref> | + | При запуске ROOT считывается файл настроек .rootrc сначала в текущей директории, а, если здесь его нет, то в домашней; затем берётся системный файл /etc/root/system.rootrc. От версии к версии эта последовательность может меняться <ref>В руководстве пользователя в этом месте присутствуют ошибки.</ref>. |
По умолчанию есть ещё три файла, которые могут управлять поведением программы: | По умолчанию есть ещё три файла, которые могут управлять поведением программы: | ||
Строка 133: | Строка 135: | ||
Выйти из ROOT можно с помощью команды .q. Если в процессе анализа удалось зациклить программу, то желание выйти можно усилить с | Выйти из ROOT можно с помощью команды .q. Если в процессе анализа удалось зациклить программу, то желание выйти можно усилить с | ||
− | помощью команд .qqq, .qqqqq или <ref>. | + | помощью команд .qqq, .qqqqq или .qqqqqqq <ref>Чем больше q, тем «сильнее» желание.</ref>. ^C так же может помочь в непредвиденных ситуациях. |
=== «Командная логика» === | === «Командная логика» === | ||
Строка 139: | Строка 141: | ||
root [0] { | root [0] { | ||
− | end with | + | end with '}', '@':abort > int a=0,b=1; |
− | end with | + | end with '}', '@':abort > cout << a << " " << b << " "; |
− | end with | + | end with '}', '@':abort > for (int i=2;i<=10;i++) { |
− | end with | + | end with '}', '@':abort > int x=a; a=b; b=x+b; |
− | end with | + | end with '}', '@':abort > cout << b << " "; |
− | end with | + | end with '}', '@':abort > } |
− | end with | + | end with '}', '@':abort > cout << endl; |
− | end with | + | end with '}', '@':abort > } |
0 1 1 2 3 5 8 13 21 34 55 | 0 1 1 2 3 5 8 13 21 34 55 | ||
Строка 172: | Строка 174: | ||
Все необходимые для анализа объекты представлены в виде классов. Класс TFile соответствует файлу, в который можно сохранять ROOT-структуры. Объект TTree представляет из себя более изощрённую реализацию идеи ntuple: | Все необходимые для анализа объекты представлены в виде классов. Класс TFile соответствует файлу, в который можно сохранять ROOT-структуры. Объект TTree представляет из себя более изощрённую реализацию идеи ntuple: | ||
− | root [6] TFile *f=new TFile( | + | root [6] TFile *f=new TFile("ee-ang.root") |
root [7] TTree *tree; | root [7] TTree *tree; | ||
− | root [8] tree= (TTree *) f->Get( | + | root [8] tree= (TTree *) f->Get("h1"); |
root [9] tree->Draw(«TAB» | root [9] tree->Draw(«TAB» | ||
void Draw(Option_t* opt) | void Draw(Option_t* opt) | ||
Long64_t Draw(const char* varexp, const TCut& selection, Option_t* | Long64_t Draw(const char* varexp, const TCut& selection, Option_t* | ||
− | option = | + | option = "", Long64_t nentries = 1000000000, Long64_t firstentry = 0) |
Long64_t Draw(const char* varexp, const char* selection, Option_t* | Long64_t Draw(const char* varexp, const char* selection, Option_t* | ||
− | option = | + | option = "", Long64_t nentries = 1000000000, Long64_t firstentry = 0) |
− | root [10] tree->Draw( | + | root [10] tree->Draw("E1","E1<2.&&f1==-11&&f2==11") |
В строке [9] после скобки была нажата клавиша Tab, что привело к выводу подсказки по возможным командам. Отсутствие команды help восполняется автоматически создаваемой подсказкой. | В строке [9] после скобки была нажата клавиша Tab, что привело к выводу подсказки по возможным командам. Отсутствие команды help восполняется автоматически создаваемой подсказкой. | ||
Строка 187: | Строка 189: | ||
=== Графический интерфейс === | === Графический интерфейс === | ||
− | [[Изображение: | + | [[Изображение:Img 83 93 1.png|thumb|200px|Пример графического представления гистограммы (канва E1).]] |
Графическое окно в ROOT называется «канвой» (объект TCanvas). Можно открыть сколько угодно таких окон: | Графическое окно в ROOT называется «канвой» (объект TCanvas). Можно открыть сколько угодно таких окон: | ||
Строка 193: | Строка 195: | ||
<pre> | <pre> | ||
//Создаём новую канву E1. | //Создаём новую канву E1. | ||
− | root [11] TCanvas *E1=new TCanvas( | + | root [11] TCanvas *E1=new TCanvas("E1") |
//Создаём новую канву cfunc. | //Создаём новую канву cfunc. | ||
− | root [12] TCanvas *cfunc=new TCanvas( | + | root [12] TCanvas *cfunc=new TCanvas("func") |
//Переходим в канву E1. | //Переходим в канву E1. | ||
root [13] E1->cd(); | root [13] E1->cd(); | ||
//Рисуем гистограмму по параметру E1 с условием. | //Рисуем гистограмму по параметру E1 с условием. | ||
− | root [14] tree->Draw( | + | root [14] tree->Draw("E1","E1<2.&&f1==-11&&f2==11") |
//Переходим в канву cfunc. | //Переходим в канву cfunc. | ||
root [15] cfunc->cd() | root [15] cfunc->cd() | ||
Строка 205: | Строка 207: | ||
root [16] cfunc->Divide(1,2) | root [16] cfunc->Divide(1,2) | ||
//Создаём функцию. | //Создаём функцию. | ||
− | root [17] TF1 f1( | + | root [17] TF1 f1("difr","0.1+(sin(x)/x)**2",-10,10) |
//Переходим в верхнюю половину канвы cfunc. | //Переходим в верхнюю половину канвы cfunc. | ||
root [18] cfunc->cd(1) | root [18] cfunc->cd(1) | ||
Строка 217: | Строка 219: | ||
root [22] cfunc->cd(2)->SetLogy() | root [22] cfunc->cd(2)->SetLogy() | ||
//Из канвы cfunc создаём векторный eps-файл. | //Из канвы cfunc создаём векторный eps-файл. | ||
− | root [23] cfunc->Print( | + | root [23] cfunc->Print("root-cfunc.eps") |
//Из канвы E1 создаём растровый png-файл. | //Из канвы E1 создаём растровый png-файл. | ||
− | root [24] E1->Print( | + | root [24] E1->Print("root-E1.png") |
</pre> | </pre> | ||
− | [[Изображение: | + | [[Изображение:Img 83 93 2.png|thumb||200pxПример графического представления функции (канва cfunc).]] |
В отличие от своего предка PAW, ROOT позволяет интерактивно менять параметры картинки с помощью выпадающих меню. Тип меню зависит от того, на какой объект направлен указатель мыши. Также с помощью левой кнопки можно интерактивно изменять масштаб графика. Для возврата в исходное состояние в меню, относящемся к выбранной оси, следует выбрать команду UnZoom. | В отличие от своего предка PAW, ROOT позволяет интерактивно менять параметры картинки с помощью выпадающих меню. Тип меню зависит от того, на какой объект направлен указатель мыши. Также с помощью левой кнопки можно интерактивно изменять масштаб графика. Для возврата в исходное состояние в меню, относящемся к выбранной оси, следует выбрать команду UnZoom. | ||
Строка 233: | Строка 235: | ||
=== Гистограммы === | === Гистограммы === | ||
− | [[Изображение: | + | [[Изображение:Img 83 93 3.png|thumb|200px|Пример подогнанной гистограммы.]] |
Гистограмма является одним из основных объектов анализа. По сравнению с PAW, в ROOT было добавлено больше типов гистограмм. Конструктор гистограмм имеет вид TH1F. Для двумерной гистограммы вместо 1 надо подставить 2, а для трёхмерной (да, такие тоже есть, правда, непонятно, как их смотреть) – 3. F означает, что на один бин используется Float_t, аналогично возможны и другие типы переменных для хранения значения в бине. | Гистограмма является одним из основных объектов анализа. По сравнению с PAW, в ROOT было добавлено больше типов гистограмм. Конструктор гистограмм имеет вид TH1F. Для двумерной гистограммы вместо 1 надо подставить 2, а для трёхмерной (да, такие тоже есть, правда, непонятно, как их смотреть) – 3. F означает, что на один бин используется Float_t, аналогично возможны и другие типы переменных для хранения значения в бине. | ||
Строка 239: | Строка 241: | ||
<pre> | <pre> | ||
//Создаём новую канву. | //Создаём новую канву. | ||
− | root [25] TCanvas *ch=new TCanvas( | + | root [25] TCanvas *ch=new TCanvas("Hist Test","Hist") |
//Создаём гистограмму в 100 бинов от -3. до 3. | //Создаём гистограмму в 100 бинов от -3. до 3. | ||
− | root [26] TH1F *h = new TH1F( | + | root [26] TH1F *h = new TH1F("h","Hist Test",100,-3.,3.) |
//Обычно гистограммы заполняются с помощью метода Fill. | //Обычно гистограммы заполняются с помощью метода Fill. | ||
root [27] h->Fill(«TAB» | root [27] h->Fill(«TAB» | ||
Строка 249: | Строка 251: | ||
//Но мы сейчас идём другим путём: | //Но мы сейчас идём другим путём: | ||
// а) создаём функцию G, | // а) создаём функцию G, | ||
− | root [28] TF1 *func = new TF1( | + | root [28] TF1 *func = new TF1("G","exp(-x**2)",-3,3) |
// б) заполняем гистограмму случайным образом | // б) заполняем гистограмму случайным образом | ||
// по форме функции G. | // по форме функции G. | ||
− | root [29] h->FillRandom( | + | root [29] h->FillRandom("G",1000) |
//Меняем цвет гистограммы. | //Меняем цвет гистограммы. | ||
root [30] h->SetFillColor(45) | root [30] h->SetFillColor(45) | ||
//Подгоняем гистограмму распределением Гаусса | //Подгоняем гистограмму распределением Гаусса | ||
− | root [31] h->Fit( | + | root [31] h->Fit("gaus") |
… | … | ||
//Сохраняем полученную картинку. | //Сохраняем полученную картинку. | ||
− | root [32] ch->Print( | + | root [32] ch->Print("root-histexample.eps") |
</pre> | </pre> | ||
Строка 266: | Строка 268: | ||
=== Деревья === | === Деревья === | ||
− | [[Изображение: | + | [[Изображение:Img 83 94 1.png|thumb|200px|Графическое представление дерева lkravg. Видно, что красные точки в среднем ниже чёрных, что и требовалось доказать.]] |
Деревья (tree) в ROOT – это логичное развитие идеи ntuple. ntuple, по сути дела, был таблицей со столбцами переменных типа float. В случае деревьев этого ограничения не существует, и в дереве можно сохранять любые объекты. | Деревья (tree) в ROOT – это логичное развитие идеи ntuple. ntuple, по сути дела, был таблицей со столбцами переменных типа float. В случае деревьев этого ограничения не существует, и в дереве можно сохранять любые объекты. | ||
Строка 272: | Строка 274: | ||
<pre> | <pre> | ||
//Создаём файл на диске. | //Создаём файл на диске. | ||
− | root [33] TFile *f = new TFile( | + | root [33] TFile *f = new TFile("lkravg.root","RECREATE") |
//Заводим новое дерево | //Заводим новое дерево | ||
− | root [34] TTree *lkravg = new TTree( | + | root [34] TTree *lkravg = new TTree("lkravg","LKr degrad") |
− | //Считаем файл lkravg.dat - тот самый, что | + | //Считаем файл lkravg.dat - тот самый, что "мучили" в |
//статье про PAW | //статье про PAW | ||
− | root [35] Long64_t nlines = lkravg->ReadFile( | + | root [35] Long64_t nlines = lkravg->ReadFile("lkravg.dat", |
//список переменных | //список переменных | ||
− | + | "time:run:avg:avg_er:P:H") | |
− | root [36] cout << | + | root [36] cout << "Number of lines: " << nlines << endl |
//Рисуем картинку: чёрные маркеры - есть магнитное поле, | //Рисуем картинку: чёрные маркеры - есть магнитное поле, | ||
//красные маркеры - нет магнитного поля. | //красные маркеры - нет магнитного поля. | ||
root [37] lkravg->SetMarkerStyle(5) | root [37] lkravg->SetMarkerStyle(5) | ||
− | root [38] lkravg->Draw( | + | root [38] lkravg->Draw("avg:time","H>0.1") |
root [39] lkravg->SetMarkerColor(kRed) | root [39] lkravg->SetMarkerColor(kRed) | ||
− | root [40] lkravg->Draw( | + | root [40] lkravg->Draw("avg:time","H<=0.1","same") |
//Пишем дерево в файл и закрываем файл. | //Пишем дерево в файл и закрываем файл. | ||
root [41] lkravg->Write(); | root [41] lkravg->Write(); | ||
root [42] f->Close(); | root [42] f->Close(); | ||
//Теперь этот файл можно открыть | //Теперь этот файл можно открыть | ||
− | root [43] TFile *f2 = new TFile( | + | root [43] TFile *f2 = new TFile("lkravg2.root") |
//и посмотреть что в нём есть - дерево сохранилось. | //и посмотреть что в нём есть - дерево сохранилось. | ||
root [44] .ls | root [44] .ls | ||
Строка 303: | Строка 305: | ||
=== Функции === | === Функции === | ||
− | [[Изображение: | + | [[Изображение:Img 83 94 2.png|thumb|200px|Примеры графического представления двумерной функции или гистограммы. Множество Мандельброта.]] |
Как и в PAW, в ROOT есть мощная поддержка функций как объектов. С помощью метода Fit можно подогнать гистограмму или график. Но до этого следует определить функцию, например, так: | Как и в PAW, в ROOT есть мощная поддержка функций как объектов. С помощью метода Fit можно подогнать гистограмму или график. Но до этого следует определить функцию, например, так: | ||
Строка 330: | Строка 332: | ||
//Теперь можно обращаться к функции. | //Теперь можно обращаться к функции. | ||
root [45] .L mandel.cxx | root [45] .L mandel.cxx | ||
− | root [46] TCanvas *cm=new TCanvas( | + | root [46] TCanvas *cm=new TCanvas("mandelbrot","Mandelbrot") |
//Создаём объект «двумерная функция» TF2 | //Создаём объект «двумерная функция» TF2 | ||
root [47] TF2 *Mandelbrot=new | root [47] TF2 *Mandelbrot=new | ||
− | TF2( | + | TF2("Mandelbrot",mandel,-2.4,.8,-1.2,1.2,0) |
root [48] cm->Divide(2,2) | root [48] cm->Divide(2,2) | ||
root [49] cm->cd(1) | root [49] cm->cd(1) | ||
Строка 343: | Строка 345: | ||
root [52] Mandelbrot->SetNpy(200) | root [52] Mandelbrot->SetNpy(200) | ||
//Контурное графическое представление. | //Контурное графическое представление. | ||
− | root [53] Mandelbrot->Draw( | + | root [53] Mandelbrot->Draw("cont") |
root [54] cm->cd(2) | root [54] cm->cd(2) | ||
//Графическое представление в виде поверхность. | //Графическое представление в виде поверхность. | ||
− | root [55] Mandelbrot->Draw( | + | root [55] Mandelbrot->Draw("surf2") |
root [56] cm->cd(3) | root [56] cm->cd(3) | ||
//Множество Мандельброта в цилиндрических координатах. | //Множество Мандельброта в цилиндрических координатах. | ||
− | root [57] Mandelbrot->Draw( | + | root [57] Mandelbrot->Draw("surf4cyl") |
root [58] cm->cd(4) | root [58] cm->cd(4) | ||
//Графическое представление в стиле LEGO. | //Графическое представление в стиле LEGO. | ||
− | root [59] Mandelbrot->Draw( | + | root [59] Mandelbrot->Draw("lego") |
− | root [60] cm->Print( | + | root [60] cm->Print("root-mandel.eps") |
</pre> | </pre> | ||
Строка 375: | Строка 377: | ||
/*Файл myfile.h*/ | /*Файл myfile.h*/ | ||
#ifdef __cplusplus | #ifdef __cplusplus | ||
− | extern | + | extern "C" { |
#endif | #endif | ||
extern void myfunc1(); | extern void myfunc1(); | ||
Строка 404: | Строка 406: | ||
> gcc -c -fPIC myfile.c | > gcc -c -fPIC myfile.c | ||
# Компилируем словарик. | # Компилируем словарик. | ||
− | > g++ -c -fPIC | + | > g++ -c -fPIC 'root-config --cflags' myfileDict.cxx |
# Создаём разделяемую библиотеку. | # Создаём разделяемую библиотеку. | ||
> g++ -shared -o myfile.so myfile.o myfileDict.o | > g++ -shared -o myfile.so myfile.o myfileDict.o | ||
Строка 411: | Строка 413: | ||
Теперь эту вновь созданную библиотеку можно загрузить в ROOT для интерактивной работы: | Теперь эту вновь созданную библиотеку можно загрузить в ROOT для интерактивной работы: | ||
− | root [68] gSystem->Load( | + | root [68] gSystem->Load("myfile") |
root [69] myfunc1() | root [69] myfunc1() | ||
− | root [70] Int_t icount=myfunc2( | + | root [70] Int_t icount=myfunc2("string") |
Это далеко не единственный способ подключить пользовательскую библиотеку к ROOT. Для компиляции скриптов можно использовать подсистему ACLiC. | Это далеко не единственный способ подключить пользовательскую библиотеку к ROOT. Для компиляции скриптов можно использовать подсистему ACLiC. | ||
Строка 424: | Строка 426: | ||
ROOT – не просто инструмент анализа; это среда для генерации таких инструментов. Он, возможно, неповоротлив и избыточен, но гибок и очень легко расширяем. Это не идеал, но идеал, скорее всего, будет на него похож. | ROOT – не просто инструмент анализа; это среда для генерации таких инструментов. Он, возможно, неповоротлив и избыточен, но гибок и очень легко расширяем. Это не идеал, но идеал, скорее всего, будет на него похож. | ||
+ | === Примечения === | ||
<references /> | <references /> | ||
+ | |||
+ | [[Категория:ROOT]] |
Текущая версия на 12:04, 6 января 2009
|
|
|
- Метамодернизм в позднем творчестве В.Г. Сорокина
- ЛитРПГ - последняя отрыжка постмодерна
- "Ричард III и семиотика"
- 3D-визуализация обложки Ridero создаем обложку книги при работе над самиздатом.
- Архитектура метамодерна - говоря о современном искусстве, невозможно не поговорить об архитектуре. В данной статье будет отмечено несколько интересных принципов, характерных для построек "новой волны", столь притягательных и скандальных.
- Литература
- Метамодерн
- Рокер-Прометей против изначального зла в «Песне про советскую милицию» Вени Дркина, Автор: Нина Ищенко, к.ф.н, член Союза Писателей ЛНР - перепубликация из журнала "Топос".
- Как избавиться от комаров? Лучшие типы ловушек.
- Что делать если роблокс вылетает на windows
- Что делать, если ребенок смотрит порно?
- Почему собака прыгает на людей при встрече?
- Какое масло лить в Задний дифференциал (мост) Visco diff 38434AA050
- О чем может рассказать хвост вашей кошки?
- Верветки
- Отчетность бюджетных учреждений при закупках по Закону № 223-ФЗ
- Срок исковой давности как правильно рассчитать
- Дмитрий Патрушев минсельхоз будет ли преемником Путина
- Кто такой Владислав Поздняков? Что такое "Мужское Государство" и почему его признали экстремистским в России?
- Как правильно выбрать машинное масло в Димитровграде?
- Как стать богатым и знаменитым в России?
- Почему фильм "Пипец" (Kick-Ass) стал популярен по всему миру?
- Как стать мудрецом?
- Как правильно установить FreeBSD
- Как стать таким как Путин?
- Где лучше жить - в Димитровграде или в Ульяновске?
- Почему город Димитровград так называется?
- Что такое метамодерн?
- ВАЖНО! Временное ограничение движения автотранспортных средств в Димитровграде
- Тарифы на электроэнергию для майнеров предложено повысить
Содержание |
[править] Продолжая традиции: ROOT
Часть 3 Данные мало получить – надо ещё понять, а есть ли от них польза. Евгений Балдин представляет вашему вниманию «новинку» среди приложений для анализа данных.
Даже если данных много – их надо как-то проанализировать. Это может сделать только человек. Компьютер в этом деле только помощник. Выбор инструмента очень важен. ROOT – хороший инструмент. У него был достойный предок и он мог бы быть гораздо лучше. Но здесь и сейчас надо анализировать данные, фиксируя недостатки, дабы исправить их в будущем. Это возможно, потому что ROOT – это свободный продукт.
Примерно через десять лет после возникновения команде PAW (Physics Analysis Workstation) стало скучно, и ее лидер PAW Рене Брюн (Ren Brun) сотоварищи начал новый проект ROOT – An Object Oriented Data Analysis Framework [1].
Компьютеры стали много мощнее, но и поток данных увеличился. ROOT стал разрабатываться в рамках эксперимента NA49, где поток данных за один заход мог превышает 10 Тб [2].
С начала 2006 года ROOT (http://root.cern.ch/) стал выпускаться под лицензией GNU, и, возможно, скоро попадёт во все основные дис трибутивы GNU/Linux.
[править] Сравнение с PAW
PAW является предком ROOT, если уж не в смысле кода, то уж в смысле реализации идей точно. Поэтому полезно понять, чем эти пакеты отличаются и в чём совпадают. Сравнительная таблица не претендует на фундаментальность, а просто отражает личные пристрастия автора.
Почему PAW? Если в вашем проекте PAW уже используется, особых причин для смены инструмента нет. Для стандартных операций анализа ROOT использовать значительно сложнее, чем PAW. Это плата за попытку объять необъятное.
Почему ROOT? [3] С++ популярнее FORTRAN и KUIP. С++ привычнее и с его помощью проще решать задачи, которые являются вспомогательными к анализу – для всего используется один инструмент. ROOT активно поддерживается и развивается. У ROOT есть довольно мощное сообщество. На сайте http://root.cern.ch можно найти ответ почти на все вопросы, касающиеся пакета, в RootTalk (там же) можно задать вопрос любой сложности, на который вам с очень большой вероятностью ответят.
Признак | PAW | ROOT |
---|---|---|
Авторы | Рене Брюн и др. | Рене Брюн и др. |
Возраст | 20 лет | Чуть больше 10 лет |
GNU | Начиная с 2000 года | С начала 2006 года |
Интерпретатор | FORTRAN (COMIS) | C++ (CINT) |
Командный процессор | KUIP | C++ (CINT) |
Ускорение набора команд | Сокращение | TAB-completion |
Кириллица? | Никак | Аналогично |
Состояние | Матёрая, но немного устаревшая система | Надо повзрослеть, пора бы уже |
Система помощи | Подробная официальная документация в
почти 500 страниц, help в командной строке |
Пухлое руководство пользователя,
автодокументация по исходным текстам, но нет help. |
Что бы сказал Брукс? | Старая школа | Все признаки «второй системы» |
Что есть? | То, что нужно для анализа данных | То же, плюс много чего ещё лишнего и не очень |
[править] Запускаем ROOT
Так как ROOT получил лицензию LGPL совсем недавно, то, скорее всего, в вашем настольном дистрибутиве его нет. Поэтому запуск придётся отложить «на потом» после сборки и установки.
Брать исходные тексты лучше всего с основного сайта: http://root.cern.ch. После распаковки дерева пакетов следует внимательно изучить инструкцию README/INSTALL. Сборка стандартная:
> ./configure --prefix=/usr/local ; make ; make install
make install необходимо делать от имени root.
Можно попробовать собрать rpm- или deb-пакет. Собрать deb-пакет под Debian 3.1 (Sarge) без дополнительных телодвижений не удаётся, так как отсутствует пакет, на который указывают зависимости. По-видимому, разработка ведётся для тестовой или нестабильной ветки дистрибутива.
После установки перед запуском необходимо установить переменные окружения. Для bash это будет выглядеть примерно так:
> export ROOTSYS=/usr/local/ > export PATH=$PATH:$ROOTSYS/bin > export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$ROOTSYS/lib/root
Установка LD_LIBRARY_PATH необходима из-за того, что почти весь функционал ROOT вынесен в разделяемые библиотеки, которые подгружаются во время работы программы. Аналогично можно оформить и свою библиотеку, расширив, таким образом, возможности ROOT.
Всё. Теперь открываем терминал и запускаем ROOT:
> root *********************************************************** * * * W E L C O M E to R O O T * * * * Version 5.11/02 19 April 2006 * * * * You are welcome to visit our Web site * * http://root.cern.ch * * * *********************************************************** FreeType Engine v2.1.9 used to render TrueType fonts. Compiled on 19 May 2006 for linux with thread support. CINT/ROOT C/C++ Interpreter version 5.16.11, April 14, 2006 Type ? for help. Commands must be C++ statements. Enclose multiple statements between { }. root [0]
Получив приглашение, можно приступать к работе. Сказать "Hello World" из ROOT можно следующим образом:
root [0] cout << "Hello World" << endl; Hello World
При запуске ROOT считывается файл настроек .rootrc сначала в текущей директории, а, если здесь его нет, то в домашней; затем берётся системный файл /etc/root/system.rootrc. От версии к версии эта последовательность может меняться [4].
По умолчанию есть ещё три файла, которые могут управлять поведением программы:
- rootlogon.C – выполняется при запуске,
- rootalias.C – загружается при запуске, но не выполняется,
- rootlogoff.C – выполняется при завершении сеанса.
ROOT можно запускать и не в интерактивном режиме. Для этого при запуске следует указать опцию -b. Полный список поддерживаемых опций можно получить при указании ключа -h.
Выйти из ROOT можно с помощью команды .q. Если в процессе анализа удалось зациклить программу, то желание выйти можно усилить с помощью команд .qqq, .qqqqq или .qqqqqqq [5]. ^C так же может помочь в непредвиденных ситуациях.
[править] «Командная логика»
В качестве командного процессора используется интерпретатор С++ CINT. Это означает, что интерактивная работа очень похожа на написание обычной программы. Знание языка C/C++ при «общении» с ROOT является обязательным. Как и для PAW, напишем программу по вычислению чисел Фибоначчи:
root [0] { end with '}', '@':abort > int a=0,b=1; end with '}', '@':abort > cout << a << " " << b << " "; end with '}', '@':abort > for (int i=2;i<=10;i++) { end with '}', '@':abort > int x=a; a=b; b=x+b; end with '}', '@':abort > cout << b << " "; end with '}', '@':abort > } end with '}', '@':abort > cout << endl; end with '}', '@':abort > } 0 1 1 2 3 5 8 13 21 34 55
Команды группируются с помощью фигурных скобок. Этот же код можно сохранить в файл fibonacci.cxx и выполнить его как скрипт:
root [1] .x fibonacci.cxx 0 1 1 2 3 5 8 13 21 34 55
В случае C++ окончание команды отмечается «;». Если «;» опустить, то из ROOT получится неплохой калькулятор:
root [2] 2*sqrt(5)*sin(2*3.14*75/180)/3.14**2 (const double)2.27312089125660893e-01 root [3] 2**10 (const int)1024 root [4] 2.**1023 (const double)8.98846567431157954e+307
Все вспомогательные команды ROOT начинаются с точки (.). Для выполнения команд оболочки используется команда .!, за которой следуют shell-инструкции:
root [5] .! ls *.cxx fibonacci.cxx
Полный список вспомогательных команд можно получить с помощью инструкции .?.
Все необходимые для анализа объекты представлены в виде классов. Класс TFile соответствует файлу, в который можно сохранять ROOT-структуры. Объект TTree представляет из себя более изощрённую реализацию идеи ntuple:
root [6] TFile *f=new TFile("ee-ang.root") root [7] TTree *tree; root [8] tree= (TTree *) f->Get("h1"); root [9] tree->Draw(«TAB» void Draw(Option_t* opt) Long64_t Draw(const char* varexp, const TCut& selection, Option_t* option = "", Long64_t nentries = 1000000000, Long64_t firstentry = 0) Long64_t Draw(const char* varexp, const char* selection, Option_t* option = "", Long64_t nentries = 1000000000, Long64_t firstentry = 0) root [10] tree->Draw("E1","E1<2.&&f1==-11&&f2==11")
В строке [9] после скобки была нажата клавиша Tab, что привело к выводу подсказки по возможным командам. Отсутствие команды help восполняется автоматически создаваемой подсказкой.
[править] Графический интерфейс
Графическое окно в ROOT называется «канвой» (объект TCanvas). Можно открыть сколько угодно таких окон:
//Создаём новую канву E1. root [11] TCanvas *E1=new TCanvas("E1") //Создаём новую канву cfunc. root [12] TCanvas *cfunc=new TCanvas("func") //Переходим в канву E1. root [13] E1->cd(); //Рисуем гистограмму по параметру E1 с условием. root [14] tree->Draw("E1","E1<2.&&f1==-11&&f2==11") //Переходим в канву cfunc. root [15] cfunc->cd() //Делим канву cfunc на две части по Y. root [16] cfunc->Divide(1,2) //Создаём функцию. root [17] TF1 f1("difr","0.1+(sin(x)/x)**2",-10,10) //Переходим в верхнюю половину канвы cfunc. root [18] cfunc->cd(1) //Отображаем функцию. root [19] f1->Draw() //Переходим в нижнюю половину канвы cfunc. root [20] cfunc->cd(2) root [21] f1->Draw() //Устанавливаем для нижней половины канвы cfunc //логарифмический масштаб для оси Y. root [22] cfunc->cd(2)->SetLogy() //Из канвы cfunc создаём векторный eps-файл. root [23] cfunc->Print("root-cfunc.eps") //Из канвы E1 создаём растровый png-файл. root [24] E1->Print("root-E1.png")
В отличие от своего предка PAW, ROOT позволяет интерактивно менять параметры картинки с помощью выпадающих меню. Тип меню зависит от того, на какой объект направлен указатель мыши. Также с помощью левой кнопки можно интерактивно изменять масштаб графика. Для возврата в исходное состояние в меню, относящемся к выбранной оси, следует выбрать команду UnZoom.
Не стоит этим увлекаться, так как кажущаяся простота увеличивает время, потраченное на создание картинок. В отличие от набранных команд, осмысленные движения и клики мыши сохранить для повторного использования невозможно.
[править] Базовые объекты
ROOT унаследовал все базовые объекты анализа, которые были в PAW. Но, в отличие от PAW, ROOT не ограничивается исключительно анализом. Примером такого подхода, например, служит включение в пакет операций для работы с матрицами (линейная алгебра) и базовых средств для манипуляции объектов OpenGL (отображение физических объёмов). ROOT претендует на нечто большее, чем быть просто пакетом анализа, но всё же в этом разделе будут перечислены только те объекты, которые могут пригодиться для представления данных.
[править] Гистограммы
Гистограмма является одним из основных объектов анализа. По сравнению с PAW, в ROOT было добавлено больше типов гистограмм. Конструктор гистограмм имеет вид TH1F. Для двумерной гистограммы вместо 1 надо подставить 2, а для трёхмерной (да, такие тоже есть, правда, непонятно, как их смотреть) – 3. F означает, что на один бин используется Float_t, аналогично возможны и другие типы переменных для хранения значения в бине.
//Создаём новую канву. root [25] TCanvas *ch=new TCanvas("Hist Test","Hist") //Создаём гистограмму в 100 бинов от -3. до 3. root [26] TH1F *h = new TH1F("h","Hist Test",100,-3.,3.) //Обычно гистограммы заполняются с помощью метода Fill. root [27] h->Fill(«TAB» Int_t Fill(Double_t x) Int_t Fill(Double_t x, Double_t w) Int_t Fill(const char* name, Double_t w) //Но мы сейчас идём другим путём: // а) создаём функцию G, root [28] TF1 *func = new TF1("G","exp(-x**2)",-3,3) // б) заполняем гистограмму случайным образом // по форме функции G. root [29] h->FillRandom("G",1000) //Меняем цвет гистограммы. root [30] h->SetFillColor(45) //Подгоняем гистограмму распределением Гаусса root [31] h->Fit("gaus") … //Сохраняем полученную картинку. root [32] ch->Print("root-histexample.eps")
Подгонкой «заведует» всё тот же Minuit, что был и в PAW, правда, переписанный на C++. Алгоритмы не поменялись.
[править] Деревья
Деревья (tree) в ROOT – это логичное развитие идеи ntuple. ntuple, по сути дела, был таблицей со столбцами переменных типа float. В случае деревьев этого ограничения не существует, и в дереве можно сохранять любые объекты.
//Создаём файл на диске. root [33] TFile *f = new TFile("lkravg.root","RECREATE") //Заводим новое дерево root [34] TTree *lkravg = new TTree("lkravg","LKr degrad") //Считаем файл lkravg.dat - тот самый, что "мучили" в //статье про PAW root [35] Long64_t nlines = lkravg->ReadFile("lkravg.dat", //список переменных "time:run:avg:avg_er:P:H") root [36] cout << "Number of lines: " << nlines << endl //Рисуем картинку: чёрные маркеры - есть магнитное поле, //красные маркеры - нет магнитного поля. root [37] lkravg->SetMarkerStyle(5) root [38] lkravg->Draw("avg:time","H>0.1") root [39] lkravg->SetMarkerColor(kRed) root [40] lkravg->Draw("avg:time","H<=0.1","same") //Пишем дерево в файл и закрываем файл. root [41] lkravg->Write(); root [42] f->Close(); //Теперь этот файл можно открыть root [43] TFile *f2 = new TFile("lkravg2.root") //и посмотреть что в нём есть - дерево сохранилось. root [44] .ls TFile** lkravg2.root TFile* lkravg2.root KEY: TTree lkravg;1 LKr degrad
В ROOT есть множество способов создать и заполнить дерево. Подробности лучше посмотреть в пользовательской документации.
[править] Функции
Как и в PAW, в ROOT есть мощная поддержка функций как объектов. С помощью метода Fit можно подогнать гистограмму или график. Но до этого следует определить функцию, например, так:
//Файл mandel.cxx //Множество Мандельброта Double_t mandel(Double_t *XP,Double_t *par) { const Int_t nmax=30; Double_t xx=0.,yy=0.,tt,x,y; x=XP[0];y=XP[1]; for (Int_t n=1;n<nmax;n++) { tt=xx*xx-yy*yy+x; yy=2.*xx*yy+y; xx=tt; if (xx*xx+yy*yy>4.) break; } return Double_t(n)/Double_t(nmax); }
Текст функции следует сохранить в файле mandel.cxx. После с ним можно работать из ROOT:
//Загружаем описание функции mandel.cxx. //Теперь можно обращаться к функции. root [45] .L mandel.cxx root [46] TCanvas *cm=new TCanvas("mandelbrot","Mandelbrot") //Создаём объект «двумерная функция» TF2 root [47] TF2 *Mandelbrot=new TF2("Mandelbrot",mandel,-2.4,.8,-1.2,1.2,0) root [48] cm->Divide(2,2) root [49] cm->cd(1) root [50] Mandelbrot->SetNpx(«TAB» void SetNpx(Int_t npx = 100) // *MENU* //Увеличиваем число шагов отображения. //Как и в PAW функции отображаются через гистограммы. root [51] Mandelbrot->SetNpx(200) root [52] Mandelbrot->SetNpy(200) //Контурное графическое представление. root [53] Mandelbrot->Draw("cont") root [54] cm->cd(2) //Графическое представление в виде поверхность. root [55] Mandelbrot->Draw("surf2") root [56] cm->cd(3) //Множество Мандельброта в цилиндрических координатах. root [57] Mandelbrot->Draw("surf4cyl") root [58] cm->cd(4) //Графическое представление в стиле LEGO. root [59] Mandelbrot->Draw("lego") root [60] cm->Print("root-mandel.eps")
[править] Интерпретатор C++ (CINT)
Интерпретатор С++ или CINT, который используется в ROOT, был независимым проектом. Сейчас он является составной частью ROOT, но его можно использовать и отдельно. Домашняя страничка CINT доступна по адресу http://root.cern.ch/root/Cint.html.
CINT охватывает примерно 95% конструкций ANSI C и 85% от C++. Следует понимать, что полное соответствие стандартам никогда не было основной целью CINT. Не следует писать больших программ, опираясь на интерпретатор, так как скорость выполнения команд уступает компилируемой версии программы примерно в десять раз. А где один порядок, там и два. Для небольших скриптов автоматизации анализа CINT вполне подходит, но для серьёзных целей надо писать обычные программы. Благо, абсолютно всё, что доступно в ROOT интерактивно, доступно и через библиотечные вызовы. Так уж ROOT сделан.
Для внешних CINT-скриптов есть две полезные команды:
//Выполняем скрипт script.cxx root [66] .x script.cxx //Загружаем функции, описанные в lib.cxx root [67] .L lib.cxx
Одной из отличительных особенностей ROOT является возможность делать функции из внешних библиотек доступными для выполнения в скриптах CINT или интерактивно. Ниже будет приведён пример, как подключить пользовательскую C-библиотеку.
Допустим, у вас есть C-библиотека, в которой есть функции myfunc1() и myfunc2(char*), которые необходимо экспортировать в среду ROOT. Для этого нужно создать заголовочный файл myfile.h примерно следующего вида:
/*Файл myfile.h*/ #ifdef __cplusplus extern "C" { #endif extern void myfunc1(); extern int myfunc2(char *); #ifdef __cplusplus } #endif
Пока всё как обычно. Чтобы экспортировать функции в ROOT, необходимо создать ещё один заголовочный файл myfileLinkDef.h (к myfile добавляется LinkDef):
/*Файл myfileLinkDef.h */ #ifdef __CINT__ #pragma link C++ function myfunc1(); #pragma link C++ function myfunc2(char*); #endif
Так же можно экспортировать и структуры, подставив вместо слова function слово struct. После создания описанных заголовочных файлов необходимо создать «словарик»:
> rootcint -f myfileDict.cxx -c myfile.h myfileLinkDef.h
В результате будут созданы файлы myfileDict.h и myfileDict.cxx.
Далее нужно собрать саму библиотеку. Пусть для простоты вся библиотека представляет из себя один C-файл myfile.c:
# Компилируем myfile.c. > gcc -c -fPIC myfile.c # Компилируем словарик. > g++ -c -fPIC 'root-config --cflags' myfileDict.cxx # Создаём разделяемую библиотеку. > g++ -shared -o myfile.so myfile.o myfileDict.o
Теперь эту вновь созданную библиотеку можно загрузить в ROOT для интерактивной работы:
root [68] gSystem->Load("myfile") root [69] myfunc1() root [70] Int_t icount=myfunc2("string")
Это далеко не единственный способ подключить пользовательскую библиотеку к ROOT. Для компиляции скриптов можно использовать подсистему ACLiC.
P.S. Кроме CINT, в среде ROOT можно использовать скрипты, написанные на Python или Ruby. И наоборот: из этих языков можно общаться с библиотеками ROOT. К сожалению, описание этих механизмов выходит за рамки данной статьи.
[править] Заключение
Эта статья – не описание ROOT, а всего лишь набор штрихов к его портрету. Для более подробного знакомства настоятельно рекомендуем посетить http://root.cern.ch.
ROOT – не просто инструмент анализа; это среда для генерации таких инструментов. Он, возможно, неповоротлив и избыточен, но гибок и очень легко расширяем. Это не идеал, но идеал, скорее всего, будет на него похож.
[править] Примечения
- ↑ Почему ROOT так называется? У меня есть только догадки: OO — видимо, Object Oriented, а сам ROOT от английского «корень» или «источник» (root). Предполагается, что ROOT — это база для разработок, а не просто система анализа, то есть корень всех …
- ↑ Таких заходов было чуть меньше 5 тысяч. Грубо, <math>1</math>Тб=<math>10^3</math>Гб=<math>10^6</math>Мб.
- ↑ Я слышал такой вариант ответа: «потому что, в отличие от PAW, в графическом окне ROOT можно мышкой подправить экспериментальные данные» – очень надеюсь, что это была шутка.
- ↑ В руководстве пользователя в этом месте присутствуют ошибки.
- ↑ Чем больше q, тем «сильнее» желание.