0% found this document useful (0 votes)
3 views16 pages

Signals Lab Function and NumPy Reference

The document serves as a quick reference guide for CSE 219/CSE 220, detailing essential functions for signals and linear systems, organized into two parts: a function library and a NumPy/Matplotlib quick reference. Part 1 covers various signal processing functions including time shifts, interpolation, and system property tests, while Part 2 lists relevant NumPy and Matplotlib functions with usage notes. This resource is designed to aid students during lab exams by providing ready-to-use code snippets and quick lookup information.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views16 pages

Signals Lab Function and NumPy Reference

The document serves as a quick reference guide for CSE 219/CSE 220, detailing essential functions for signals and linear systems, organized into two parts: a function library and a NumPy/Matplotlib quick reference. Part 1 covers various signal processing functions including time shifts, interpolation, and system property tests, while Part 2 lists relevant NumPy and Matplotlib functions with usage notes. This resource is designed to aid students during lab exams by providing ready-to-use code snippets and quick lookup information.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

CSE 219 / CSE 220 – Signals & Linear

Systems
Copy-Paste Function & NumPy/Matplotlib Quick Reference

Part 1 — every function that could plausibly be asked for in the lab exam (time shift/scale/reverse, interpolation,
even/odd decomposition, step/impulse synthesis, convolution, energy/power, system-property tests, and plotting
helpers), organized by topic and ready to copy directly into your solution.

Part 2 — every NumPy and Matplotlib function that appears across your three reference documents, each with a
2-line usage note, organized by category for a fast lookup during the exam.
Built from: DSP Lab Exam Guide, Signals Coding Question Bank, and the Python Signals Lab Handnote.
Contents
PART 1 — Function Library
1. Time Axis & Basic Signal Builders
2. Interpolation (the single most important idea in the exam)
3. Continuous-Time Transforms (shift / scale / reverse / affine)
4. Even / Odd Decomposition
5. Discrete Sinusoid: Time Shift vs Phase Change
6. Step / Impulse Synthesis
7. Discrete-Time Index Operations (shift / reverse / resample)
8. Energy, Power, Convolution, Correlation
9. Testing System Properties (Linearity / Time-Invariance / Causality)
10. Plotting Helpers
11. General Python Patterns (occasionally tested)

PART 2 — NumPy / Matplotlib Quick Reference


A. Array Creation
B. Universal Functions (element-wise math)
C. Aggregation / Reduction
D. Boolean Masks & Comparisons
E. Searching & Sorting
F. Shape, Indexing & Structure
G. Interpolation & Signal-Specific
H. Misc / Constants
I. Matplotlib — Plot Types
J. Matplotlib — Layout & Decoration
PART 1 — Function Library
Every function below is copy-paste ready. Where the source documents disagreed on a convention (e.g. the direction of a
discrete time shift), both variants are shown with a note on how to tell which one your paper wants.

1. Time Axis & Basic Signal Builders


make_axis_and_signal() — continuous grid + a starter signal
The two lines you type first in almost every solution.

def make_axis_and_signal():
t = [Link](T_MIN, T_MAX, N) # N points, endpoints included
x = [Link](2*[Link]*0.5*t) + 0.5*[Link](2*[Link]*1.5*t)
return t, x

make_index() — discrete integer axis


arange's stop is EXCLUSIVE, so pass 21 to include 20.

def make_index():
n = [Link](-20, 21) # -20, -19, ..., 20
return n

x_of_t_triangle(t) — triangular pulse, half-width 1 at t=0


Classic base signal for shift / scale demos.

def x_of_t_triangle(t):
x = np.zeros_like(t)
m = [Link](t) <= 1.0
x[m] = 1.0 - [Link](t[m])
return x

x_of_t_gaussian_cosine(t) — smooth bump, good for time-scaling


Asymmetric-looking so compression/stretch is visually obvious.

def x_of_t_gaussian_cosine(t):
return [Link](-t**2) * [Link](2*[Link]*0.75*t)

x_of_t_piecewise_ramp(t) — step then down-ramp


Used in the worked x(-3t+2) affine-transform example.

def x_of_t_piecewise_ramp(t):
y = np.zeros_like(t)
y[(t >= 0) & (t < 1)] = 1.0
m = (t >= 1) & (t <= 2)
y[m] = 2.0 - t[m]
return y

