1.3 ADC/TDC 信号处理:从物理量到数字化¶
1. 目的¶
- 掌握模拟电信号(时间、幅度)如何进行数字化(保存为整数道值)。
- 理解基线偏移(Pedestal)、超界(Overflow)。
- 有效事件的选择(cut)
2. Digitization (数字化)¶
在模拟代码中,事件的变量(如 $q_L/q_R$, $t_L/t_R$)通常是无限精度的浮点数 (double)。但在真实实验中,探测器输出的连续模拟信号经过电子学模块(ADC / TDC / QDC)后,会被量化为离散的整数(Channel / 道值),这个过程就叫数字化。
A. ADC / QDC (模拟/电荷-数字转换器)¶
ADC / QDC 用于记录输入信号的大小(ADC 测电压幅度,QDC 测电荷积分)。
假设一个 12-bit 的 ADC,硬件输入量程为 0-4V。 它的转换公式可以直白地写为:
$$ \mathrm{Raw\_ADC} = \mathrm{Int}(\text{信号幅度} \times \mathrm{Gain} + \mathrm{Pedestal} + \text{噪声涨落}) $$
具体参数说明:¶
- 信号幅度 (Input Signal): 实际进入 ADC 的模拟电压(例如 2.5V)。
- Gain (增益/转换系数): 把电压映射到道值的比例。
- 例如量程 0-4V 对应 0-4095 ch,那么 Gain 大约是 $4095 / 4\mathrm{mV} \approx 1.024 \text{ ch/mV}$。输入 2.5V 就会被放大/转换到 2560 ch。
- Pedestal (基线/直流偏置):
- 因为真实的零信号总带有电子学噪声,噪声有正有负。如果基线设在 0 ch,负向噪声就会被 ADC 丢弃(无法记录负数)。
- 在硬件上给输入端叠加一个固定的直流电压,将“没有信号时的零点”推高(比如推到 140 ch)。这样噪声再怎么负向波动,也不会低于 0 ch。
- Pedestal 并不是一个固定的数值,而是一个分布。即使没有物理信号输入(Signal=0),ADC 读数也会在某个基准值附近波动。这种波动主要来源于:探测器噪声以及电子学噪声。这使得 Pedestal 呈现为一个高斯分布,其宽度由标准差 $\sigma$ 描述。如果只扣除均值(Mean),那么噪声的正向涨落就会被误认为是微弱的物理信号。

