Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TMVA_CNN_Classification.C
Go to the documentation of this file.
1/// \file
2/// \ingroup tutorial_tmva
3/// \notebook
4/// TMVA Classification Example Using a Convolutional Neural Network
5///
6/// This is an example of using a CNN in TMVA. We do classification using a toy image data set
7/// that is generated when running the example macro
8///
9/// \macro_image
10/// \macro_output
11/// \macro_code
12///
13/// \author Lorenzo Moneta
14
15/***
16
17 # TMVA Classification Example Using a Convolutional Neural Network
18
19
20**/
21
22/// Helper function to create input images data
23/// we create a signal and background 2D histograms from 2d gaussians
24/// with a location (means in X and Y) different for each event
25/// The difference between signal and background is in the gaussian width.
26/// The width for the background gaussian is slightly larger than the signal width by few % values
27///
28///
29void MakeImagesTree(int n, int nh, int nw)
30{
31
32 // image size (nh x nw)
33 const int ntot = nh * nw;
34 const TString fileOutName = TString::Format("images_data_%dx%d.root", nh, nw);
35
36 const int nRndmEvts = 10000; // number of events we use to fill each image
37 double delta_sigma = 0.1; // 5% difference in the sigma
38 double pixelNoise = 5;
39
40 double sX1 = 3;
41 double sY1 = 3;
42 double sX2 = sX1 + delta_sigma;
43 double sY2 = sY1 - delta_sigma;
44
45 auto h1 = new TH2D("h1", "h1", nh, 0, 10, nw, 0, 10);
46 auto h2 = new TH2D("h2", "h2", nh, 0, 10, nw, 0, 10);
47
48 auto f1 = new TF2("f1", "xygaus");
49 auto f2 = new TF2("f2", "xygaus");
50 TTree sgn("sig_tree", "signal_tree");
51 TTree bkg("bkg_tree", "background_tree");
52
53 TFile f(fileOutName, "RECREATE");
54
55 std::vector<float> x1(ntot);
56 std::vector<float> x2(ntot);
57
58 // create signal and background trees with a single branch
59 // an std::vector<float> of size nh x nw containing the image data
60
61 std::vector<float> *px1 = &x1;
62 std::vector<float> *px2 = &x2;
63
64 bkg.Branch("vars", "std::vector<float>", &px1);
65 sgn.Branch("vars", "std::vector<float>", &px2);
66
67 // std::cout << "create tree " << std::endl;
68
69 sgn.SetDirectory(&f);
70 bkg.SetDirectory(&f);
71
72 f1->SetParameters(1, 5, sX1, 5, sY1);
73 f2->SetParameters(1, 5, sX2, 5, sY2);
74 gRandom->SetSeed(0);
75 std::cout << "Filling ROOT tree " << std::endl;
76 for (int i = 0; i < n; ++i) {
77 if (i % 1000 == 0)
78 std::cout << "Generating image event ... " << i << std::endl;
79 h1->Reset();
80 h2->Reset();
81 // generate random means in range [3,7] to be not too much on the border
82 f1->SetParameter(1, gRandom->Uniform(3, 7));
83 f1->SetParameter(3, gRandom->Uniform(3, 7));
84 f2->SetParameter(1, gRandom->Uniform(3, 7));
85 f2->SetParameter(3, gRandom->Uniform(3, 7));
86
87 h1->FillRandom("f1", nRndmEvts);
88 h2->FillRandom("f2", nRndmEvts);
89
90 for (int k = 0; k < nh; ++k) {
91 for (int l = 0; l < nw; ++l) {
92 int m = k * nw + l;
93 // add some noise in each bin
94 x1[m] = h1->GetBinContent(k + 1, l + 1) + gRandom->Gaus(0, pixelNoise);
95 x2[m] = h2->GetBinContent(k + 1, l + 1) + gRandom->Gaus(0, pixelNoise);
96 }
97 }
98 sgn.Fill();
99 bkg.Fill();
100 }
101 sgn.Write();
102 bkg.Write();
103
104 Info("MakeImagesTree", "Signal and background tree with images data written to the file %s", f.GetName());
105 sgn.Print();
106 bkg.Print();
107 f.Close();
108}
109
110/// @brief Run the TMVA CNN Classification example
111/// @param nevts : number of signal/background events. Use by default a low value (1000)
112/// but increase to at least 5000 to get a good result
113/// @param opt : vector of bool with method used (default all on if available). The order is:
114/// - TMVA CNN
115/// - Keras CNN
116/// - TMVA DNN
117/// - TMVA BDT
118/// - PyTorch CNN
119void TMVA_CNN_Classification(int nevts = 1000, std::vector<bool> opt = {1, 1, 1, 1, 1})
120{
121
122 bool useTMVACNN = (opt.size() > 0) ? opt[0] : false;
123 bool useKerasCNN = (opt.size() > 1) ? opt[1] : false;
124 bool useTMVADNN = (opt.size() > 2) ? opt[2] : false;
125 bool useTMVABDT = (opt.size() > 3) ? opt[3] : false;
126 bool usePyTorchCNN = (opt.size() > 4) ? opt[4] : false;
127#ifndef R__HAS_TMVACPU
128#ifndef R__HAS_TMVAGPU
129 Warning("TMVA_CNN_Classification",
130 "TMVA is not build with GPU or CPU multi-thread support. Cannot use TMVA Deep Learning for CNN");
131 useTMVACNN = false;
132#endif
133#endif
134
135 bool writeOutputFile = true;
136
137 int num_threads = 4; // use by default 4 threads if value is not set before
138 // switch off MT in OpenBLAS to avoid conflict with tbb
139 gSystem->Setenv("OMP_NUM_THREADS", "1");
140
142
143 // do enable MT running
144 if (num_threads >= 0) {
145 ROOT::EnableImplicitMT(num_threads);
146 }
147
148
149 std::cout << "Running with nthreads = " << ROOT::GetThreadPoolSize() << std::endl;
150
151#ifdef R__HAS_PYMVA
152 gSystem->Setenv("KERAS_BACKEND", "tensorflow");
153 // for using Keras
155#else
156 useKerasCNN = false;
157 usePyTorchCNN = false;
158#endif
159
160 TFile *outputFile = nullptr;
161 if (writeOutputFile)
162 outputFile = TFile::Open("TMVA_CNN_ClassificationOutput.root", "RECREATE");
163
164 /***
165 ## Create TMVA Factory
166
167 Create the Factory class. Later you can choose the methods
168 whose performance you'd like to investigate.
169
170 The factory is the major TMVA object you have to interact with. Here is the list of parameters you need to pass
171
172 - The first argument is the base of the name of all the output
173 weight files in the directory weight/ that will be created with the
174 method parameters
175
176 - The second argument is the output file for the training results
177
178 - The third argument is a string option defining some general configuration for the TMVA session.
179 For example all TMVA output can be suppressed by removing the "!" (not) in front of the "Silent" argument in the
180 option string
181
182 - note that we disable any pre-transformation of the input variables and we avoid computing correlations between
183 input variables
184 ***/
185
186 TMVA::Factory factory(
187 "TMVA_CNN_Classification", outputFile,
188 "!V:ROC:!Silent:Color:AnalysisType=Classification:Transformations=None:!Correlations");
189
190 /***
191
192 ## Declare DataLoader(s)
193
194 The next step is to declare the DataLoader class that deals with input variables
195
196 Define the input variables that shall be used for the MVA training
197 note that you may also use variable expressions, which can be parsed by TTree::Draw( "expression" )]
198
199 In this case the input data consists of an image of 16x16 pixels. Each single pixel is a branch in a ROOT TTree
200
201 **/
202
203 TMVA::DataLoader *loader = new TMVA::DataLoader("dataset");
204
205 /***
206
207 ## Setup Dataset(s)
208
209 Define input data file and signal and background trees
210
211 **/
212
213 int imgSize = 16 * 16;
214 TString inputFileName = "images_data_16x16.root";
215
216 bool fileExist = !gSystem->AccessPathName(inputFileName);
217
218 // if file does not exists create it
219 if (!fileExist) {
220 MakeImagesTree(nevts, 16, 16);
221 }
222
223 // TString inputFileName = "tmva_class_example.root";
224
225 auto inputFile = TFile::Open(inputFileName);
226 if (!inputFile) {
227 Error("TMVA_CNN_Classification", "Error opening input file %s - exit", inputFileName.Data());
228 return;
229 }
230
231 // --- Register the training and test trees
232
233 TTree *signalTree = (TTree *)inputFile->Get("sig_tree");
234 TTree *backgroundTree = (TTree *)inputFile->Get("bkg_tree");
235
236 int nEventsSig = signalTree->GetEntries();
237 int nEventsBkg = backgroundTree->GetEntries();
238
239 // global event weights per tree (see below for setting event-wise weights)
240 Double_t signalWeight = 1.0;
241 Double_t backgroundWeight = 1.0;
242
243 // You can add an arbitrary number of signal or background trees
244 loader->AddSignalTree(signalTree, signalWeight);
245 loader->AddBackgroundTree(backgroundTree, backgroundWeight);
246
247 /// add event variables (image)
248 /// use new method (from ROOT 6.20 to add a variable array for all image data)
249 loader->AddVariablesArray("vars", imgSize);
250
251 // Set individual event weights (the variables must exist in the original TTree)
252 // for signal : factory->SetSignalWeightExpression ("weight1*weight2");
253 // for background: factory->SetBackgroundWeightExpression("weight1*weight2");
254 // loader->SetBackgroundWeightExpression( "weight" );
255
256 // Apply additional cuts on the signal and background samples (can be different)
257 TCut mycuts = ""; // for example: TCut mycuts = "abs(var1)<0.5 && abs(var2-0.5)<1";
258 TCut mycutb = ""; // for example: TCut mycutb = "abs(var1)<0.5";
259
260 // Tell the factory how to use the training and testing events
261 //
262 // If no numbers of events are given, half of the events in the tree are used
263 // for training, and the other half for testing:
264 // loader->PrepareTrainingAndTestTree( mycut, "SplitMode=random:!V" );
265 // It is possible also to specify the number of training and testing events,
266 // note we disable the computation of the correlation matrix of the input variables
267
268 int nTrainSig = 0.8 * nEventsSig;
269 int nTrainBkg = 0.8 * nEventsBkg;
270
271 // build the string options for DataLoader::PrepareTrainingAndTestTree
272 TString prepareOptions = TString::Format(
273 "nTrain_Signal=%d:nTrain_Background=%d:SplitMode=Random:SplitSeed=100:NormMode=NumEvents:!V:!CalcCorrelations",
274 nTrainSig, nTrainBkg);
275
276 loader->PrepareTrainingAndTestTree(mycuts, mycutb, prepareOptions);
277
278 /***
279
280 DataSetInfo : [dataset] : Added class "Signal"
281 : Add Tree sig_tree of type Signal with 10000 events
282 DataSetInfo : [dataset] : Added class "Background"
283 : Add Tree bkg_tree of type Background with 10000 events
284
285
286
287 **/
288
289 // signalTree->Print();
290
291 /****
292 # Booking Methods
293
294 Here we book the TMVA methods. We book a Boosted Decision Tree method (BDT)
295
296 **/
297
298 // Boosted Decision Trees
299 if (useTMVABDT) {
300 factory.BookMethod(loader, TMVA::Types::kBDT, "BDT",
301 "!V:NTrees=200:MinNodeSize=2.5%:MaxDepth=2:BoostType=AdaBoost:AdaBoostBeta=0.5:"
302 "UseBaggedBoost:BaggedSampleFraction=0.5:SeparationType=GiniIndex:nCuts=20");
303 }
304 /**
305
306 #### Booking Deep Neural Network
307
308 Here we book the DNN of TMVA. See the example TMVA_Higgs_Classification.C for a detailed description of the
309 options
310
311 **/
312
313 if (useTMVADNN) {
314
315 TString layoutString(
316 "Layout=DENSE|100|RELU,BNORM,DENSE|100|RELU,BNORM,DENSE|100|RELU,BNORM,DENSE|100|RELU,DENSE|1|LINEAR");
317
318 // Training strategies
319 // one can catenate several training strings with different parameters (e.g. learning rates or regularizations
320 // parameters) The training string must be concatenates with the `|` delimiter
321 TString trainingString1("LearningRate=1e-3,Momentum=0.9,Repetitions=1,"
322 "ConvergenceSteps=5,BatchSize=100,TestRepetitions=1,"
323 "MaxEpochs=20,WeightDecay=1e-4,Regularization=None,"
324 "Optimizer=ADAM,DropConfig=0.0+0.0+0.0+0.");
325
326 TString trainingStrategyString("TrainingStrategy=");
327 trainingStrategyString += trainingString1; // + "|" + trainingString2 + ....
328
329 // Build now the full DNN Option string
330
331 TString dnnOptions("!H:V:ErrorStrategy=CROSSENTROPY:VarTransform=None:"
332 "WeightInitialization=XAVIER");
333 dnnOptions.Append(":");
334 dnnOptions.Append(layoutString);
335 dnnOptions.Append(":");
336 dnnOptions.Append(trainingStrategyString);
337
338 TString dnnMethodName = "TMVA_DNN_CPU";
339// use GPU if available
340#ifdef R__HAS_TMVAGPU
341 dnnOptions += ":Architecture=GPU";
342 dnnMethodName = "TMVA_DNN_GPU";
343#elif defined(R__HAS_TMVACPU)
344 dnnOptions += ":Architecture=CPU";
345#endif
346
347 factory.BookMethod(loader, TMVA::Types::kDL, dnnMethodName, dnnOptions);
348 }
349
350 /***
351 ### Book Convolutional Neural Network in TMVA
352
353 For building a CNN one needs to define
354
355 - Input Layout : number of channels (in this case = 1) | image height | image width
356 - Batch Layout : batch size | number of channels | image size = (height*width)
357
358 Then one add Convolutional layers and MaxPool layers.
359
360 - For Convolutional layer the option string has to be:
361 - CONV | number of units | filter height | filter width | stride height | stride width | padding height | paddig
362 width | activation function
363
364 - note in this case we are using a filer 3x3 and padding=1 and stride=1 so we get the output dimension of the
365 conv layer equal to the input
366
367 - note we use after the first convolutional layer a batch normalization layer. This seems to help significantly the
368 convergence
369
370 - For the MaxPool layer:
371 - MAXPOOL | pool height | pool width | stride height | stride width
372
373 The RESHAPE layer is needed to flatten the output before the Dense layer
374
375
376 Note that to run the CNN is required to have CPU or GPU support
377
378 ***/
379
380 if (useTMVACNN) {
381
382 TString inputLayoutString("InputLayout=1|16|16");
383
384 // Batch Layout
385 TString layoutString("Layout=CONV|10|3|3|1|1|1|1|RELU,BNORM,CONV|10|3|3|1|1|1|1|RELU,MAXPOOL|2|2|1|1,"
386 "RESHAPE|FLAT,DENSE|100|RELU,DENSE|1|LINEAR");
387
388 // Training strategies.
389 TString trainingString1("LearningRate=1e-3,Momentum=0.9,Repetitions=1,"
390 "ConvergenceSteps=5,BatchSize=100,TestRepetitions=1,"
391 "MaxEpochs=20,WeightDecay=1e-4,Regularization=None,"
392 "Optimizer=ADAM,DropConfig=0.0+0.0+0.0+0.0");
393
394 TString trainingStrategyString("TrainingStrategy=");
395 trainingStrategyString +=
396 trainingString1; // + "|" + trainingString2 + "|" + trainingString3; for concatenating more training strings
397
398 // Build full CNN Options.
399 TString cnnOptions("!H:V:ErrorStrategy=CROSSENTROPY:VarTransform=None:"
400 "WeightInitialization=XAVIER");
401
402 cnnOptions.Append(":");
403 cnnOptions.Append(inputLayoutString);
404 cnnOptions.Append(":");
405 cnnOptions.Append(layoutString);
406 cnnOptions.Append(":");
407 cnnOptions.Append(trainingStrategyString);
408
409 //// New DL (CNN)
410 TString cnnMethodName = "TMVA_CNN_CPU";
411// use GPU if available
412#ifdef R__HAS_TMVAGPU
413 cnnOptions += ":Architecture=GPU";
414 cnnMethodName = "TMVA_CNN_GPU";
415#else
416 cnnOptions += ":Architecture=CPU";
417 cnnMethodName = "TMVA_CNN_CPU";
418#endif
419
420 factory.BookMethod(loader, TMVA::Types::kDL, cnnMethodName, cnnOptions);
421 }
422
423 /**
424 ### Book Convolutional Neural Network in Keras using a generated model
425
426 **/
427
428 if (useKerasCNN) {
429
430 Info("TMVA_CNN_Classification", "Building convolutional keras model");
431 // create python script which can be executed
432 // create 2 conv2d layer + maxpool + dense
433 TMacro m;
434 m.AddLine("import tensorflow");
435 m.AddLine("from tensorflow.keras.models import Sequential");
436 m.AddLine("from tensorflow.keras.optimizers import Adam");
437 m.AddLine(
438 "from tensorflow.keras.layers import Input, Dense, Dropout, Flatten, Conv2D, MaxPooling2D, Reshape, BatchNormalization");
439 m.AddLine("");
440 m.AddLine("model = Sequential() ");
441 m.AddLine("model.add(Reshape((16, 16, 1), input_shape = (256, )))");
442 m.AddLine("model.add(Conv2D(10, kernel_size = (3, 3), kernel_initializer = 'glorot_normal',activation = "
443 "'relu', padding = 'same'))");
444 m.AddLine("model.add(BatchNormalization())");
445 m.AddLine("model.add(Conv2D(10, kernel_size = (3, 3), kernel_initializer = 'glorot_normal',activation = "
446 "'relu', padding = 'same'))");
447 // m.AddLine("model.add(BatchNormalization())");
448 m.AddLine("model.add(MaxPooling2D(pool_size = (2, 2), strides = (1,1))) ");
449 m.AddLine("model.add(Flatten())");
450 m.AddLine("model.add(Dense(256, activation = 'relu')) ");
451 m.AddLine("model.add(Dense(2, activation = 'sigmoid')) ");
452 m.AddLine("model.compile(loss = 'binary_crossentropy', optimizer = Adam(learning_rate = 0.001), weighted_metrics = ['accuracy'])");
453 m.AddLine("model.save('model_cnn.h5')");
454 m.AddLine("model.summary()");
455
456 m.SaveSource("make_cnn_model.py");
457 // execute
458 auto ret = (TString *)gROOT->ProcessLine("TMVA::Python_Executable()");
459 TString python_exe = (ret) ? *(ret) : "python";
460 gSystem->Exec(python_exe + " make_cnn_model.py");
461
462 if (gSystem->AccessPathName("model_cnn.h5")) {
463 Warning("TMVA_CNN_Classification", "Error creating Keras model file - skip using Keras");
464 } else {
465 // book PyKeras method only if Keras model could be created
466 Info("TMVA_CNN_Classification", "Booking tf.Keras CNN model");
467 factory.BookMethod(
468 loader, TMVA::Types::kPyKeras, "PyKeras",
469 "H:!V:VarTransform=None:FilenameModel=model_cnn.h5:tf.keras:"
470 "FilenameTrainedModel=trained_model_cnn.h5:NumEpochs=20:BatchSize=100:"
471 "GpuOptions=allow_growth=True"); // needed for RTX NVidia card and to avoid TF allocates all GPU memory
472 }
473 }
474
475 if (usePyTorchCNN) {
476
477 Info("TMVA_CNN_Classification", "Using Convolutional PyTorch Model");
478 TString pyTorchFileName = gROOT->GetTutorialDir() + TString("/tmva/PyTorch_Generate_CNN_Model.py");
479 // check that pytorch can be imported and file defining the model and used later when booking the method is existing
480 auto ret = (TString *)gROOT->ProcessLine("TMVA::Python_Executable()");
481 TString python_exe = (ret) ? *(ret) : "python";
482 if (gSystem->Exec(python_exe + " -c 'import torch'") || gSystem->AccessPathName(pyTorchFileName)) {
483 Warning("TMVA_CNN_Classification", "PyTorch is not installed or model building file is not existing - skip using PyTorch");
484 } else {
485 // book PyTorch method only if PyTorch model could be created
486 Info("TMVA_CNN_Classification", "Booking PyTorch CNN model");
487 TString methodOpt = "H:!V:VarTransform=None:FilenameModel=PyTorchModelCNN.pt:"
488 "FilenameTrainedModel=PyTorchTrainedModelCNN.pt:NumEpochs=20:BatchSize=100";
489 methodOpt += TString(":UserCode=") + pyTorchFileName;
490 factory.BookMethod(loader, TMVA::Types::kPyTorch, "PyTorch", methodOpt);
491 }
492 }
493
494
495 //// ## Train Methods
496
497 factory.TrainAllMethods();
498
499 /// ## Test and Evaluate Methods
500
501 factory.TestAllMethods();
502
503 factory.EvaluateAllMethods();
504
505 /// ## Plot ROC Curve
506
507 auto c1 = factory.GetROCCurve(loader);
508 c1->Draw();
509
510 // close outputfile to save output file
511 outputFile->Close();
512}
#define f(i)
Definition RSha256.hxx:104
double Double_t
Definition RtypesCore.h:59
void Info(const char *location, const char *msgfmt,...)
Use this function for informational messages.
Definition TError.cxx:221
void Error(const char *location, const char *msgfmt,...)
Use this function in case an error occurred.
Definition TError.cxx:188
void Warning(const char *location, const char *msgfmt,...)
Use this function in warning situations.
Definition TError.cxx:232
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
#define gROOT
Definition TROOT.h:406
R__EXTERN TRandom * gRandom
Definition TRandom.h:62
R__EXTERN TSystem * gSystem
Definition TSystem.h:560
A specialized string object used for TTree selections.
Definition TCut.h:25
virtual void SetParameters(const Double_t *params)
Definition TF1.h:649
virtual void SetParameter(Int_t param, Double_t value)
Definition TF1.h:639
A 2-Dim function with parameters.
Definition TF2.h:29
A ROOT file is composed of a header, followed by consecutive data records (TKey instances) with a wel...
Definition TFile.h:54
static TFile * Open(const char *name, Option_t *option="", const char *ftitle="", Int_t compress=ROOT::RCompressionSetting::EDefaults::kUseCompiledDefault, Int_t netopt=0)
Create / open a file.
Definition TFile.cxx:4061
void Close(Option_t *option="") override
Close a file.
Definition TFile.cxx:924
void Reset(Option_t *option="") override
Reset.
Definition TH1.cxx:9979
virtual void FillRandom(const char *fname, Int_t ntimes=5000, TRandom *rng=nullptr)
Fill histogram following distribution in function fname.
Definition TH1.cxx:3513
virtual Double_t GetBinContent(Int_t bin) const
Return content of bin number bin.
Definition TH1.cxx:5025
2-D histogram with a double per channel (see TH1 documentation)}
Definition TH2.h:300
void AddVariablesArray(const TString &expression, int size, char type='F', Double_t min=0, Double_t max=0)
user inserts discriminating array of variables in data set info in case input tree provides an array ...
void AddSignalTree(TTree *signal, Double_t weight=1.0, Types::ETreeType treetype=Types::kMaxTreeType)
number of signal events (used to compute significance)
void PrepareTrainingAndTestTree(const TCut &cut, const TString &splitOpt)
prepare the training and test trees -> same cuts for signal and background
void AddBackgroundTree(TTree *background, Double_t weight=1.0, Types::ETreeType treetype=Types::kMaxTreeType)
number of signal events (used to compute significance)
This is the main MVA steering class.
Definition Factory.h:80
static void PyInitialize()
Initialize Python interpreter.
static Tools & Instance()
Definition Tools.cxx:71
Class supporting a collection of lines with C++ code.
Definition TMacro.h:31
virtual Double_t Gaus(Double_t mean=0, Double_t sigma=1)
Samples a random number from the standard Normal (Gaussian) Distribution with the given mean and sigm...
Definition TRandom.cxx:274
virtual void SetSeed(ULong_t seed=0)
Set the random generator seed.
Definition TRandom.cxx:608
virtual Double_t Uniform(Double_t x1=1)
Returns a uniform deviate on the interval (0, x1).
Definition TRandom.cxx:672
Basic string class.
Definition TString.h:139
const char * Data() const
Definition TString.h:380
static TString Format(const char *fmt,...)
Static method which formats a string using a printf style format descriptor and return a TString.
Definition TString.cxx:2357
virtual Int_t Exec(const char *shellcmd)
Execute a command.
Definition TSystem.cxx:656
virtual Bool_t AccessPathName(const char *path, EAccessMode mode=kFileExists)
Returns FALSE if one can access a file using the specified access mode.
Definition TSystem.cxx:1299
virtual void Setenv(const char *name, const char *value)
Set environment variable.
Definition TSystem.cxx:1650
A TTree represents a columnar dataset.
Definition TTree.h:79
virtual Long64_t GetEntries() const
Definition TTree.h:460
return c1
Definition legend1.C:41
const Int_t n
Definition legend1.C:16
TH1F * h1
Definition legend1.C:5
TF1 * f1
Definition legend1.C:11
void EnableImplicitMT(UInt_t numthreads=0)
Enable ROOT's implicit multi-threading for all objects and methods that provide an internal paralleli...
Definition TROOT.cxx:527
UInt_t GetThreadPoolSize()
Returns the size of ROOT's thread pool.
Definition TROOT.cxx:565
TMarker m
Definition textangle.C:8
TLine l
Definition textangle.C:4