1.3. Units and dimensional analysis#

Now would be a good time to pause and solidify some concepts.

In the previous section, we learned about sinusoidal waves, which have a standard form

(1.6)#\[x(t) = A \cdot \cos(2\pi \cdot f\cdot t + \phi).\]

In code, this would look something like:

import numpy as np

def x(t, amplitude, frequency, phase):
    '''Compute the value of the wave at time t
    with a given amplitude, frequency, and phase offset
    '''
    return amplitude * np.cos(2 * np.pi * frequency * t + phase)

For many new-comers (and not-so-new-comers) this string of letters can be difficult to remember and reassemble when necessary. What I want to stress in this function is that this becomes much easier when you can reason about what the pieces mean. To do that properly, we’ll need to think about the units of measurement involved. Once we have each variable with its corresponding units, it’s easier to see the right way to arrange them, and then you won’t have to memorize so much.

1.3.1. Defining our variables#

In the form above, our signal \(x(t)\) has three fundamental properties:

  • \(A\), the amplitude;

  • \(f\), the frequency; and

  • \(\phi\), the phase offset.

Now, imagine that we’ve temporarily forgotten the exact form of (1.6), but we know it involves amplitude, frequency, and phase. How could we reconstruct (1.6)?

Remember from the previous section: cosines (and sines) take angles as their input, and produce a distance measurement (positive or negative) as output. However we combine \(A\), \(f\), and \(\phi\), we know that whatever input we give to \(\cos\) must be interpretable as an angle.

For now, let’s not worry about the amplitude \(A\), since that happens outside the \(\cos\) (or the call to np.cos in the code above). What are each of the remaining quantities measuring, and in what units?

  • Time \(t\) is measured in [seconds]

  • Frequency \(f\) is measured in [cycles per second] or [cycles / second]

  • \(2\pi\) is measured in [radians per cycle]

  • phase \(\phi\) is measured in [radians]

So if you multiply \(2\pi \cdot f \cdot t\), you’ll get a product of the form:

\[\begin{split}\left(2\pi \left[\frac{\text{radians}}{\text{cycle}} \right]\right) \cdot \left(f \left[\frac{\text{cycles}}{\text{second}} \right]\right) \cdot \left(t \left[\text{seconds} \right]\right) &= \left(2\pi \left[\frac{\text{radians}}{\red{\cancel{\text{cycle}}}} \right]\right) \cdot \left(f \left[\frac{\red{\cancel{\text{cycles}}}}{\blue{\cancel{\text{second}}}} \right]\right) \cdot \left(t \left[\blue{\cancel{\text{seconds}}} \right]\right)\\ &= 2\pi \cdot f \cdot t \left[\text{radians}\right]\end{split}\]

Keeping track of units allows us to see that we were dividing seconds by seconds (which cancel each other), and cycles by cycles (which also cancel). The end result must be in units of radians.

Because \(\phi\) was also in radians, it is okay to add the two together, as is done in the equation for \(x(t)\). If one or the other of these was not in units of radians, we could not add them directly, or interpret the answer as an angle. For example, if we tried \(2\pi \cdot t / f\), we’d get the following:

This derivation is incorrect! Do not do this.

\[\begin{align*} & \left(2\pi \left[\frac{\text{radians}}{\text{cycle}} \right]\right) \cdot \left(t \left[\text{seconds} \right]\right) / \left(f \left[\frac{\text{cycles}}{\text{second}} \right]\right)\\ =&\; \left(2\pi \left[\frac{\text{radians}}{\text{cycle}} \right]\right) \cdot \left(t \left[\text{seconds} \right]\right) \cdot \left(\frac{1}{f} \left[\frac{\text{seconds}}{\text{cycle}} \right]\right)\\ =&\; 2\pi \cdot \frac{t}{f} \left[\frac{\text{radians}\cdot \text{seconds}^2}{\text{cycle}^2} \right] \end{align*}\]

The result has units of radian-seconds-seconds per cycle per cycle (yikes!), and that is definitely not the same as radians. We would therefore not have been able to compute \(\cos\) of the result – we would have had an error! This is an example of dimensional analysis helping us: because the units at the end of the calculation do not meet our expectation (radians), we know there must have been a mistake somewhere.

Some readers might remember this kind of reasoning from a high-school physics or chemistry class, and might remember that it’s called dimensional analysis. It’s one of the most useful tools that one can pick up in a science classroom!

1.3.2. Why do this?#

This may seem like belaboring the point, but it serves a purpose. When multiplying quantities together, you should be able to track what the corresponding units are. This is often the easiest way to check whether your calculation is correct, and is a good skill to develop.

By far, the most common types of mistakes that people make when first learning to work with signals arise from mis-matching quantities, such as adding a frequency to a phase angle, or dividing time by frequency rather than multiplying. These are errors that can be caught directly by checking units!

Note that software doesn’t really help us here. Most of the time, we simply write down these quantities as numbers, and the computer has no idea what the numbers mean. We therefore must be careful to document our assumptions carefully, so that we can reason about programs. For example, the program given above would be much better with a bit more explanatory documentation, like so:

import numpy as np

def x(t, amplitude, frequency, phase):
    '''Compute the value of the wave at time t
    with a given amplitude, frequency, and phase offset.
    
    Parameters
    ----------
    t : time in seconds (real number)
    
    amplitude : amplitude scaling (real number)
    
    frequency : cycles per second (real number)
    
    phase : offset in radians (real number)
    '''
    return amplitude * np.cos(2 * np.pi * frequency * t + phase)

Because we’re writing in Python, which allows us to define functions without clearly specifying the data types that it supports, we need to be explicit in documenting what the function expects (e.g., real number). However, even in strongly typed languages like Java (or, to some extent, C++), the computer still wouldn’t understand the semantics of the different variables, like that time is measured in seconds (and not milliseconds or fortnights), or that phase is in radians and not degrees.