x_of_t_mixed_even_odd(t) — deliberately neither even nor odd


Use this for even/odd decomposition demos so both parts are non-trivial.

def x_of_t_mixed_even_odd(t):
tri = np.zeros_like(t); m = [Link](t) <= 1.0
tri[m] = 1.0 - [Link](t[m])
ramp = np.zeros_like(t); ramp[m] = t[m]
return tri + 0.6 * ramp
2. Interpolation (the single most important idea in the exam)
interpolate_signal(t, x, q) — hand-rolled, midpoint-average form
Matches the rule y(1)=0.5*(x(0)+x(1)); identical to [Link] to ~1e-16.

def interpolate_signal(t, x, q):


idx_r = [Link]([Link](t, q, side="left"), 1, len(t)-1)
idx_l = idx_r - 1
tL, tR = t[idx_l], t[idx_r]
xL, xR = x[idx_l], x[idx_r]
w = [Link](tR != tL, (q - tL) / (tR - tL), 0.0)
return xL + w * (xR - xL) # == 0.5*(xL+xR) at a midpoint

interpolate_signal(t_org, x_org, t_query) — exact-hit + NaN-outside version


Keeps exact grid hits exact; returns NaN outside range (plot() skips NaNs).

def interpolate_signal(t_org, x_org, t_query):


order = [Link](t_org)
ts, xs = t_org[order], x_org[order]
n = len(ts)
idx = [Link](ts, t_query, side="left")
idc = [Link](idx, 0, n - 1)
exact = (idx < n) & [Link](ts[idc], t_query)
left = xs[[Link](idx - 1, 0, n - 1)]
right = xs[[Link](idx, 0, n - 1)]
res = [Link](exact, xs[idc], 0.5 * (left + right))
outside = (t_query < ts[0]) | (t_query > ts[-1])
return [Link](outside, [Link], res)

True linear interpolation (weighted, not just the midpoint average)


Use if a question explicitly wants distance-weighted interpolation.

# i0 = idx - 1 (left neighbour), i1 = idx (right neighbour)


w = (t_query - ts[i0]) / (ts[i1] - ts[i0]) # 0 at left, 1 at right
val = (1 - w) * xs[i0] + w * xs[i1]
# built-in equivalent on a sorted grid:
val = [Link](t_query, ts, xs)

[Link] one-liner — use this unless a question forbids it


left=0.0, right=0.0 zero-fills outside the recorded window (default clamps instead).

y = [Link](query_times, t, x, left=0.0, right=0.0)

Fixing the classic searchsorted IndexError


searchsorted can return len(ts) -- always clip before indexing.

idx = [Link](ts, t_query)


n = len(ts)
right = xs[[Link](idx, 0, n - 1)]
left = xs[[Link](idx - 1, 0, n - 1)]

3. Continuous-Time Transforms (shift / scale / reverse / affine)


time_shift(t, x, t0) — y(t) = x(t - t0)
Positive t0 delays (slides right); negative advances (slides left).

def time_shift(t, x, t0):


q = t - t0
return [Link](q, t, x, left=0.0, right=0.0)

time_scale(t, x, a) — general y(t) = x(a t)


a > 1 compresses (narrower); 0 < a < 1 stretches (wider).

def time_scale(t, x, a):


q = a * t
y = np.zeros_like(t)
inr = (q >= t[0]) & (q <= t[-1])
y[inr] = [Link](q[inr], t, x) # or interpolate_signal(t,x,q[inr])
return y

time_scale(t, x, k) — sub-scaling y(t) = x(t / k)


The exact A1/A2 task: query the SAMPLES, never re-call the analytic x_of_t.

def time_scale(t, x, k):


return interpolate_signal(t, x, t / k)

time_reverse(x) — y(t) = x(-t) on a symmetric grid


Only valid if t is symmetric about 0 (e.g. linspace(-4,4,4001), odd N).

def time_reverse(x):
return x[::-1].copy() # .copy() -> standalone, not an aliased view

time_reverse on an ASYMMETRIC grid


The array-flip shortcut only works on a symmetric grid; otherwise remap directly.

xr = [Link](-t, t, x, left=0.0, right=0.0)

affine_transform(t, x, a, b) — general y(t) = x(a t + b)


Folds shift+reverse+scale into ONE remap/interpolation -- no error compounding.

def affine_transform(t, x, a, b):


