[ROOT] 三次元グラフを描くTips

更新日:2022年11月20日(初版作成日:2021年11月15日)

サンプルヒストグラム ©SKラボラ

三次元グラフの描画

ROOTでは、TGraph2DもしくはTH2Dを使用すると、三次元グラフを描画できる。
しかし、データによって、少し注意が必要になる。
本記事では、それぞれのサンプル、注意点を紹介する。

サンプル三次元データ

まず、次のようなデータを使用する。

  1. x 0.1
  2. y 0.001
  3. z 2.77643
  4. x 0.1
  5. y 0.002
  6. z 2.76138
  7. x 0.1
  8. y 0.003
  9. z 2.75712
  10. x 0.2
  11. y 0.001
  12. z 2.78065
  13. x 0.2
  14. y 0.002
  15. z 2.76376
  16. x 0.2
  17. y 0.003
  18. z 2.75256
  19. x 0.3
  20. y 0.001
  21. z 2.76777
  22. x 0.3
  23. y 0.002
  24. z 2.74981
  25. x 0.3
  26. y 0.003
  27. z 2.73483
  28. x 0.4
  29. y 0.001
  30. z 2.80185
  31. x 0.4
  32. y 0.002
  33. z 2.7848
  34. x 0.4
  35. y 0.003
  36. z 2.76798

これは、下図のような、右手前に大きな山があって、奥方向(y方向)に下がり、真ん中(xの中間)に谷があるようなデータである。

サンプルヒストグラム ©SKラボラ

三次元データ描画

