Skip to content

Jupyter notebook mode

from matplotlib import pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
from scipy.integrate import quad

import random
from scipy import signal

Lecture 1: Noise in measurements

Expected prior knowledge

Before the start of this lecture, you should be able to:

  • Recall the definition of a Fourier transform

Learning goals

After this lecture you will be able to:

  1. Estimate average quantities and their statistical error from noisy measurements
  2. Characterize noise via its power spectral density
  3. Identify common kinds of noise spectra

Interactive notebook

In this notebook, you can explore how to use the interactive mode.

  1. Find and click the icon next to the title of this lecture.
  2. This will initialize a Jupyter server hosted by mybinder.org
  3. It might take a while, in the worst case more than 10 minutes to get the kernel ready, but usually much quicker. It depends on the availability of the binders and the status will show as "launching".
  4. Any (hidden) code on this website will become available for execution and editing like in a Jupyter notebook when the status turns to "ready".
  5. To turn off the interactive mode, refresh the website.

Consider the following problem. We have a small voltage that we want to measure. We assume the voltage to be constant in time. To measure it, we connect the small voltage to an amplifier and then connect our amplified signal to an oscilloscope that records the voltage at its input as a function of time.

On our oscilloscope screen, we see the following trace:

mu, sigma = 0, 1
ts = np.linspace(0,100,100)
vs = np.asarray([np.random.normal(mu,sigma) for t in ts])

plt.plot(ts, vs)
plt.title("Signal")
plt.xlabel("Time (s)")
plt.ylim(-3,3)
plt.ylabel("Voltage (mV)")
plt.show()

svg

What is approximately the value of the voltage? - the average of the trace seems to be about 0 mV - How can we quantify how close it is to 0 mV?

A good first step: create a histogram of the data, which might look like

count, bins, ignored = plt.hist(vs, 20, density=True)
plt.plot(bins, 1/(sigma * np.sqrt(2 * np.pi)) * np.exp( - (bins - mu)**2 / (2 * sigma**2) ),
         linewidth=2, color='r')
plt.title("Histogram of measured voltages and fit to a Gaussian probability distribution")
plt.xlabel("Voltage [mV]")
plt.ylabel("Probability of voltage value")
plt.show()

svg

(In this histogram, we have normalized the bin counts to match the Gaussian fit.)

Fitting to a Gaussian, we find a full-width half-maximum (FWHM) of 2 mV. We thus estimate that, on average, the statistical error in each measurement point is about mV.

However, because we assumed that the voltage we are trying to measure is constant in time, we can reduce the error in our estimate of the unknown small voltage by averaging points together. We know how to calculate the average, but what is the uncertainty in this average value?

Standard error of the mean

The error of our average of points is related to the error of a single point by The quantity is known as the standard error of the mean. How is this quantity related to our histogram above? Adding more points will not change the shape of the distribution, it will only give more counts in each bin.

The reduction of with respect to , however, has nothing to do with the width of the histogram. Rather, it determines how accurately we can determine the center of the peak (the average): The more points we add, the smaller the (relative) statistical fluctuations in the height of each bin will become, and the more accurately we will be able to find the center of the peak.

Caveat

The above equation relating the standard error of the mean to the standard error of a single measurement is only true if the noise in your data is uncorrelated, which means that each data point in your trace represents an independent sampling of the random noise of your amplifier.

Autocorrelation function

How can one know if the noise is uncorrelated? By calculating its autocorrelation function. For a function it is defined as where the angled brackets denote the expectation value/ensemble average.

A common example of correlated noise arises when your signal has some "memory" that is slower than your sampling rate such that consecutive samples will have similar values. For example, if you put a 1 kHz low-pass filter after your amplifier, but configure your oscilloscope to record the signal with a 10 kHz sampling rate, then will look something like this:

ts = np.linspace(0,3,31)
ys = np.exp(-ts)

fig, ax = plt.subplots()
ax.plot(ts, ys)
ax.set_title("Autocorrelation function")
ax.set_ylabel("$R_{vv}$")
ax.set_xlabel("Time difference between data points (ms)")
fig.show()

svg

