Skip to content

Commit 053533a

Browse files
committed
transforms wip
1 parent a516536 commit 053533a

1 file changed

Lines changed: 43 additions & 21 deletions

File tree

src/dsp/fourier_from_finite_sequences.clj

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -901,11 +901,39 @@ inner-product-diff-freq
901901

902902
;; Apply Hann window to the leaky signal
903903
(def hann-window
904-
(dfn/* 0.5
905-
(dfn/- 1.0
906-
(dfn/cos (dfn/* 2.0 Math/PI (dfn// (range n-samples) (dec n-samples)))))))
904+
(let [indices (range n-samples)
905+
normalized (dfn// indices (double (dec n-samples)))]
906+
(dfn/* 0.5
907+
(dfn/- 1.0
908+
(dfn/cos (dfn/* 2.0 Math/PI normalized))))))
907909

908910
(def sine-windowed (dfn/* sine-leaky hann-window))
911+
912+
;; Visualize what windowing does to the signal:
913+
(-> (tc/concat
914+
(tc/dataset {:time sample-times
915+
:value sine-leaky
916+
:signal "Original 10.5 Hz sine"})
917+
(tc/dataset {:time sample-times
918+
:value hann-window
919+
:signal "Hann window"})
920+
(tc/dataset {:time sample-times
921+
:value sine-windowed
922+
:signal "Windowed result"}))
923+
(plotly/base {:=x :time
924+
:=y :value
925+
:=color :signal
926+
:=x-title "Time (s)"
927+
:=y-title "Amplitude"
928+
:=title "How Windowing Tapers the Signal"
929+
:=width 700
930+
:=height 350})
931+
(plotly/layer-line))
932+
933+
;; Notice how the window smoothly tapers the sine wave to zero at both edges,
934+
;; eliminating the discontinuity that causes leakage.
935+
936+
;; Now let's see the effect in the frequency domain:
909937
(def spectrum-windowed (t/forward-1d dft-transformer sine-windowed))
910938
(def mags-windowed (extract-magnitudes spectrum-windowed 30))
911939

@@ -1025,30 +1053,23 @@ inner-product-diff-freq
10251053
(def k1-magnitude (Math/sqrt (+ (* a1 a1) (* b1 b1))))
10261054
(def k1-phase-rad (Math/atan2 (- b1) a1))
10271055

1028-
(def triangle-viz
1029-
(tc/dataset
1030-
[{:x 0.0 :y 0.0 :component "Origin"}
1031-
{:x a1 :y 0.0 :component "Cosine coefficient (a₁)"}
1032-
{:x a1 :y (- b1) :component "DFT[1] = a₁ - ib₁"}
1033-
{:x 0.0 :y 0.0 :component "Magnitude line"}]))
1034-
10351056
(-> (tc/concat
10361057
;; Right triangle edges
1037-
(tc/dataset [{:x [0.0 a1] :y [0.0 0.0] :line "Cosine (a₁)"}
1038-
{:x [a1 a1] :y [0.0 (- b1)] :line "Sine (b₁)"}
1039-
{:x [0.0 a1] :y [0.0 (- b1)] :line "Magnitude"}])
1058+
(tc/dataset {:x [0.0 a1] :y [0.0 0.0] :line "Cosine (a₁)"})
1059+
(tc/dataset {:x [a1 a1] :y [0.0 (- b1)] :line "Sine (b₁)"})
1060+
(tc/dataset {:x [0.0 a1] :y [0.0 (- b1)] :line "Magnitude"})
10401061
;; Points
1041-
(tc/dataset [{:x 0.0 :y 0.0 :point "Origin"}
1042-
{:x a1 :y (- b1) :point (format "DFT[1] = (%.1f, %.1f)" a1 (- b1))}]))
1062+
(tc/dataset {:x 0.0 :y 0.0 :point "Origin"}
1063+
{:x a1 :y (- b1) :point (format "DFT[1] = (%.1f, %.1f)" a1 (- b1))}))
10431064
(plotly/base {:=x-title "Cosine Coefficient (a₁)"
10441065
:=y-title "−Sine Coefficient (−b₁)"
10451066
:=title (format "Geometric View: Magnitude = %.2f, Phase = %.1f°"
10461067
k1-magnitude
10471068
(Math/toDegrees k1-phase-rad))
10481069
:=width 500
10491070
:=height 500})
1050-
(plotly/layer-line {:=x :x :=y :y :=group :line :=mark-color :line})
1051-
(plotly/layer-point {:=x :x :=y :y :=size 10 :=mark-color "black"})
1071+
(plotly/layer-line {:=x :x :=y :y :=group :line :=color :line})
1072+
(plotly/layer-point {:=x :x :=y :y :=mark-size 10 :=mark-color "black"})
10521073
plotly/plot
10531074
(assoc-in [:layout :yaxis :scaleanchor] "x"))
10541075

@@ -1118,8 +1139,9 @@ inner-product-diff-freq
11181139
;; ### Practical Consequences
11191140

11201141
;; This symmetry means:
1121-
;; - We only need to store $N/2+1$ coefficients (not all $N$)
1122-
;; - Still have $N$ independent values (same as input)
1142+
;; - We only need to store $N/2+1$ complex coefficients (not all $N$)
1143+
;; - Each complex coefficient has 2 real values (real + imaginary parts), except k=0 and k=N/2 which are real-only
1144+
;; - Total: $N$ independent real values (same as the N-sample input)
11231145
;; - Half the frequencies are redundant (mirror images of the other half)
11241146

11251147
;; For our $N=8$ temperatures:
@@ -1244,9 +1266,9 @@ inner-product-diff-freq
12441266

12451267
;; ## The Core Insight
12461268

1247-
;; **Fourier transforms are about rotations, not waves.**
1269+
;; **Fourier transforms are about rotations—waves are the shadows.**
12481270
;;
1249-
;; Waves (sine and cosine) are what you see when you project rotation onto axes.
1271+
;; Sine and cosine are what you see when you project circular motion onto axes.
12501272
;; The circle is more fundamental.
12511273
;;
12521274
;; When you have N numbers:

0 commit comments

Comments
 (0)