построение гистограмм в ROOT с различными именами переменных

Я не уверен, как правильно сформулировать этот вопрос, но это то, что я пытаюсь сделать.

Одну гистограмму можно построить с помощью cern ROOT с помощью следующей команды:

(TH1F*)electron->Draw();

Но у меня есть десятки гистограмм, названных в последовательности, например, электрон1, электрон2, электрон3 и т. д., и я хочу написать простой цикл, чтобы построить их все. Я пробовал использовать sprintf и простой цикл for, но ROOT это не нравится.

char name[20];
(TH1F*)electron->Draw();
for(int j=0;j<5;j++){
            sprintf(name, "%s%d","electron",j);
            (TH1F*)name->Draw("same");
 }

Что я делаю не так?

Заранее спасибо.


person intsymmetry    schedule 04.10.2012    source источник


Ответы (2)


Вам нужен еще один шаг. Как говорит @twalberg, у вас есть строка, а не указатель объекта. Для root вы можете просто изменить свой код, добавив одну дополнительную строку.

char name[20];
electron->Draw();
for(int j=0;j<5;j++){
   sprintf(name, "%s%d","electron",j);
   TH1F *h = (TH1F*)gDirectory->Get(name); // THIS IS THE MISSING LINE
   if ( h ) h->Draw("same"); // make sure the Get succeeded 
 }

Дополнительная строка получает указанный объект по имени из локального каталога TDirectory. Приведение необходимо для того, чтобы gDirectory приводилось к правильному виду объекта.

Когда вы используете root в интерактивном режиме, это происходит волшебным образом за кулисами.

person Sol Arnu    schedule 19.10.2012
comment
Это правильный ответ. Хотя вы прекрасно следуете стилю ROOT, то же самое можно сделать с std::string и boost::lexical_cast, которые являются гораздо более идеоматичными C++, но, вероятно, также более запутанными для большинства пользователей ROOT, поскольку они не слишком хорошо работают в макросах CINT. - person Benjamin Bannier; 20.10.2012
comment
Спасибо, гудок. Как вы, наверное, знаете, Root не особо ценит C++ :) - person Sol Arnu; 20.10.2012
comment
Скоро все наверняка изменится с выходом root-6, где cling заменит cint. Все получат программу на высоком, почти функциональном уровне, характерном для современного C++. Макросы ROOT, которые когда-то спагетти для 20 тысяч строк для создания и заполнения различных гистограмм, будут выполнены в нескольких строках сопоставления алгоритма с контейнером данных. Да, я уверен, что как только нам будет разрешено писать правильный C++ в макросах анализа ROOT, мы сможем сделать то, что мы можем сделать. - person Benjamin Bannier; 20.10.2012

Создание строки с надписью «electron0», преобразование char *, указывающего на начало строки, в TH1F * и разыменование ее, как если бы строка символов была на самом деле struct TH1F * (или class TH1F *), скорее всего, просто приведет к сбою программы, и не то же самое, что ссылка на переменную с именем electron0.

Вероятно, вам лучше всего вместо того, чтобы называть кучу переменных electron0, electron1 и т. д., создать массив, как в TH1F electron[NELECTRONS];, а затем ссылаться на них как electron[0], electron[1] и т. д. (В качестве альтернативы, если объекты распределяются динамически, используйте TH1F *electron[NELECTRONS]; и сохраните указатели (с соответствующими косвенными ссылками на них (*(electron[0]).Draw(...) или electron[0]->Draw(...)).

person twalberg    schedule 04.10.2012