q = a * t + b
y = np.zeros_like(t)
inr = (q >= t[0]) & (q <= t[-1])
y[inr] = [Link](q[inr], t, x)
return y

Hand-recipe for x(at+b) (for the drawing / explanation part of the answer)
Order matters: doing shift-then-scale != scale-then-shift.

# 1. shift first: g1(t) = x(t + b)


# 2. reverse if a<0: g2(t) = g1(-t)
# 3. scale by |a|: g3(t) = g2(|a| t) = x(a t + b)

amp_combine(x, z, A, B) — y(t) = A x(t) + B z(t)


Amplitude only -- no interpolation needed, but x and z MUST share the same t.

def amp_combine(x, z, A, B):


return A * x + B * z
4. Even / Odd Decomposition
even_odd_decompose(x)
Must be built from time_reverse per the spec; two element-wise lines.

def even_odd_decompose(x):
xr = time_reverse(x) # x(-t)
xe = 0.5 * (x + xr) # even part
xo = 0.5 * (x - xr) # odd part
return xe, xo

Numeric proof checks (print these -- all should be ~0)


Reconstruction, evenness, oddness -- the three identities graders ask for.

print([Link]([Link]((xe + xo) - x))) # reconstruction


print([Link]([Link](time_reverse(xe) - xe))) # xe even
print([Link]([Link](time_reverse(xo) + xo))) # xo odd

5. Discrete Sinusoid: Time Shift vs Phase Change


sinusoid(n, A, Omega0, phi) — x[n] = A cos(Omega0 n + phi)
The base building block for all of Section 5.

def sinusoid(n, A, Omega0, phi):


return A * [Link](Omega0 * n + phi)

time_shift_sinusoid — CHECK WHICH CONVENTION YOUR PAPER USES


Convention 1 = a delay x[n-n0] (DSP Guide). Convention 2 = x[n+n0] (Question Bank/Handnote).

# Convention 1: DELAY, x[n - n0]


def time_shift_sinusoid(n, A, Omega0, phi, n0):
return A * [Link](Omega0 * (n - n0) + phi)

# Convention 2: x[n + n0]


def time_shift_sinusoid(n, A, Omega0, phi, n0):
return sinusoid(n + n0, A, Omega0, phi)

phase_change_sinusoid(n, A, Omega0, phi, phi0)


Adds phi0 to the existing phase argument.

def phase_change_sinusoid(n, A, Omega0, phi, phi0):


return sinusoid(n, A, Omega0, phi + phi0)

phi0_equiv — the EXACT phase that reproduces a given time shift


Sign must match whichever time_shift_sinusoid convention you used above.

# if using x[n - n0]: phi0_equiv = -Omega0 * n0


# if using x[n + n0]: phi0_equiv = +Omega0 * n0
phi0_equiv = Omega0 * n0 # <-- flip sign to match your convention

mse(a, b) — mean squared error helper


Never compare float signals with ==; use this instead.

def mse(a, b):


return float([Link]((a - b) ** 2))
Best-integer-shift search (Part B pattern)
Finds the integer k whose time-shift best matches an arbitrary phase change.

best_k, best_err = None, None


for k in range(-12, 13):
e = mse(time_shift_sinusoid(n, A, Omega0, phi, k), x_phase)
if best_err is None or e < best_err:
best_err, best_k = e, k

discrete_period(Omega0, max_N=1000) — smallest integer period, or None


Periodic iff Omega0*N is a multiple of 2*pi for some integer N.

def discrete_period(Omega0, max_N=1000):


for N in range(1, max_N + 1):
ratio = Omega0 * N / (2 * [Link])
if [Link](ratio, round(ratio)):
return N
return None

6. Step / Impulse Synthesis


unit_step(n) — u[n]
1 for n >= 0, else 0, as an integer array.

def unit_step(n):
return (n >= 0).astype(int)

unit_impulse(n) — delta[n]
1 only at n == 0.

def unit_impulse(n):
return (n == 0).astype(int)

shifted_step(n, n0) — u[n - n0]


Positive n0 delays the step (moves right); negative advances it (moves left).

def shifted_step(n, n0):


return (n - n0 >= 0).astype(int)

gated_exponential(n, a) — a^n * u[n]


Multiplying by the boolean mask zeroes out the n < 0 part.

def gated_exponential(n, a):


return (a ** n) * (n >= 0)

