60{
   63  
   66  string                opera;
   67  string                name;
   69 
   70  try {
   71 
   72    JParser<> zap(
"Auxiliary program for histogram operations.");
 
   73 
   74    zap[
'f'] = 
make_field(inputFile,  
"<input file>:<object name>");
 
   76      JOpera::Add(), 
   77      JOpera::add(), 
   78      JOpera::Subtract(), 
   79      JOpera::subtract(), 
   80      JOpera::Multiply(), 
   81      JOpera::multiply(),  
   82      JOpera::Divide(), 
   83      JOpera::divide(), 
   84      JOpera::efficiency(), 
   85      JOpera::stdev(),
   86      JOpera::sqrt(),
   87      JOpera::Replace();
   90                          << "\n\t\"" << JOpera::SAME_AS_OPERATION() << "\" -> same as operation; or"
   91                          << "\n\t\"" << JOpera::SAME_AS_INPUT()     << "\" -> same as input; else"
   92                          << "\n\t as specified")                       = JOpera::SAME_AS_OPERATION();
   94 
   95    zap(argc, argv);
   96  }
   97  catch(const exception &error) {
   98    FATAL(error.what() << endl);
 
   99  }
  100 
  101 
  103 
  104  for (vector<JRootObjectID>::const_iterator input = inputFile.begin(); input != inputFile.end(); ++input) {
  105 
  106    DEBUG(
"Input: " << *input << endl);
 
  107 
  109 
  110    if (dir == NULL) {
  111      ERROR(
"File: " << input->getFullFilename() << 
" not opened." << endl);
 
  112      continue;
  113    }
  114 
  115    const TRegexp regexp(input->getObjectName());
  116 
  117    TIter iter(dir->GetListOfKeys());
  118 
  119    for (TKey* key; (
key = (TKey*) iter.Next()) != NULL; ) {
 
  120 
  121      const TString tag(
key->GetName());
 
  122 
  123      DEBUG(
"Key: " << tag << 
" match = " << tag.Contains(regexp) << endl);
 
  124 
  125      
  126 
  127      if (tag.Contains(regexp) && 
isTObject(key)) {
 
  128 
  130        TProfile* q = dynamic_cast<TProfile*>(p);
  131 
  132        if (q != NULL) {
  133          p = q->ProjectionX();
  134        }
  135 
  136        if (dynamic_cast<TH1*>(p) == NULL) {
  137          FATAL(
"Object " << p->GetName() << 
" not compatible with histogram operations." << endl);
 
  138        }
  139        
  140        listOfObjects.push_back(p);
  141      }
  142    }
  143  }
  144 
  145 
  146  TH1* h3 = NULL;
  147 
  148  if        (listOfObjects.size() == 0) {
  149 
  150    FATAL(
"Number of histograms " << listOfObjects.size() << 
" = 0." << endl);
 
  151 
  152  } else if (listOfObjects.size() == 1 && (opera == JOpera::Add()      ||
  153                                           opera == JOpera::Subtract() ||
  154                                           opera == JOpera::Multiply() ||
  155                                           opera == JOpera::Divide()   ||
  156                                           opera == JOpera::Replace())) {
  157 
  158    
  159 
  160    TH1* h1 = dynamic_cast<TH1*>(listOfObjects[0]);
  161    TF1* 
f1 = (TF1*) h1->GetListOfFunctions()->First();
 
  162 
  163    if (f1 == NULL) {
  164      FATAL(h1->GetName() << 
" has no associated function." << endl);
 
  165    }
  166            
  167    NOTICE(h1->GetName() << 
' ' << opera << 
' ' << 
f1->GetName() << endl);
 
  168 
  169    if      (name == JOpera::SAME_AS_OPERATION())
  170      h3 = (TH1*) h1->Clone(opera.c_str());
  171    else if (name == JOpera::SAME_AS_INPUT())
  172      h3 = (TH1*) h1->Clone(h1->GetName());
  173    else
  174      h3 = (TH1*) h1->Clone(name.c_str());
  175      
  176    if        (opera == JOpera::Add()) {
  177 
  178      h3->Add     (f1, +1.0);
  179 
  180    } else if (opera == JOpera::Subtract()) {
  181        
  182      h3->Add     (f1, -1.0);
  183 
  184    } else if (opera == JOpera::Multiply()) {
  185        
  186      h3->Multiply(f1);
  187 
  188    } else if (opera == JOpera::Divide()) {
  189 
  190      h3->Divide  (f1);
  191 
  192    } else if (opera == JOpera::Replace()) {
  193 
  194      h3->Reset();
  195      h3->Fill(0.0, 0.0);          
  196      h3->Add     (f1);
  197    }
  198    
  199  } else if (listOfObjects.size() == 2) {
  200 
  201    
  202 
  203    TH1* h1 = dynamic_cast<TH1*>(listOfObjects[0]);
  204    TH1* h2 = dynamic_cast<TH1*>(listOfObjects[1]);
  205 
  206    NOTICE(h1->GetName() << 
' ' << opera << 
' ' << h2->GetName() << endl);
 
  207 
  208    if      (name == JOpera::SAME_AS_OPERATION())
  209      h3 = (TH1*) h1->Clone(opera.c_str());
  210    else if (name == JOpera::SAME_AS_INPUT())
  211      h3 = (TH1*) h1->Clone(h1->GetName());
  212    else
  213      h3 = (TH1*) h1->Clone(name.c_str());
  214      
  215    if        (opera == JOpera::Add()) {
  216 
  217      h3->Add     (h1, h2, +1.0, +1.0);
  218 
  219    } else if (opera == JOpera::Subtract()) {
  220        
  221      h3->Add     (h1, h2, +1.0, -1.0);
  222 
  223    } else if (opera == JOpera::Multiply()) {
  224        
  225      h3->Multiply(h1, h2, +1.0, +1.0);
  226 
  227    } else if (opera == JOpera::Divide()) {
  228 
  229      h3->Divide  (h1, h2, +1.0, +1.0);
  230 
  231    } else if (opera == JOpera::add()       ||
  232               opera == JOpera::subtract()  ||
  233               opera == JOpera::multiply()  ||
  234               opera == JOpera::divide()) {
  235 
  236      for (Int_t i = 1; i <= h1->GetNbinsX(); ++i) {
  237 
  238        const Double_t 
x  = h1->GetBinCenter (i);
 
  239        const Double_t w1 = h1->GetBinContent(i);
  240          
  241        const Int_t    
j  = h2->FindBin(x);
 
  242        const Double_t w2 = h2->GetBinContent(j);
  243 
  244        Double_t w3 = 0.0;
  245 
  246        if        (opera == JOpera::add()) {
  247 
  248          w3 = w1 + w2;
  249            
  250        } else if (opera == JOpera::subtract()) {
  251 
  252          w3 = w1 - w2;
  253 
  254        } else if (opera == JOpera::multiply()) {
  255 
  256          w3 = w1 * w2;
  257 
  258        } else if (opera == JOpera::divide()) {
  259 
  260          if (w2 == 0.0) {
  261            ERROR(
"Bin " << h2->GetName() << 
"[" << j << 
"] empty." << endl);
 
  262            continue;
  263          }
  264              
  265          w3 = w1 / w2;
  266        }
  267 
  268        h3->SetBinContent(i, w3);
  269      }
  270 
  271    } else if (opera == JOpera::efficiency() ||
  272               opera == JOpera::stdev()      ||
  273               opera == JOpera::sqrt()) {
  274 
  275      for (Int_t i = 1; i <= h1->GetNbinsX(); ++i) {
  276 
  277        const Double_t y1 = h1->GetBinContent(i);
  278        const Double_t y2 = h2->GetBinContent(i);
  279 
  280        Double_t w1 = h1->GetBinError(i);
  281        Double_t w2 = h2->GetBinError(i);
  282 
  283        Double_t y3 = 0.0;
  284        Double_t w3 = 0.0;
  285 
  286        if        (opera == JOpera::efficiency()) {
  287          
  288          if (y2 == 0.0) {
  289            ERROR(
"Bin " << h2->GetName() << 
"[" << i << 
"] empty." << endl);
 
  290            continue;
  291          }
  292 
  293          y3 = y1 / y2;
  294 
  295          if (y1 != 0.0 &&
  296              y2 != 0.0) {
  297 
  298            w1 /= y1;
  299            w2 /= y2;
  300 
  301            w3  = y3 * fabs(y3 - 1.0) * sqrt(w1*w1 + w2*w2);
  302          }
  303          
  304        } else if (opera == JOpera::stdev()) {
  305 
  306          w3 = sqrt(w1*w1 + w2*w2);
  307 
  308          if (w3 != 0.0) {
  309            y3 = (y1 - y2) / w3;
  310            w3 = 0.0;
  311          }
  312            
  313        } else if (opera == JOpera::sqrt()) {
  314 
  315          y3 = (y1+y2) * (y1-y2);
  316            
  317          if (y3 < 0.0)
  318            y3 = -sqrt(-y3);
  319          else
  320            y3 = +sqrt(+y3);
  321 
  322          w3 = 0.0;
  323        }
  324 
  325        h3->SetBinContent(i, y3);
  326        h3->SetBinError  (i, w3);
  327      }
  328    }
  329 
  330  } else if (opera == JOpera::Add()      ||
  331             opera == JOpera::Multiply()) {
  332 
  333    
  334 
  336 
  337      TH1* h1 = dynamic_cast<TH1*>(*i);
  338 
  339      NOTICE(h1->GetName() << 
' ' << opera << endl);
 
  340 
  341      if (h3 == NULL) {
  342 
  343        if      (name == JOpera::SAME_AS_OPERATION())
  344          h3 = (TH1*) h1->Clone(opera.c_str());
  345        else if (name == JOpera::SAME_AS_INPUT())
  346          h3 = (TH1*) h1->Clone(h1->GetName());
  347        else
  348          h3 = (TH1*) h1->Clone(name.c_str());
  349 
  350      } else {
  351 
  352        if        (opera == JOpera::Add()) {
  353        
  354          h3->Add     (h3, h1, +1.0, +1.0);
  355          
  356        } else if (opera == JOpera::Multiply()) {
  357          
  358          h3->Multiply(h3, h1, +1.0, +1.0);
  359        }
  360      }
  361    }
  362 
  363  } else {
  364 
  365    FATAL(
"Incompatible number of histograms " << listOfObjects.size() << 
" with option " << opera << endl);
 
  366  }
  367 
  368  if (h3 != NULL) {
  369 
  371    
  372    h3->Write();
  373    
  374    out.Write();
  375    out.Close();
  376  }
  377}
#define DEBUG(A)
Message macros.
 
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
 
Utility class to parse command line options.
 
const JPolynome f1(1.0, 2.0, 3.0)
Function.
 
TDirectory * getDirectory(const JRootObjectID &id)
Get TDirectory pointer.
 
bool isTObject(const TKey *key)
Check if given key corresponds to a TObject.
 
This name space includes all other name spaces (except KM3NETDAQ, KM3NET and ANTARES).