Setting Up the Environment
To start, we need to set up Octave and install the necessary libraries within Google Colab. This process will set up our environment to facilitate seamless integration between Python and Octave.
!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 pillow
After installing, we initialize an Oct2Py session and define a helper function for displaying plots generated in Octave:
from oct2py import Oct2Py, Oct2PyError
import numpy as np, matplotlib.pyplot as plt, textwrap
from scipy.io import savemat, loadmat
from PIL import Image
oc = 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()
Basic Operations and Data Exchange
Now, let’s explore how to perform basic operations and exchange data between Python and Octave. This integration allows us to utilize the strengths of both languages.
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)
Working with Structs and Files
This section demonstrates how to push Python lists into Octave as cell arrays, create a struct, and retrieve it back into Python:
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 also create a custom gradient_descent.m function in Octave and call it from Python:
print("\n--- Writing and calling .m files ---")
gd_code = r"""
function [w, hist] = gradient_descent(X, y, alpha, iters)
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));
endfor
endfunction
"""
with open("gradient_descent.m","w") as f: f.write(textwrap.dedent(gd_code))
Plotting and Visualization
Next, we visualize a damped sine plot generated in Octave and display it inline in our Python notebook:
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")
Advanced Usage: Packages and Function Handles
In this section, we load the signal and control packages in Octave to design a Butterworth filter and visualize the results back in Python:
print("\n--- Packages (signal/control) ---")
signal_ok = True
try:
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()
.mat File Exchange and Error Handling
We can also exchange .mat files between Python and Octave, ensuring a smooth data flow:
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()))
We also demonstrate error handling by catching an Octave error as a Python exception:
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])
Benchmarking and Multi-File Pipelines
We perform a benchmarking exercise to compare vectorized versus looped operations in Octave:
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")
Finally, we create a multi-file pipeline in Octave:
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.0
sig = 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])
In conclusion, we have demonstrated how to integrate Octave’s MATLAB-compatible features directly into Python and Colab. This integration allows for effective data exchange, function calls, plotting, and performance benchmarking, showcasing the versatility of mixing MATLAB/Octave workflows with Python.
FAQs
1. What is Octave, and how does it relate to MATLAB?
Octave is a high-level programming language primarily used for numerical computations. It is largely compatible with MATLAB, which makes it a popular choice for users transitioning from MATLAB.
2. Can I run Octave code in Python without using Oct2Py?
While there are other methods, Oct2Py provides a straightforward interface for executing Octave code from Python, making it the preferred choice for most users.
3. Do I need to install Octave separately to use Oct2Py?
Yes, Octave must be installed on your system or in your Google Colab environment to use Oct2Py effectively.
4. What are some common errors when using Oct2Py?
Common errors include mismatched data types and function names that do not exist in Octave. Proper error handling in Python can help manage these issues.
5. Is it possible to use Octave toolboxes with Oct2Py?
Yes, you can load Octave toolboxes in your Oct2Py session, provided they are available in your Octave installation.



























