{ "cells": [ { "cell_type": "markdown", "id": "d1b83798", "metadata": {}, "source": [ "# tree143_drawsparse\n", "Convert a THnSparse to a TTree using efficient iteration through the THnSparse\n", "and draw a THnSparse using TParallelCoord.\n", "The plot will contain one line for each filled bin,\n", "with the bin's coordinates on each axis, and the bin's content on\n", "the rightmost axis.\n", "\n", " Run as\n", "```\n", " .L $ROOTSYS/tutorials/io/tree/tree143_drawsparse.C+\n", "```\n", "\n", "\n", "\n", "\n", "**Author:** Axel Naumann \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:19 PM." ] }, { "cell_type": "markdown", "id": "2a07f812", "metadata": {}, "source": [ " Definition of a helper function: " ] }, { "cell_type": "code", "execution_count": 1, "id": "3b04aca6", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:34.728662Z", "iopub.status.busy": "2026-05-19T20:19:34.728519Z", "iopub.status.idle": "2026-05-19T20:19:34.747726Z", "shell.execute_reply": "2026-05-19T20:19:34.747143Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "\n", "#include \"TParallelCoord.h\"\n", "#include \"TParallelCoordVar.h\"\n", "#include \"TROOT.h\"\n", "#include \"TTree.h\"\n", "#include \"TLeaf.h\"\n", "#include \"THnSparse.h\"\n", "#include \"TAxis.h\"\n", "#include \"TCanvas.h\"\n", "#include \"TRandom.h\"\n", "#include \"TFile.h\"\n", "#include \"TH3.h\"\n", "\n", "TTree* toTree(THnSparse* h)\n", "{\n", " // Creates a TTree and fills it with the coordinates of all\n", " // filled bins. The tree will have one branch for each dimension,\n", " // and one for the bin content.\n", "\n", " Int_t dim = h->GetNdimensions();\n", " TString name(h->GetName()); name += \"_tree\";\n", " TString title(h->GetTitle()); title += \" tree\";\n", "\n", " TTree* tree = new TTree(name, title);\n", " Double_t* x = new Double_t[dim + 1];\n", " memset(x, 0, sizeof(Double_t) * (dim + 1));\n", "\n", " TString branchname;\n", " for (Int_t d = 0; d < dim; ++d) {\n", " if (branchname.Length())\n", " branchname += \":\";\n", " TAxis* axis = h->GetAxis(d);\n", " branchname += axis->GetName();\n", " branchname += \"/D\";\n", " }\n", " tree->Branch(\"coord\", x, branchname);\n", " tree->Branch(\"bincontent\", &x[dim], \"bincontent/D\");\n", "\n", " Int_t *bins = new Int_t[dim];\n", " for (Long64_t i = 0; i < h->GetNbins(); ++i) {\n", " x[dim] = h->GetBinContent(i, bins);\n", " for (Int_t d = 0; d < dim; ++d) {\n", " x[d] = h->GetAxis(d)->GetBinCenter(bins[d]);\n", " }\n", "\n", " tree->Fill();\n", " }\n", "\n", " delete [] bins;\n", " //delete [] x;\n", " return tree;\n", "}" ] }, { "cell_type": "markdown", "id": "f361f8fd", "metadata": {}, "source": [ " Definition of a helper function: " ] }, { "cell_type": "code", "execution_count": 2, "id": "53315baf", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:34.749120Z", "iopub.status.busy": "2026-05-19T20:19:34.748981Z", "iopub.status.idle": "2026-05-19T20:19:34.760000Z", "shell.execute_reply": "2026-05-19T20:19:34.759441Z" } }, "outputs": [], "source": [ "%%cpp -d\n", "void drawsparse_draw(THnSparse* h)\n", "{\n", " // Draw a THnSparse using TParallelCoord, creating a temporary TTree.\n", "\n", " TTree* tree = toTree(h);\n", "\n", " TString whatToDraw;\n", " TIter iLeaf(tree->GetListOfLeaves());\n", " const TLeaf* leaf = nullptr;\n", " while ((leaf = (const TLeaf*)iLeaf())) {\n", " if (whatToDraw.Length())\n", " whatToDraw += \":\";\n", " whatToDraw += leaf->GetName();\n", " }\n", " tree->Draw(whatToDraw, \"\", \"para\");\n", " TParallelCoord* parallelCoord = (TParallelCoord*)gPad->GetListOfPrimitives()->FindObject(\"ParaCoord\");\n", "\n", " TIter iVar(parallelCoord->GetVarList());\n", " TParallelCoordVar* var = nullptr;\n", " for (Int_t d = 0;(var = (TParallelCoordVar*) iVar()) && d < h->GetNdimensions(); ++d) {\n", " TAxis* axis = h->GetAxis(d);\n", " var->SetHistogramBinning(axis->GetNbins());\n", " var->SetCurrentLimits(axis->GetXmin(), axis->GetXmax());\n", " var->SetTitle(axis->GetTitle());\n", " }\n", " var->SetTitle(\"bin content\");\n", "}" ] }, { "cell_type": "markdown", "id": "8cc99b26", "metadata": {}, "source": [ "create a THnSparse and draw it." ] }, { "cell_type": "code", "execution_count": 3, "id": "f6abf069", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:34.761149Z", "iopub.status.busy": "2026-05-19T20:19:34.761034Z", "iopub.status.idle": "2026-05-19T20:19:35.263467Z", "shell.execute_reply": "2026-05-19T20:19:35.262755Z" } }, "outputs": [], "source": [ "const Int_t ndims = 8;\n", "Int_t bins[ndims] = {10, 10, 5, 30, 10, 4, 18, 12};\n", "Double_t xmin[ndims] = {-5., -10., -1000., -3., 0., 0., 0., 0.};\n", "Double_t xmax[ndims] = {10., 70., 3000., 3., 5., 2., 2., 5.};\n", "auto hs = new THnSparseD(\"hs\", \"Sparse Histogram\", ndims, bins, xmin, xmax);" ] }, { "cell_type": "markdown", "id": "23117a98", "metadata": {}, "source": [ "fill it" ] }, { "cell_type": "code", "execution_count": 4, "id": "16126a6e", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:35.265193Z", "iopub.status.busy": "2026-05-19T20:19:35.265075Z", "iopub.status.idle": "2026-05-19T20:19:35.470634Z", "shell.execute_reply": "2026-05-19T20:19:35.469893Z" } }, "outputs": [], "source": [ "Double_t x[ndims];\n", "for (Long_t i = 0; i < 100000; ++i) {\n", " for (Int_t d = 0; d < ndims; ++d) {\n", " switch (d) {\n", " case 0:\n", " x[d] = gRandom->Gaus() * 2 + 3.;\n", " break;\n", " case 1:\n", " case 2:\n", " case 3:\n", " x[d] = (x[d - 1] * x[d - 1] - 1.5) / 1.5 + (0.5 * gRandom->Rndm());\n", " break;\n", " default:\n", " x[d] = sin(gRandom->Gaus()*i/1000.) + 1.;\n", " }\n", " }\n", " hs->Fill(x);\n", "}\n", "\n", "auto f = TFile::Open(\"drawsparse.root\", \"RECREATE\");\n", "\n", "auto canv = new TCanvas(\"hDrawSparse\", \"Drawing a sparse hist\");\n", "canv->Divide(2);" ] }, { "cell_type": "markdown", "id": "133a0c61", "metadata": {}, "source": [ "draw it" ] }, { "cell_type": "code", "execution_count": 5, "id": "4e3e037d", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:35.472262Z", "iopub.status.busy": "2026-05-19T20:19:35.472146Z", "iopub.status.idle": "2026-05-19T20:19:35.677578Z", "shell.execute_reply": "2026-05-19T20:19:35.676953Z" } }, "outputs": [], "source": [ "canv->cd(1);\n", "drawsparse_draw(hs);" ] }, { "cell_type": "markdown", "id": "c2da09b4", "metadata": {}, "source": [ "project it" ] }, { "cell_type": "code", "execution_count": 6, "id": "d5a5b935", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:35.679764Z", "iopub.status.busy": "2026-05-19T20:19:35.679594Z", "iopub.status.idle": "2026-05-19T20:19:35.883778Z", "shell.execute_reply": "2026-05-19T20:19:35.883097Z" } }, "outputs": [], "source": [ "canv->cd(2);\n", "TH3D* h3proj = hs->Projection(2, 3, 6);\n", "h3proj->SetLineColor(kOrange);\n", "h3proj->SetDirectory(nullptr);\n", "h3proj->Draw(\"lego1\");" ] }, { "cell_type": "markdown", "id": "324c88eb", "metadata": {}, "source": [ "save everything to a file" ] }, { "cell_type": "code", "execution_count": 7, "id": "3b3a01ed", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:35.885840Z", "iopub.status.busy": "2026-05-19T20:19:35.885722Z", "iopub.status.idle": "2026-05-19T20:19:36.091076Z", "shell.execute_reply": "2026-05-19T20:19:36.090439Z" } }, "outputs": [], "source": [ "canv->Write();\n", "hs->Write();\n", "h3proj->Write();\n", "\n", "delete f;" ] }, { "cell_type": "markdown", "id": "7d5f883c", "metadata": {}, "source": [ "Draw all canvases " ] }, { "cell_type": "code", "execution_count": 8, "id": "7c2bf3d2", "metadata": { "collapsed": false, "execution": { "iopub.execute_input": "2026-05-19T20:19:36.093158Z", "iopub.status.busy": "2026-05-19T20:19:36.093040Z", "iopub.status.idle": "2026-05-19T20:19:36.548802Z", "shell.execute_reply": "2026-05-19T20:19:36.548040Z" } }, "outputs": [ { "data": { "text/html": [ "\n", "\n", "