9.2節 ランダムノイズ
著者:梅谷 武
放射線計数にランダムノイズが重畳したときにχ2適合度検定でそれを検知する実験について述べる。
作成:2012-03-17
更新:2012-03-17
9.1節の実験において、入力パルス列に与えられた割合のランダムノイズを合成し、その影響を調べる。
 λ=1.0(60cpm相当)においてランダムノイズの割合を変えながら、1000回繰り返したときの、標本平均、標準偏差、有意水準5%χ2検定棄却数を記す。

ノイズ: 0%

[1] " 59.0 ±   5.6 [cpm], err = 45"

ノイズ:10%

[1] " 65.7 ±   6.8 [cpm], err = 53"

ノイズ:20%

[1] " 73.8 ±   8.1 [cpm], err = 94"

ノイズ:30%

[1] " 84.2 ±   9.5 [cpm], err = 329"
# 関数:乱数による計数列生成
# 戻値:時間間隔毎計数列
# sampling(
#   num,	総数
#   rat,	平均到着率[1/s]
#   dt,		計測時間間隔[s]
#   per		ランダムノイズの割合
# )
# 1. 指数分布乱数により待ち時間生成
# 2. パルス時刻列作成
# 3. 時間間隔内の計数列作成
sampling <- function( num, rat, dt, per ) {
  numnoi <- num*per
  numexp <- num - numnoi
  waitings <- rexp( numexp, rate=rat )
  times <- numeric( numexp )
  i <- 1
  for ( t in waitings ) {
    if ( i == 1 ) times[i] <- t
    else times[i] <- times[i-1] + t
    i <- i + 1
  }
  if ( numnoi > 0 ) {
    noise <- runif( numnoi, min=0.0, max=max( times ) )
    times <- c( times, noise )
    times <- sort( times )
  }
  n <- ceiling( max( times ) / dt )
  freq <- numeric( n )
  for ( t in times ) {
    i <- ceiling( t / dt )
    freq[i] <- freq[i] + 1
  }
  return( freq )
}
 
# 関数:乱数による計数列生成し、測定結果を戻す
# 戻値:測定結果表
# measure(
#   num,	総数
#   rat,	平均到着率[1/s]
#   dt,		計測時間間隔[s]
#   per		ランダムノイズの割合
# )
# 1. 乱数による計数列生成
# 2. χ^2適合度検定
# 3. (λ,自由度,χ^2,右側確率,cpm)を戻す
measure <- function( num, rat, dt, per ) {
  r <- sampling( num, rat, dt, per )
  n <- length( r )
  k <- max( r ) + 1
  o <- numeric( k )
  for ( i in r ) {
    o[i+1] <- o[i+1] + 1
  }
  x <- 0:(k-1)
  l <- sum( o * x ) / n
  p <- exp(-l) * l^x / factorial(x)
  p[k] <- 1 - sum( p[-k] )
  e <- n * p
  #plot( x, o, type="h", xlab="", ylab="" )
  #points( x, e, type="l", col="red" )
  while ( e[1] < 5 ) {
    o[2] <- o[2] + o[1]
    e[2] <- e[2] + e[1]
    o <- o[-1]
    e <- e[-1]
    k <- k - 1
  }
  while ( e[k] < 5 ) {
    o[k-1] <- o[k-1] + o[k]
    e[k-1] <- e[k-1] + e[k]
    o <- o[-k]
    e <- e[-k]
    k <- k - 1
  }
  z <- sum( (o - e)^2 / e )
  q <- pchisq( z, (k-2), lower.tail=FALSE )
  if ( is.nan(q) ) q = -1
  cpm <- num * 60 / (n*dt)
  return( c( l, (k-2), z, q, cpm ) )
}
 
# メインルーチン
# 指定パラメータで測定シミュレーションを繰り返し、
# 平均値、分散、χ^2検定棄却数を表示する。
per <- 0.0
rat <- 1.0
if ( rat <= 1.0 ) {
  num <- 100
} else {
  num <- 100 * rat
}
dt  <- 5
len <- 1000
cpm <- numeric( len )
err <- 0
for ( i in 1:len ) {
  dat <- measure( num, rat, dt, per )
  sprintf("m = %4.2f, n = %d, chi = %5.3f, p = %5.4f, cpm = %5.1f",
    dat[1], dat[2], dat[3], dat[4], dat[5] )
  cpm[i] <- dat[5]
  if ( dat[4] < 0.05 ) err <- err + 1
}
sprintf( "%5.1f ± %5.1f [cpm], err = %d",
  mean( cpm ), sd( cpm ), err )