TGraph2Dは、それらしい領域を生成する。
TH2Dは、自前でデータ区切りを生成する。
以下、前半がTGraph2Dによる描画、後半がTH2Dによる描画である。

  1. #include <iostream>
  2. #include <fstream>
  3. #include "TApplication.h"
  4. #include "TCanvas.h"
  5. #include "TH2D.h"
  6. #include "TPaletteAxis.h"
  7. #include "TGraph2D.h"
  8. #include "TLatex.h"
  9. #include "TROOT.h"
  10. #include "TStyle.h"
  11.  
  12. int main (int argc, char **argv)
  13. {
  14. using namespace std;
  15. TApplication app("app", &argc, argv);
  16. //
  17. ifstream fin;
  18. fin.open (app.Argv(1));
  19. if (fin.fail()){
  20. cout << "No data file" << endl;
  21. exit(-1);
  22. }
  23. //
  24. char x_char[3];
  25. char y_char[3];
  26. char z_char[3];
  27. //
  28. int number_of_x = 4;
  29. int number_of_y = 3;
  30. int data_size = number_of_x * number_of_y;
  31. int read_data_size = 0;
  32. //
  33. double x;
  34. double y;
  35. double z;
  36. //
  37. double x_array[data_size];
  38. double y_array[data_size];
  39. double z_array[data_size];
  40. //
  41. cout << "Reading data file..." << endl;
  42. //
  43.  
  44. // This depdends on the data format.
  45. fin >> x_char >> x;
  46. fin >> y_char >> y;
  47. fin >> z_char >> z;
  48. //
  49. for (int i=0;i<data_size;i++) { // "<=" is for cheking data size
  50. if (fin.eof()) {
  51. cout << "Last data was read. Not completed data." << endl;
  52. cout << i << endl;
  53. read_data_size = i;
  54. break;
  55. }
  56. //
  57. cout << x_char << " " << x << endl;
  58. cout << y_char << " " << y << endl;
  59. cout << z_char << " " << z << endl;
  60. //
  61. if (strcmp(x_char, "x")) {
  62. cout << "x data error!" << endl; exit(-1);
  63. }
  64. if (strcmp(y_char, "y")) {
  65. cout << "y data error!" << endl; exit(-1);
  66. }
  67. if (strcmp(z_char, "z")) {
  68. cout << "z data error!" << endl; exit(-1);
  69. }
  70.  
  71. x_array[i] = x;
  72. y_array[i] = y;
  73. z_array[i] = z;
  74. cout << i+1 << " data stored." << endl;
  75. read_data_size = i+1;
  76.  
  77. // This depdends on the data format.
  78. fin >> x_char >> x;
  79. fin >> y_char >> y;
  80. fin >> z_char >> z;
  81. }
  82.  
  83. cout << "Drawing graphs." << endl;
  84.  
  85. gROOT->SetStyle("Plain");
  86. gStyle->SetFrameFillColor(0);
  87. gStyle->SetCanvasColor(0);
  88. gStyle->SetOptStat(0);
  89. gStyle->SetPaperSize(40, 52);
  90. gStyle->SetPalette(1);
  91. //
  92. //
  93. //////////////////////////////////////////////////////////////////////////////////////
  94. // canvas size
  95. int canvas_y_size = 500;
  96. double silver_ratio = 1.4142;
  97. //
  98. TCanvas *c = new TCanvas("c", "c", 0, 0, (int)(double)canvas_y_size*silver_ratio, canvas_y_size);
  99. TPad *p = new TPad("p", "p", 0.05, 0.05, 0.95, 1.0);
  100. p->SetFillStyle(4000);
  101. p->Draw();
  102. p->cd();
  103. //
  104.  
  105. TGraph2D *g1 = new TGraph2D();
  106. int n = 0;
  107. while(n < read_data_size){
  108. g1->SetPoint(n, x_array[n], y_array[n], z_array[n]);
  109. n++;
  110. }
  111.  
  112. g1->SetTitle("");
  113. g1->SetNpx(10);
  114. g1->SetNpy(10);
  115. g1->Draw("COLZ"); // COLS, surf1 and surf3
  116. // g1->Draw("LEGO2Z");
  117.  
  118. c->Update();
  119. p->Update();
  120.  
  121. TAxis *x_axis = g1->GetHistogram("empty")->GetXaxis();
  122. x_axis->SetLabelSize(0.03);
  123. x_axis->SetLabelOffset(0.02);
  124. TAxis *y_axis = g1->GetHistogram("empty")->GetYaxis();
  125. y_axis->SetLabelSize(0.03);
  126. TPaletteAxis *pal = (TPaletteAxis *)g1->GetHistogram("empty")->GetListOfFunctions()->FindObject("palette");
  127. pal->GetAxis()->SetLabelSize(0.03);
  128.  
  129. g1->Draw("COLZ");
  130. // g1->Draw("LEGO2Z");
  131. // g1->Draw("surf1");
  132. // g1->Draw("surf3");
  133.  
  134. c->cd();
  135. TLatex *c_title = new TLatex (0.03, 0.95, Form("TGraph2D sample"));
  136. c_title->Draw();
  137. //
  138. //
  139. TLatex *x_axis_title = new TLatex (0.50, 0.03, Form("X title"));
  140. x_axis_title->Draw();
  141. //
  142. TLatex *y_axis_title = new TLatex (0.05, 0.51, Form("Y title"));
  143. y_axis_title->SetTextAngle(90);
  144. y_axis_title->Draw();
  145. //
  146. TLatex *z_axis_title = new TLatex (0.99, 0.51, Form("Z title"));
  147. z_axis_title->SetTextAngle(90);
  148. z_axis_title->Draw();
  149.  
  150. ///////////////////////////////////////////////////////////////////////////////////////
  151. TCanvas *c2 = new TCanvas("c2", "c2", 0, 0, (int)(double)canvas_y_size*silver_ratio, canvas_y_size);
  152. TPad *p2 = new TPad("p2", "p2", 0.05, 0.05, 0.95, 1.0);
  153. p2->SetFillStyle(4000);
  154. p2->Draw();
  155. p2->cd();
  156. //
  157. // You should make your own boxes.
  158. double x_axis_array[5] = {0.08, 0.15, 0.25, 0.32, 0.45};
  159. double y_axis_array[4] = {0.0005, 0.0015, 0.0025, 0.0035};
  160. TH2D *h = new TH2D ("h", "", number_of_x, x_axis_array, number_of_y, y_axis_array);
  161.  
  162. for (int i=1;i<=number_of_x;i++){
  163. for (int j=1;j<=number_of_y;j++) {
  164. for (int m=0;m< read_data_size;m++){
  165. if (
  166. (x_axis_array[i-1] < x_array[m] && x_array[m] < x_axis_array[i]) &&
  167. (y_axis_array[j-1] < y_array[m] && y_array[m] < y_axis_array[j])
  168. ) {
  169. h->SetBinContent(i, j, z_array[m]);
  170. break;
  171. }
  172. }
  173. }
  174. }
  175. h->GetXaxis()->SetLabelSize(0.03);
  176. h->GetXaxis()->SetLabelOffset(0.02);
  177. h->GetYaxis()->SetLabelSize(0.03);
  178. h->GetZaxis()->SetLabelSize(0.03);
  179. h->SetMaximum(2.8);
  180. h->SetMinimum(2.733);
  181. h->Draw("COLZ");
  182. // h->Draw("LEGO2Z");
  183. // h->Draw("surf1");
  184. // h->Draw("surf3");
  185.  
  186. c2->cd();
  187. TLatex *c2_title = new TLatex (0.03, 0.95, Form("TH2D sample"));
  188. c2_title->Draw();
  189. //
  190. TLatex *x_axis_title2 = new TLatex (0.50, 0.03, Form("X title"));
  191. x_axis_title2->Draw();
  192. //
  193. TLatex *y_axis_title2 = new TLatex (0.05, 0.51, Form("Y title"));
  194. y_axis_title2->SetTextAngle(90);
  195. y_axis_title2->Draw();
  196. //
  197. TLatex *z_axis_title2 = new TLatex (0.99, 0.51, Form("Z title"));
  198. z_axis_title2->SetTextAngle(90);
  199. z_axis_title2->Draw();
  200. //
  201. p2->Draw();
  202. //
  203. app.Run();
  204. }

