【问题标题】:Matlab to Python code conversion: Binary phase-shift keying (BPSK)Matlab 到 Python 代码转换:二进制相移键控 (BPSK)
【发布时间】:2015-04-30 01:39:02
【问题描述】:

我有这个 MATLAB 代码:

d=[1 0 1 1 0]; % Data sequence
b=2*d-1; % Convert unipolar to bipolar
T=1; % Bit duration
Eb=T/2; % This will result in unit amplitude waveforms
fc=3/T; % Carrier frequency
t=linspace(0,5,1000); % discrete time sequence between 0 and 5*T (1000 samples)
N=length(t); % Number of samples
Nsb=N/length(d); % Number of samples per bit
dd=repmat(d',1,Nsb); % replicate each bit Nsb times
bb=repmat(b',1,Nsb); dw=dd'; % Transpose the rows and columns
dw=dw(:)'; 
% Convert dw to a column vector (colum by column) and convert to a row vector
bw=bb';
bw=bw(:)'; % Data sequence samples
w=sqrt(2*Eb/T)*cos(2*pi*fc*t); % carrier waveform
bpsk_w=bw.*w; % modulated waveform

% plotting commands follow

subplot(4,1,1);
plot(t,dw); axis([0 5 -1.5 1.5])

subplot(4,1,2);
plot(t,bw); axis([0 5 -1.5 1.5])

subplot(4,1,3);
plot(t,w); axis([0 5 -1.5 1.5])

subplot(4,1,4);
plot(t,bpsk_w,'.'); axis([0 5 -1.5 1.5])
xlabel('time')

这给了我下面显示的图表:

下面是我使用 Numpy / Scipy 转换的 Python 代码

import numpy as np
import scipy
import matplotlib.pylab as plt
plt.clf()
plt.close('all')

d = np.array(np.hstack((1, 0, 1, 1, 0)))
b = 2*d-1.
T = 1
Eb = T/2
fc = 3/T
t = np.linspace(0, 5, 1000)
N = t.shape
Nsb = np.divide(N, d.shape)
dd = np.tile(d.conj().T, Nsb)
bb = np.tile(b.conj().T, Nsb)
dw = dd.conj().T
dw = dw.flatten(0).conj()
bw = bb.conj().T
bw = bw.flatten(0).conj()
w = np.dot(np.sqrt(np.divide(2*Eb, T)), np.cos(np.dot(np.dot(2*np.pi, fc), t)))
bpsk_w = bw*w
plt.subplot(4, 1, 1)
plt.plot(t, dw)
plt.axis(np.array(np.hstack((0, 5, -1.5, 1.5))))
plt.subplot(4, 1, 2)
plt.plot(t, bw)
plt.axis(np.array(np.hstack((0, 5, -1.5, 1.5))))
plt.subplot(4, 1, 3)
plt.plot(t, w)
plt.axis(np.array(np.hstack((0, 5, -1.5, 1.5))))
plt.subplot(4, 1, 4)
plt.plot(t, bpsk_w, '.')
plt.axis(np.array(np.hstack((0, 5, -1.5, 1.5))))
plt.xlabel('time')
plt.show()

但我既没有得到错误也没有得到正确的输出:

请让我知道我在迁移此代码时的错误在哪里?

=====更新======

当我将 Python 代码更改为使用以下行时,我得到了一些更好的输出:

..............
b = 2.*d-1.
T = 1.
Eb = T/2.
fc = 3./T
...............
w = np.dot(np.sqrt(np.divide(2.*Eb, T)), np.cos(np.dot(np.dot(2.*np.pi, fc), t)))
.............

【问题讨论】:

    标签: matlab numpy matplotlib scipy porting


    【解决方案1】:

    您的问题源于使用np.tile 而不是np.repeat

    举一个简单的例子说明两者的区别:

    >>> a = np.arange(3)
    >>> a
    array([0, 1, 2])
    >>> np.repeat(a, 4)
    array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2])
    >>> np.tile(a, 4)
    array([0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2])
    

    所以基本上tile 采用“平铺数组”并将其连接起来,类似于平铺厨房地板的方式,而repeat 在获取下一个元素之前将向量中的每个元素重复指定次数那个向量。

    现在,利用这些知识,您可以重写 matlab 示例并得到以下结果:

    from __future__ import division
    
    import numpy as np
    import scipy
    import matplotlib.pylab as plt
    
    unipolar_arr = np.array([1, 0, 1, 1, 0])
    bipolar = 2*unipolar_arr - 1
    bit_duration = 1
    amplitude_scaling_factor = bit_duration/2  # This will result in unit amplitude waveforms
    freq = 3/bit_duration  # carrier frequency
    n_samples = 1000
    time = np.linspace(0, 5, n_samples)
    
    samples_per_bit = n_samples/unipolar_arr.size  # no need for np.divide. Also, use size rather than shape if you want something similar to Matlab's "length"
    # 1. Use repeat rather than tile (read the docs)
    # 2. No need for conjugate transpose
    dd = np.repeat(unipolar_arr, samples_per_bit)  # replicate each bit Nsb times
    bb = np.repeat(bipolar, samples_per_bit)  # Transpose the rows and columns
    dw = dd
    # no idea why this is here
    #dw = dw.flatten(0).conj()
    bw = bb  # one again, no need for conjugate transpose
    # no idea why this is here
    #bw = bw.flatten(0).conj()
    waveform = np.sqrt(2*amplitude_scaling_factor/bit_duration) * np.cos(2*np.pi * freq * time)  # no need for np.dot to perform scalar-scalar multiplication or scalar-array multiplication
    bpsk_w = bw*waveform
    
    f, ax = plt.subplots(4,1, sharex=True, sharey=True, squeeze=True)
    ax[0].plot(time, dw)
    ax[1].plot(time, bw)
    ax[2].plot(time, waveform)
    ax[3].plot(time, bpsk_w, '.')
    ax[0].axis([0, 5, -1.5, 1.5])
    ax[0].set_xlabel('time')
    plt.show()
    

    我添加了更多 cmets 以显示根本不需要的内容(如此混乱,您向我们展示的代码是由转换程序以某种方式生成的吗?)并冒昧地更改了大部分 1-2 字符变量把名字改成更易读的东西,这只是我最讨厌的事情之一。

    另外,在 Python2.x 中,整数除法是默认设置,因此 5/2 将计算为 2,而不是 2.5。在 Python3.x 中,这一点得到了改善,通过使用 from __future__ import division 行,您也可以在 Python2.x 中获得这种行为。

    【讨论】:

    • 非常感谢您的澄清。我确实使用了一些转换工具,但没有完全使用。基本上,我逐行转换代码,以免将不同的变量值输出到下一行代码。但您似乎采取了一种理解 MATLAB 代码然后在 Python 代码中实现逻辑的方法。请纠正我您进行转换的方法?有很多程序我需要转换,其他人安静大我知道我的方法可能是错误的 - 你能详细告诉我你采取的方法吗?
    • @Prakash,我确实手动进行了转换:我尝试了解您想要做什么,您的 matlab 代码 + 屏幕截图显示得相当好。然后,我从该代码开始,并删除了所有杂乱无章的内容(例如从列向量到列向量的转换)。自动转换工具并非没有缺陷。如果您有许多 m 文件要转换,我的建议是手动转换它们,一次一个,只要您打开一个:这是了解 Python 并同时提高代码可读性的好机会。跨度>
    猜你喜欢
    • 1970-01-01
    • 2017-02-04
    • 2012-07-25
    • 2020-08-25
    • 1970-01-01
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    • 2015-07-10
    相关资源
    最近更新 更多