让(实验和测量仪器的)物理学指导您。
最终,吸收是通过测量穿过介质的辐射量来确定的,而这些测量归结为光子计数。当介质是宏观的时,浓度的热力学波动可以忽略不计,因此误差的主要来源在于计数。该误差(或“散粒噪声”)具有泊松分布。这意味着当很少有辐射通过时,在高浓度时误差相对较大。
在实验室中,如果有足够的注意,通常可以非常准确地测量浓度,因此我不会担心浓度误差。
吸光度本身与测量辐射的对数直接相关。取对数可以平衡整个可能浓度范围内的误差量。仅出于这个原因,最好根据其通常值来分析吸光度,而不是重新表达它们。 特别是,我们应该避免记录吸光度,即使这会简化 Beer-Lambert 定律的表达。
我们还应该警惕可能的非线性。Beer-Lambert 定律 的推导表明,吸光度与浓度曲线在高浓度下将变为非线性。需要某种方法来检测或测试这一点。
这些考虑提出了一个简单的程序来分析一系列对浓度和测量的吸光度:(Ci,Ai)
估计系数作为的。κA/Cκ^=∑iAiCi
根据估计系数预测每个浓度的吸光度:A^(C)=κ^C.
检查中非线性趋势的加性残差。Ai−Ai^Ci
当然,所有这些都是理论上的,有些推测——我们没有任何实际数据可供分析——但这是一个合理的起点。如果重复的实验室经验表明数据与此处描述的统计行为不同,则需要对这些程序进行一些修改。
为了说明这些想法,我创建了一个模拟来实现测量的关键方面,包括泊松噪声和可能的非线性响应。通过多次运行,我们可以观察到实验室中可能遇到的那种变化。这是一次模拟运行的结果。(其他模拟可以简单地通过更改下面代码中的起始种子并根据需要修改各种参数来执行。)

至的吸光度。散点图中明显的垂直扩散值显示了 (a) 透射测量中的散粒噪声和 (b) 零浓度下初始透射测量中的散粒噪声的影响。(注意这实际上是如何产生一些负吸光度值的。)虽然由此产生的误差在每个浓度下不会具有完全相同的分布,但大致相等的分布是经验证据,表明分布足够接近我们需要的相同'不用担心。换言之,无需根据浓度对吸光度进行加权。11/32
红色对角线是根据所有 50 次模拟估算的。它的斜率为 ,与模拟中使用略有不同。这个偏差如此之大,因为我认为要测量的辐射非常少;最大光子数仅为。在实践中,最大计数可能比这大许多数量级,从而导致高度精确的斜率估计——但是我们不会从这个数字中学到很多东西!κ^=2.1321000
残差直方图看起来不太好:它向右倾斜。这表明某种麻烦。问题不在于每个浓度的残差不对称;相反,它来自于不合身。这在右边的箱线图中很明显:虽然前五个几乎水平排列,但最后一个 - 在最高浓度 - 位置(太高)和规模(太长)明显不同. 这是我在模拟中内置的非线性响应造成的。尽管非线性存在于整个浓度范围内,但仅在最高浓度时才具有明显的影响。这或多或少也将在实验室中发生。然而,只有一次校准运行可用,我们无法绘制这样的箱线图。 如果非线性可能是一个问题,请考虑分析多个独立运行。
模拟在R. 但是,使用实际数据的计算很容易手动或使用电子表格进行:只需确保检查残差的非线性即可。
#
# Simulate instrument responses:
# `concentration` is an array of concentrations to use.
# `kappa` is the Beer-Lambert law coefficient.
# `n.0` is the largest expected photon count (at 0 concentration).
# `start` is a tiny positive value used to avoid logs of zero.
# `beta` is the amount of nonlinearity (it is a quadratic perturbation
# of the Beer-Lambert law).
# The return value is a parallel array of measured absorbances; it is subject
# to random fluctuations.
#
observe <- function(concentration, kappa=1, n.0=10^3, start=1/6, beta=0.2) {
transmission <- exp(-kappa * concentration - beta * concentration^2)
transmission.observed <- start + rpois(length(transmission), transmission * n.0)
absorbance <- -log(transmission.observed / rpois(1, n.0))
return(absorbance)
}
#
# Perform a set of simulations.
#
concentration <- 2^(-(0:5)) # Concentrations to use
n.iter <- 50 # Number of iterations
set.seed(17) # Make the results reproducible
absorbance <- replicate(n.iter, observe(concentration, kappa=2))
#
# Put the results into a data frame for further analysis.
#
a.df <- data.frame(absorbance = as.vector(absorbance))
a.df$concentration <- concentration # ($ interferes with TeX processing on this site)
#
# Create the figures.
#
par(mfrow=c(1,3))
#
# Set up a region for the scatterplot.
#
plot(c(min(concentration), max(concentration)),
c(min(absorbance), max(absorbance)), type="n",
xlab="Concentration", ylab="Absorbance",
main=paste("Scatterplot of", n.iter, "iterations"))
#
# Make the scatterplot.
#
invisible(apply(absorbance, 2,
function(a) points(concentration, a, col="#40404080")))
slope <- mean(a.df$absorbance / a.df$concentration)
abline(c(0, slope), col="Red")
#
# Show the residuals.
#
a.df$residuals <- a.df$absorbance - slope * a.df$concentration # $
hist(a.df$residuals, main="Histogram of residuals", xlab="Absorbance Difference") # $
#
# Study the residual distribution vs. concentration.
#
boxplot(a.df$residuals ~ a.df$concentration, main="Residual distributions",
xlab="Concentration")