Makefile
注意)コピペの場合、18、21、25行目の先頭はタブ

  1. source = sample.cc
  2. object = sample.o
  3. target = sample
  4.  
  5. CC = g++ -O2
  6. CFLAGS = -Wall
  7.  
  8. ROOTCONFIG := root-config
  9. ROOTCFLAGS := $(shell $(ROOTCONFIG) --cflags)
  10. ROOTLDFLAGS := $(shell $(ROOTCONFIG) --ldflags)
  11. ROOTLIBS := $(shell $(ROOTCONFIG) --libs)
  12. ROOTGLIBS := $(shell $(ROOTCONFIG) --glibs)
  13.  
  14. ALLROOTLIBS = $(ROOTLIBS) $(ROOTGLIBS) $(HASTHREAD)
  15. ALLROOTFLAGS = $(ROOTCFLAGS) $(ROOTLDFLAGS)
  16.  
  17. $target : $(object)
  18. $(CC) -o $(target) $(ALLROOTLIBS) -lRooFit -lRooFitCore -lFoam -lMinuit -lGui $(object)
  19.  
  20. $(object): $(source)
  21. $(CC) -c $(CFLAGS) $(ALLROOTFLAGS) $(source)
  22.  
  23. .PHONY: clean
  24. clean:
  25. rm $(target) $(object)

描画結果

このようなデータ、グラフ作成の場合、TGraph2D、TH2Dで本質的な違いは無い。
(TH2Dの描画でデータが無い領域をつくらないように調整している)

サンプル©SKラボラ
サンプル©SKラボラ

TH2Dで、データが無い領域がある場合

上記データにおいて、上から1番目、左から2番目の領域にあるデータと上から2番目、左から4番目のデータを削除する。

  1. x 0.1
  2. y 0.001
  3. z 2.77643
  4. x 0.1
  5. y 0.002
  6. z 2.76138
  7. x 0.1
  8. y 0.003
  9. z 2.75712
  10. x 0.2
  11. y 0.001
  12. z 2.78065
  13. x 0.2
  14. y 0.002
  15. z 2.76376
  16. x 0.3
  17. y 0.001
  18. z 2.76777
  19. x 0.3
  20. y 0.002
  21. z 2.74981
  22. x 0.3
  23. y 0.003
  24. z 2.73483
  25. x 0.4
  26. y 0.001
  27. z 2.80185
  28. x 0.4
  29. y 0.003
  30. z 2.76798

描画結果

TGraph2Dは、ナチュラルに補完するため、先程のデータほぼ同じになる。
TH2Dは、”データの無し”を検出できる。

サンプル©SKラボラ
サンプル©SKラボラ

注意)legoプロットの場合、”データ無し”は検出できない。
下図のように、最低点の色で描画される。TGraph2Dとは意味の異なるデータになる。

サンプル©SKラボラ

参考

ROOT

改訂履歴

2022年11月20日:参考追加
2022年10月25日:体裁調整
通し番号:040(管理用)

タイトルとURLをコピーしました