MarkTechPost@AI 09月20日
在Python中运行MATLAB风格代码:Octave与oct2py库的结合
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

本教程演示了如何通过oct2py库将Octave与Python连接,从而在Python环境中无缝运行MATLAB风格的代码。我们将详细介绍如何在Google Colab上设置环境,实现NumPy与Octave之间的数据交换,编写和调用.m文件,以及在Python中可视化Octave生成的图表。此外,教程还涵盖了如何处理Octave的工具箱、结构体和.mat文件。通过这种方式,用户可以在利用Python生态系统的灵活性的同时,继续使用熟悉的MATLAB/Octave语法及其强大的数值计算能力,实现一体化的工作流程。

🧩 **环境搭建与基础功能展示**: 教程首先在Google Colab中配置了Octave及相关Python库,并展示了如何初始化oct2py会话。通过`eval`命令,可以直接在Octave中执行MATLAB风格的代码,如矩阵运算、特征值分解和三角函数计算。同时,还演示了如何使用`push`和`pull`函数在Python的NumPy数组与Octave之间进行数据交换,例如对NumPy数组进行卷积滤波操作。

🛠️ **自定义.m文件调用与绘图集成**: 教程详细介绍了如何从Python创建并调用Octave的`.m`脚本文件。通过编写一个梯度下降算法的Octave函数,并从Python中执行,成功估计出模型参数并验证了损失函数的变化。此外,还展示了如何在Octave中生成图形,将其保存为PNG图片,然后直接在Python环境中显示,实现了Octave绘图在Python工作流中的无缝集成。

📦 **Octave工具箱与函数句柄应用**: 教程进一步展示了Octave工具箱(如signal和control)在Python中的应用。通过加载这些工具箱,可以在Python中设计和应用Butterworth滤波器,并可视化处理后的信号。同时,还演示了如何处理Octave的函数句柄,包括匿名函数和命名函数`.m`文件,展示了在Python中调用这些函数以执行计算的灵活性。

🗂️ **.mat文件读写与错误处理**: 教程说明了如何在Python和Octave之间进行`.mat`文件的读写操作,确保数据在两种环境之间能够双向传输。此外,还包含了Octave错误在Python中的异常捕获机制,增强了程序的健壮性。最后,通过基准测试对比了Octave中向量化操作与循环操作的性能差异,并构建了一个包含信号处理和分析的`mini_pipeline`,展示了Octave代码模块化和复用的能力。

🚀 **整合优势,提升效率**: 总体而言,该教程证明了在Python和Colab环境中集成Octave的MATLAB兼容功能的有效性。通过数据交换、自定义函数调用、绘图、包使用和性能基准测试,展示了在不离开Notebook的情况下混合使用MATLAB/Octave和Python工作流的可行性。结合这两种环境的优势,用户可以更高效、更灵活地解决问题。

In this tutorial, we explore how we can seamlessly run MATLAB-style code inside Python by connecting Octave with the oct2py library. We set up the environment on Google Colab, exchange data between NumPy and Octave, write and call .m files, visualize plots generated in Octave within Python, and even work with toolboxes, structs, and .mat files. By doing this, we gain the flexibility of Python’s ecosystem while continuing to leverage the familiar syntax and numerical power of MATLAB/Octave in a single workflow. Check out the FULL CODES here.

!apt-get -qq update!apt-get -qq install -y octave gnuplot octave-signal octave-control > /dev/null!python -m pip -q install oct2py scipy matplotlib pillowfrom oct2py import Oct2Py, Oct2PyErrorimport numpy as np, matplotlib.pyplot as plt, textwrapfrom scipy.io import savemat, loadmatfrom PIL import Imageoc = Oct2Py()print("Octave version:", oc.eval("version"))def show_png(path, title=None):   img = Image.open(path)   plt.figure(figsize=(5,4)); plt.imshow(img); plt.axis("off")   if title: plt.title(title)   plt.show()

