|
93 | 93 | ;; |
94 | 94 | ;; Let's begin by learning to generate the signals we'll be transforming! |
95 | 95 |
|
96 | | -;; # Part 1: Signal Generation and Visualization |
| 96 | +;; # Signal Generation and Visualization |
97 | 97 |
|
98 | 98 | ;; Before we can analyze frequencies, we need signals to analyze. This section introduces |
99 | 99 | ;; signal generation and visualization—the foundation for everything that follows. |
|
276 | 276 | ;; Next, we'll explore the FFT—but first, we need to understand why its output is complex-valued |
277 | 277 | ;; even though our input signals are real numbers. |
278 | 278 |
|
279 | | -;; ## Part 1.5: Understanding Complex Transform Outputs |
| 279 | +;; ## Understanding Complex Transform Outputs |
280 | 280 |
|
281 | 281 | ;; Before we dive into the FFT, we need to address a puzzling fact: when we transform a |
282 | 282 | ;; real-valued signal (just regular numbers like 1.5, -0.3, 2.7), the FFT returns |
|
462 | 462 | ;; |
463 | 463 | ;; Now that we understand the complex output format, let's put the FFT to work! |
464 | 464 |
|
465 | | -;; ## Part 2: DFT and FFT - Discovering Frequencies in Signals |
| 465 | +;; ## DFT and FFT - Discovering Frequencies in Signals |
466 | 466 |
|
467 | 467 | ;; We're finally ready to answer our opening question: how do we write code to discover the |
468 | 468 | ;; frequencies in a signal? The answer is the **[Discrete Fourier Transform](https://en.wikipedia.org/wiki/Discrete_Fourier_transform) (DFT)**, computed |
|
790 | 790 | ;; But the FFT has a weakness: it's not optimal for compression. Let's explore why the Discrete |
791 | 791 | ;; Cosine Transform (DCT) outperforms FFT for smooth signals. |
792 | 792 |
|
793 | | -;; ## Part 3: DCT - The Compression Transform |
| 793 | +;; ## DCT - The Compression Transform |
794 | 794 |
|
795 | 795 | ;; The FFT is excellent for finding frequencies, but it's not the best choice for compression. |
796 | 796 | ;; Here's why: the FFT uses both sines AND cosines (complex output), which means we're storing |
|
964 | 964 | ;; whole signal—it can't tell us that a frequency appears only briefly. Let's explore wavelets, |
965 | 965 | ;; which solve this problem. |
966 | 966 |
|
967 | | -;; ## Part 4: Wavelets - Time-Frequency Localization |
| 967 | +;; ## Wavelets - Time-Frequency Localization |
968 | 968 |
|
969 | 969 | ;; Remember our chirp signal—frequency increasing from 5 to 50 Hz over time? The FFT told us |
970 | 970 | ;; "this signal contains frequencies between 5 and 50 Hz," but it couldn't tell us WHEN each |
|
1181 | 1181 | (kind/table |
1182 | 1182 | (map #(update % :wavelet name) wavelet-tests)) |
1183 | 1183 |
|
1184 | | -;; ## Part 5: Other Transforms - DST and DHT |
| 1184 | +;; ## Other Transforms - DST and DHT |
1185 | 1185 |
|
1186 | 1186 | ;; ### Discrete Sine Transform (DST) |
1187 | 1187 |
|
|
1236 | 1236 | {:transform "DHT" :use-case "Real-valued convolution" :basis "Hartley" :output "Real" :algorithm "Fast DHT"} |
1237 | 1237 | {:transform "Wavelet" :use-case "Time-frequency, denoising" :basis "Localized" :output "Real" :algorithm "Fast Wavelet"}]) |
1238 | 1238 |
|
1239 | | -;; ## Part 6: 2D Transforms for Images |
| 1239 | +;; ## 2D Transforms for Images |
1240 | 1240 |
|
1241 | 1241 | ;; ### Creating a 2D Signal |
1242 | 1242 |
|
|
1351 | 1351 | ;; - Baseline JPEG keeps low-frequency basis (top-left) and discards high-frequency (bottom-right) |
1352 | 1352 | ;; - This is why JPEG compression works well for natural images (most energy in low frequencies) |
1353 | 1353 |
|
1354 | | -;; ## Part 7: Practical Applications |
| 1354 | +;; ## Practical Applications |
1355 | 1355 |
|
1356 | 1356 | ;; Now that we understand the theory behind FFT, DCT, and wavelets, let's see how to apply |
1357 | 1357 | ;; these transforms to solve real-world problems. We'll build practical tools for filtering, |
|
1454 | 1454 | :magnitude-rmse (format "%.4f" (Math/sqrt (dfn/mean (dfn/sq (dfn/- original compressed-magnitude))))) |
1455 | 1455 | :note "Keeping largest coefficients works better than keeping first N!"} |
1456 | 1456 |
|
1457 | | -;; ## Part 8: Testing and Validation Framework |
| 1457 | +;; ## Testing and Validation Framework |
1458 | 1458 |
|
1459 | 1459 | ;; Transform operations can seem like black boxes. How do we know they're working correctly? |
1460 | 1460 | ;; This section builds a comprehensive testing framework to validate transform properties: |
|
1566 | 1566 |
|
1567 | 1567 | (:all-passed? final-test-results) |
1568 | 1568 |
|
1569 | | -;; ## Part 9: Best Practices and Decision Guide |
| 1569 | +;; ## Best Practices and Decision Guide |
1570 | 1570 |
|
1571 | 1571 | ;; ### dtype-next Best Practices Summary |
1572 | 1572 |
|
|
0 commit comments