Skip to content

Commit ff5f437

Browse files
authored
Merge pull request #3 from AUAS-Pulsar/vzero
modularity for algorithms
2 parents bfa5e7f + 2242f6d commit ff5f437

File tree

9 files changed

+627
-0
lines changed

9 files changed

+627
-0
lines changed

examples/visualize_psd.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import os,sys,inspect
2+
currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
3+
parentdir = os.path.dirname(currentdir)
4+
sys.path.insert(0,parentdir)
5+
6+
from rtlsdr import RtlSdr
7+
import matplotlib.pyplot as plt
8+
import numpy as np
9+
from fourier import fourier
10+
from plot import psd
11+
12+
# Initiate RtlSdr
13+
sdr = RtlSdr()
14+
15+
# configure device
16+
sdr.sample_rate = 2.4e6
17+
sdr.center_freq = 102.2e6
18+
19+
# Read samples
20+
samples = sdr.read_samples(1024)
21+
22+
# Close RTLSDR device connection
23+
sdr.close()
24+
25+
# Number of samples equals the length of samples
26+
N = samples.shape[0]
27+
28+
# T equals N/Fs
29+
T = N/sdr.sample_rate
30+
31+
# Get the powerlevels and the frequencies
32+
Pxx, freqs, _ = psd(samples, NFFT=1024, Fs=sdr.sample_rate/1e6, scale_by_freq=True, sides='twosided')
33+
34+
# Calculate the powerlevel dB's
35+
power_levels = 10*np.log10(Pxx/(sdr.sample_rate/1e6))
36+
37+
# Add the center frequency to the frequencies so it matches the actual frequencies
38+
freqs = freqs + sdr.center_freq/1e6
39+
40+
# Plot the PSD
41+
plt.plot(freqs, power_levels)
42+
plt.show()

examples/visualize_time_domain.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
from rtlsdr import RtlSdr
2+
import matplotlib.pyplot as plt
3+
import numpy as np
4+
5+
# Initiate RtlSdr
6+
sdr = RtlSdr()
7+
8+
# configure device
9+
sdr.sample_rate = 2.4e6
10+
sdr.center_freq = 102.2e6
11+
# sdr.gain = 0
12+
13+
# Read samples
14+
samples = sdr.read_samples(256*1024)
15+
16+
# Close RTLSDR device connection
17+
sdr.close()
18+
19+
# Number of samples equals the length of samples
20+
N = samples.shape[0]
21+
22+
# T equals N/Fs
23+
T = N/sdr.sample_rate
24+
25+
# Define the x axis
26+
x = np.linspace(0.0, T, N)
27+
28+
# Generate the plot
29+
fig, ax = plt.subplots()
30+
ax.plot(x, samples)
31+
plt.show()

fourier/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .fourier import *

fourier/fourier.py

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
import numpy as np
2+
3+
4+
def DFT_slow(x):
5+
""" Compute the discrete Fourier Transform of the one-dimensional array x"""
6+
x = np.asarray(x)
7+
N = x.shape[0]
8+
n = np.arange(N)
9+
k = n.reshape((N, 1))
10+
M = np.exp(-2j * np.pi * k * n / N)
11+
return np.dot(M, x)
12+
13+
14+
def FFT_vectorized(x):
15+
"""A vectorized, non-recursive version of the Cooley-Tukey FFT"""
16+
x = np.asarray(x)
17+
N = x.shape[0]
18+
19+
if np.log2(N) % 1 > 0:
20+
raise ValueError("size of x must be a power of 2")
21+
22+
# N_min here is equivalent to the stopping condition above,
23+
# and should be a power of 2
24+
N_min = min(N, 32)
25+
26+
# Perform an O[N^2] DFT on all length-N_min sub-problems at once
27+
n = np.arange(N_min)
28+
k = n[:, None]
29+
M = np.exp(-2j * np.pi * n * k / N_min)
30+
X = np.dot(M, x.reshape((N_min, -1)))
31+
32+
# build-up each level of the recursive calculation all at once
33+
while X.shape[0] < N:
34+
X_even = X[:, :X.shape[1] // 2]
35+
X_odd = X[:, X.shape[1] // 2:]
36+
factor = np.exp(-1j * np.pi * np.arange(X.shape[0])
37+
/ X.shape[0])[:, None]
38+
X = np.vstack([X_even + factor * X_odd,
39+
X_even - factor * X_odd])
40+
41+
return X.ravel()
42+
43+
44+
def fftfreq(n, d=1.0):
45+
"""
46+
Return the Discrete Fourier Transform sample frequencies.
47+
48+
The returned float array `f` contains the frequency bin centers in cycles
49+
per unit of the sample spacing (with zero at the start). For instance, if
50+
the sample spacing is in seconds, then the frequency unit is cycles/second.
51+
52+
Given a window length `n` and a sample spacing `d`::
53+
54+
f = [0, 1, ..., n/2-1, -n/2, ..., -1] / (d*n) if n is even
55+
f = [0, 1, ..., (n-1)/2, -(n-1)/2, ..., -1] / (d*n) if n is odd
56+
57+
Parameters
58+
----------
59+
n : int
60+
Window length.
61+
d : scalar, optional
62+
Sample spacing (inverse of the sampling rate). Defaults to 1.
63+
64+
Returns
65+
-------
66+
f : ndarray
67+
Array of length `n` containing the sample frequencies.
68+
69+
Examples
70+
--------
71+
>>> signal = np.array([-2, 8, 6, 4, 1, 0, 3, 5], dtype=float)
72+
>>> fourier = np.fft.fft(signal)
73+
>>> n = signal.size
74+
>>> timestep = 0.1
75+
>>> freq = np.fft.fftfreq(n, d=timestep)
76+
>>> freq
77+
array([ 0. , 1.25, 2.5 , 3.75, -5. , -3.75, -2.5 , -1.25])
78+
79+
"""
80+
81+
val = 1.0 / (n * d)
82+
results = np.empty(n, int)
83+
N = (n-1)//2 + 1
84+
p1 = np.arange(0, N, dtype=int)
85+
results[:N] = p1
86+
p2 = np.arange(-(n//2), 0, dtype=int)
87+
results[N:] = p2
88+
return results * val

plot/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from .plot import *

0 commit comments

Comments
 (0)