Why we keep two coordinates
In the circle experiment, we recorded only the horizontal coordinate. Points above and below the horizontal axis could give the same cosine value. Now we keep both coordinates. This lets us tell such positions apart, and also tell the directions of rotation apart.
We call the horizontal coordinate and the vertical coordinate . For example, means: 0.8 to the right and 0.6 up.
It is easy to write this pair as one complex number:
is the name of the full number. It joins the two coordinates; there is no third dimension here. The coefficient of is , and the part without is .
The number is the imaginary unit. It satisfies . This rule defines the arithmetic of complex numbers. Radio engineering uses the letter because often means current. In Python, the imaginary unit is written as 1j:
z = 0.8 + 1j * 0.6
I = z.real # 0.8: real part
Q = z.imag # 0.6: imaginary part
In the figure, the number is shown as a vector from to .
Keep the amplitude at 1 and change the angle. At you get and , at you get and , at you get and .
The four quadrants of the plane
The and axes divide the plane into four areas, the quadrants. The numbering goes counterclockwise and starts at the upper right:
| Quadrant | Where the point is | Angle in the quadrant | Sign of | Sign of |
|---|---|---|---|---|
| 1 | upper right | + | + | |
| 2 | upper left | − | + | |
| 3 | lower left | − | − | |
| 4 | lower right | + | − |
Points on the axes are not in any quadrant. For example, the angle is on the positive axis.
Length, angle and Euler’s formula
For a point on the unit circle, geometry gives , . The complex number is
Euler’s formula lets us write it in a shorter form:
For now, read as: a unit vector at angle . If its length is , we get
Why is this form useful? When you multiply two such numbers, their angles add. A rotation by and then by gives a rotation by . In radians, we write it like this:
This is an example of the property, not a proof of Euler’s formula. For now, we use the formula and check it with the known sin and cos coordinates. This is sufficient for our current experiments.
Degrees and radians
These are two units for the same angle: radians.
| Degrees | Radians | |
|---|---|---|
| 0° | ||
| 90° | ||
| 180° | ||
| 270° | ||
| 360° |
On diagrams, degrees are often easier. In the calculations np.sin(theta), np.cos(theta) and np.exp(1j * theta), the angle theta must be in radians. To convert, we use:
import numpy as np
theta = np.deg2rad(90) # pi/2
degrees = np.rad2deg(theta) # 90.0
z = np.exp(1j * theta) # approximately 0 + 1j
The number 90 without conversion would mean 90 radians.
How to find the length and angle from I/Q
We find the length of the vector (the magnitude of the number) with the Pythagorean theorem:
For the angle, we use the function . It uses the signs of both coordinates and selects the correct quadrant. The usual loses this information, and when the division is not possible.
z = 1 + 1j * np.sqrt(3)
amplitude = np.abs(z) # 2
phase_rad = np.arctan2(z.imag, z.real) # pi/3
phase_deg = np.rad2deg(phase_rad) # 60 degrees
np.angle(z) also returns the angle in radians. The number has no defined direction: a vector of zero length does not point anywhere.
From one number to a signal
A complex digital signal is a sequence of complex samples:
Each sample contains two real numbers. For example, if the angle increases at a constant rate,
we get a complex tone: a vector of constant length turns at frequency . Its coordinates are:
Let kHz, kS/s, , . The angle step is :
| Angle | ||||
|---|---|---|---|---|
| 0 | 0° | 1 | 0 | |
| 1 | 45° | 0.707 | 0.707 | |
| 2 | 90° | 0 | 1 | |
| 3 | 135° | −0.707 | 0.707 |
The coordinate alone gives a usual cosine. The pair also shows on which side of the horizontal axis the vector is.
In an I/Q receiver, two matched processing channels give the two coordinates. Their names are in-phase and quadrature: the reference oscillations of the two channels have a shift. It is also possible to calculate I/Q digitally from a sequence of real samples. But one single number does not give the unknown coordinate by itself. We will examine how these chains work later. Now we learn to work with a pair that is already available.
The complex conjugate
Conjugation keeps the real part and changes the sign of the imaginary part:
Here the asterisk means conjugation. On the plane, it is a reflection across the horizontal axis. The length stays the same, and the angle changes sign:
For example, is in the second quadrant at an angle of approximately . After conjugation, we get in the third quadrant. Its angle is , which is the same direction as .
If you conjugate each sample of a rotating vector, the direction of rotation becomes the opposite. One more useful property:
The product of a number and its conjugate is equal to the square of its magnitude. In Python, you calculate the conjugate like this:
z = -0.866 + 1j * 0.5
z_conjugate = np.conj(z) # -0.866 - 0.5j
Lab: one signal in four representations
The script shows the position of the selected vector, the and sequences, the magnitude and the phase:
uv run labs/02/01-complex-iq.py --show

On the phase plot, the angle continues to increase after a full turn. This is the unwrapped phase: we keep the accumulated turns. The usual np.angle returns an angle in the range from to , so you see a jump at the limit of this range. np.unwrap removes such jumps between adjacent samples. For our slow rotation, this lets us see a straight line.
Select a different sample and initial phase:
uv run labs/02/01-complex-iq.py --index 12 --phase-deg 45 --show --output-dir /tmp/dsp-iq
To open interactive Python after the script runs:
PYTHONINSPECT=1 uv run labs/02/01-complex-iq.py
In it, the arrays z, i, q, theta are available. Try z[8], np.abs(z[8]), np.rad2deg(np.angle(z[8])) and np.conj(z[8]).
Self-check
A vector has length 1 and an angle of counterclockwise from the positive axis.
In which quadrant is the end of the vector, and what are the signs of and ?
is between and , so it is quadrant 2. The point is to the left of the axis and above the axis: , .
We apply conjugation. Which coordinate changes sign, and in which quadrant is the end of the vector now?
Conjugation is a reflection across the horizontal axis: stays the same, changes sign, and the angle becomes (the same as ). The end of the vector moves to quadrant 3.
Does the length of the vector change after conjugation?
A reflection does not stretch or compress the vector. Formally: .
For the sample , find the magnitude . Which two numbers does this sample store?
. The sample itself is the pair of coordinates and . The magnitude and the angle are derived values.