rect_pulse(n, a, b) — 1 on [a, b] inclusive, else 0


Combine two conditions with & (parenthesised), never Python's and.

def rect_pulse(n, a, b):


return ((n >= a) & (n <= b)).astype(int)
Weighted sum of shifted impulses — build any x[n] = sum ck*delta[n-nk]
Example: x[n] = 2*delta[n-1] - 3*delta[n-2] + 2*delta[n-4].

x = (2*unit_impulse(n-1)
- 3*unit_impulse(n-2)
+ 2*unit_impulse(n-4)).astype(float)

Impulse from step (first difference)


delta[n] = u[n] - u[n-1]; prepend keeps the same length.

delta = [Link](u, prepend=u[0])

Step from impulse (running sum)


cumsum accumulates left to right, turning a single spike into a step.

u = [Link](delta)

Step built from a sum of K delayed impulses


Demonstrates u[n] = sum_{k=0}^{K} delta[n-k] for n up to K.

K = 30
acc = np.zeros_like(n)
for k in range(K + 1):
acc = acc + unit_impulse(n - k)
# vectorized alternative:
acc = ((n >= 0) & (n <= K)).astype(int)

7. Discrete-Time Index Operations (shift / reverse / resample)


shift(x, n0) — y[n] = x[n - n0], zero-padded, same length
[Link] wraps around instead -- NOT the same as a finite-signal time shift.

def shift(x, n0):


y = np.zeros_like(x)
if n0 >= 0:
y[n0:] = x[:len(x)-n0] if n0 < len(x) else y[n0:]
else:
y[:n0] = x[-n0:]
return y

reverse_seq(x) — x[-n] for an arbitrary stored index


Same one-liner as time_reverse; named separately for non-symmetric indices.

def reverse_seq(x):
return x[::-1].copy()

Combined reversal + shift, e.g. y[n] = x[-n + 2]


Rewrite as x[-(n-2)]: shift the argument by 2, THEN reverse.

# want y[n] = x[-n + 2] = x[-(n - 2)]


xr = reverse_seq(x) # x[-n]
y = shift(xr, 2) # x[-(n-2)] = x[-n+2]
downsample(x, k) — keep every k-th sample
x[0], x[k], x[2k], ...

def downsample(x, k):


return x[::k]

upsample(x, k) — insert k-1 zeros between samples


Output length is k * len(x).

def upsample(x, k):


y = [Link](len(x) * k, dtype=[Link])
y[::k] = x
return y

8. Energy, Power, Convolution, Correlation


continuous_energy_power(t, x)
Riemann-sum energy (version-proof: no [Link]/[Link] needed).

def continuous_energy_power(t, x):


dt = t[1] - t[0]
E = [Link]([Link](x)**2) * dt
P = E / (t[-1] - t[0])
return E, P

discrete_energy_power(x)
P divides by the SAMPLE COUNT ([Link]), matching n2-n1+1 for an inclusive range.

def discrete_energy_power(x):
E = [Link]([Link](x)**2)
P = E / [Link]
return E, P

energy(x) / average_power(x) — simple standalone versions


Plain sum-of-squares / mean-of-squares, returned as float.

def energy(x):
return float([Link](x ** 2))

def average_power(x):
return float([Link](x ** 2))

classify(x) — heuristic energy-signal vs power-signal


On a finite window this is only illustrative (the true test is a limit as N->inf).

def classify(x):
E = energy(x); P = average_power(x)
return "energy" if P < 1e-6 and E < [Link] else "power"

convolve(x, h) — full linear convolution


Output length is len(x)+len(h)-1. mode='same'/'valid' for other lengths.

def convolve(x, h):


return [Link](x, h, mode="full")
Convolving with a unit impulse leaves a signal unchanged
The sifting property, verified numerically.

x = [Link]([2.0, -1.0, 3.0, 0.5])


d = [Link]([1.0])
y = [Link](x, d, mode="full")
print([Link](y, x)) # True

moving_average(x, L) — boxcar smoothing filter


Convolving with a length-L box of height 1/L, same-length output.

def moving_average(x, L):


h = [Link](L) / L
return [Link](x, h, mode="same")

cross_corr(x, y) — full cross-correlation


Auto-correlation is cross_corr(x, x); its peak sits at zero lag.

def cross_corr(x, y):


return [Link](x, y, mode="full")