We begin by setting up Octave and essential libraries in Google Colab, ensuring that we have Octave-Forge packages and Python dependencies ready. We then initialize an Oct2Py session and define a helper function so we can display Octave-generated plots directly in our Python workflow. Check out the FULL CODES here.

print("\n--- Basic eval ---")print(oc.eval("A = magic(4); A"))print("eig(A) diag:", oc.eval("[V,D]=eig(A); diag(D)'"))print("sin(pi/4):", oc.eval("sin(pi/4)"))print("\n--- NumPy exchange ---")x = np.linspace(0, 2*np.pi, 100)y = np.sin(x) + 0.1*np.random.randn(x.size)y_filt = oc.feval("conv", y, np.ones(5)/5.0, "same") print("y_filt shape:", np.asarray(y_filt).shape)print("\n--- Cells & Structs ---")cells = ["hello", 42, [1,2,3]]oc.push("C", cells)oc.eval("s = struct('name','Ada','score',99,'tags',{C});")s = oc.pull("s")print("Struct from Octave -> Python:", s)

We test the bridge between Python and Octave by running basic matrix operations, eigenvalue decomposition, and trigonometric evaluations directly in Octave. We then exchange NumPy arrays with Octave to perform a convolution filter and verify its shape. Finally, we demonstrate how to push Python lists into Octave as cell arrays, build a struct, and retrieve it back into Python for seamless data sharing. Check out the FULL CODES here.

print("\n--- Writing and calling .m files ---")gd_code = r"""function [w, hist] = gradient_descent(X, y, alpha, iters) % X: (n,m), y: (n,1). Adds bias; returns weights and loss history. if size(X,2) == 0, error('X must be 2D'); end n = rows(X); Xb = [ones(n,1), X]; m = columns(Xb); w = zeros(m,1); hist = zeros(iters,1); for t=1:iters   yhat = Xb*w;   g = (Xb'*(yhat - y))/n;   w = w - alpha * g;   hist(t) = (sum((yhat - y).^2)/(2*n)); endforendfunction"""with open("gradient_descent.m","w") as f: f.write(textwrap.dedent(gd_code))np.random.seed(0)X = np.random.randn(200, 3)true_w = np.array([2.0, -1.0, 0.5, 3.0])    y = true_w[0] + X @ true_w[1:] + 0.3*np.random.randn(200)w_est, hist = oc.gradient_descent(X, y.reshape(-1,1), 0.1, 100, nout=2)print("Estimated w:", np.ravel(w_est))print("Final loss:", float(np.ravel(hist)[-1]))print("\n--- Octave plotting -> PNG -> Python display ---")oc.eval("x = linspace(0,2*pi,400); y = sin(2*x) .* exp(-0.2*x);")oc.eval("figure('visible','off'); plot(x,y,'linewidth',2); grid on; title('Damped Sine (Octave)');")plot_path = "/content/oct_plot.png"oc.eval(f"print('{plot_path}','-dpng'); close all;")show_png(plot_path, title="Octave-generated Plot")

We write a custom gradient_descent.m in Octave, call it from Python with nout=2, and confirm that we recover reasonable weights and a decreasing loss. We then render a damped sine plot in an off-screen Octave figure and display the saved PNG inline in our Python notebook, keeping the whole workflow seamless. Check out the FULL CODES here.

print("\n--- Packages (signal/control) ---")signal_ok = Truetry:   oc.eval("pkg load signal; pkg load control;")   print("Loaded: signal, control")except Oct2PyError as e:   signal_ok = False   print("Could not load signal/control, skipping package demo.\nReason:", str(e).splitlines()[0])if signal_ok:   oc.push("t", np.linspace(0,1,800))   oc.eval("x = sin(2*pi*5*t) + 0.5*sin(2*pi*40*t);")   oc.eval("[b,a] = butter(4, 10/(800/2)); xf = filtfilt(b,a,x);")   xf = oc.pull("xf")   plt.figure(); plt.plot(xf); plt.title("Octave signal package: filtered"); plt.show()print("\n--- Function handles ---")oc.eval("""f = @(z) z.^2 + 3*z + 2;vals = feval(f, [0 1 2 3]);""")vals = oc.pull("vals")print("f([0,1,2,3]) =", np.ravel(vals))quadfun_code = r"""function y = quadfun(z) y = z.^2 + 3*z + 2;end"""with open("quadfun.m","w") as f: f.write(textwrap.dedent(quadfun_code))vals2 = oc.quadfun(np.array([0,1,2,3], dtype=float))print("quadfun([0,1,2,3]) =", np.ravel(vals2))

