MATLAB转Python代码(NumPy, SciPy, MatplotLib?)

4 投票
2 回答
16704 浏览
提问于 2025-04-15 19:40

我正在尝试把以下代码从MATLAB转换成Python,用于一个脑电图项目(部分原因是Python稍微便宜一些!)

希望有人能给我指个方向:我已经开始修改代码,但遇到了一些困难,特别是在寻找等效的函数方面。

我试过scipy.org(NumPy_for_Matlab_Users等),但不确定我的参数格式和数量是否正确。

我最开始使用的是pyserial

ser.read()

来读取数据,然后

ord()

把它转换成整数,但这个MATLAB代码用的是另一种方法('uchar')

我主要的问题在于

fopen
fread
find
repmat

还有整个绘图部分,因为我对Python中的这部分(MatPlotLib?)更是一无所知。

MATLAB通常是从'1'开始,而Python是从0开始:我尝试过修改这些,但有些我不太确定,没改到。

Python能接受用冒号分隔的整个范围吗

...repmat(0:2:10, .....

还是不行呢?

那么,这里是MATLAB的代码:

% EEG data grabber and plotter

N = 256;    % Required number of sample frames

% Read in a block of data from the OpenEEG board
hCom = serial('COM1','BaudRate',57600,'timeout',5);
fopen(hCom);
numBlocks = (ceil(17*N/256) + 1);
rawdata = zeros(numBlocks*256,1);
for n = 1:numBlocks
    rawdata((0:255) + n*256) = fread(hCom, 256, 'uchar');  % Read data
end
fclose(hCom);

% Convert raw data into a Matlab matrix
% First find the first frame start
startIndex = find(rawdata == 165);
while(rawdata(startIndex(1) + 1) ~= 90)
   startIndex = startIndex(2:end);
end
% Now extract the samples
frameStarts = (0:(N-1))'*17 + startIndex(1);
indices = 4 + repmat(frameStarts, 1, 6) + repmat(0:2:10, length(frameStarts), 1);
eegData = (rawdata(indices)*256 + rawdata(indices + 1)) - 512;
% eegData is now a N by 6 matrix, each column is a channel of sampled data

% Plot time-series data
figure(1)
subplot(2,1,1)
plot((0:255)/256,eegData(:,1:2))
xlabel('Time [s]');
ylabel('EEG data'); 
% Calculate FFT and plot spectra
subplot(2,1,2)
window = 0.5 - 0.5 * cos(2*pi*(0:255)/255); % Von-Hann Window
f = abs(fft(repmat(window',1,2) .* eegData(:,1:2)));
plot((0:127),f(1:128,:))
xlabel('Frequency [Hz]');
ylabel('EEG FFT');

这是我这个“可怜的表亲”版本

import scipy
import serial                       #Serial Module to read serial port
from numpy import ceil,zeros        #Ceil module & zeros for blank matrix

N = 256    #no of sample frames (256 = 1s)

#Reads a block of data from the serial port

ser = serial.Serial('COM18',57600,timeout=5)

scipy.fopen(ser)       #MATLAB CODE: fopen(ser)  is this correct????

numBlocks = (ceil(17*N/256) + 1)
rawdata = scipy.zeros(numBlocks*256,1)
for n = 1:numBlocks
    rawdata((0:255) + n*256) = numpyio.fread(ser,256,'i')  # read each byte as     unsigned integer
end
ser.close()


#convert raw data to MATLAB matrix
#find start of frame (1st Byte always 165, 2nd always 90)

startIndex = find(rawdata == 165);
while (rawdata(startIndex(0) + 1) ~=90) #confirms 165,90 sequence
    startIndex = startIndex(1:end) #uses rest of frame as data
end

#Extraction of sample values

#MATLAB CODE
frameStarts = (0: (N-1))'*17 + startIndex(1);      #'#how to transpose matrix('): zip()??
indices = 4 + (numpy.tile(frameStarts, 1,6)) + (numpy.tile(0:2:10,length(frameStarts), 1); 
eegData = (rawdata(indices)*256 + rawdata(indices +1)) - 512  #values are unsigned     integers 0-1023 and must subtract 512 for actual value
#eeg data now N*6 Matrix each column is a channel of data

#MATLAB CODE: plot time series data  (MatPlotLib?)

figure(1)
subplot (2,1,1)
plot((0:255)/256,eegData(:,1:2))
xlabel('Time [s]')
ylabel('EEG Voltage')
#fft
subplot(2,1,2)
window = 0.5 - 0.5*cos(2*pi*(0:255)/255);
f = abs(fft(repmat(window',1,2) .* eegData(:,1:2)))    '#repmat=tile()? matrix     transposition (')?
plot((0:127),f(1:128,:))
xlabel('Freq [Hz]')
ylabel('EEG FFT')

非常感谢所有的建议!

Dave!

2 个回答

5

有一点很重要,就是这两种语言的索引方式不一样。如果你只是把MATLAB的代码直接复制到Python里,就会非常困惑。比如,MATLAB中的x(1:5:end)在Python中是x[0::5]。建议你回去看看NumPy for MATLAB Users这个页面,找到“线性代数等价物”这一部分(大约在页面中间)。那里有一个字典,可以帮助你理解如何在两者之间转换。

11

嗯……有很多事情要说。

Python没有end这个关键词,所以你显然需要多了解一下Python的语法。

在Python中,数组和切片是用[]来索引的,而不是()。比如,范围可以用range(0,10)来表示,但像Matlab那样的切片功能只在像numpy这样的扩展包中存在,每个扩展包都有自己的一套用法。

是的,你应该使用matplotlib来绘图,它的功能几乎和Matlab的绘图界面一样,至少在这个层面上是这样的。

看起来你在猜测Python会在某个随机的包中有和Matlab相同的方法名。这并不是一个好主意。相反,查一下Matlab方法的在线文档,弄清楚它具体做了什么,然后再去查找Python包的文档,找一个能实现你想要功能的方法。这个方法可能不存在,但我敢打赌,在这么简单的程序中,你需要的大部分功能都是有的。

在把任何Matlab代码转换成其他语言时,你最需要理解的就是Matlab数组的工作方式,这种方式非常独特(但对它的目标应用非常优秀)。Numpy的功能大致相同,但表示方式完全不同。

串口模块已经给你提供了一个打开的文件对象,所以你不需要使用fopen。

我觉得你需要花很多时间去阅读Python和Matlab的文档,因为很明显你现在对这两者都不太了解。

别让我打击你,我只是诚实地告诉你你现在的情况。

撰写回答