9. Testing System Properties (Linearity / Time-Invariance / Causality)


is_linear(S, x1, x2, a, b)
Checks S(a*x1 + b*x2) ~= a*S(x1) + b*S(x2). Passing is strong evidence, not proof.

def is_linear(S, x1, x2, a, b):


lhs = S(a * x1 + b * x2)
rhs = a * S(x1) + b * S(x2)
return bool([Link](lhs, rhs))

is_time_invariant(S, x, n0)
Shifting the input by n0 should shift the output by n0; ignore zero-fill edge samples.

def is_time_invariant(S, x, n0):


lhs = S(shift(x, n0))
rhs = shift(S(x), n0)
return bool([Link](lhs[n0:], rhs[n0:]))

depends_on_future(S, x, i) — causality probe


Perturbs a strictly-future sample; True means the system is non-causal at i.

def depends_on_future(S, x, i):


x2 = [Link]()
if i + 1 < len(x):
x2[i + 1] += 1.0
return not [Link](S(x)[i], S(x2)[i])

10. Plotting Helpers


plot_pair(t, x, y, title) — continuous x(t) vs y(t)
Standard decorated two-curve plot with zero-axes drawn in.

def plot_pair(t, x, y, title):


[Link](figsize=(9, 4))
[Link](t, x, label="x(t)")
[Link](t, y, label="y(t)", linestyle="--")
[Link](title); [Link]("t"); [Link]("Amplitude")
[Link](0, color="k", lw=0.8); [Link](0, color="k", lw=0.8)
[Link](True); [Link]()

plot_three(t, x, xe, xo) — original + even + odd


The standard C1/C2-style even/odd figure.

def plot_three(t, x, xe, xo):


[Link]()
[Link](t, x, label="x(t)")
[Link](t, xe, label="xe(t)")
[Link](t, xo, label="xo(t)")
[Link]("Even-Odd Decomposition")
[Link]("t"); [Link]("Amplitude")
[Link](True); [Link]()

stem_plot(ax, n, x, label) — single discrete series


stem returns 3 artists; hide the baseline for a cleaner look.

def stem_plot(ax, n, x, label):


ml, sl, bl = [Link](n, x, label=label)
bl.set_visible(False)
[Link](True, alpha=0.3); ax.set_xlabel("n"); ax.set_ylabel("Amplitude")

stem_pair(n, x1, x2, l1, l2) — two discrete series overlaid


Used to visually confirm a time-shift equals a phase change.

def stem_pair(n, x1, x2, l1, l2):


fig, ax = [Link](figsize=(9, 4))
for x, lab in [(x1, l1), (x2, l2)]:
_, _, base = [Link](n, x, label=lab)
base.set_visible(False)
ax.set_xlabel("n"); ax.set_ylabel("Amplitude")
[Link](); [Link](True, alpha=0.3)

2x2 dashboard skeleton (line / bar / scatter / stacked-bar)


Practice-Problem-4 style; fixes the 3 classic bugs (width vs color, size vs s, list + vs array +).
fig, axs = [Link](2, 2, figsize=(14, 10))
axs[0,0].plot(months, north, linestyle="-", color="blue", label="North")
axs[0,0].plot(months, south, linestyle="--", color="green", label="South")
axs[0,0].plot(months, central, linestyle=":", color="red", label="Central")
axs[0,0].legend(); axs[0,0].grid(True)

axs[0,1].bar(branches, values, color=["blue","green","red"]) # color is KEYWORD


axs[0,1].grid(True, axis="y")

axs[1,0].scatter(months, north, color="blue", s=60) # s = size, not "size"

north_q = [Link](4,3).sum(axis=1) # NumPy arrays add element-wise


south_q = [Link](4,3).sum(axis=1)
axs[1,1].bar(q, north_q, color="blue", label="North")
axs[1,1].bar(q, south_q, bottom=north_q, color="green", label="South")

[Link]("Overall Title", fontsize=16)


plt.tight_layout(rect=[0,0,1,0.96])
[Link]()

11. General Python Patterns (occasionally tested)


Employee-style class — class attr vs instance attr, __str__
[Link] etc. are per-object; company_name is shared (like a Java static field).