We load the signal and control packages so we can design a Butterworth filter in Octave and visualize the filtered waveform back in Python. We also work with function handles by evaluating an anonymous quadratic inside Octave and, for robustness, define a named quadfun.m that we call from Python, showing both handle-based and file-based function calls in the same flow. Check out the FULL CODES here.

print("\n--- .mat I/O ---")data_py = {"A": np.arange(9).reshape(3,3), "label": "demo"}savemat("demo.mat", data_py)oc.eval("load('demo.mat'); A2 = A + 1;")oc.eval("save('-mat','demo_from_octave.mat','A2','label');")back = loadmat("demo_from_octave.mat")print("Keys from Octave-saved mat:", list(back.keys()))print("\n--- Error handling ---")try:   oc.eval("no_such_function(1,2,3);")except Oct2PyError as e:   print("Caught Octave error as Python exception:\n", str(e).splitlines()[0])print("\n--- Simple Octave benchmark ---")oc.eval("N = 2e6; a = rand(N,1);")oc.eval("tic; s1 = sum(a); tv = toc;")t_vec = float(oc.pull("tv"))oc.eval("tic; s2 = 0; for i=1:length(a), s2 += a(i); end; tl = toc;")t_loop = float(oc.pull("tl"))print(f"Vectorized sum: {t_vec:.4f}s | Loop sum: {t_loop:.4f}s")print("\n--- Multi-file pipeline ---")pipeline_m = r"""function out = mini_pipeline(x, fs) try, pkg load signal; catch, end [b,a] = butter(6, 0.2); y = filtfilt(b,a,x); y_env = abs(hilbert(y)); out = struct('rms', sqrt(mean(y.^2)), 'peak', max(abs(y)), 'env', y_env(1:10));end"""with open("mini_pipeline.m","w") as f: f.write(textwrap.dedent(pipeline_m))fs = 200.0sig = np.sin(2*np.pi*3*np.linspace(0,3,int(3*fs))) + 0.1*np.random.randn(int(3*fs))out = oc.mini_pipeline(sig, fs, nout=1)print("mini_pipeline -> keys:", list(out.keys()))print("RMS ~", float(out["rms"]), "| Peak ~", float(out["peak"]), "| env head:", np.ravel(out["env"])[:5])print("\nAll sections executed. You are now running MATLAB/Octave code from Python!")

We exchange .mat files between Python and Octave, confirming that data flows both ways without issues. We also test error handling by catching an Octave error as a Python exception. Next, we benchmark vectorized versus looped summations in Octave, showing the performance edge of vectorization. Finally, we built a multi-file pipeline that applies filtering and envelope detection, returning key statistics to Python, which demonstrates how we can organize Octave code into reusable components within our Python workflow.

In conclusion, we see how we can integrate Octave’s MATLAB-compatible features directly into Python and Colab. We successfully test data exchange, custom functions, plotting, package usage, and performance benchmarking, demonstrating that we can mix MATLAB/Octave workflows with Python without leaving our notebook. By combining the strengths of both environments, we put ourselves in a position to solve problems more efficiently and with greater flexibility.


Check out the FULL CODES here. Feel free to check out our GitHub Page for Tutorials, Codes and Notebooks. Also, feel free to follow us on Twitter and don’t forget to join our 100k+ ML SubReddit and Subscribe to our Newsletter.

The post Run MATLAB-Style Code Inside Python by Connecting Octave with the oct2py Library appeared first on MarkTechPost.

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Python Octave oct2py MATLAB Google Colab 科学计算 数据分析 机器学习 数值计算 代码集成
相关文章