In this example, we can see that each measured value displayed on our oscilloscope will be strongly correlated with several values in its direct neighborhood. In this case, the values are not independently drawn from the random distribution, and the error in our estimate of the average voltage will not scale with if we average such points

1.2. Power Spectral Density

To summarize so far:

  • The error in estimating the average of a noisy measurement depends on how many (uncorrelated) points we measure
  • If we record a dataset of uncorrelated points for a time , the error in our estimate of the mean value will go down as

However, if we measure for longer periods of time, then our measurements are slower. This becomes an issue if we want to measure a signal that is not constant in time, because increasing reduces the speed at which we can record a changing signal. Thus, there is a tradeoff between the noise level and the bandwidth of your measurement.

Question

if you want buy an amplifier, does it make sense to look at its noise level without looking at its bandwidth? Why (not)?

So then, how do we characterize noisy, time-varying signals? We can compute the power spectral density , which tells us how the "noise power" is distributed across different frequencies.

Definitions

  1. For a signal , we first define a (finite-time, truncated) Fourier transform: where the prefactor is for normalization.

  2. The power spectral density is then defined as the "ensemble average" of the magnitude of :

  3. What do we mean by "ensemble average"?

    • If the noise in our measurement is random, its Fourier transform is also random
    • To reduce the "noise" in our estimate of the noise, we average over the of many different measurement traces

The power spectral density describes how the power in a signal is distributed over different frequencies. It is also called the power spectrum.

How could we measure a power spectral density in practice?

Here, the bandpass filter transmits the part of the signal within a frequency band centered at . The rectifier converts the transmitted signal into a DC voltage . As a result, is proportional to the amount of power present in in the frequency band , given by

1.1. Types of noise specta

White noise

Uncorrelated noise is called 'white noise'. Its power spectral density is flat (independent of frequency)

fs = 1e3
N = 1e5
amp = 2*np.sqrt(2)
freq = 1234.0
noise_power = 0.001 * fs / 2
time = np.arange(N) / fs
x = 0
# x = amp*np.sin(2*np.pi*freq*time)
x += np.random.normal(scale=np.sqrt(noise_power), size=time.shape)

f, Pxx_den = signal.welch(x, fs, nperseg=len(x)//4)
plt.semilogy(f, Pxx_den)
plt.ylim([1e-7, 1e2])
plt.title("White Noise")
plt.xlabel('frequency [Hz]')
plt.ylabel('PSD [V**2/Hz]')
plt.show()

svg

1/f noise

Common in many experiments, particularly for f < 100kHz

plt.semilogy(f[1:], Pxx_den[1:]/f[1:])
#plt.ylim([1e-7, 1e2])
plt.xlim([0,200])
plt.title("1/f Noise (also called 'pink' noise)")
plt.xlabel('frequency [Hz]')
plt.ylabel('PSD [V**2/Hz]')
plt.show()

svg

"Peaked" noise

plt.semilogy(f, Pxx_den/(1+(f-100)**2))
plt.ylim([1e-8, 1e-2])
plt.xlim([0,200])
plt.title("Peaked noise")
plt.xlabel('frequency [Hz]')
plt.ylabel('PSD [V**2/Hz]')
plt.show()

svg

Calculating the noise in a measurement from a known power spectral density

Suppose the spec sheet of our amplifier specifies within the amplifier bandwidth (0-1 MHz).

  1. We can then calculate the expected fluctuations of the data points in a timetrace that we would measure with an oscilloscope, using
  2. What determines and ? If we measure for a total time , we are insensitive to frequencies below . Furthermore, is given by the upper limit of the bandwidth of our amplifier (1 MHz), assuming that our oscilloscope does not limit the measurement bandwidth. If s, then so the RMS noise on the measurement will be 1V
  3. What if we put a 1 kHZ low-pass filter on the output of our amplifier?

Conclusions

  1. Measuring longer decreases the uncertainty in the average of the measured quantity according to , provided the N data points are uncorrelated.
  2. The power spectral density is the Fourier transform of the autocorrelation function :
  3. For uncorrelated noise, , such that is a constant (white noise)
  4. The expected noise in a data trace can be calculated by integrating over the power spectral density