class Employee:
company_name = "ACME" # class attribute (shared)
def __init__(self, name, emp_id):
[Link] = name # instance attributes (per object)
self.employee_id = emp_id
[Link] = []
def add_salary(self, s): [Link](s)
def average_salary(self): return sum([Link])/len([Link])
def highest_salary(self): return max([Link])
def annual_income(self): return sum([Link])
def __str__(self):
return f"Employee Name : {[Link]}"

dict accumulator pattern (Java HashMap-style)


The standard group-and-total-by-key idiom.

summary = {}
for name, sev, tt in visits:
if name not in summary:
summary[name] = {"time": 0, "sev": 0}
summary[name]["time"] += tt
summary[name]["sev"] += sev

Sort / pick best with a tie-break key


Negate for descending; add the name as a tie-breaker.

top = min(summary, key=lambda k: (-summary[k]["sev"], k))


PART 2 — NumPy / Matplotlib Quick Reference
Every built-in function used anywhere in your three source documents, grouped by category. Each entry is a signature plus a
2-line usage note — scan for the function name, read the note, move on.

A. Array Creation

[Link](list) Builds an ndarray from a Python list/nested list. dtype is inferred unless given
explicitly.

[Link](N) / All-zero array of the given shape, float64 by default (like calloc).
[Link]((r,c))

np.zeros_like(a) Zeros with the SAME shape and dtype as a. The standard 'blank canvas' for
building signals.

[Link](shape) All-ones array of the given shape.

[Link](N, val) Array of the given shape filled entirely with val.

[Link](start, stop, Integers from start up to but NOT including stop. Never use a float step here.
step)

[Link](start, stop, num evenly spaced points INCLUDING both endpoints. Use for continuous time
num) axes.

B. Universal Functions (element-wise math)

[Link](a), [Link](a), Element-wise trig on a whole array. Never use [Link] on an array (it only
[Link](a) accepts scalars).

[Link](a), [Link](a), Element-wise exponential, square root, and natural log.


[Link](a)

[Link](a) Element-wise absolute value. Use [Link](x)**2 (not x**2) for energy so complex
signals work too.

[Link](a, lo, hi) Clamps every element into [lo, hi], element-wise. Like std::clamp applied to a
whole array.

[Link](cond, A, B) Vectorized ternary: picks from A where cond is True, else from B, element-wise.

[Link](a, k) Rounds every element to k decimal places.

C. Aggregation / Reduction

[Link]() / [Link](a) Total of all elements; pass axis=0 (columns) or axis=1 (rows) to reduce along one
direction only.

[Link]() / [Link](a) Average of all elements, or per-axis with axis=...

[Link]() / [Link]() Largest / smallest element, overall or per axis.

[Link](a) / [Link](a) Index of the largest / smallest element (per axis if axis= given).

[Link]() Standard deviation of the elements.


[Link]([Link](t - v)) Idiom: index of the sample whose time/value is closest to v. Handy for
spot-checks.

D. Boolean Masks & Comparisons

a > v, a == v, a <= v ... Element-wise comparison; returns a boolean array (a 'mask'), not a single
True/False.

& , | , ~ AND / OR / NOT for NumPy boolean arrays. ALWAYS parenthesise; never use
Python's and/or/not on arrays.

[Link](a, b) Element-wise test of whether each element of a appears anywhere in b.

[Link](a, b) / Float-safe (near-)equality test. Never compare floating-point arrays with ==.
[Link](a, b)

E. Searching & Sorting

[Link](sorted_a, Insertion index that keeps sorted_a sorted; the core primitive behind every
q, side=) interpolation function.

[Link](a) Indices that would sort a in ascending order (does not sort a itself).

[Link](a) Returns a new sorted copy of a; the original is untouched.

F. Shape, Indexing & Structure

[Link] / [Link] / [Link] Metadata: dimensions tuple, total element count, and element type.

[Link](r, c) A view of a with a new shape (same underlying data, same total element count).

a[::-1] A reversed VIEW of a (aliases the same memory). Call .copy() if you need an
independent array.

[Link]() An independent deep copy of a; safe to mutate without affecting the original.

[Link]([a, b, ...]) Stacks 1-D arrays as rows of a new 2-D array.

[Link](int) / Casts to a different dtype, e.g. turning a boolean mask into 0/1 integers.
[Link](float)

G. Interpolation & Signal-Specific

[Link](q, xp, fp, left=, Linear interpolation on a sorted grid xp/fp, evaluated at query points q. THE key
right=) exam function.

