如何使用 matplotlib 从 ROOT 模拟 Draw('same')

How to mimic the Draw('same') from ROOT with matplotlib

我有一个来自 ROOT 的用例,我无法用 matplotlib 重现。这是一个最小的例子

import numpy as np
import matplotlib.pyplot as plt

fig, ax = plt.subplots()
dist1x = np.random.normal(5, 0.05, 10_000)  
dist1y = np.random.normal(5, 0.05, 10_000)
dist2x = np.random.normal(15, 0.05, 10_000)  
dist2y = np.random.normal(15, 0.05, 10_000)

ax.hist2d(dist1x, dist1y, bins=100, cmap='viridis')
ax.hist2d(dist2x, dist2y, bins=100, cmap='viridis')

plt.show()

输出为

有了ROOT可以做到:

TCanvas *c1 = new TCanvas("c1","c1");

TH1D *h1 = new TH1D("h1","h1",500,-5,5);
h1->FillRandom("gaus");

TH1D *h2 = new TH1D("h2","h2",500,-5,5);
h2->FillRandom("gaus");

h1->Draw();
h2->Draw("SAME");

并且两个直方图会共享canvas、轴等。为什么在同一张图中绘制两个直方图只显示最后一个?如何重现 ROOT 行为?

我认为预期的行为是绘制两个直方图的总和。您可以通过在绘图之前连接数组来做到这一点:

ax.hist2d(np.concatenate([dist1x, dist2x]),
          np.concatenate([dist1y, dist2y]),
          bins=100, cmap='viridis')

(我稍微修改了数字,以确保两个斑点重叠。)


SAMETH2F 在 ROOT 中的默认行为可能是不可取的。

第二个直方图绘制覆盖另一个直方图,覆盖 bin 的填充颜色。如果第二个直方图中至少有一个事件,则第一个直方图中的信息将在每个单元格中被丢弃。

要重现此行为,我建议使用 numpy.histogram2d。如果第二个直方图中有条目,则将第一个直方图的 bin 设置为零,然后绘制两者的总和。

bins = np.linspace(0, 20, 100), np.linspace(0, 20, 100)
hist1, _, _ = np.histogram2d(dist1x, dist1y, bins=bins)
hist2, _, _ = np.histogram2d(dist2x, dist2y, bins=bins)
hist1[hist2 > 0] = 0
sum_hist = hist1 + hist2
plt.pcolormesh(*bins, sum_hist)


如果两个直方图没有任何共同填充的 bin,则这两个行为是相同的。