- Range (量程):
- 12-bit:
0 ~ 4095ch - 14-bit:
0 ~ 16383ch
- 12-bit:
- Overflow (上溢): 如果输入信号太大(比如 5V),算出来的道值超过了 4095,ADC 只能强制记录为最大值
4095。
B. TDC (时间-数字转换器)¶
TDC 用于记录 Start 和 Stop 两个信号之间的时间差。
假设这个 TDC 的时间测量量程是 0-100ns,精度是 12-bit (0-4095 ch)。 它的转换公式为:
$$ \mathrm{Raw\_TDC} = \mathrm{Int}\left( (T_{\mathrm{stop}} - T_{\mathrm{start}} + \mathrm{Delay}) \times \mathrm{转换系数} \right) $$
具体参数说明:¶
- 转换系数: 把时间差换算成道值的系数。
- 在这个例子中,100ns 对应 4096 个道址,转换系数就是 $4096 / 100\mathrm{ns} \approx 40.96 \text{ ch/ns}$。
- Delay:
- TDC 只能测正的时间差(0-100ns)。但在实际连线中,因为电缆长度或触发逻辑,
Stop信号有可能比Start信号先到(时间差变成负的,比如 -10ns),TDC 就无法记录。 - 在硬件或逻辑上给信号强行加上一段固定的 Delay(比如 +30ns),把原本 -10ns 的时间差整体平移到 +20ns,让它稳稳地落在 0-100ns 的合法量程内。
- TDC 只能测正的时间差(0-100ns)。但在实际连线中,因为电缆长度或触发逻辑,
- Range (量程):
- 12-bit:
0 ~ 4095ch - 14-bit:
0 ~ 16383ch
- 12-bit:
- Overflow (上溢): 如果两个信号的时间差超过了 TDC 的最大量程(比如相差 150ns),超出部分无法记录,强制记录为满刻度
4095。
3. 物理过程¶
- 束流轰击靶以产生带电粒子、n、$\gamma$等粒子,重带电粒子碎片被靶后 Dipole magnet偏走,而部分轻带电粒子(LP: light particles,主要为质子)没有被完全偏走,仍然进入中子探测器。
真实数据获取 (DAQ) 中,触发逻辑决定了我们记录什么事件:
- 物理触发 (Trig_Phys):中子,Gamma或LP 击中探测器。(
pid=0, 1,2) - 束流/时钟触发 (Trig_Clock):强制触发,用于监测电子学基线状态。在此类事件中,探测器没有物理信号,只有电子学噪声。(
pid=3)
4. 代码:基于 1.1 代码进行修改¶
定义数字化参数与分支¶
// --- 新增变量 ---
Int_t iAL, iAR; // QDC道值 (0-4095)
Int_t itL, itR; // TDC道值 (0-4095)
Int_t pid; // 0:G, 1:N, 2:LP, 3:Pedestal
// --- 数字化与电子学参数 ---
const Double_t ADC_Gain = 5.0; // 增益
const Double_t TDC_Gain = 25.0; // 转换系数 (如40ps/ch)
const Double_t Ped_L = 140.0, Ped_R = 130.0; // 基线
const Double_t Noise = 8.5; // 电子学噪声
const Double_t Trig_Dly = 50.0; // 延迟
const Int_t Max_ADC = 4095; // 12-bit
const Int_t Threshold = 180; // 触发阈值(道值)
// --- Branch 映射 (省略原有部分) ---
opt->Branch("pid", &pid, "pid/I");
opt->Branch("iAL", &iAL, "iAL/I"); // ... 其余同理
事件生成 ($E_n \to E_p \to E_{ee}$)¶
// 1. 抽样生成 pid
Double_t rnd = gr->Uniform();
if (rnd < 0.10) pid = 3; // 空触发/时钟触发
else if (rnd < 0.20) pid = 2; // LP (质子)
else pid = (gr->Uniform() < 0.3) ? 0 : 1;
// 2. 物理过程修改
...
if (pid == 2) {
Eee = gr->Gaus(50.0, 5.0); // LP 假设能量全沉积
}
if (pid == 3) {
Eee = 0.0; // Pedestal 无能量
}
数字化 (Digitization) 与 触发逻辑 (Trigger)¶
...
// 1. ADC: 幅度 * 增益 + 基线 + 噪声
iAL = (Int_t)(AL* ADC_Gain + Ped_L + gr->Gaus(0, Noise));
iAR = (Int_t)(AR * ADC_Gain + Ped_R + gr->Gaus(0, Noise));
// 2. TDC: (时间 + 延迟) * 转换系数
if (pid == 3) {
itL = Max_ADC; itR = Max_ADC; // 无物理信号,TDC默认溢出
} else {
itL = (Int_t)((tL + Trig_Dly) * TDC_Gain );
itR = (Int_t)((tR + Trig_Dly) * TDC_Gain );
}
// 3. 超界截断处理
if (iAL > Max_ADC) iAL = Max_ADC; if (iAL < 0) iAL = 0;
// ... iAR, itL, itR 同理 ...
// 4. DAQ 触发逻辑 (物理符合触发 OR 时钟触发)
bool Trig_Phys = (iAL > Threshold) && (iAR > Threshold);
bool Trig_Clock = (pid == 3);
if (Trig_Phys || Trig_Clock) {
tree->Fill(); // 只有满足触发条件才存入 Tree
}
3. 数字化信号处理:筛选 (Cut) 与连续化 (Dithering)¶
从电子学插件(ADC/TDC)获取的原始数据是整数道值(Integers)。在将这些道值转换为物理量(如能量、时间)时,必须经过两个关键步骤:有效范围筛选与变量连续化。
3.1. 运算的前提:合理选择有效范围¶
在对原始变量进行任何数学运算(如求和、平均、开方)之前,必须确保参与运算的数据具有物理意义。
确定低能阈值¶
为了区分“纯噪声”和“真实微弱信号”,需要设定一个阈值(Threshold)。
- 方法:对空触发(或无束流)数据绘制 ADC 谱,拟合 Pedestal 峰得到均值 $\mu_{ped}$ 和标准差 $\sigma_{ped}$。
- 标准:通常选择 $\mu_{ped} + 3\sigma_{ped}$ 作为阈值。
- 根据高斯分布性质,噪声涨落超过 $3\sigma$ 的概率仅为 0.13%。
- 这意味着:凡是超过这个阈值的信号,有 99.87% 的把握不是噪声。
有效范围筛选 (Cut)¶
在进行任何物理计算(如 $A = k \cdot (ADC - Ped)$)之前,必须先剔除无效数据:
- 噪声区:$ADC < \mu_{ped} + 3\sigma_{ped}$
- 溢出区 (Overflow):$ADC \ge 4095$(12-bit 量程上限)
TDC (针对时间):通常关注溢出 (Overflow)。
- 有效信号必须满足:
itL > 0且itL < Max_TDC(通常为 4095)。 - 说明:若任一端探测器未被击中,TDC 通常记录为 0 或 4095。
以计算平均时间 $T_{avg} = (itL + itR) / 2$ 为例:如果其中一端是无效值(如 4095),直接运算得到的结果将完全错误。
// 在 tree->Draw() 中应用合理范围条件
// 只有当左右两端都在有效量程内,计算平均值才有意义
TCut valid_tdc = "itL > 0 && itL < 4095 && itR > 0 && itR < 4095";
tree->Draw("(itL + itR)/2.0 >> h_avg", valid_tdc);
锯齿现象与连续化 (Dithering)¶
锯齿的成因
ADC/TDC 输出的是离散整数(1, 2, 3...)。当我们对这些整数进行非整数倍的缩放(例如 $Time = 0.5 \times Channel$)或数学运算(如取平均)时,数据点的间距会被拉伸或压缩。 如果直方图的 Bin 宽度与这种拉伸后的间距不匹配(Mismatched Binning),就会导致某些 Bin 收集的数据多,某些 Bin 收集的少,从而在平滑的物理谱上产生非物理的锯齿结构。
解决方案:加入随机抖动(Dithering)
原理:由于量子化误差,真实的物理值等概率分布在 $[N, N+1)$ 区间内。 操作:在每个整数道值上叠加一个 $[0, 1)$ 的随机数。
$$ Val_{cont} = Val_{int} + \text{Random}(0, 1) $$
实例演示:模拟锯齿与连续化¶
下列代码模拟产生一组均匀分布的整数数据,观察对其进行简单运算后的效果。
// 1. 创建直方图
// h_raw: 直接运算,观察锯齿
// h_dither: 连续化后运算,观察平滑
TH1D *h_raw = new TH1D("h_raw", "Raw Calculation;Val;Counts", 100, 40, 60);
TH1D *h_dither = new TH1D("h_dither", "With Dithering;Val;Counts", 100, 40, 60);
TRandom3 rnd(0);
// 2. 模拟 100000 个事件
for (int i = 0; i < 100000; i++) {
// 模拟两个独立的测量值 (假设物理值是50附近的高斯分布,但被数字化成了整数)
Int_t iL = (Int_t)rnd.Gaus(50, 5);
Int_t iR = (Int_t)rnd.Gaus(50, 5);
// --- 场景:计算两个变量的平均值 ---
// A. 错误做法:直接使用整数计算
// 结果只能是 x.0 或 x.5,在直方图 Bin 宽不为 0.5 的倍数时会出现锯齿
Double_t avg_raw = (iL + iR) / 2.0;
// B. 正确做法:先 Dithering 再计算
// 给每个整数加上 [0,1) 的随机量,还原连续性
Double_t iL_cont = iL + rnd.Uniform(0, 1);
Double_t iR_cont = iR + rnd.Uniform(0, 1);
Double_t avg_dither = (iL_cont + iR_cont) / 2.0;
h_raw->Fill(avg_raw);
h_dither->Fill(avg_dither);
}
// 3. 绘图对比
TCanvas *c1 = new TCanvas("c1", "Dithering Demo", 800, 400);
c1->Divide(2, 1);
c1->cd(1);
h_raw->SetLineColor(kRed);
h_raw->Draw(); // 你会看到明显的梳齿状结构
c1->cd(2);
h_dither->SetLineColor(kBlue);
h_dither->Draw(); // 平滑的高斯分布,反映真实物理
c1->Draw();
结果分析¶
- 左图 (Raw):由于
(int + int)/2的结果只能是整数或半整数(如 50.0, 50.5, 51.0...),数据点在数轴上是离散跳跃的。当直方图的 Bin 划分(这里是 100 bins / 20 range = 0.2 width)与这些离散点不对齐时,就会出现剧烈的高低交替(锯齿)。 - 右图 (Dither):加入随机数后,数据填补了整数间的空隙,恢复了物理量的连续性,直方图呈现出平滑高斯形态。
总结¶
对原始变量进行运算时:
- 筛选合理范围:排除噪声以及超界信号, 选择物理上合理的信号区间。
- 连续化:凡是对原始道值做非整数运算(除法、刻度、坐标变换),必须先连续化(叠加 $[0, 1)$ 随机数)。