{
"cells": [
{
"cell_type": "markdown",
"id": "606a8615",
"metadata": {},
"source": [
"# tree109_friend\n",
"Illustrates how to use Tree friends:\n",
" - create a simple TTree\n",
" - Copy a subset of this TTree to a new TTree\n",
" - Create a Tree Index\n",
" - Make a friend TTree\n",
" - compare two TTrees\n",
" - Draw a variable from the first tree versus a variable\n",
" in the friend Tree\n",
"\n",
"You can run this tutorial with:\n",
"```\n",
" root > .x tree109_friend.C (interpreted via Cling)\n",
" root > .x tree109_friend.C+ (executed via ACLIC & the native compiler)\n",
"```\n",
"or, variants like:\n",
"```\n",
" root > .L tree109_friend.C+\n",
" root > CreateParentTree();\n",
" root > CreateFriendTree();\n",
" root > CompareTrees();\n",
" root > DrawFriend();\n",
"```\n",
"\n",
"\n",
"\n",
"\n",
"**Author:** Rene Brun \n",
"This notebook tutorial was automatically generated with ROOTBOOK-izer from the macro found in the ROOT repository on Tuesday, May 19, 2026 at 08:18 PM."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "81bee71b",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:18:13.958740Z",
"iopub.status.busy": "2026-05-19T20:18:13.958625Z",
"iopub.status.idle": "2026-05-19T20:18:13.967287Z",
"shell.execute_reply": "2026-05-19T20:18:13.966783Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"#include \"TTree.h\"\n",
"#include \"TFile.h\"\n",
"#include \"TRandom.h\"\n",
"#include \"TTree.h\"\n",
"#include \"TTree.h\"\n",
"\n",
"Int_t Run, Event;\n",
"Float_t x, y, z;"
]
},