[Link](x, h, mode=) Discrete convolution; mode='full' (default length), 'same', or 'valid'.

[Link](x, y, mode=) Cross-correlation of x and y; auto-correlation is [Link](x, x, ...).

[Link](a, prepend=) First difference between consecutive elements; prepend keeps the output the
same length.

[Link](a) Running/cumulative sum along the array; turns an impulse into a step.

[Link](a, k) Circularly shifts elements by k, WRAPPING around -- not the same as a


zero-filled time shift.
H. Misc / Constants

[Link] The constant pi = 3.14159...; used everywhere in sinusoid/frequency formulas.

[Link].* Random number generation; rarely required in this course but occasionally used
for test signals.

I. Matplotlib — Plot Types

[Link](figsize=(w,h)) Starts a new figure of the given size in inches. Call once per new plot window.

[Link](x, y, label=, Line plot connecting samples; use for continuous-time x(t), never for discrete x[n].
linestyle=, color=)

[Link](n, x, label=) Lollipop plot for discrete x[n]; returns (markerline, stemlines, baseline) -- hide the
baseline for a clean look.

[Link](x, y, s=, c=) Scatter plot of discrete points; s sets marker SIZE (not 'size').

[Link](names, vals, Bar chart; the 3rd POSITIONAL argument is width, so always pass color= by
color=, bottom=) keyword.

[Link](data, bins=) Histogram of one or more data series.

J. Matplotlib — Layout & Decoration

[Link](rows, cols, Creates a figure plus a grid of Axes, indexed like a matrix: axs[row, col].
figsize=)

[Link] / xlabel / Labels the current axes: chart title, x-axis label, y-axis label.
ylabel(text)

[Link]() Displays a legend built from each plotted series' label= argument.

[Link](True, axis=) Toggles gridlines; axis='y' or axis='x' restricts gridlines to one direction only.

[Link](0) / Draws a horizontal/vertical reference line, e.g. the y=0 or t=0 axis, to show
[Link](0) symmetry.

[Link](a,b) / Clips the visible axis range to [a, b].


[Link](a,b)

[Link](text, One overall title spanning an entire multi-panel figure.


fontsize=)

plt.tight_layout(rect=) Auto-spaces subplots so titles/labels don't overlap; use rect=[0,0,1,0.96] to leave


room for suptitle.

[Link]() Renders the figure on screen. REQUIRED at the end -- nothing appears without
it.

[Link](path, dpi=) Writes the current figure to an image file instead of (or as well as) displaying it.
Exam-Day Quick Checklist
Boilerplate to type first (from memory)
import numpy as np
import [Link] as plt
T_MIN, T_MAX, N = -4.0, 4.0, 4001
t = [Link](T_MIN, T_MAX, N) # continuous grid
# n = [Link](-20, 21) # discrete grid

The transform decision tree


1. Touches TIME (x(t-t0), x(at), x(-t), x(at+b))? Build q = remap, then [Link](q, t, x, left=0, right=0), zero-fill
out-of-range. Never shift raw indices.
2. Touches AMPLITUDE only (Ax+Bz)? Plain element-wise A*x+B*z, no interpolation, same grid required.
3. Reversal on a symmetric grid: x[::-1].copy(). Otherwise: [Link](-t, t, x, left=0, right=0).
4. Discrete signal: stem plot, integer arange, no interpolation for integer shifts.

Ten traps, condensed


1 x(t - t0) shifts RIGHT (delay), not left.
2 Time scaling acts on time, not amplitude; a > 1 compresses.
3 Fractional source index => must interpolate; there is no x[0.5].
4 Use & / | / ~ with parentheses, never and/or on arrays.
5 Slices are views (aliased); use .copy() when in doubt.
6 Compare floats with [Link] / MSE, never ==.
7 Discrete power denominator is n2-n1+1 ([Link]) -- watch the fencepost.
8 [Link]'s stop is exclusive; [Link]'s stop is inclusive.
9 axs from subplots(2,2) is a 2-D array -- index axs[r, c].
10 Energy uses [Link](x)**2 (complex-safe); stem() returns 3 artists -- hide the baseline.

Sanity print before you submit


i0 = [Link]([Link](t)) # index nearest t = 0
print("y(0) =", y[i0], " x(0) =", x[i0])
print("reconstruction:", [Link]([Link]((xe + xo) - x))) # ~1e-16 means correct

You might also like