
{
"cell_type": "markdown",
"id": "11b1d58f",
"metadata": {},
"source": [
" Definition of a helper function: "
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "a4f93ae0",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:18:13.968398Z",
"iopub.status.busy": "2026-05-19T20:18:13.968284Z",
"iopub.status.idle": "2026-05-19T20:18:13.981306Z",
"shell.execute_reply": "2026-05-19T20:18:13.980796Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"void CreateParentTree()\n",
"{\n",
" // create a simple TTree with 5 branches\n",
" // Two branches (\"Run\" and \"Event\") will be used to index the Tree\n",
" auto f = TFile::Open(\"treeparent.root\", \"recreate\");\n",
" auto T = new TTree(\"T\", \"test friend trees\");\n",
" T->Branch(\"Run\", &Run, \"Run/I\");\n",
" T->Branch(\"Event\", &Event, \"Event/I\");\n",
" T->Branch(\"x\", &x, \"x/F\");\n",
" T->Branch(\"y\", &y, \"y/F\");\n",
" T->Branch(\"z\", &z, \"z/F\");\n",
" TRandom r;\n",
" for (Int_t i=0; i<10000; i++) {\n",
" if (i < 5000)\n",
" Run = 1;\n",
" else\n",
" Run = 2;\n",
" Event = i;\n",
" x = r.Gaus(10, 1);\n",
" y = r.Gaus(20, 2);\n",
" z = r.Landau(2, 1);\n",
" T->Fill();\n",
" }\n",
" T->Print();\n",
" T->Write();\n",
" delete f;\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "fe9ed005",
"metadata": {},
"source": [
" Definition of a helper function: "
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "3cb1e2c0",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:18:13.982492Z",
"iopub.status.busy": "2026-05-19T20:18:13.982376Z",
"iopub.status.idle": "2026-05-19T20:18:13.986478Z",
"shell.execute_reply": "2026-05-19T20:18:13.986019Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"void CreateFriendTree()\n",
"{\n",
" // Open the file created by CreateParentTree\n",
" // Copy a subset of the TTree into a new TTree\n",
" // (see also tutorials tree110_copy.C, tree111_copy.C and tree112_copy.C)\n",
" // Create an index on the new TTree (\"Run\", \"Event\")\n",
" // Write the new TTree (including its index)\n",
"\n",
" auto f = TFile::Open(\"treeparent.root\");\n",
" auto T = f->Get(\"T\");\n",
" auto ff = TFile::Open(\"treefriend.root\", \"recreate\");\n",
" auto TF = T->CopyTree(\"z<10\");\n",
" TF->SetName(\"TF\");\n",
" TF->BuildIndex(\"Run\", \"Event\");\n",
" TF->Write();\n",
" TF->Print();\n",
" delete ff;\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "851c31de",
"metadata": {},
"source": [
" Definition of a helper function: "
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "fda7d8f8",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:18:13.987584Z",
"iopub.status.busy": "2026-05-19T20:18:13.987473Z",
"iopub.status.idle": "2026-05-19T20:18:13.994138Z",
"shell.execute_reply": "2026-05-19T20:18:13.993638Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"void CompareTrees()\n",
"{\n",
" // The two TTrees created above are compared.\n",
" // The subset of entries in the small TTree must be identical\n",
" // to the entries in the original TTree.\n",
"\n",
" Int_t fRun, fEvent;\n",
" Float_t fx, fy, fz;\n",
" auto f = TFile::Open(\"treeparent.root\");\n",
" auto T = f->Get(\"T\");\n",
" auto ff = TFile::Open(\"treefriend.root\");\n",
" auto TF = ff->Get(\"TF\");\n",
" T->SetBranchAddress(\"Run\", &Run);\n",
" T->SetBranchAddress(\"Event\", &Event);\n",
" T->SetBranchAddress(\"x\", &x);\n",
" T->SetBranchAddress(\"y\", &y);\n",
" T->SetBranchAddress(\"z\", &z);\n",
" TF->SetBranchAddress(\"Run\", &fRun);\n",
" TF->SetBranchAddress(\"Event\", &fEvent);\n",
" TF->SetBranchAddress(\"x\", &fx);\n",
" TF->SetBranchAddress(\"y\", &fy);\n",
" TF->SetBranchAddress(\"z\", &fz);\n",
" T->AddFriend(TF);\n",
"\n",
" Long64_t nentries = T->GetEntries();\n",
" Int_t nok = 0;\n",
" for (Long64_t i=0; iGetEntry(i);\n",
" if (fRun == Run && fEvent==Event && x==fx && y==fy && z==fz) {\n",
" nok++;\n",
" } else {\n",
" if (TF->GetEntryWithIndex(Run, Event) > 0) {\n",
" if (i <100)\n",
" printf(\"i=%lld, Run=%d, Event=%d, x=%g, y=%g, z=%g : fRun=%d, fEvent=%d, fx=%g, fy=%g, fz=%g\\n\",\n",
" i, Run, Event, x, y, z, fRun, fEvent, fx, fy, fz);\n",
" }\n",
" }\n",
" }\n",
" printf(\"nok = %d, fentries=%lld\\n\", nok, TF->GetEntries());\n",
"\n",
" delete f;\n",
" delete ff;\n",
"}"
]
},
{
"cell_type": "markdown",
"id": "71f054dc",
"metadata": {},
"source": [
" Definition of a helper function: "
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "b84c27c4",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:18:13.995187Z",
"iopub.status.busy": "2026-05-19T20:18:13.995075Z",
"iopub.status.idle": "2026-05-19T20:18:13.998290Z",
"shell.execute_reply": "2026-05-19T20:18:13.997810Z"
}
},
"outputs": [],
"source": [
"%%cpp -d\n",
"void DrawFriend()\n",
"{\n",
" // Draw a scatter plot of variable x in the parent TTree versus\n",
" // the same variable in the subtree.\n",
" // This should produce points along a straight line.\n",
"\n",
" auto f = TFile::Open(\"treeparent.root\");\n",
" auto T = f->Get(\"T\");\n",
" T->AddFriend(\"TF\", \"treefriend.root\");\n",
" T->Draw(\"x:TF.x\");\n",
"}"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "f5f04d33",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:18:13.999295Z",
"iopub.status.busy": "2026-05-19T20:18:13.999183Z",
"iopub.status.idle": "2026-05-19T20:18:14.581133Z",
"shell.execute_reply": "2026-05-19T20:18:14.580503Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
"
\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"******************************************************************************\n",
"*Tree :T : test friend trees *\n",
"*Entries : 10000 : Total = 203762 bytes File Size = 100358 *\n",
"* : : Tree compression factor = 1.59 *\n",
"******************************************************************************\n",
"*Br 0 :Run : Run/I *\n",
"*Entries : 10000 : Total Size= 40698 bytes File Size = 262 *\n",
"*Baskets : 1 : Basket Size= 32000 bytes Compression= 122.13 *\n",
"*............................................................................*\n",
"*Br 1 :Event : Event/I *\n",
"*Entries : 10000 : Total Size= 40712 bytes File Size = 17635 *\n",
"*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.81 *\n",
"*............................................................................*\n",
"*Br 2 :x : x/F *\n",
"*Entries : 10000 : Total Size= 40684 bytes File Size = 26767 *\n",
"*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.20 *\n",
"*............................................................................*\n",
"*Br 3 :y : y/F *\n",
"*Entries : 10000 : Total Size= 40684 bytes File Size = 26662 *\n",
"*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.20 *\n",
"*............................................................................*\n",
"*Br 4 :z : z/F *\n",
"*Entries : 10000 : Total Size= 40684 bytes File Size = 29032 *\n",
"*Baskets : 1 : Basket Size= 32000 bytes Compression= 1.10 *\n",
"*............................................................................*\n",
"******************************************************************************\n",
"*Tree :TF : test friend trees *\n",
"*Entries : 8460 : Total = 375780 bytes File Size = 144998 *\n",
"* : : Tree compression factor = 1.59 *\n",
"******************************************************************************\n",
"*Br 0 :Run : Run/I *\n",
"*Entries : 8460 : Total Size= 34463 bytes File Size = 370 *\n",
"*Baskets : 2 : Basket Size= 32000 bytes Compression= 91.82 *\n",
"*............................................................................*\n",
"*Br 1 :Event : Event/I *\n",
"*Entries : 8460 : Total Size= 34475 bytes File Size = 18880 *\n",
"*Baskets : 2 : Basket Size= 32000 bytes Compression= 1.80 *\n",
"*............................................................................*\n",
"*Br 2 :x : x/F *\n",
"*Entries : 8460 : Total Size= 34451 bytes File Size = 28500 *\n",
"*Baskets : 2 : Basket Size= 32000 bytes Compression= 1.19 *\n",
"*............................................................................*\n",
"*Br 3 :y : y/F *\n",
"*Entries : 8460 : Total Size= 34451 bytes File Size = 28389 *\n",
"*Baskets : 2 : Basket Size= 32000 bytes Compression= 1.20 *\n",
"*............................................................................*\n",
"*Br 4 :z : z/F *\n",
"*Entries : 8460 : Total Size= 34451 bytes File Size = 30521 *\n",
"*Baskets : 2 : Basket Size= 32000 bytes Compression= 1.11 *\n",
"*............................................................................*\n",
"nok = 8460, fentries=8460\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"Info in : created default TCanvas with name c1\n"
]
}
],
"source": [
"CreateParentTree();\n",
"CreateFriendTree();\n",
"CompareTrees();\n",
"DrawFriend();"
]
},
{
"cell_type": "markdown",
"id": "80c3514a",
"metadata": {},
"source": [
"Draw all canvases "
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "1fc9779d",
"metadata": {
"collapsed": false,
"execution": {
"iopub.execute_input": "2026-05-19T20:18:14.582373Z",
"iopub.status.busy": "2026-05-19T20:18:14.582257Z",
"iopub.status.idle": "2026-05-19T20:18:14.787629Z",
"shell.execute_reply": "2026-05-19T20:18:14.786966Z"
}
},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"\n",
"
\n",
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"gROOT->GetListOfCanvases()->Draw()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "ROOT C++",
"language": "c++",
"name": "root"
},
"language_info": {
"codemirror_mode": "text/x-c++src",
"file_extension": ".C",
"mimetype": " text/x-c++src",
"name": "c++"
}
},
"nbformat": 4,
"nbformat_minor": 5
}