Matrices & Basic Operations
Creating Matrices & Vectors
MATLAB (MATrix LABoratory) treats all variables as matrices. Vectors are 1xN or Nx1 matrices. Use spaces or commas to separate elements in a row, semicolons for new rows. zeros, ones, eye, rand, and magic create common test matrices. The colon operator start:step:stop generates ranges (default step 1). linspace(a, b, n) creates n evenly-spaced points — ideal for plot axes.
% row vector
v = [1 2 3 4 5];
% column vector (semicolon = new row)
c = [1; 2; 3];
% 3x3 matrix
A = [1 2 3; 4 5 6; 7 8 9];
% special matrices
Z = zeros(3); % 3x3 zeros
O = ones(2, 4); % 2x4 ones
I = eye(3); % 3x3 identity
R = rand(2, 3); % 2x3 uniform random
N = randn(4); % 4x4 normal random
M = magic(4); % 4x4 magic square
D = diag([1 2 3]); % diagonal matrix
% linear spacing
l = linspace(0, 1, 5); % [0 0.25 0.5 0.75 1]
r = 0:0.5:2; % [0 0.5 1 1.5 2]Matrix Indexing & Slicing
MATLAB is 1-indexed (not 0-indexed). The colon : means 'all' — A(:,2) is the entire second column. A(1:3, :) selects rows 1-3. 'end' refers to the last index in that dimension. Logical indexing (A(A > 5)) is extremely powerful — it extracts or modifies elements matching a condition. find returns the indices of nonzero/true elements, and with two outputs gives row and column separately.
A = magic(4); % 4x4 magic square
% single element (1-indexed!)
A(2, 3) % row 2, col 3
% entire row or column
A(1, :) % first row (all columns)
A(:, 2) % second column (all rows)
% submatrix
A(1:2, 2:4) % rows 1-2, cols 2-4
% linear indexing (column-major)
A(5) % 5th element counting down columns
% end keyword
A(end, :) % last row
A(:, end-1) % second-to-last column
% logical indexing
A(A > 10) % all elements > 10 (as vector)
A(A > 10) = 0; % set large elements to 0
% find indices
[r, c] = find(A == 16) % row and col of value 16Matrix Arithmetic
The dot before an operator (.*) makes it element-wise instead of matrix-wise — this is the #1 source of beginner bugs. A*B is matrix multiplication; A.*B multiplies corresponding elements. The backslash operator (\) solves linear systems efficiently and accurately (LU decomposition) — always prefer x = A\b over inv(A)*b. The apostrophe (') transposes; for complex matrices use .' for non-conjugate transpose.
A = [1 2; 3 4];
B = [5 6; 7 8];
% matrix operations
C = A + B; % addition
D = A - B; % subtraction
E = A * B; % matrix multiplication
F = A'; % transpose
G = A^2; % matrix power (A * A)
% element-wise operations (use the dot!)
H = A .* B; % element-wise multiply
I = A ./ B; % element-wise divide
J = A .^ 2; % element-wise power
K = 2 * A; % scalar multiply
% matrix functions
det(A) % determinant
inv(A) % inverse
pinv(A) % pseudo-inverse
rank(A) % rank
trace(A) % trace (sum of diagonal)
% solving linear systems Ax = b
b = [5; 11];
x = A \ b; % left division: solves A*x = b
x = inv(A) * b; % equivalent but slowerMatrix Manipulation
Concatenation with [A B] (spaces) joins horizontally; [A; B] (semicolons) joins vertically — mirroring row creation syntax. reshape fills column-major (down then across). flipud/fliplr/rot90 reorient matrices. repmat tiles a matrix in a grid pattern. Setting a row or column to [] deletes it. size returns dimensions, length returns the largest dimension, numel returns total element count.
A = [1 2; 3 4];
B = [5 6; 7 8];
% concatenation
C = [A B]; % horizontal: [1 2 5 6; 3 4 7 8]
D = [A; B]; % vertical: 4x4
% reshape
E = reshape(1:12, 3, 4); % 3x4 matrix from 1..12
% flip and rotate
F = flipud(A); % flip up-down
G = fliplr(A); % flip left-right
H = rot90(A); % rotate 90 degrees
% repmat (tile)
I = repmat([1 2], 2, 3); % repeat [1 2] in a 2x3 grid
% size and length
[m, n] = size(A); % m=2, n=2
len = length(A); % max dimension = 2
num = numel(A); % total elements = 4
% remove rows/cols
A(2, :) = []; % delete row 2
A(:, 1) = []; % delete column 1Element-wise Functions & Vectorization
MATLAB's strength is vectorization — applying operations to entire arrays at once, which runs in optimized C/Fortran under the hood. sin, exp, sqrt etc. operate element-wise automatically. sum/prod/max/min work column-wise by default (dimension 1); pass dimension 2 for row-wise. A(:) flattens a matrix to a vector. Always prefer vectorized operations over for-loops for performance — they can be 10-100x faster.
% math functions operate element-wise
x = 0:0.1:2*pi;
y = sin(x); % sine of each element
z = exp(x); % exponential
w = sqrt(x); % square root
% rounding
round(3.7) % 4
floor(3.7) % 3
ceil(3.2) % 4
fix(-3.7) % -3 (toward zero)
% sums and products along dimensions
A = magic(3);
sum(A) % sum of each column (row vector)
sum(A, 2) % sum of each row (column vector)
sum(A(:)) % sum of ALL elements
prod(A) % product of each column
cumsum(A) % cumulative sum
% min, max, sort
[v, i] = max(A(:)) % max value and its index
sort(A, 'descend') % sort each column descending
% AVOID loops — vectorize!
% BAD: for i=1:1000, y(i)=sin(i); end
% GOOD:
i = 1:1000;
y = sin(i); % fast, vectorizedControl Flow & Logic
If / Elseif / Else
MATLAB uses if/elseif/else/end (note: elseif is one word). Logical operators: && (scalar AND), || (scalar OR), & (element-wise AND), | (element-wise OR), ~ (NOT, not !). For string comparison use strcmp/strcmpi (case-insensitive) — the == operator only works for character arrays of the same length. Always end blocks with 'end'.
score = 85;
if score >= 90
grade = 'A';
elseif score >= 80
grade = 'B';
elseif score >= 70
grade = 'C';
else
grade = 'F';
end
disp(grade); % B
% logical operators: && (and), || (or), ~ (not)
if x > 0 && x < 10
disp('in range');
end
% compare strings with strcmp
if strcmp(name, 'Alice')
disp('hi Alice');
endFor & While Loops
for iterates over each column of the given expression (for vectors, each element). while runs while the condition is true. ALWAYS preallocate arrays before loops (result = zeros(1,N)) — growing an array in a loop forces reallocation every iteration and is extremely slow. The colon operator 1:5 creates [1 2 3 4 5]. fprintf prints formatted output (like C's printf).
% for loop over a range
for i = 1:5
fprintf('i = %d\n', i);
end
% iterate over a vector
v = [10 20 30];
for val = v
disp(val);
end
% nested loop over a matrix
A = zeros(3, 3);
for r = 1:3
for c = 1:3
A(r, c) = r * c;
end
end
% while loop
n = 10;
while n > 1
n = n / 2;
fprintf('%.2f\n', n);
end
% preallocate for speed (IMPORTANT!)
result = zeros(1, 1000);
for i = 1:1000
result(i) = i^2;
endSwitch & Break/Continue
switch matches a value against case labels — no break needed (unlike C/Java). case can take a cell array for multiple values. otherwise is the default. break exits the innermost loop; continue skips to the next iteration. try/catch handles errors gracefully; ME is an MException object with .message and .identifier. MATLAB does not have a ternary operator — use if/else or inline functions.
% switch statement
method = 'linear';
switch method
case 'linear'
disp('using linear');
case 'cubic'
disp('using cubic');
case {'nearest', 'spline'}
disp('using nearest or spline');
otherwise
disp('unknown method');
end
% break and continue
for i = 1:10
if i == 5
break % exit the loop entirely
end
if mod(i, 2) == 0
continue % skip to next iteration
end
disp(i); % prints 1 3
end
% try-catch for error handling
try
x = 1 / 0; % may error
catch ME
fprintf('Error: %s\n', ME.message);
endLogical Operations & Indexing
Logical indexing is MATLAB's killer feature — A(condition) selects elements where the logical array is true. ~= is 'not equal' (not !=). & and | are element-wise; && and || are short-circuit (scalar only, preferred in if conditions). find returns linear indices of true values. any/all test if any/all elements are true, optionally along a dimension. The is* family tests types and special values (NaN, Inf).
A = [1 2 3 4 5 6 7 8 9 10];
% comparison operators
A > 5 % logical array
A == 5
A ~= 5 % not equal (NOT !=)
A >= 3 & A <= 7 % element-wise AND
A < 3 | A > 7 % element-wise OR
% logical indexing (powerful!)
A(A > 5) % [6 7 8 9 10]
A(A > 5) = 0; % set elements > 5 to 0
A(mod(A, 2) == 0) % even numbers
% find indices
idx = find(A > 5); % indices of elements > 5
[r, c] = find(A > 5); % row and col (for matrices)
% any and all
any(A > 5) % true if ANY element > 5
all(A > 0) % true if ALL elements > 0
any(A > 5, 2) % per row
% is functions
isnan(x); isinf(x); isfinite(x);
isnumeric(x); ischar(x); iscell(x);Strings & Formatting
MATLAB has two string types: char arrays ('text', legacy) and string scalars ("text", R2017+). String scalars are more flexible for manipulation. sprintf returns a formatted string; fprintf prints to console or file. Common format specifiers: %s (string), %d (integer), %f (float), %.2f (2 decimals), %e (scientific). strsplit/strjoin handle delimited lists. num2str/mat2str convert numbers to strings.
% string creation
s1 = 'Hello'; % char array
s2 = "World"; % string scalar (R2017+)
% concatenation
greeting = [s1 ', ' s2 '!']; % char array concat
full = s1 + " " + s2; % string concat
% formatting
name = 'Alice';
age = 30;
fprintf('Name: %s, Age: %d\n', name, age);
str = sprintf('Pi is %.2f', pi); % returns string
% common string functions
upper('hello') % HELLO
lower('WORLD') % world
strlength("hello") % 5 (string)
length('hello') % 5 (char array)
strcmp('a', 'a') % true
strfind('hello', 'll') % 3 (index)
strrep('cat', 'c', 'b') % bat
strsplit('a,b,c', ',') % {'a','b','c'}
strjoin({'a','b'}, '-') % a-b
num2str(42) % '42'Functions & Scripts
Function Definition
Functions must be in a file with the same name (add.m for function add), or at the end of a script file. The first line is the function declaration. Functions have their own workspace (separate from the base workspace). nargin/nargout let you handle optional arguments — nargin counts actual inputs. Multiple outputs are captured with [a, b] = func(). If you call with fewer outputs, extra ones are discarded.
% function in a file named 'add.m'
function result = add(a, b)
% ADD returns the sum of a and b
result = a + b;
end
% with multiple inputs and outputs
function [mn, mx, avg] = stats(v)
mn = min(v);
mx = max(v);
avg = mean(v);
end
% calling functions
s = add(3, 4); % 7
[lo, hi, mu] = stats([1 2 3 4 5]);
% capture only first output
minimum = stats([1 2 3]); % gets mn only
% nargin and nargout (number of args)
function y = power(x, n)
if nargin < 2
n = 2; % default value
end
y = x .^ n;
endAnonymous & Inline Functions
Anonymous functions (@(args) expr) are quick one-line functions defined inline — perfect for passing to solvers (fzero, integral, ode45) without creating files. They capture workspace variables at creation time. Function handles (@sin) let you pass built-in or user functions as arguments. This is essential for numerical computing: integral(@(x) f(x), a, b) integrates any function you define.
% anonymous function (one-liner, no file needed)
square = @(x) x .^ 2;
square(5) % 25
square([1 2 3]) % [1 4 9]
% with multiple inputs
add = @(a, b) a + b;
add(3, 4) % 7
% capture variables from workspace
c = 10;
addc = @(x) x + c;
addc(5) % 15
% function handle to built-in
f = @sin;
f(pi/2) % 1
% pass functions as arguments
result = integral(@(x) x.^2, 0, 1); % integrate x^2 from 0 to 1
result = fzero(@(x) x^2 - 2, 1); % find root near 1
% array of function handles
funs = {@sin, @cos, @tan};
funs{1}(0) % 0Scripts & Live Scripts
Scripts are sequences of commands that run in the base workspace (unlike functions, which have isolated workspaces). The %% marker creates 'cells' (sections) you can run independently with Ctrl+Enter — great for incremental development. Live Scripts (.mlx) are like Jupyter notebooks: they combine code, formatted text, equations, and inline plots in one interactive document. Prefer functions over scripts for reusable code.
% A script is just a sequence of commands in a .m file
% It shares the base workspace
% script: analyze_data.m
data = load('data.mat');
cleaned = data.values(data.values > 0);
mean_val = mean(cleaned);
fprintf('Mean: %.2f\n', mean_val);
plot(cleaned);
title('Cleaned Data');
% sections (cells) with %%
%% Initialize
x = linspace(0, 2*pi, 100);
%% Plot
plot(x, sin(x));
%% Analyze
disp(mean(sin(x)));
% Run a section: Ctrl+Enter (in editor)
% Live Scripts (.mlx): rich text, inline plots, equationsNested & Local Functions
Scripts can contain local functions at the end of the file (since R2016b) — they're only visible within that file. Nested functions (defined inside another function) share the parent's workspace, so they can read and modify its variables — useful for callbacks and accumulators but can make code harder to follow. Local functions in function files are helpers visible only within that file. Use local functions to keep scripts organized without creating many files.
% local functions in a script (must be at the end)
% main_script.m
x = 1:10;
y = process(x);
disp(y);
function r = process(v)
r = normalize(scale(v)); % calls another local function
end
function s = scale(v)
s = v * 10;
end
function n = normalize(v)
n = v / max(v);
end
% nested function (inside another function)
function outer(x)
y = 0;
function inner()
y = y + x; % can access outer's variables
end
inner();
disp(y);
endVariable Scope & Global
MATLAB passes arguments by value (copy-on-modify), so functions can't accidentally change caller variables — unlike C/Python. Use global for truly shared state (declare in every function that uses it), but prefer passing arguments. persistent variables retain their value between function calls (like static in C) — useful for counters, caches, or memoization. Initialize persistent variables with isempty check on first call. Avoid globals in favor of function returns or nested functions.
% base workspace variables
x = 10;
% functions have their OWN workspace
function y = myfunc()
% x is NOT accessible here
y = 5;
end
% pass by value (modifications don't affect caller)
function y = modify(v)
v = v * 2; % local copy
y = v;
end
a = 5;
b = modify(a); % b=10, a still 5
% global variables (use sparingly!)
global COUNTER
COUNTER = 0;
function increment()
global COUNTER
COUNTER = COUNTER + 1;
end
% persistent variables (like static in C)
function counter()
persistent count
if isempty(count)
count = 0;
end
count = count + 1;
disp(count);
endData Structures
Cell Arrays
Cell arrays are MATLAB's container for mixed-type data (like Python lists). Use curly braces {} to access the CONTENT of a cell, and parentheses () to get a cell (useful for slicing). This distinction is crucial: c{1} gives the string; c(1) gives a cell containing the string. Cells are essential for handling strings of different lengths, variable-size matrices, and ragged data. num2cell/mat2cell convert between numeric arrays and cells.
% cell arrays hold mixed data types
c = {'Alice', 30, [1 2 3], magic(2)};
% access with {} (content) vs () (cell)
c{1} % 'Alice' (the string itself)
c(1) % {'Alice'} (a 1x1 cell)
c{3}(2) % 2 (second element of third cell)
% modify and append
c{2} = 31;
c{end+1} = 'new'; % append
c{5} = 'skip'; % auto-fills gaps with []
% multi-dimensional cell array
c2 = {'a', 'b'; 'c', 'd'}; % 2x2 cell
% iterate over cells
for i = 1:numel(c)
disp(c{i});
end
% convert: cell2mat, mat2cell, num2cell
nums = num2cell(1:5); % {1, 2, 3, 4, 5}Structs & Tables
Structs group related data with named fields — like objects without methods. Tables (R2013+) are MATLAB's equivalent of dataframes: column-oriented, with named variables and row names. Tables are ideal for CSV/Excel data. Access columns by name (T.ages) or index. Logical indexing works on rows: T(T.age > 25, :) filters rows. summary() gives statistics for each column. Tables integrate with readtable/writetable for data I/O.
% struct: named fields with any data
user.name = 'Alice';
user.age = 30;
user.scores = [90 85 88];
disp(user.name); % Alice
% struct constructor
s = struct('name', 'Bob', 'age', 25, 'active', true);
% array of structs
users(1) = struct('name', 'Alice', 'age', 30);
users(2) = struct('name', 'Bob', 'age', 25);
disp(users(2).name); % Bob
% table (like a dataframe) — great for tabular data
names = {'Alice'; 'Bob'; 'Carol'};
ages = [30; 25; 28];
scores = [90; 85; 88];
T = table(names, ages, scores);
% access table columns
T.ages % column as array
T(:, 2) % column as table
T(1:2, :) % first 2 rows
T.age > 26 % logical indexing
T(T.age > 26, :) % rows where age > 26
% summary statistics
summary(T)String Arrays & Char Handling
Modern MATLAB (R2017+) prefers string arrays ("text") over char arrays ('text'). String arrays support vectorized operations: strlength, +, split, join, contains, matches, replace all work element-wise. Char arrays are still common in older code and are needed for some functions. Use string arrays for collections of text; they handle different lengths naturally (unlike char arrays which need padding or cells).
% string array (R2017+) — recommended for text
names = ["Alice", "Bob", "Carol"];
names(1) % "Alice"
names' % column string array
strlength(names) % [5 3 5]
% char array (legacy)
c = 'Hello World';
c(1:5) % 'Hello'
size(c) % [1 11]
% cell array of char vectors (legacy mixed-length)
old = {'Alice', 'Bob', 'Carol'};
% convert between types
s = string('hello'); % char -> string
c = char("hello"); % string -> char
cellarr = cellstr(names); % string array -> cell of char
% combine and split
full = "Alice" + " " + "Smith"; % "Alice Smith"
parts = split("a,b,c", ","); % ["a", "b", "c"]
joined = join(["a" "b" "c"], "-"); % "a-b-c"
% pattern matching
matches(names, 'A*') % logical: [true false false]
contains(names, 'li') % [true false false]
replace("hello", 'l', 'L') % "heLLo"Containers.Map & Sets
containers.Map is MATLAB's key-value dictionary (hash map) — useful for lookup tables and configuration. Keys can be strings or numbers. isKey checks existence; keys/values retrieve all. Set operations (union, intersect, setdiff, setxor, ismember) work on numeric arrays and cell arrays of strings. ismember tests membership and returns a logical array — great for filtering. These complement logical indexing for data manipulation.
% map (dictionary / hash table)
m = containers.Map;
m('name') = 'Alice';
m('age') = 30;
m('scores') = [90 85];
% access
m('name') % 'Alice'
isKey(m, 'name') % true
keys(m) % {'age', 'name', 'scores'}
values(m) % {30, 'Alice', [90 85]}
remove(m, 'age');
% create with initial values
m2 = containers.Map({'a','b','c'}, {1, 2, 3});
% set operations
A = [1 2 3 4 5];
B = [4 5 6 7 8];
union(A, B) % [1 2 3 4 5 6 7 8]
intersect(A, B) % [4 5]
setdiff(A, B) % [1 2 3]
setxor(A, B) % [1 2 3 6 7 8]
ismember(3, A) % true
ismember([1 6], A) % [true false]Categorical & Datetime
categorical arrays store text data efficiently (as integers with a label map) and support ordering — ideal for survey responses, ratings, or any fixed set of categories. datetime/duration (R2014+) replace the legacy datenum/datestr functions with a modern, timezone-aware date system. Date arithmetic is intuitive: add days(), hours(), minutes(). These types integrate with tables and plotting for time-series analysis.
% categorical data (efficient for repeated strings)
colors = categorical({'red', 'blue', 'red', 'green', 'blue'});
categories(colors) % list of categories
summary(colors) % count per category
ord = categorical({'low','med','high'}, ...
{'low','med','high'}, 'Ordinal', true);
ord(1) < ord(2) % true (ordered)
% datetime
t = datetime('now') % current date and time
t = datetime(2024, 1, 15)
t.Format = 'yyyy-MM-dd HH:mm:ss';
% duration
d = duration(2, 30, 0); % 2 hours 30 min
d = hours(2) + minutes(30);
% date arithmetic
t2 = t + days(7); % add a week
t2 - t % duration of 7 days
% date strings and numbers
s = datestr(t, 'yyyy-mm-dd'); % to string (legacy)
n = datenum(t); % to serial number
t = datetime(n, 'ConvertFrom', 'datenum');
% generate date range
dates = datetime(2024,1,1) + days(0:6); % one weekPlotting & Visualization
Basic 2D Plots
plot() is the core 2D plotting function. The third argument specifies color and style ('b-' = blue solid). hold on lets you overlay multiple plots; hold off releases. Always label axes and add a legend. axis([xmin xmax ymin ymax]) sets limits. saveas/print export figures — print with -r300 gives 300 DPI. gcf gets the current figure handle. The 'Location','best' option auto-places the legend.
x = linspace(0, 2*pi, 100);
% line plot
plot(x, sin(x), 'b-', 'LineWidth', 2);
hold on;
plot(x, cos(x), 'r--', 'LineWidth', 2);
hold off;
% labels and legend
xlabel('x (radians)');
ylabel('amplitude');
title('Sine and Cosine');
legend('sin(x)', 'cos(x)', 'Location', 'best');
grid on;
% line styles: b- blue solid, r-- red dashed
% g: green dotted, m-. magenta dash-dot
% markers: o circle, * star, s square, + plus
% axis control
axis([0 2*pi -1.5 1.5]); % [xmin xmax ymin ymax]
xlim([0 2*pi]);
ylim([-1.5 1.5]);
% save figure
saveas(gcf, 'plot.png');
print('-dpng', '-r300', 'plot.png');Multiple Plots & Subplots
subplot(r, c, n) divides the figure into an r-by-c grid and selects the nth cell for plotting. tiledlayout (R2019+) is the modern replacement — cleaner spacing and a shared title. nexttile advances to the next subplot. yyaxis creates plots with two y-axes (left and right) for data with different scales. Always call figure first to open a new window, or you'll overwrite the current plot.
% subplot(rows, cols, index)
figure;
subplot(2, 2, 1);
plot(x, sin(x));
title('Sine');
subplot(2, 2, 2);
plot(x, cos(x));
title('Cosine');
subplot(2, 2, 3);
plot(x, tan(x));
title('Tangent');
ylim([-5 5]);
subplot(2, 2, 4);
plot(x, exp(-x));
title('Decay');
% tiledlayout (newer, cleaner)
figure;
t = tiledlayout(2, 2);
nexttile; plot(x, sin(x)); title('Sine');
nexttile; plot(x, cos(x)); title('Cosine');
nexttile; plot(x, tan(x)); title('Tangent');
nexttile; plot(x, exp(-x)); title('Decay');
title(t, 'Trig Functions'); % overall title
% multiple y-axes
yyaxis left; plot(x, sin(x));
yyaxis right; plot(x, 100*cos(x));Specialized Plots
MATLAB has dozens of specialized plots: bar/barh (bar charts), histogram (replaces hist), scatter (with optional color/size mapping), pie, area, stem, stairs, compass, feather. scatter(x, y, size, color, 'filled') is especially powerful — the 4th argument colors points by a value, revealing a third dimension. histogram with 'Normalization','pdf' normalizes to a probability density for comparison with continuous distributions.
% bar chart
bar([1 2 3], [10 15 7]);
bar([1 2 3; 4 5 6], 'grouped'); % grouped bars
bar([1 2 3; 4 5 6], 'stacked'); % stacked bars
% histogram
data = randn(1000, 1);
histogram(data, 30); % 30 bins
histogram(data, 'Normalization', 'pdf');
% scatter plot
x = rand(100, 1);
y = 2*x + randn(100, 1)*0.1;
scatter(x, y, 50, 'filled');
% colored scatter
scatter(x, y, 50, y, 'filled'); % color by y value
colorbar;
% pie chart
pie([30 20 50], {'A', 'B', 'C'});
% area plot
area(1:5, [1 3 2 4 5]);
% stem (discrete)
stem(0:5, [1 4 9 16 25 36]);
% boxplot (requires Statistics toolbox)
boxplot(randn(100, 3));3D Plots & Surfaces
plot3 draws 3D parametric lines. For surfaces, first create a grid with meshgrid, then compute Z = f(X, Y). surf draws a filled surface; mesh draws a wireframe; contour draws 2D level curves. colormap (jet, parula, hot, cool) controls the color mapping; colorbar adds a legend. shading interp removes grid lines for smooth gradients. view(az, el) sets the camera angle. 'EdgeColor','none' hides mesh lines for a clean look.
% 3D line plot
t = 0:0.1:10*pi;
plot3(sin(t), cos(t), t);
xlabel('x'); ylabel('y'); zlabel('z');
% meshgrid for surface plots
[X, Y] = meshgrid(-2:0.1:2);
Z = X .* exp(-X.^2 - Y.^2);
% surface plots
figure;
subplot(1, 3, 1);
surf(X, Y, Z); % surface
title('surf');
subplot(1, 3, 2);
mesh(X, Y, Z); % wireframe
title('mesh');
subplot(1, 3, 3);
contour(X, Y, Z, 20); % contour lines
title('contour');
% colored surface with colorbar
figure;
surf(X, Y, Z, 'EdgeColor', 'none');
colorbar;
colormap jet;
shading interp; % smooth colors
% view angle
view(45, 30); % azimuth, elevation
axis equal;Plot Customization & Export
Almost every visual aspect is customizable via name-value pairs or set(). Colors are RGB triples [r g b] from 0-1. set(gca, ...) modifies the current axes (font, scale, limits). MATLAB supports LaTeX in titles/labels with 'Interpreter','latex'. exportgraphics (R2020+) is the modern export function with vector and high-DPI options. Use figure handles (f1, f2) to manage multiple windows. annotation() adds arrows, text boxes, and shapes.
% customize line appearance
plot(x, y, ...
'Color', [0.2 0.6 0.8], ... % RGB 0-1
'LineWidth', 2, ...
'Marker', 'o', ...
'MarkerSize', 8, ...
'MarkerFaceColor', 'r');
% annotations
text(1, 0.5, 'important point');
annotation('arrow', [0.3 0.5], [0.3 0.5]);
% figure and axes properties
set(gcf, 'Position', [100 100 800 600]);
set(gca, 'FontSize', 14, 'FontName', 'Arial');
set(gca, 'XScale', 'log'); % log scale
% latex in labels
title('Function: \\alpha + \\beta^2', 'Interpreter', 'latex');
% export high quality
exportgraphics(gcf, 'plot.pdf', 'ContentType', 'vector');
exportgraphics(gcf, 'plot.png', 'Resolution', 300);
% legend customization
legend('show', 'Location', 'northwest', ...
'FontSize', 12, 'Box', 'off');
% multiple figures
f1 = figure; plot(x, sin(x));
f2 = figure; plot(x, cos(x));
figure(f1); % switch back to f1Data Analysis & Statistics
Descriptive Statistics
MATLAB provides comprehensive statistics functions. mean/median/mode for central tendency; std/var/range/iqr for spread. By default these operate along the first dimension (columns). Use 'omitnan' to skip NaN values (important for real-world data). quantile/prctile give percentiles. The Statistics and Machine Learning Toolbox adds geomean, harmmean, zscore, and distribution functions. Always check for NaNs before analysis — they propagate through most operations.
data = [1 2 3 4 5 6 7 8 9 10];
% central tendency
mean(data) % 5.5
median(data) % 5.5
mode(data) % 1 (first mode)
geomean(data) % geometric mean (Stats toolbox)
harmmean(data) % harmonic mean
% dispersion
std(data) % standard deviation
var(data) % variance
range(data) % max - min
iqr(data) % interquartile range
mad(data) % mean absolute deviation
% extremes and quantiles
min(data); max(data);
quantile(data, 0.25) % 25th percentile
prctile(data, 95) % 95th percentile
% along dimensions
A = randn(100, 3);
mean(A) % mean of each column
mean(A, 2) % mean of each row
mean(A, 'all') % overall mean
% ignoring NaNs
data(5) = NaN;
mean(data, 'omitnan') % skip NaN values
nanmean(data) % legacy equivalentCurve Fitting & Regression
polyfit fits a polynomial of given degree; polyval evaluates it. For linear regression, regress() gives coefficients plus statistics (R², F-statistic, p-value). corrcoef returns the full correlation matrix. The Curve Fitting Toolbox provides fit() for interactive and programmatic fitting with custom models. lsqcurvefit (Optimization Toolbox) fits arbitrary nonlinear models. Always plot the fit against data to check quality — high-order polynomials can overfit.
% polynomial fit
x = 0:0.5:10;
y = 2*x + 1 + randn(size(x))*2; % noisy linear data
% linear least squares (degree 1)
p = polyfit(x, y, 1); % [slope, intercept]
yfit = polyval(p, x);
plot(x, y, 'o', x, yfit, '-');
% higher-order polynomial
p3 = polyfit(x, y, 3);
yfit3 = polyval(p3, x);
% fit with fittype (Curve Fitting Toolbox)
f = fit(x', y', 'poly2'); % quadratic
plot(f, x, y);
% custom model fit
% fit y = a*exp(b*x) using lsqcurvefit
model = @(p, x) p(1)*exp(p(2)*x);
params = lsqcurvefit(model, [1 0.1], x, y);
% correlation
r = corrcoef(x, y); % correlation matrix
r = corr(x, y); % correlation coefficient
% linear regression with stats
X = [ones(size(x)) x']; % design matrix
[b, bint, r, rint, stats] = regress(y', X);
% stats = [R^2, F, p, error_var]Interpolation & Resampling
interp1 interpolates 1D data — 'linear' is fast, 'spline' is smooth (can overshoot), 'pchip' preserves shape (no overshoot). interp2 does the same for 2D grids. For repeated queries, griddedInterpolant is more efficient (build once, query many times). resample changes the sampling rate of a signal (requires Signal Processing Toolbox). Always choose the method based on your data: spline for smooth functions, pchip for monotonic data, nearest for categorical.
% 1D interpolation
x = 0:5;
y = [0 1 4 9 16 25];
xi = 0:0.5:5;
yi = interp1(x, y, xi, 'linear'); % linear (default)
yi = interp1(x, y, xi, 'spline'); % cubic spline
yi = interp1(x, y, xi, 'pchip'); % shape-preserving
yi = interp1(x, y, xi, 'nearest'); % nearest neighbor
% extrapolation
yi = interp1(x, y, xi, 'linear', 'extrap');
% 2D interpolation
[X, Y] = meshgrid(0:2:10);
Z = X.^2 + Y.^2;
[Xi, Yi] = meshgrid(0:0.5:10);
Zi = interp2(X, Y, Z, Xi, Yi, 'spline');
% resample signal to new rate
y_resampled = resample(y, 3, 2); % 3/2 times the rate
% griddedInterpolant (efficient for repeated queries)
F = griddedInterpolant(x, y, 'spline');
y1 = F(2.5);
y2 = F([1.5 3.5 4.5]);FFT & Signal Processing
fft computes the Fast Fourier Transform — the foundation of frequency analysis. The output is complex; take abs() for magnitude. Convert to a single-sided spectrum by taking the first half and doubling (except DC and Nyquist). Frequencies range from 0 to fs/2 (Nyquist). ifft inverts back to time domain. Filtering in the frequency domain (zeroing unwanted frequencies) is simple but can cause ringing; use designfilt for proper filters. spectrogram shows frequency content over time.
% generate a signal with two frequencies
fs = 1000; % sampling rate (Hz)
t = 0:1/fs:1-1/fs; % 1 second of time
x = 2*sin(2*pi*50*t) + 1*sin(2*pi*120*t);
% compute FFT
N = length(x);
Y = fft(x);
P2 = abs(Y/N); % two-sided spectrum
P1 = P2(1:N/2+1); % one-sided spectrum
P1(2:end-1) = 2*P1(2:end-1);
f = fs*(0:(N/2))/N;
% plot
plot(f, P1);
xlabel('Frequency (Hz)');
ylabel('Amplitude');
title('Single-Sided Spectrum');
% filtering (simple low-pass)
cutoff = 100; % Hz
Y_filt = Y;
Y_filt(f > cutoff) = 0; % zero out high freqs (simplified)
x_filtered = real(ifft(Y_filt));
% spectrogram
spectrogram(x, 128, 120, 128, fs, 'yaxis');Optimization & Root Finding
fzero finds roots of 1D functions (needs a bracketing interval or guess). fminbnd minimizes a 1D function on a bounded interval; fminsearch uses Nelder-Mead for multivariate unconstrained optimization. fmincon (Optimization Toolbox) handles constraints. linprog solves linear programs. Always provide a good initial guess (x0) for iterative solvers. Check the exitflag output to confirm convergence. For global optimization, use GlobalSearch or MultiStart.
% find root of f(x) = 0
f = @(x) x^2 - 2;
x_root = fzero(f, 1); % ~1.4142 (sqrt(2))
x_root = fsolve(f, 1); % alternative
% minimize a function
fun = @(x) (x-3)^2 + 1;
[x_min, f_min] = fminbnd(fun, 0, 5); % bounded 1D
% x_min = 3, f_min = 1
% multivariate minimization
fun2 = @(x) x(1)^2 + x(2)^2; % sphere function
x0 = [1, 1];
[x_opt, f_opt] = fminsearch(fun2, x0);
% x_opt ≈ [0, 0]
% constrained optimization (Optimization Toolbox)
% minimize fun subject to A*x <= b
A = []; b = []; Aeq = []; beq = [];
lb = [0 0]; ub = [];
[x, fval] = fmincon(fun2, x0, A, b, Aeq, beq, lb, ub);
% linear programming
% minimize f'*x subject to A*x <= b
f = [-1; -1]; % maximize x+y
A = [1 1; -1 0; 0 -1];
b = [2; 0; 0];
[x, fval] = linprog(f, A, b);File I/O & Data Import
MAT-Files & Save/Load
.mat is MATLAB's native binary format — fast, compact, and preserves all variable types. save/load are the primary commands. Use -v7.3 for files over 2GB (HDF5-based). -ascii exports to human-readable text (loses type info). Loading into a struct (s = load(...)) avoids polluting the workspace. clear removes variables; clearvars -except keeps specified ones. Always save intermediate results in long computations to enable resuming.
% save variables to a .mat file
x = 1:10;
y = sin(x);
save('data.mat'); % save ALL variables
save('data.mat', 'x', 'y'); % save specific variables
save('data.mat', '-append'); % add more variables
% load variables
load('data.mat'); % load all into workspace
loaded = load('data.mat'); % load into a struct
loaded.x % access via struct
% save with compression
save('data.mat', 'x', 'y', '-v7.3'); % large files (>2GB)
save('data.mat', '-v7'); % compressed (default)
% save specific format
save('data.txt', 'x', '-ascii'); % plain text
save('data.csv', 'x', '-ascii', '-double');
% clear variables
clear x y; % remove specific
clear all; % remove everything
clearvars -except x; % keep only xReading Text & CSV Files
readtable is the modern way to read CSV/Excel — it returns a table with named columns and handles headers automatically. readmatrix reads numeric data into a matrix. For full control, use fopen/fgetl/fprintf/fclose (always close files!). fscanf reads formatted data like C. Always check fid for errors: if fid == -1, the file couldn't be opened. readcell handles mixed-type data that doesn't fit a matrix or table.
% readtable (recommended for tabular data)
T = readtable('data.csv');
T = readtable('data.xlsx', 'Sheet', 'Sheet1');
T = readtable('data.csv', 'Delimiter', ',');
% access columns by name
T.Var1; T.age;
% readmatrix (numeric data)
M = readmatrix('numbers.csv');
M = readmatrix('data.txt', 'Delimiter', '\t');
% readcell (mixed data)
C = readcell('mixed.csv');
% low-level file I/O
fid = fopen('data.txt', 'r');
while ~feof(fid)
line = fgetl(fid);
disp(line);
end
fclose(fid);
% read formatted data
fid = fopen('data.txt', 'r');
data = fscanf(fid, '%f %f', [2, inf]);
fclose(fid);
% write text
fid = fopen('output.txt', 'w');
fprintf(fid, 'Result: %.2f\n', 3.14159);
fclose(fid);Excel & Spreadsheet I/O
readtable/writetable are the recommended functions for Excel I/O. They handle headers, types, and sheets automatically. detectImportOptions lets you customize how columns are parsed (e.g., force a column to int32 or string). Use 'Range' to read/write specific cells. 'WriteMode','append' adds rows to an existing sheet. For large Excel files, consider CSV (faster) or .mat (native). The Spreadsheet Link toolbox connects MATLAB directly to Excel.
% read Excel files
T = readtable('data.xlsx');
T = readtable('data.xlsx', 'Sheet', 'Sales', 'Range', 'A1:D100');
% numeric data only
M = readmatrix('data.xlsx', 'Sheet', 1);
% write to Excel
writetable(T, 'output.xlsx');
writetable(T, 'output.xlsx', 'Sheet', 'Results');
% write matrix
writematrix(M, 'output.xlsx', 'Sheet', 1);
% cell array (mixed types)
C = {'Name','Age'; 'Alice',30; 'Bob',25};
writecell(C, 'people.xlsx');
% append to existing sheet
writetable(T, 'data.xlsx', 'Sheet', 1, 'WriteMode', 'append');
% read specific range
T = readtable('data.xlsx', 'Range', 'B2:D10');
% detect import options (customize parsing)
opts = detectImportOptions('data.csv');
opts = setvartype(opts, 'age', 'int32');
T = readtable('data.csv', opts);Working with Paths & Directories
dir() returns a struct array with .name, .date, .bytes, .isdir, .datenum for each file. fullfile joins paths portably (uses the right separator on each OS). fileparts splits a path into directory, name, and extension. exist('name', 'file') checks if a file exists. addpath adds directories to MATLAB's search path so functions in them are accessible; savepath persists this. These are essential for batch-processing files in folders.
% current directory
pwd
cd('C:\\Users\\data')
% list files
files = dir(); % struct array of files
files = dir('*.mat'); % filter by pattern
files = dir('subdir/'); % list a subdirectory
% access file info
for i = 1:length(files)
if ~files(i).isdir
fprintf('%s - %d bytes\n', files(i).name, files(i).bytes);
end
end
% path operations
fullfile('data', '2024', 'file.csv') % data/2024/file.csv
[filepath, name, ext] = fileparts('C:\\data\\test.csv')
% filepath = 'C:\data', name = 'test', ext = '.csv'
% create and remove directories
mkdir('output');
rmdir('output', 's'); % remove recursively
% file existence
if exist('data.mat', 'file')
load('data.mat');
end
% add folder to path
addpath('C:\\myfunctions');
savepath(); % save for future sessionsImages & Audio
imread/imshow/imwrite handle images (JPEG, PNG, TIFF, BMP). Images are stored as uint8 matrices (0-255) or doubles (0-1). rgb2gray converts color to grayscale. The Image Processing Toolbox adds imresize, imrotate, imfilter, edge detection, and morphological operations. audioread/audiowrite/sound handle audio files. Images and audio are just matrices, so all MATLAB math and plotting tools apply directly.
% read and display an image
img = imread('photo.jpg');
imshow(img);
[m, n, c] = size(img); % dimensions, c=3 for RGB
% write image
imwrite(img, 'output.png');
imwrite(img, 'output.jpg', 'Quality', 90);
% convert to grayscale
if size(img, 3) == 3
gray = rgb2gray(img);
imshow(gray);
end
% image processing
img2 = imresize(img, 0.5); % scale 50%
img3 = imrotate(img, 45); % rotate 45 degrees
img4 = imadjust(img, [0.2 0.8], []); % contrast adjust
% audio
[y, fs] = audioread('song.wav'); % y = samples, fs = sample rate
sound(y, fs); % play audio
audiowrite('output.wav', y, fs);
% record audio
recObj = audiorecorder(44100, 16, 1);
recordblocking(recObj, 3); % record 3 seconds
y = getaudiodata(recObj);Symbolic Math & Advanced
Symbolic Variables & Simplification
The Symbolic Math Toolbox enables exact (not numeric) computation. syms declares symbolic variables. simplify, expand, factor, collect manipulate algebraic expressions. subs substitutes values or variables. vpa (variable-precision arithmetic) computes to arbitrary precision — useful when floating-point roundoff matters. Symbolic results are exact (e.g., sqrt(2) stays as sqrt(2), not 1.4142...). Convert to numeric with double() when needed.
% create symbolic variables (Symbolic Math Toolbox)
syms x y z
% symbolic expressions
f = x^2 + 2*x + 1;
g = sin(x)^2 + cos(x)^2;
% simplify
simplify(f) % (x + 1)^2
simplify(g) % 1
expand((x+1)^3) % x^3 + 3*x^2 + 3*x + 1
factor(x^2 - 1) % (x - 1)*(x + 1)
collect(x^2 + 2*x + x^2)% 2*x^2 + 2*x
% substitute values
subs(f, x, 3) % 16 (f at x=3)
subs(f, x, y) % y^2 + 2*y + 1
% pretty print
pretty(f)
disp(f)
% convert between numeric and symbolic
double(sym('1/3')) % 0.3333
sym(0.5) % 1/2
vpa(pi, 50) % 50-digit pi: 3.1415926535897...Calculus: Derivatives & Integrals
diff differentiates (pass a second argument for higher-order derivatives). int integrates — without bounds it returns the antiderivative; with bounds it computes the definite integral. limit computes limits (including one-sided with 'left'/'right'). taylor expands a function as a Taylor series around a point. These return symbolic expressions; use double() or vpa() for numeric results. Symbolic calculus is exact and avoids numerical roundoff.
syms x
% differentiation
f = x^3 + 2*x^2 + x;
df = diff(f) % 3*x^2 + 4*x + 1
d2f = diff(f, 2) % second derivative: 6*x + 4
diff(f, x, 3) % third derivative: 6
% partial derivatives
syms x y
g = x^2 * y + sin(x*y);
diff(g, x) % 2*x*y + y*cos(x*y)
diff(g, y) % x^2 + x*cos(x*y)
% integration
int(x^2) % x^3/3 (indefinite)
int(x^2, x, 0, 1) % 1/3 (definite, 0 to 1)
int(sin(x), x, 0, pi) % 2
% limits
limit(sin(x)/x, x, 0) % 1
limit(1/x, x, inf) % 0
limit(1/x, x, 0, 'left') % -inf
% Taylor series
taylor(exp(x), x, 0, 'Order', 6)
% 1 + x + x^2/2 + x^3/6 + x^4/24 + x^5/120Solving Equations
solve finds exact (symbolic) solutions to algebraic equations and systems. For equations without closed-form solutions, use vpasolve (numeric). dsolve solves ordinary differential equations symbolically — provide initial/boundary conditions for a particular solution. Results are symbolic; convert with double/vpa for plotting. For complex ODEs that can't be solved symbolically, use ode45 (numeric solver) instead. Always check if solve returned empty (no solution found).
syms x y
% solve algebraic equations
solve(x^2 - 4 == 0, x) % [2; -2]
solve(x^2 + 1 == 0, x) % [i; -i] (complex roots)
% solve a system
sol = solve([x + y == 5, x - y == 1], [x, y]);
sol.x % 3
sol.y % 2
% solve with parameters
syms a b c
r = solve(a*x^2 + b*x + c == 0, x);
% r = -(b + (b^2 - 4*a*c)^(1/2))/(2*a), ...
% numerical solve (no closed form)
vpasolve(x^5 - 3*x + 1 == 0, x)
% differential equations
syms y(t) t
ode = diff(y, t) == -k*y; % dy/dt = -k*y
cond = y(0) == y0;
ySol(t) = dsolve(ode, cond); % y0*exp(-k*t)
% system of ODEs
syms x(t) y(t)
eq1 = diff(x,t) == y;
eq2 = diff(y,t) == -x;
sol = dsolve([eq1, eq2]);Laplace & Fourier Transforms
laplace/ilaplace compute the Laplace transform pair — essential for solving linear ODEs and analyzing control systems. fourier/ifourier do the same for the Fourier transform (continuous frequency). ztrans/iztrans handle discrete signals (digital filters). The workflow for solving ODEs via Laplace: transform the ODE to algebraic, solve for Y(s), then inverse-transform. These are exact symbolic operations; for numerical transforms use fft.
syms t s w
% Laplace transform
f = exp(-a*t);
F = laplace(f) % 1/(a + s)
% default: f(t) -> F(s)
% inverse Laplace
f2 = ilaplace(1/(s+1)) % exp(-t)
% Fourier transform
g = exp(-t^2);
G = fourier(g) % pi^(1/2)*exp(-w^2/4)
% inverse Fourier
g2 = ifourier(G)
% Z-transform (for discrete signals)
syms n z
h = a^n;
H = ztrans(h) % -z/(a - z) (for |z| > |a|)
h2 = iztrans(z/(z-a)) % a^n
% apply transform to solve ODE
% y'' + y = 0, y(0)=0, y'(0)=1
syms y(t) Y(s)
ode = diff(y, t, 2) + y == 0;
% take Laplace of both sides, solve for Y(s), then invertNumerical ODE Solvers
ode45 is the go-to ODE solver — a Runge-Kutta (4,5) method that's accurate and adaptive. For systems, the state is a vector v, and the function returns a column vector of derivatives. ode15s is for stiff problems (where dynamics operate on very different timescales). odeset configures tolerances and events. To pass parameters, use an anonymous function that captures them. Always plot the solution to verify it looks reasonable. For boundary-value problems, use bvp4c.
% solve dy/dt = f(t, y) numerically with ode45
% define the ODE as a function
f = @(t, y) -2*y; % dy/dt = -2y (exponential decay)
% solve on [0, 5] with y(0) = 1
[t, y] = ode45(f, [0 5], 1);
plot(t, y);
xlabel('t'); ylabel('y');
% system of ODEs (Lotka-Volterra predator-prey)
% dx/dt = 1.5x - xy, dy/dt = -0.7y + 0.1xy
ode_sys = @(t, v) [1.5*v(1) - v(1)*v(2);
-0.7*v(2) + 0.1*v(1)*v(2)];
[t, V] = ode45(ode_sys, [0 20], [10; 5]);
plot(t, V(:,1), 'b', t, V(:,2), 'r');
legend('Prey', 'Predator');
% stiff ODE solver (for fast dynamics)
[t, y] = ode15s(f, [0 5], 1);
% set options
opts = odeset('RelTol', 1e-6, 'AbsTol', 1e-9);
[t, y] = ode45(f, [0 5], 1, opts);
% pass parameters via anonymous function
a = 0.5;
f = @(t, y, a) -a*y;
[t, y] = ode45(@(t,y) f(t,y,a), [0 10], 1);Matrix Operations Deep Dive
Linear Equations & Decompositions
The backslash operator (\) is MATLAB's preferred linear solver — it auto-selects LU, QR, or Cholesky based on the matrix. Never use inv(A)*b unless you actually need the inverse; it's slower and less numerically stable. lu, qr, and chol return the standard matrix factorizations. eig computes eigenvalues/eigenvectors, and svd gives the singular value decomposition — fundamental for PCA, pseudo-inverses, and low-rank approximations.
% solve Ax = b
A = [3 2 -1; 2 -2 4; -1 0.5 -1];
b = [1; -2; 0];
x = A \ b; % backslash: preferred solver
x = inv(A) * b; % explicit inverse (slower, less stable)
x = linsolve(A, b); % optimized linear solver
% LU, QR, Cholesky decompositions
[L, U, P] = lu(A); % PA = LU
[Q, R] = qr(A); % QR factorization
R = chol(A'*A); % Cholesky (needs SPD matrix)
% eigenvalues and eigenvectors
[V, D] = eig(A); % A*V = V*D
eigenvalues = diag(D);
% singular value decomposition
[U, S, V] = svd(A); % A = U*S*V'Sparse Matrices
Sparse matrices store only nonzero entries — essential when working with 100k+ dimensional matrices that are mostly zeros (common in finite-element methods, graph algorithms, and PDEs). sparse(i,j,v) builds from triplet form; full converts back. Arithmetic between sparse matrices stays sparse. nnz counts nonzeros and spy plots the sparsity pattern. Sparse linear solves (A\b) use specialized solvers like UMFPACK automatically.
% create sparse matrix (memory efficient for large, mostly-zero)
S = sparse(10000, 10000);
S(1, 1) = 5;
S(2, 3) = 10;
% from triplets (row, col, value)
i = [1 2 2 3];
j = [1 1 3 3];
v = [4 5 7 9];
S = sparse(i, j, v, 3, 3);
% convert sparse <-> full
F = full(S);
S2 = sparse(F);
% sparse identity and diagonal
I = speye(1000);
D = spdiags(ones(1000,1), 0, 1000, 1000);
% operations preserve sparsity
nnz(S) % number of nonzeros
spy(S) % visualize sparsity patternMatrix Functions & Reshaping
reshape rearranges elements column-major (down columns first) — a common source of bugs when porting from row-major languages. flipud/fliplr/rot90 are handy for reversing or transposing in non-standard ways. repmat tiles a matrix; repelem duplicates individual elements. Concatenation uses [A; B] (vertical) and [A B] (horizontal), or horzcat/vertcat for programmatic use. arrayfun applies a function element-wise when vectorization isn't possible.
A = [1 2 3; 4 5 6];
% reshape (column-major order!)
B = reshape(A, 3, 2); % [1 5; 4 3; 2 6]
C = reshape(A, 6, 1); % column vector
% flip and rotate
flipud(A) % flip up-down
fliplr(A) % flip left-right
rot90(A) % rotate 90 degrees
rot90(A, 2) % rotate 180 degrees
% repmat and repelem
repmat([1 2], 2, 3) % tile 2x3
repelem([1 2 3], 2) % [1 1 2 2 3 3]
% concatenation
[A; A] % vertical (must have same # cols)
[A A] % horizontal (must have same # rows)
horzcat(A, A); vertcat(A, A);
% matrix functions (apply element-wise via fun)
arrayfun(@(x) x^2, A)Broadcasting & Vectorization
Since R2016b, MATLAB automatically broadcasts (expands) dimensions of size 1 to match the other operand — no need for bsxfun or repmat. Vectorization (operating on whole arrays instead of element-by-element loops) is the single biggest performance win in MATLAB, because the underlying BLAS/LAPACK routines are highly optimized. Always preallocate arrays before filling them in a loop; growing arrays dynamically forces reallocation on every iteration and is O(n^2).
% MATLAB implicitly expands (broadcasts) since R2016b
A = [1 2 3; 4 5 6]; % 2x3
b = [10 20 30]; % 1x3
C = A + b; % 2x3: b added to each row
c = [1; 2]; % 2x1
D = A + c; % 2x3: c added to each column
% vectorized operations (much faster than loops)
x = linspace(0, 2*pi, 1e6);
y = sin(x) .* cos(x); % element-wise, no loop needed
% avoid growing arrays in loops
% BAD: for k=1:1e6, s(k) = k; end
% GOOD: preallocate
s = zeros(1, 1e6);
for k = 1:1e6
s(k) = k;
end
% even better: vectorize
s = 1:1e6;
% bsxfun (legacy, before auto-broadcasting)
E = bsxfun(@plus, A, b);Numerical Linear Algebra Applications
The backslash operator solves least-squares problems automatically when A is rectangular (more rows than columns). polyfit/polyval fit and evaluate polynomials. PCA is most stably computed via SVD of the centered data matrix — the columns of V are principal directions and diag(S) gives the standard deviations. cond(A) measures numerical sensitivity; values above 1e12 mean the matrix is essentially singular for double-precision arithmetic.
% least-squares fit (overdetermined system)
A = [1 1; 1 2; 1 3; 1 4];
b = [6; 5; 7; 10];
x = A \ b; % least-squares solution
% polynomial curve fitting
t = 0:0.1:5;
y = 2*t.^2 + 1 + 0.5*randn(size(t));
p = polyfit(t, y, 2); % degree-2 fit
yfit = polyval(p, t);
% PCA via SVD
X = randn(100, 5);
Xc = X - mean(X); % center
[U, S, V] = svd(Xc, 0);
scores = Xc * V; % principal components
variances = diag(S).^2 / (size(X,1)-1);
% condition number (numerical stability)
cond(A) % large = ill-conditioned2D & 3D Plotting Deep Dive
Line Plots & Customization
plot is the workhorse 2D plotting function. Line spec strings like 'r--' (red dashed) combine color, marker, and style. hold on lets you overlay multiple plots. subplot(m,n,k) creates an m-by-n grid and selects the kth cell (row-major). set(gca, ...) modifies the current axes; gcf is the current figure. print with -dpng and -r300 exports a 300 DPI PNG — much higher quality than saveas.
x = linspace(0, 2*pi, 200);
y1 = sin(x); y2 = cos(x);
figure;
plot(x, y1, 'b-', 'LineWidth', 2); hold on;
plot(x, y2, 'r--', 'LineWidth', 1.5);
hold off;
% annotations
xlabel('Angle (rad)');
ylabel('Amplitude');
title('Sine and Cosine');
legend('sin(x)', 'cos(x)', 'Location', 'best');
grid on;
% axis control
axis([0 2*pi -1.2 1.2]);
set(gca, 'FontSize', 12, 'FontName', 'Arial');
% multiple subplots
subplot(2, 1, 1); plot(x, y1);
subplot(2, 1, 2); plot(x, y2);
% save figure
saveas(gcf, 'plot.png');
print('-dpng', '-r300', 'plot_hi.png');3D Surface, Mesh & Contour Plots
meshgrid creates the X, Y coordinate grids needed for surface plots. surf draws a filled surface, mesh draws a wireframe, and contour projects to 2D level curves. colormap changes the color mapping (jet, parula, hot, cool, gray); parula is the modern default. shading interp smooths color transitions. plot3 draws 3D parametric curves. view(az, el) sets the camera angle; axis equal prevents distortion.
[X, Y] = meshgrid(-2:0.1:2);
Z = X .* exp(-X.^2 - Y.^2);
figure;
subplot(2,2,1); surf(X, Y, Z); title('surf');
subplot(2,2,2); mesh(X, Y, Z); title('mesh');
subplot(2,2,3); contour(X, Y, Z, 20); title('contour');
subplot(2,2,4); surfc(X, Y, Z); title('surfc');
% color mapping
colormap(jet(256)); colorbar;
shading interp; % smooth colors
% 3D line plot (parametric)
t = 0:0.01:10;
plot3(sin(t), cos(t), t, 'LineWidth', 2);
xlabel('x'); ylabel('y'); zlabel('z');
% view angle
view(45, 30); % azimuth, elevation
axis equal;Statistical & Specialized Plots
histogram (R2014b+) replaces hist with more features like 'Normalization' for PDFs. boxplot compares distributions across groups. scatterhist shows a scatter plot with marginal histograms — great for visualizing correlations. bar supports grouped and stacked layouts. errorbar adds uncertainty visualization. These specialized plots are essential for scientific data presentation and exploratory analysis.
data = randn(1000, 1);
% histogram (modern)
histogram(data, 30, 'Normalization', 'pdf');
hold on; x = -4:0.1:4; plot(x, normpdf(x), 'r-', 'LineWidth', 2);
% box plot by group
g = randi([1 3], 100, 1);
boxplot(data, g);
% scatter with marginal histograms
x = randn(200,1); y = x + 0.5*randn(200,1);
scatterhist(x, y);
% bar chart
sales = [10 25 30; 20 15 40];
bar(sales); legend('Q1','Q2','Q3');
% pie chart
pie([30 20 50], {'A','B','C'});
% error bars
y = [1 2 3 4]; e = [0.1 0.2 0.15 0.3];
errorbar(y, e, 'o-');Animations & Interactive Graphics
Animations update plot data inside a loop and call drawnow to refresh. For smooth performance, create the plot once and update XData/YData rather than re-plotting. getframe captures the current figure; movie plays a sequence. VideoWriter exports to MP4 or AVI — useful for sharing results. Always set axis limits outside the loop to prevent auto-rescaling jitter.
% animated line plot
figure;
h = plot(NaN, NaN);
axis([0 10 -1 1]); xlabel('t'); ylabel('y');
for t = 0:0.1:10
set(h, 'XData', [get(h,'XData') t], ...
'YData', [get(h,'YData') sin(t)]);
drawnow;
end
% getframe to capture animation
frames = [];
for k = 1:50
plot(sin(linspace(0, k*pi/10, 200)));
axis([0 200 -1 1]);
frames = [frames, getframe];
end
movie(frames, 1, 30); % play once at 30 fps
% write to video file
v = VideoWriter('anim.mp4', 'MPEG-4');
v.FrameRate = 30; open(v);
for k = 1:50
plot(sin(linspace(0, k*pi/10, 200)));
writeVideo(v, getframe);
end
close(v);Graphics Objects & Handle Customization
MATLAB graphics are built on a tree of handle objects (figure → axes → lines, text, patches). set/get modify properties; findobj locates objects by property. The 'Interpreter' option enables TeX or full LaTeX rendering for mathematical notation. exportgraphics (R2020a+) produces publication-quality vector PDFs with tight bounding boxes — far better than the old print for embedding in papers.
% everything in MATLAB graphics is a handle object
h = plot(1:10, 'r-');
set(h, 'LineWidth', 3, 'Marker', 'o', 'MarkerSize', 8);
get(h, 'Color') % returns [1 0 0]
% find objects
ax = gca; % current axes
fig = gcf; % current figure
lines = findobj(ax, 'Type', 'line');
% property exploration
get(ax) % list all axes properties
set(ax) % list possible values
% text annotations with LaTeX
text(2, 0.5, '\alpha^2 + \beta^2', 'Interpreter', 'tex');
title('$\int_0^1 x^2 dx$', 'Interpreter', 'latex');
% legend with custom location and orientation
legend({'data1','data2'}, 'Location','northwest','Orientation','horizontal');
% export with tight bounding box
exportgraphics(gcf, 'fig.pdf', 'ContentType','vector');Simulink Basics
Creating & Running Simulink Models
Simulink models dynamic systems using block diagrams. While most users build models interactively in the Simulink Editor, you can also script them with new_system, add_block, set_param, and add_line — useful for parameter sweeps and automated model generation. sim runs the simulation. Each block has parameters accessible via set_param/get_param. The block path is 'library/Sublibrary/Block' for sources and 'model/Block' for instances.
% create a new Simulink model programmatically
mdl = 'my_model';
new_system(mdl);
open_system(mdl);
% add blocks
add_block('simulink/Sources/Sine Wave', [mdl '/Sine']);
add_block('simulink/Sinks/Scope', [mdl '/Scope']);
add_block('simulink/Math Operations/Gain', [mdl '/Gain']);
% set block parameters
set_param([mdl '/Gain'], 'Gain', '2');
% connect blocks (port handles)
sine_out = get_param([mdl '/Sine'], 'PortHandles');
gain_in = get_param([mdl '/Gain'], 'PortHandles');
gain_out = get_param([mdl '/Gain'], 'PortHandles');
scope_in = get_param([mdl '/Scope'], 'PortHandles');
add_line(mdl, sine_out.Outport(1), gain_in.Inport(1));
add_line(mdl, gain_out.Outport(1), scope_in.Inport(1));
% set simulation time and run
set_param(mdl, 'StopTime', '10');
sim(mdl);Configuring Solvers & Simulation
Solver choice affects accuracy and speed: ode45 (variable-step Runge-Kutta) is the default for non-stiff problems; ode15s for stiff systems; fixed-step solvers (ode4) are required for code generation and real-time targets. sim returns a SimulationOutput object containing tout, yout, and logs. SimulationInput objects let you override parameters and inputs per-run — essential for Monte Carlo studies. Rapid Accelerator mode precompiles the model for fast repeated simulations.
% configure solver
set_param(mdl, 'Solver', 'ode45');
set_param(mdl, 'StopTime', '20');
set_param(mdl, 'MaxStep', '0.1');
set_param(mdl, 'RelTol', '1e-4');
% variable-step vs fixed-step
% variable-step: ode45, ode15s, ode23tb (auto-adjusts)
% fixed-step: ode1, ode4, ode5 (real-time/hardware)
% simulate and capture output
out = sim(mdl, 'ReturnWorkspaceOutputs', 'on');
t = out.tout;
y = out.yout;
% simulate from workspace with input
set_param([mdl '/In1'], 'VariableName', 'u');
simIn = Simulink.SimulationInput(mdl);
simIn = setExternalInput(simIn, [t, u]);
out = sim(simIn);
% rapid accelerator for repeated runs
rtp = Simulink.BlockDiagram.buildRapidAcceleratorTarget(mdl);Subsystems & Masking
Subsystems group related blocks hierarchically, improving readability. Masking lets you expose parameters on a subsystem's dialog so users configure it without opening the internals — the foundation of reusable custom blocks. Library blocks (saved in .slx libraries) can be dragged into multiple models and updated centrally. Model references link separate .slx files for large-scale modular development. Variant subsystems select between implementations at compile time.
% create a subsystem
add_block('simulink/Ports & Subsystems/Subsystem', [mdl '/Controller']);
% mask a subsystem to expose parameters
Simulink.Mask.create([mdl '/Controller']);
mask = Simulink.Mask.get([mdl '/Controller']);
mask.addParameter('Type', 'edit', 'Name', 'Kp', 'Prompt', 'Proportional gain');
mask.addParameter('Type', 'edit', 'Name', 'Ki', 'Prompt', 'Integral gain');
% use the mask parameter inside the subsystem
set_param([mdl '/Controller/Gain'], 'Gain', 'Kp');
% library blocks (reusable)
% save model as .slx library: save_system(mdl, 'my_lib.slx');
% set_param(mdl, 'BlockDiagramType', 'Library');
% model reference (separate .slx file)
set_param(mdl, 'ModelReferenceSimulationMode', 'normal');
% variant subsystems (compile-time selection)
add_block('simulink/Ports & Subsystems/Variant Subsystem', [mdl '/Var']);Stateflow for State Machines
Stateflow (included with Simulink) adds finite state machines and flow charts for event-driven logic — common in embedded controllers, mode supervisors, and protocol implementations. States have entry/during/exit actions. Transitions fire on events or conditions. The MATLAB API (sfroot, Stateflow.State, etc.) lets you generate charts programmatically. Stateflow is essential for hybrid systems combining continuous dynamics (Simulink) with discrete mode logic.
% Stateflow charts model event-driven logic
% add a Stateflow chart to a model
sf = sfnew;
chart = sfroot.find('-isa', 'Stateflow.Chart');
% MATLAB API to add states and transitions
s1 = Stateflow.State(chart);
s1.Name = 'Off';
s1.Position = [50 50 80 60];
s1.LabelString = 'entry: led = 0;';
s2 = Stateflow.State(chart);
s2.Name = 'On';
s2.Position = [200 50 80 60];
s2.LabelString = 'entry: led = 1;';
% transition from Off to On on event 'press'
t = Stateflow.Transition(chart);
t.Source = s1; t.Destination = s2;
t.Event = 'press';
% simulate chart from MATLAB
% chart inputs: events and data defined in the chartCode Generation & Deployment
Simulink Coder generates C/C++ from models; Embedded Coder produces production-quality code with optimizations for specific processors. This lets engineers go from block diagram to deployed embedded controller without manual coding. Fixed-point conversion (via fxptool) prepares models for integer-only hardware like microcontrollers. PLC Coder generates IEC 61131-3 code for industrial controllers. Real-time target support (Speedgoat, dSPACE) enables hardware-in-the-loop testing.
% generate C/C++ code from a Simulink model
set_param(mdl, 'SystemTargetFile', 'grt.tlc'); % generic real-time
slbuild(mdl); % build
% embed code generation
set_param(mdl, 'SystemTargetFile', 'ert.tlc'); % embedded coder
slbuild(mdl);
% configure for specific hardware
set_param(mdl, 'HardwareImplementation', ...
'Manufacturer', 'ARM Compatible', 'Type', 'Cortex-M');
% fixed-point conversion (for integer-only hardware)
fxp_cfg = fxptool(mdl);
% generate PLC code (industrial controllers)
plcgeneratecode(mdl);
% deploy to Speedgoat, dSPACE, or other real-time targets
% via vendor-specific blocks and target files
% HIL (hardware-in-the-loop) testing
slrealtime('Speedgoat');GUI & App Designer
App Designer Basics
App Designer (launched with appdesigner) is the modern visual tool for building MATLAB GUIs, saving .mlapp files that bundle layout and code. For programmatic UIs, uifigure (R2014b+) creates modern figure windows with uibutton, uilabel, uieditfield, uislider, uidropdown, and uiaxes. Callbacks are function handles assigned to properties like ButtonPushedFcn. The older GUIDE is deprecated; new code should use uifigure-based components or App Designer.
% App Designer (appdesigner command) creates .mlapp files
% Modern replacement for GUIDE (deprecated in R2020a)
% programmatic UI (alternative to App Designer)
f = uifigure('Name', 'My App', 'Position', [100 100 600 400]);
% add components
btn = uibutton(f, 'Text', 'Click Me', ...
'Position', [50 300 100 30]);
lbl = uilabel(f, 'Text', 'Hello', ...
'Position', [50 250 200 30]);
fld = uieditfield(f, 'text', 'Position', [50 200 200 30]);
% slider and drop-down
sld = uislider(f, 'Position', [50 150 200 3]);
dd = uidropdown(f, 'Items', {'A','B','C'}, ...
'Position', [50 100 100 30]);
% axes for plotting
ax = uiaxes(f, 'Position', [300 100 250 250]);
plot(ax, 1:10, rand(1,10));
% callback
btn.ButtonPushedFcn = @(src,event) clickHandler(lbl);
function clickHandler(lbl)
lbl.Text = ['Clicked at ' datestr(now)];
endLayout Managers & Containers
uigridlayout (R2018b+) is the modern responsive layout manager — rows and columns can be fixed, proportional ('1x'), or fit-content. uitabgroup/uitab create tabbed interfaces. uipanel groups related components visually. uiscrollbox adds scrolling for content that exceeds the window. Dialog functions (uigetfile, inputdlg, msgbox, questdlg) handle standard file selection, input, and notifications. These layout tools are essential for building professional, resizable MATLAB applications.
f = uifigure;
% grid layout (responsive)
g = uigridlayout(f, [3 2]);
g.RowHeight = {'1x', '2x', '1x'};
g.ColumnWidth = {'1x', '2x'};
btn1 = uibutton(g); btn1.Layout.Row = 1; btn1.Layout.Column = 1;
btn2 = uibutton(g); btn2.Layout.Row = 1; btn2.Layout.Column = 2;
% tab group
tg = uitabgroup(f);
t1 = uitab(tg, 'Title', 'Plot');
t2 = uitab(tg, 'Title', 'Data');
ax = uiaxes(t1); plot(ax, rand(5));
% panel for grouping
p = uipanel(f, 'Title', 'Settings', 'Position', [20 20 200 150]);
% scrollable container for long content
sf = uiscrollbox(f);
% add many components inside sf
% dialog windows
uigetfile('*.mat', 'Select MAT file');
inputdlg({'Name','Age'}, 'Enter data');
msgbox('Operation complete');Callbacks & Event Handling
Modern MATLAB uses function-handle callbacks with two arguments (src, event) where event carries structured data like event.Value or event.Key. ValueChangingFcn fires continuously during interaction; ValueChangedFcn fires once at the end. addlistener creates persistent listeners on any property. timer objects run callbacks on a schedule — useful for live data acquisition UIs. Always clean up listeners and timers (delete) to avoid memory leaks.
% value-changing callback (slider)
sld = uislider(f);
sld.ValueChangingFcn = @(src,event) onSlider(src, event);
function onSlider(src, event)
disp(['Dragging: ' num2str(event.Value)]);
end
% value-changed callback (final value)
sld.ValueChangedFcn = @(src,event) disp(['Final: ' num2str(event.Value)]);
% button callback with event data
btn.ButtonPushedFcn = @onButton;
function onButton(src, event)
fprintf('Button %s pushed
', src.Text);
end
% keyboard callback on figure
f.WindowKeyPressFcn = @(src,event) onKey(event);
function onKey(event)
fprintf('Key: %s
', event.Key);
end
% listener pattern (any property change)
lh = addlistener(btn, 'Text', 'PostSet', @(src,event) disp('Text changed'));
delete(lh); % remove listener
% timer for periodic updates
t = timer('ExecutionMode','fixedRate','Period',1, ...
'TimerFcn',@(~,~) disp('tick'));
start(t);Packaging Apps for Distribution
matlab.apputil.package bundles an App Designer app into a .mlappinstall file that users install via the Apps tab. The Application Compiler (deploytool) produces standalone executables (.exe) that run with the free MATLAB Runtime — no MATLAB license needed on the target. Web Apps (R2020a+) deploy to a MATLAB Web App Server and run in any browser. This distribution pipeline lets you share MATLAB applications with non-MATLAB users.
% package an App Designer app as a .mlappinstall file
% using the Application Compiler (deploytool app)
% programmatically create a packaged app
appFile = matlab.apputil.package(...
'Name', 'MyPlotTool', ...
'Summary', 'A simple plotting utility', ...
'Description', 'Plots user-supplied data.', ...
'MainFile', 'MyPlotTool.mlapp', ...
'FolderPath', 'my_app_package');
% install the app
matlab.apputil.install('MyPlotTool.mlappinstall');
% list installed apps
apps = matlab.apputil.getInstalledApps;
% uninstall
matlab.apputil.uninstall('MyPlotTool');
% standalone desktop app (MATLAB Runtime required)
% deploytool -> Application Compiler -> produce .exe
% web app (runs in browser, MATLAB Web App Server)
% deploytool -> Web AppCommon UI Patterns
drawnow limitrate updates graphics without blocking — critical for live data displays. uitable displays tabular data with sortable columns. uiprogressdlg shows a modal progress bar for long operations. uicontextmenu adds right-click menus to any component. These patterns cover the most common UI needs: live updates, data tables, progress feedback, and context-sensitive actions. For high-throughput live plots, consider animatedline which is optimized for streaming data.
% live plot update from worker
f = uifigure; ax = uiaxes(f); h = plot(ax, NaN, NaN);
for k = 1:100
set(h, 'XData', 1:k, 'YData', rand(1,k));
drawnow limitrate; % throttle for performance
end
% table display
tdata = table({'A';'B';'C'}, [1;2;3], 'VariableNames', {'Name','Val'});
uit = uitable(f, 'Data', tdata.Variables, ...
'ColumnName', tdata.Properties.VariableNames, ...
'Position', [20 20 200 150]);
% progress dialog
d = uiprogressdlg(f, 'Title', 'Working', 'Message', 'Processing...');
for k = 1:100
pause(0.01);
d.Value = k;
d.Message = sprintf('%d%% complete', k);
end
close(d);
% context menu
cm = uicontextmenu(f);
m1 = uimenu(cm, 'Text', 'Reset', 'MenuSelectedFcn', @reset);
ax.UIContextMenu = cm;Image Processing Toolbox
Reading, Writing & Displaying Images
imread supports PNG, JPEG, TIFF, BMP, and many scientific formats. Image data types matter: uint8 (0-255) is common for files, double (0-1) for processing. Always use im2double/im2uint8 (which rescale) rather than double()/uint8() (which truncate). im2gray (R2020b+) replaces rgb2gray. imwrite supports format-specific options like JPEG quality. imfinfo reads metadata without loading pixel data.
% read and display an image
img = imread('peppers.png');
imshow(img);
title('RGB image');
% image types
% uint8 (0-255), uint16, double (0-1), logical (binary)
whos img
class(img) % uint8
size(img) % rows x cols x channels
% convert between types
d = im2double(img); % scale to [0,1]
u = im2uint8(d); % scale to [0,255]
g = im2gray(img); % RGB to grayscale (R2020b+, replaces rgb2gray)
% write to file
imwrite(g, 'gray.png');
imwrite(g, 'gray.jpg', 'Quality', 90);
% info without loading
info = imfinfo('peppers.png');
disp(info.Width);
% montage of multiple images
fileList = dir('*.png');
montage({fileList.name});Filtering & Enhancement
imgaussfilt is the modern Gaussian blur (replaces fspecial('gaussian') + imfilter). medfilt2 removes salt-and-pepper noise without blurring edges. fspecial creates predefined kernels (sobel, prewitt, laplacian, gaussian). imsharpen enhances edges via unsharp masking. histeq performs global histogram equalization; adapthisteq (CLAHE) does it locally for better contrast in non-uniform images. imadjust maps intensity ranges for brightness/contrast correction.
img = im2double(imread('cameraman.tif'));
% Gaussian blur
h = imgaussfilt(img, 2); % sigma = 2
h2 = imgaussfilt(img, [3 3], 1.5);
% median filter (salt-and-pepper noise)
noisy = imnoise(img, 'salt & pepper', 0.05);
m = medfilt2(noisy, [3 3]);
% custom 2D filter
kernel = fspecial('sobel');
edge_img = imfilter(img, kernel);
% unsharp masking (sharpen)
sharp = imsharpen(img, 'Amount', 0.8, 'Radius', 1.5);
% histogram equalization
eq = histeq(img); % global
eq2 = adapthisteq(img); % CLAHE (local)
% image arithmetic
bright = imadd(img, 0.1);
contrast = imadjust(img, [0.3 0.7], []);Morphological Operations & Segmentation
Morphological operations (erode, dilate, open, close) process binary images using structuring elements (strel). Opening removes small objects; closing fills small holes. bwconncomp finds connected regions; regionprops extracts measurements (area, centroid, bounding box) for each. watershed segments touching objects. edge detects boundaries (Canny is most robust). graythresh computes Otsu's global threshold; multithresh does multi-level. These tools form the core of computer vision preprocessing.
bw = imread('text.png');
bw = imbinarize(bw);
% morphological operations
se = strel('disk', 3);
er = imerode(bw, se); % shrink objects
di = imdilate(bw, se); % grow objects
op = imopen(bw, se); % erode then dilate (removes small noise)
cl = imclose(bw, se); % dilate then erode (fills small holes)
% connected components
cc = bwconncomp(bw);
stats = regionprops(cc, 'Area', 'Centroid', 'BoundingBox');
[areas, idx] = sort([stats.Area], 'descend');
% watershed segmentation
grad = imgradient(bw);
D = -bwdist(~bw);
L = watershed(D);
% edge detection
edges = edge(bw, 'canny');
edges2 = edge(bw, 'sobel');
% thresholding
T = graythresh(img); % Otsu's method
bw2 = imbinarize(img, T);Feature Detection & Transforms
Feature detection finds distinctive points for matching and tracking. Harris corners are fast but not scale-invariant; SURF and ORB are scale/rotation-invariant for robust matching across views. extractFeatures computes descriptors at detected points. The Hough transform detects lines (and circles) via voting in parameter space — useful for document skew correction and lane detection. imregtform performs intensity-based image registration, computing the geometric transform that aligns two images.
img = imread('cameraman.tif');
% corner detection (Harris)
corners = detectHarrisFeatures(img);
[~, strength] = corners;
imshow(img); hold on; plot(corners);
% SURF features (scale-invariant)
points = detectSURFFeatures(img);
[f1, vpts1] = extractFeatures(img, points);
% ORB features (faster, binary)
points = detectORBFeatures(img);
% Hough transform for line detection
bw = edge(img, 'canny');
[H, T, R] = hough(bw);
P = houghpeaks(H, 5);
lines = houghlines(bw, T, R, P);
% image registration
% (find transform between two images)
moving = imread('rotated.png');
fixed = img;
[optimizer, metric] = imregconfig('monomodal');
tform = imregtform(moving, fixed, 'affine', optimizer, metric);
registered = imwarp(moving, tform);Batch Processing & Big Images
For batch processing, parfor parallelizes across images. blockproc processes large images in tiles — essential when the full image doesn't fit in memory; the 'Destination' option streams output to disk. imageDatastore manages collections too large to enumerate manually and integrates with tall arrays and the MapReduce framework for out-of-core computation. bigTIFF support handles gigapixel microscopy and remote-sensing imagery.
% process many images in a folder
fileList = dir('*.tif');
parfor k = 1:numel(fileList)
img = imread(fileList(k).name);
result = processImage(img);
imwrite(result, ['out_' fileList(k).name]);
end
% block processing for large images
fun = @(block) std2(block);
B = blockproc('large.tif', [256 256], fun);
B = blockproc('large.tif', [256 256], fun, 'Destination', 'out.tif');
% work with very tall/wide images without loading all
% (bigTIFF, multiresolution)
t = Tiff('big.tif', 'r');
imgInfo = t.getImageInfo;
% image datastore for huge collections
imds = imageDatastore('images/', 'IncludeSubfolders', true);
imds.ReadSize = 10; % read 10 at a time
while hasdata(imds)
[imgs, info] = read(imds);
% process batch
end
% tall arrays (out-of-core) for pixel statistics
t = tall(imds);Optimization Toolbox
Unconstrained & Constrained Optimization
fminunc solves smooth unconstrained problems; fmincon handles bounds, linear, and nonlinear constraints. linprog and quadprog are specialized for linear and quadratic objectives with linear constraints — much faster than general solvers. optimoptions configures solver behavior (algorithm, tolerances, display). The 'interior-point' algorithm is robust for large problems; 'sqp' is good for nonlinear constraints. Always provide analytic gradients when available for speed and accuracy.
% unconstrained minimization
f = @(x) (x(1)-2)^2 + (x(2)-3)^2;
x0 = [0 0];
[x, fval] = fminunc(f, x0);
% constrained (with fmincon)
A = []; b = []; Aeq = []; beq = [];
lb = [0 0]; ub = [];
nonlcon = @(x) deal([], x(1) + x(2) - 4); % x1+x2 <= 4
[x, fval] = fmincon(f, x0, A, b, Aeq, beq, lb, ub, nonlcon);
% linear programming
f_lp = [-1 -1]; % minimize -x1 - x2
A_lp = [1 1; -1 1]; b_lp = [4; 2];
[x, fval] = linprog(f_lp, A_lp, b_lp, [], [], [0;0]);
% quadratic programming
H = [1 -1; -1 2]; c = [-2; -6];
[x, fval] = quadprog(H, c, [], [], [], [], [0;0]);
% set optimization options
opts = optimoptions('fmincon', 'Algorithm','interior-point', ...
'Display','iter', 'MaxIterations', 200);
[x, fval] = fmincon(f, x0, A, b, Aeq, beq, lb, ub, nonlcon, opts);Global & Multiobjective Optimization
Local solvers (fminunc, fmincon) can get stuck in local minima. GlobalSearch and MultiStart run a local solver from many starting points. ga (genetic algorithm), particleswarm, and simulannealbnd are derivative-free global methods — slower but work on discontinuous or noisy objectives. gamultiobj finds the Pareto front for multiobjective problems, returning a set of non-dominated solutions. Choose based on problem smoothness, dimensionality, and whether you need global optimality guarantees.
% GlobalSearch / MultiStart for non-convex problems
f = @(x) x(1)^2 + x(2)^2 + 10*sin(x(1)) + 10*sin(x(2));
opts = optimoptions('fmincon', 'Algorithm','sqp');
problem = createOptimProblem('fmincon','objective',f, ...
'x0',[0 0],'lb',[-5 -5],'ub',[5 5],'options',opts);
gs = GlobalSearch;
[x, fval] = run(gs, problem);
% genetic algorithm
[x, fval] = ga(f, 2, [], [], [], [], [-5 -5], [5 5]);
% particle swarm
[x, fval] = particleswarm(f, 2, [-5 -5], [5 5]);
% simulated annealing
[x, fval] = simulannealbnd(f, [0 0], [-5 -5], [5 5]);
% multiobjective (Pareto front)
f_multi = @(x) [x(1)^2 + x(2)^2, (x(1)-1)^2 + (x(2)-1)^2];
[x, fval] = gamultiobj(f_multi, 2, [], [], [], [], [-2 -2], [2 2]);
plot(fval(:,1), fval(:,2), 'o');Curve Fitting & Parameter Estimation
fittype defines custom parametric models; fit performs the regression with automatic starting-point heuristics. lsqcurvefit is the lower-level nonlinear least-squares solver — useful when you need fine control or custom Jacobians. confint and predint return confidence and prediction intervals for uncertainty quantification. The Curve Fitter app (cftool) provides an interactive interface for exploring fits. Always check residuals for systematic structure that suggests model misspecification.
% fit a custom model to data
x = linspace(0, 5, 50);
y = 2*exp(-0.5*x) + 0.1*randn(size(x));
% define model and fit
model = fittype('a*exp(-b*x)', 'independent', 'x', ...
'coefficients', {'a','b'});
f = fit(x', y', model, 'StartPoint', [1 1]);
plot(f, x, y);
% predefined models
f2 = fit(x', y', 'exp2'); % two-term exponential
f3 = fit(x', y', 'poly2'); % quadratic polynomial
% nonlinear least squares with lsqcurvefit
fun = @(p, xdata) p(1)*exp(-p(2)*xdata);
[p, resnorm] = lsqcurvefit(fun, [1 1], x, y);
% confidence intervals
ci = confint(f, 0.95);
predint(f, x', 0.95, 'observation', 'functional');
% smoothing spline
sf = fit(x', y', 'smoothingspline');Integer & Combinatorial Optimization
intlinprog solves mixed-integer linear programs — the workhorse for scheduling, routing, and assignment problems. matchpairs solves the assignment problem optimally in O(n^3). The traveling salesman problem requires iterative subtour elimination since the constraint set is exponential. surrogateopt is for expensive black-box functions (e.g., simulations taking minutes per evaluation) — it builds a surrogate model and intelligently samples. For combinatorial problems too large for exact methods, consider ga or custom heuristics.
% mixed-integer linear programming (TSP-like problems)
f = [-3 -2]; % maximize 3x + 2y
A = [1 1; 2 1]; b = [4; 6];
intcon = 1:2; % both variables integer
[x, fval] = intlinprog(f, intcon, A, b, [], [], [0;0]);
% assignment problem (Hungarian algorithm)
cost = [4 1 3; 2 3 4; 3 4 1];
[assignment, cost_total] = matchpairs(cost, false);
% traveling salesman via intlinprog
n = 8; % cities
distances = rand(n, n); distances = distances + distances';
% (build subtour elimination constraints iteratively)
% knapsack
weights = [2 3 4 5]; values = [3 4 5 6];
W = 5;
f = -values;
A = weights; b = W;
intcon = 1:4;
[x, fval] = intlinprog(f, intcon, A, b, [], [], zeros(4,1), ones(4,1));
% surrogate optimization (expensive black-box)
obj = @(x) expensive_eval(x);
[x, fval] = surrogateopt(obj, lb, ub);Optimization Workflow & Best Practices
Choosing the right solver is the most important decision — using fmincon on a linear program wastes orders of magnitude in performance. Providing analytic gradients (via the problem-based framework or optimoptions) dramatically improves speed and reliability. Scaling variables to order 1 improves conditioning. Check exitflag and firstorderopt to verify convergence. The problem-based framework (optimproblem, optimvar) is more readable and lets MATLAB auto-select the solver — preferred for new code.
% 1. choose solver based on problem type
% smooth? -> fminunc/fmincon
% linear? -> linprog/intlinprog
% integer? -> intlinprog
% nonsmooth/global? -> ga/particleswarm/GlobalSearch
% 2. provide gradients and Jacobians when possible
f = @(x) x(1)^2 + x(2)^2;
gradf = @(x) [2*x(1); 2*x(2)];
prob = optimproblem('Objective', f);
prob.Objective.Gradient = gradf;
% 3. scale variables to ~[1, 1]
x_scaled = (x - x0) / scale;
% 4. check optimality and feasibility
output.exitflag % 1 = converged
output.firstorderopt % should be near 0
% 5. warm start sequential problems
opts = optimoptions('quadprog','ObjectiveLimit',1e-8);
x_new = quadprog(H, c, A, b, [], [], lb, ub, x_old, opts);
% 6. use problem-based framework (cleaner)
x = optimvar('x', 2, 'LowerBound', 0);
prob = optimproblem('Objective', x(1)^2 + x(2)^2);
prob.Constraints.c1 = x(1) + x(2) >= 1;
sol = solve(prob);Parallel Computing
parfor Loops & Parallel Pools
parfor is the easiest path to parallelism — it distributes loop iterations across workers. Iterations must be independent (no iteration k depending on k-1). Variables are classified: loop variables (k), sliced (indexed by k alone on first/last dim), broadcast (read-only), and reduction (combined with associative op like + or *). Communication overhead means parfor helps only when each iteration does substantial work. Start the pool once; reuse it across parfor loops to avoid startup cost.
% start a parallel pool (workers = CPU cores)
pool = gcp('nocreate');
if isempty(pool)
parpool; % start default pool
end
% parfor: parallel for loop
n = 1e6;
results = zeros(1, n);
parfor k = 1:n
results(k) = expensive_computation(k);
end
% restrictions:
% - iterations must be independent (no data dependencies)
% - variables classified as loop, sliced, broadcast, reduction
% - cannot break/continue
% reduction variables (combine results)
total = 0;
parfor k = 1:n
total = total + compute(k);
end
% sliced variables (each iteration writes distinct element)
out = zeros(n, 1);
parfor k = 1:n
out(k) = k^2;
end
% control pool size
delete(gcp('nocreate')); % shut down
parpool('local', 4); % 4 workersspmd & Distributed Arrays
spmd runs the same code on all workers with labidx identifying each — useful for data-parallel algorithms where each worker processes a chunk. Composite variables (A{1}, A{2}) hold per-worker results. distributed arrays spread a single logical array across workers; localpart gives the local chunk. labSendrecv and gcat/gplus enable inter-worker communication. Use spmd for fine-grained parallelism that parfor can't express (e.g., iterative algorithms needing communication).
% spmd: single program, multiple data
spmd
labidx % worker index (1 to n)
numlabs % total workers
A = rand(1000) * labidx;
% each lab has its own A
end
% access Composite (per-worker data)
A{1} % A from worker 1
A{2} % A from worker 2
% distributed arrays (spread across workers)
D = distributed.rand(10000);
size(D) % 10000x10000 total
L = localpart(D); % this worker's chunk
% communicate between labs
spmd
data = rand(100, 1);
% send to next lab, receive from previous
next_lab = mod(labidx, numlabs) + 1;
prev_lab = mod(labidx - 2, numlabs) + 1;
rcvd = labSendrecv(data, next_lab, prev_lab);
end
% gather distributed to local
D = distributed.rand(1000);
full_matrix = gather(D);GPU Computing
gpuArray transfers data to the GPU; subsequent operations execute there and stay on the GPU until gather() brings results back. Most element-wise and linear algebra functions are GPU-enabled. arrayfun runs custom element-wise functions on the GPU (but only with scalar operations). For multi-GPU systems, assign each parfor worker a different GPU via gpuDevice(k). GPU computing excels at large dense linear algebra and element-wise operations; the overhead of data transfer makes it inefficient for small arrays.
% move data to GPU
A = gpuArray(rand(10000));
B = gpuArray(eye(10000));
% operations execute on GPU
C = A * B; % GPU matrix multiply
D = A + B;
E = sum(A, 1);
% gather results back to CPU
C_cpu = gather(C);
% many built-in functions are GPU-enabled
x = gpuArray.linspace(-10, 10, 1e6);
y = sin(x) .* exp(-x.^2);
% arrayfun on GPU (custom element-wise functions)
f = @(a, b) a.^2 + b.^2;
result = arrayfun(f, A, B);
% check GPU
gpuDevice % info about current GPU
gpuDeviceCount % number of available GPUs
% page multiple GPUs
parfor k = 1:4
gpuDevice(k);
A = gpuArray(rand(5000));
% ... compute on GPU k
endbatch & job scheduling
batch runs a function asynchronously in the background — useful for long computations you don't want to block the session. batch with 'Pool' option runs a function that itself uses parfor. The lower-level job/task API gives fine control over scheduling. parcluster selects a cluster profile; MATLAB integrates with SLURM, PBS, and LSF via the Parallel Computing Toolbox's generic scheduler interface. For HPC, save data to files and submit scripts rather than relying on shared memory.
% run a function in background
job = batch(@my_function, 0, {arg1, arg2});
% check status
job.State % 'queued', 'running', 'finished'
wait(job); % block until done
load(job); % retrieve results
% batch with parfor inside
job = batch(@my_parfor_func, 1, {input_data}, 'Pool', 4);
% job and task objects (lower-level)
job = createJob(pool);
task = createTask(job, @my_func, 1, {arg1});
submit(job);
wait(job);
result = fetchOutputs(task);
% cluster types
% 'local' - on this machine
% 'MJS' - MATLAB Job Scheduler (server cluster)
% 'SLURM'/'PBS' - HPC scheduler integration
c = parcluster('local');
c.NumWorkers = 8;
c.saveProfile;Performance & Profiling Parallel Code
Profile parallel code with profile on -parallel to see per-worker timelines. Speedup is limited by Amdahl's law: if 10% of code is serial, max speedup is 10x regardless of worker count. Common pitfalls: too-small iterations (overhead exceeds work), large broadcast variables (transfer cost), and excessive reduction operations. parallel.pool.DataQueue enables live progress updates from workers without blocking — useful for monitoring long parallel jobs. Always measure before and after to verify parallelism actually helps.
% profile parallel code
profile on -parallel
parfor k = 1:100
compute(k);
end
profile off
profview % visualize
% measure speedup
tic;
serial_result = serial_compute();
t_serial = toc;
tic;
parfor_result = parallel_compute();
t_parallel = toc;
speedup = t_serial / t_parallel;
fprintf('Speedup: %.2fx using %d workers
', speedup, pool.NumWorkers);
% avoid common pitfalls:
% 1. too little work per iteration (overhead dominates)
% 2. large broadcast variables (transfer cost)
% 3. false sharing via reduction variables
% data queue for live updates from workers
Q = parallel.pool.DataQueue;
afterEach(Q, @update_plot);
parfor k = 1:n
% ... compute ...
send(Q, partial_result);
endObject-Oriented Programming
Classes & Properties
MATLAB classes live in files named ClassName.m. The classdef block contains properties and methods. Property attributes control access: SetAccess=protected means only class methods can write; Constant defines class-level constants. The constructor is a method with the class name. MATLAB uses value semantics by default (objects are copied on assignment) — use handle classes for reference semantics. Overloaded methods like disp customize default behavior.
% class definition in a file named Point.m
classdef Point
properties
x = 0 % public, with default
y = 0
end
properties (SetAccess = protected)
id % settable only by class methods
end
properties (Constant)
PI = 3.14159
end
methods
function obj = Point(x, y)
if nargin > 0
obj.x = x;
obj.y = y;
end
obj.id = randi(1e6);
end
function r = distance(obj)
r = sqrt(obj.x^2 + obj.y^2);
end
function disp(obj)
fprintf('Point(%.2f, %.2f) [id=%d]
', ...
obj.x, obj.y, obj.id);
end
end
end
% usage
p = Point(3, 4);
p.distance() % 5
disp(p)Handle vs Value Classes
The choice between value and handle classes is fundamental. Value classes (default) copy on assignment and on method calls — safer for immutable data. Handle classes (subclass handle) are references: assignments and copies point to the same object, like Java/Python objects. Handle classes are needed for things like GUI components, file handles, and mutable state shared across callers. Use value classes for mathematical objects (vectors, matrices) where immutability is desirable.
% value class (default): copies on assignment
classdef Vec
properties
data
end
methods
function obj = Vec(d)
obj.data = d;
end
end
end
v1 = Vec([1 2 3]);
v2 = v1; % COPY
v2.data = [4 5 6];
disp(v1.data) % still [1 2 3]
% handle class: references shared
classdef HVec < handle
properties
data
end
methods
function obj = HVec(d)
obj.data = d;
end
end
end
h1 = HVec([1 2 3]);
h2 = h1; % REFERENCE (same object)
h2.data = [4 5 6];
disp(h1.data) % [4 5 6] - changed!
% handle classes support delete method
% isequal(h1, h2) -> true (same object)Inheritance & Polymorphism
Inheritance uses < in the classdef line; obj@SuperClass(args) calls the superclass constructor. MATLAB supports multiple inheritance but it's rare and can lead to diamond problems. Abstract methods (declared in methods (Abstract)) must be implemented by subclasses; the base class can't be instantiated. Polymorphism works naturally: call the method on any object and MATLAB dispatches to the correct implementation. Use isa(obj, 'ClassName') and isprop/ismethod for runtime type checks.
% single inheritance
classdef Dog < Animal
methods
function obj = Dog(name)
obj@Animal(name); % call superclass constructor
end
function sound(obj)
disp([obj.name ' says Woof']);
end
end
end
% multiple inheritance
classdef FlyingFish < Fish & Bird
methods
function obj = FlyingFish(name)
obj@Fish(name);
obj@Bird(name);
end
end
end
% abstract methods and classes
classdef Shape
methods (Abstract)
area(obj)
perimeter(obj)
end
end
classdef Circle < Shape
properties
radius
end
methods
function obj = Circle(r)
obj.radius = r;
end
function a = area(obj)
a = pi * obj.radius^2;
end
function p = perimeter(obj)
p = 2 * pi * obj.radius;
end
end
end
% polymorphism
shapes = {Circle(2), Square(3)};
for k = 1:numel(shapes)
fprintf('Area: %.2f
', shapes{k}.area());
endEvents & Listeners
The events model implements the observer pattern: classes declare events, listeners register callbacks, and notify fires events. This decouples producers from consumers — essential for GUIs, simulations, and reactive systems. Property set methods (set.PropertyName) intercept assignments and can trigger events. Listeners can be temporary (addlistener, tied to object lifetime) or persistent (listener object held in a variable). Always delete listeners when done to prevent memory leaks.
classdef TemperatureSensor < handle
properties
Temperature = 20
end
events
TemperatureChanged
Overheated
end
methods
function set.Temperature(obj, t)
obj.Temperature = t;
notify(obj, 'TemperatureChanged');
if t > 100
notify(obj, 'Overheated');
end
end
function obj = TemperatureSensor()
% nothing
end
end
end
% create sensor and listen
s = TemperatureSensor();
addlistener(s, 'TemperatureChanged', @onTempChanged);
addlistener(s, 'Overheated', @onOverheat);
function onTempChanged(src, event)
fprintf('Temp now: %.1f
', src.Temperature);
end
function onOverheat(src, event)
warning('Overheated at %.1f!', src.Temperature);
end
% trigger
s.Temperature = 25; % prints "Temp now: 25.0"
s.Temperature = 105; % prints temp + warningOperator Overloading & Indexing
Operator overloading lets user classes work with +, *, [], etc. Each operator maps to a function (plus, mtimes, minus, mrdivide, horzcat, vertcat). subsref and subsasgn customize indexing (obj(i), obj.field, obj{i}). Modern MATLAB prefers dot-notation for property access, but subsref/subsasgn are still needed for fake-indexing patterns (e.g., a tensor library where T(1,2,3) extracts an element). Overload disp for readable output and end/numel for custom indexing semantics.
classdef Complex
properties
re
im
end
methods
function obj = Complex(re, im)
obj.re = re; obj.im = im;
end
function r = plus(a, b) % a + b
r = Complex(a.re + b.re, a.im + b.im);
end
function r = mtimes(a, b) % a * b
r = Complex(a.re*b.re - a.im*b.im, ...
a.re*b.im + a.im*b.re);
end
function r = abs(obj) % |obj|
r = sqrt(obj.re^2 + obj.im^2);
end
function disp(obj)
fprintf('%.2f %+.2fi
', obj.re, obj.im);
end
end
methods
function r = subsref(obj, S) % obj(...)
if strcmp(S(1).type, '()')
r = obj.re + 1i*obj.im;
end
end
function obj = subsasgn(obj, S, val) % obj(...) = val
% custom assignment
end
end
end
c1 = Complex(1, 2); c2 = Complex(3, 4);
c3 = c1 + c2; % uses plus
c4 = c1 * c2; % uses mtimes
abs(c1) % uses absDebugging & Performance Tuning
Debugger & Breakpoints
dbstop sets breakpoints — the most powerful debugging tool. Conditional breakpoints (dbstop ... if condition) pause only when a predicate holds, essential for finding bugs in large loops. dbstop if error turns any uncaught exception into a debug pause, letting you inspect the workspace at the failure point. The ME (MException) object in catch blocks carries .message, .identifier, and .stack for rich error handling. Use dbstack to navigate the call stack and dbup/dbdown to inspect caller workspaces.
% set breakpoints in the Editor or programmatically
dbstop in my_function at 42 % line 42 of my_function.m
dbstop in my_function at 42 if x > 10 % conditional
dbstop if error % pause on any error
dbstop if naninf % pause on NaN/Inf
dbstop if warning % pause on warnings
dbclear all % clear all breakpoints
dbclear in my_function % clear in one file
% at a breakpoint, the command window enters debug mode K>>
whos % inspect workspace
x % view variables
dbstep % step to next line
dbstep in % step into function
dbstep out % step out of function
dbcont % continue execution
dbstack % show call stack
dbup / dbdown % move up/down stack frames
dbquit % exit debug mode
% error recovery
try
risky_operation();
catch ME
fprintf('Error: %s
', ME.message);
fprintf('Stack:
');
for k = 1:numel(ME.stack)
fprintf(' %s (line %d)
', ME.stack(k).name, ME.stack(k).line);
end
endProfiling & Hotspot Detection
The profiler (profile on/off + profile viewer) shows where time is spent, line by line — the single most important tool for optimization. Always profile before optimizing; intuition about bottlenecks is often wrong. timeit is more accurate than tic/toc for microbenchmarks because it runs the function multiple times and accounts for overhead. The -memory option tracks allocations, useful for finding memory leaks or excessive copying. Focus optimization effort on the top few hot lines for maximum impact.
% profile a script or function
profile on
my_expensive_script();
profile off
% view results
profile viewer % GUI
p = profile('info'); % structure
profsave(p, 'profile_results'); % HTML report
% time individual operations
tic; A = rand(5000); A = A * A; toc; % ~0.5s
% timeit for accurate single-function timing
f = @() sort(rand(1e6,1));
t = timeit(f);
% memory profiling
profile on -memory
% ... run code ...
profile viewer % shows memory allocation
% identify bottlenecks
% 1. profile viewer shows time per function/line
% 2. focus on the top few hottest lines
% 3. vectorize, preallocate, or use MEX for thoseVectorization & Preallocation
The three biggest performance wins in MATLAB: (1) preallocate arrays before filling them in loops (zeros, NaN, cell), (2) vectorize operations to leverage BLAS/LAPACK, and (3) use JIT-friendly patterns (simple loops are now fast, but growing arrays is still O(n^2)). Logical indexing replaces if/else loops with a single vectorized assignment. Avoid arrayfun unless you need its GPU support — plain preallocated loops are often faster. Measure with tic/toc or timeit to verify improvements.
% BAD: growing array in loop
tic;
s = [];
for k = 1:100000
s = [s, k^2]; % reallocates every iteration!
end
toc; % ~10 seconds
% GOOD: preallocate
tic;
s = zeros(1, 100000);
for k = 1:100000
s(k) = k^2;
end
toc; % ~0.01 seconds
% BEST: vectorize
tic;
s = (1:100000).^2;
toc; % ~0.001 seconds
% vectorize conditional logic
x = rand(10000, 1);
% BAD:
% for k = 1:numel(x)
% if x(k) > 0.5, y(k) = 1; else, y(k) = 0; end
% end
% GOOD:
y = double(x > 0.5);
% vectorize with logical indexing
y = zeros(size(x));
y(x > 0.5) = 1;
y(x > 0.8) = 2;
% use arrayfun/gpuArray only when truly needed
% (loops with preallocation are often faster than arrayfun)MEX Files & C Integration
MEX files let you call C/C++/Fortran from MATLAB — essential when a critical loop can't be vectorized or when wrapping existing libraries. mex compiles a C file into a .mexw64 (Windows) or .mexa64 (Linux) binary. The modern C++ MATLAB Data API (R2018a+) is type-safe and cleaner than the old mxGetPr/mxCreate API. For calling MATLAB from external applications, use the MATLAB Engine API or MATLAB Compiler SDK. loadlibrary wraps generic shared libraries without compilation. Profile first — only MEX-ify the actual bottleneck.
% call C/C++/Fortran code from MATLAB via MEX
% write a C file (my_func.c):
/*
#include "mex.h"
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) {
double *x = mxGetPr(prhs[0]);
size_t n = mxGetNumberOfElements(prhs[0]);
plhs[0] = mxCreateDoubleMatrix(n, 1, mxREAL);
double *y = mxGetPr(plhs[0]);
for (size_t k = 0; k < n; k++) y[k] = x[k] * x[k];
}
*/
% compile
mex my_func.c % produces my_func.mexw64
% usage:
y = my_func([1 2 3]); % [1 4 9]
% C++ with MATLAB Data API (modern, R2018a+)
% #include "mex.hpp", "mexAdapter.hpp"
% use matlab::data::TypedArray<double>
% call MATLAB from C/C++ application (MATLAB Engine API)
% #include "engine.h"
% eng = engOpen("");
% engPutVariable(eng, "x", x);
% engEvalString(eng, "y = sqrt(x)");
% loadlibrary for generic shared libraries
loadlibrary('mylib.dll', 'mylib.h');
calllib('mylib', 'my_function', arg);
unloadlibrary('mylib');Memory Management & Large Data
Memory is often the bottleneck for large computations. Use single instead of double to halve memory and double throughput. sparse matrices store only nonzeros. memmapfile maps a binary file into memory without loading it — perfect for huge datasets accessed sequentially. tall arrays (with datastore) process data in chunks that don't fit in RAM, using MapReduce under the hood. Since R2018b, MATLAB can do some in-place operations (A = A + 1) without copying, but explicit A(:) = ... guarantees it. Always clear large variables when done.
% check memory usage
[usr, sys] = memory;
disp(usr.PhysicalMemory.Available);
% view variable sizes
whos % all variables with sizes
[x_size, x_bytes] = compute_size(x);
% clear large variables when done
clear big_array;
% use single precision when possible
A = rand(5000, 'single'); % half the memory of double
B = A * A; % single precision matmul
% sparse for mostly-zero matrices
S = sparse(1e5, 1e5);
S(1, 1) = 1;
% memory-mapped files for huge data
m = memmapfile('large.bin', 'Format', 'double', 'Offset', 0, ...
'Repeat', 1e8);
m.Data(1) % access without loading all
% tall arrays for out-of-core
ds = datastore('big.csv');
t = tall(ds);
mean_t = mean(t.Var1);
gather(mean_t); % triggers computation
% avoid copies: in-place operations
A = A + 1; % may modify A in place (since R2018b)
A(:) = A(:) + 1; % definitely in placePlotting Advanced
Subplots and tiledlayout
tiledlayout (R2019b+) is the modern replacement for subplot — better spacing, easier spanning, and shared titles via title(..., 'tiledtitle'). nexttile([1 2]) spans across multiple tiles. subplot(n, m, k) still works for legacy code but is less flexible.
% tiledlayout (R2019b+) replaces subplot
tiledlayout(2, 3, 'TileSpacing', 'compact', 'Padding', 'compact');
nexttile; plot(1:10);
nexttile; scatter(rand(1, 50), rand(1, 50));
nexttile; bar(rand(5, 3));
nexttile; imagesc(magic(10));
nexttile; histogram(randn(1000, 1), 30);
nexttile; pie([30 20 50]);
% span multiple tiles
nexttile(7, [1 2]); plot(sin(0:0.1:2*pi));
% shared title and labels
title('Dashboard Demo');
xlabel('X'); ylabel('Y');
% legacy subplot
subplot(2, 2, 1); plot(1:10);
subplot(2, 2, 2); plot(10:-1:1);Customizing axes
Most axis properties are accessible via the axes handle (gca). xlim/ylim set limits; xticks/xticklabels control tick positions and labels. TeX markup like \pi renders Greek letters. set(gca, ...) is the legacy syntax; ax.Property = value is the modern (R2014b+) equivalent.
x = linspace(0, 2*pi, 100);
plot(x, sin(x));
% axis limits
xlim([0 2*pi]); ylim([-1.2 1.2]);
% ticks and labels
xticks(0:pi/2:2*pi);
xticklabels({'0', '\pi/2', '\pi', '3\pi/2', '2\pi'});
% grid and minor grid
grid on; grid minor on;
% axis appearance
box on;
ax = gca;
ax.FontSize = 12;
ax.FontName = 'Courier';
ax.LineWidth = 1.5;
ax.XColor = [0.5 0.5 0.5];
ax.YDir = 'reverse';
% log scale
semilogy(1:100, 2.^(1:100));
set(gca, 'YScale', 'log');Multiple plots and legend
hold on lets you overlay multiple plots on the same axes — always end with hold off to avoid surprises. 'Location', 'best' picks the least-overlapping corner. The 'Interpreter', 'latex' option enables full LaTeX math. Pass specific line handles to legend to include only some plots.
x = linspace(0, 2*pi, 100);
y1 = sin(x); y2 = cos(x); y3 = sin(x) + cos(x);
% hold on for multiple lines
plot(x, y1, 'r-', 'LineWidth', 2); hold on;
plot(x, y2, 'b--', 'LineWidth', 2);
plot(x, y3, 'g:', 'LineWidth', 2); hold off;
% legend with location
legend('sin(x)', 'cos(x)', 'sin+cos', ...
'Location', 'best', 'Orientation', 'horizontal');
% legend with TeX
legend('$\sin(x)$', '$\cos(x)$', 'Interpreter', 'latex');
% specify which lines to include
h1 = plot(x, y1); hold on;
h2 = plot(x, y2);
h3 = plot(x, y3);
legend([h1 h3], 'sin', 'sin+cos');3D plotting
surf draws a colored surface; mesh draws a wireframe. contour and contourf show 2D projections; clabel adds labels. plot3 plots 3D parametric curves. view(az, el) sets the camera angle (azimuth, elevation in degrees). shading interp smooths color transitions.
[X, Y] = meshgrid(-2:0.1:2, -2:0.1:2);
Z = X .* exp(-X.^2 - Y.^2);
% surface plot
figure;
surf(X, Y, Z);
colorbar; shading interp;
% mesh plot (wireframe)
figure;
mesh(X, Y, Z);
hidden off; % show hidden lines
% contour
figure;
contour(X, Y, Z, 20); colorbar;
contourf(X, Y, Z, 20); colorbar; % filled
[c, h] = contour(X, Y, Z, 20); clabel(c, h);
% 3D parametric
t = 0:0.01:10;
plot3(sin(t), cos(t), t);
xlabel('x'); ylabel('y'); zlabel('z');
view(45, 30); % azimuth, elevationAnimations and movies
Animations update plot data inside a loop with drawnow to refresh. For smooth video, use VideoWriter (replaces the deprecated avifile). getframe captures the current figure as an image. Set FrameRate before opening the video. Always close(v) when done to flush the file.
% animate a sine wave
figure;
h = plot(NaN, NaN);
xlim([0 2*pi]); ylim([-1 1]);
for k = 1:100
x = linspace(0, 2*pi, k);
set(h, 'XData', x, 'YData', sin(x));
drawnow;
end
% capture frames and save as video
v = VideoWriter('animation.mp4', 'MPEG-4');
v.FrameRate = 30; open(v);
for k = 1:60
plot(sin(0:0.1:k/10));
frame = getframe(gcf);
writeVideo(v, frame);
end
close(v);
% getframe for static snapshots
figure; plot(1:10);
frame = getframe; % struct with cdataMatrix Operations Deep
Linear algebra essentials
Always use A\b (backslash) to solve linear systems — it dispatches to the right factorization (LU, Cholesky, QR) based on the matrix. inv(A)*b is slower and numerically worse. eig returns eigenvectors as columns of V and eigenvalues on the diagonal of D. expm is the matrix exponential (different from element-wise exp).
A = [1 2; 3 4];
b = [5; 6];
% solve Ax = b
x = A \ b; % preferred (LU-based)
x = inv(A) * b; % avoid — slower, less stable
% factorizations
[L, U, P] = lu(A); % PA = LU
[Q, R] = qr(A); % A = QR
[V, D] = eig(A); % A V = V D
[U, S, V] = svd(A); % A = U S V'
% properties
det(A); trace(A); rank(A); cond(A);
null(A); % null space
orth(A); % orthonormal basis of range
% matrix functions
expm(A); logm(A); sqrtm(A); % matrix (not element-wise)Element-wise vs matrix ops
The dot prefix (.*) means element-wise; without it, ops are matrix ops. The most common MATLAB bug: x*x where x is a row vector — use x*x' for dot product or x.*x for element-wise square. ' is conjugate transpose (flips sign of imaginary parts); .' is plain transpose.
A = [1 2; 3 4];
B = [5 6; 7 8];
% element-wise (use .)
A .* B % [5 12; 21 32]
A ./ B % element-wise divide
A .^ 2 % [1 4; 9 16]
A .^ B % element-wise power
% matrix ops (no .)
A * B % matrix product
A / B % A * inv(B)
A \ B % inv(A) * B
A^2 % A * A (matrix power)
A' % conjugate transpose
A.' % non-conjugate transpose
% common gotcha
x = [1 2 3];
x * x % ERROR: inner dims mismatch
x * x' % 14 (dot product)
x .* x % [1 4 9] (element-wise)Reshaping and indexing
MATLAB stores matrices column-major, so A(5) in a 4x4 is A(1, 2). Logical indexing (A(mask)) is powerful and fast — extract or modify elements matching a condition without loops. reshape requires the total element count to match. permute generalizes transpose to N-D arrays.
A = magic(4); % 4x4 matrix
% linear indexing (column-major)
A(5) % A(1, 2)
A(:) % column vector of all elements
A(2:5) % elements 2-5
% submatrix
A(1:2, 2:4) % rows 1-2, cols 2-4
A(:, 3) % all rows, col 3
A(end, :) % last row
A(1:2:end, :) % odd rows (stride)
% logical indexing
mask = A > 10;
A(mask) % flat list of values > 10
A(A > 10) = 0; % threshold in-place
% reshape, permute, flip
B = reshape(A, 2, 8);
C = permute(A, [2 1]); % transpose N-D
flip(A); flipud(A); fliplr(A);
repmat(A, 2, 3); % tile 2x3Sparse matrices
Sparse matrices store only non-zero elements — essential for large matrices that are mostly zero (e.g., from PDE discretizations). Operations preserve sparsity when possible. The backslash S\b uses a sparse direct solver (UMFPACK) — much faster and more memory-efficient than full()\b for large sparse systems. spy visualizes the sparsity pattern.
% create sparse
S = sparse(1000, 1000);
S(1, 1) = 5;
S(500, 500) = 10;
% from triplets
i = [1 2 3 4];
j = [1 2 3 4];
v = [10 20 30 40];
S = sparse(i, j, v, 4, 4);
% sparse identity and diagonal
S = speye(1000);
S = spdiags(ones(1000, 1), 0, 1000, 1000);
% operations stay sparse
S = S + S';
S = S * S;
x = S \ b; % uses sparse solver
% convert
F = full(S); % sparse -> full
S = sparse(F); % full -> sparse
nnz(S) % count non-zeros
spy(S) % visualize sparsityBroadcasting (implicit expansion)
Since R2016b, MATLAB automatically broadcasts (like NumPy) — dimensions of size 1 expand to match. Before that, you needed bsxfun. Broadcasting makes code cleaner: M - mean(M, 2) centers each row without repmat. Dimensions must be compatible (equal or one of them is 1).
% R2016b+ — automatic broadcasting
A = magic(3); % 3x3
b = [1 2 3]; % 1x3
% older MATLAB: error (dims mismatch)
% modern MATLAB: b is broadcast across rows
C = A + b; % 3x3 result
C = A - b';
C = A .* b;
% common uses
x = (1:5)'; % column
y = (1:5); % row
outer = x * y; % 5x5 outer product
grid = x + y; % 5x5 addition grid
% mean across rows
M = magic(5);
row_means = mean(M, 2); % 5x1
centered = M - row_means; % broadcast subtraction
% bsxfun (legacy, pre-R2016b)
C = bsxfun(@plus, A, b); % same as A + bCell Arrays & Structs
Cell arrays
Cell arrays hold mixed types. Use {} to access contents (drops the cell wrapper) and () to get a sub-cell. cellfun applies a function to each cell — pass 'UniformOutput', false if results are heterogeneous. Cell arrays are the standard way to hold strings of different lengths (pre-string array).
% heterogeneous container
C = {'hello', 42, [1 2 3], magic(3)};
% access
C{1} % 'hello' (contents)
C(1) % {1x1 cell} (cell)
C{4}(2, 2) % access inside
% build dynamically
C = {};
for k = 1:5
C{k} = rand(k);
end
% multi-element
[a, b, c] = C{1:3}; % unpack
C{1:3} % comma-separated list
% cellfun
nums = {1, 2, 3, 4};
squared = cellfun(@(x) x^2, nums);
lengths = cellfun(@length, C);
% convert
cell([1 2 3]) % {1, 2, 3}
cell2mat({1 2; 3 4}) % [1 2; 3 4]
mat2cell(magic(4), [2 2], [2 2]) % 2x2 cell of blocksStruct arrays
Structs group named fields of any type. Struct arrays hold multiple records — {arr.field} gathers a field across all elements into a cell, [arr.field] into a regular array (if compatible). Nested fields use dot chaining. fieldnames lists fields; rmfield returns a copy without the field.
% scalar struct
s.name = 'Alice';
s.age = 30;
s.scores = [90 85 92];
% struct constructor
s = struct('name', 'Bob', 'age', 25, 'scores', {[80 70]});
% struct array
students(1).name = 'Alice';
students(1).age = 30;
students(2).name = 'Bob';
students(2).age = 25;
% access across array
names = {students.name}; % all names (cell)
ages = [students.age]; % all ages (vector)
% nested
s.course.code = 'CS101';
s.course.credits = 3;
s.course.instructor.name = 'Dr. Smith';
% field operations
fieldnames(s) % list fields
isfield(s, 'age') % check field
rmfield(s, 'age') % remove field
orderfields(s) % sort fieldsTables (tabular data)
Tables (R2013b+) are the modern way to hold tabular data — like a DataFrame in pandas. Access columns by name (T.Age) or index (T.(2)). sortrows sorts by one or more columns. readtable/writetable handle CSV, Excel, etc. summary gives stats per column. Prefer tables over raw matrices for heterogeneous data.
% create table
Names = {'Alice'; 'Bob'; 'Carol'};
Age = [30; 25; 42];
Score = [90; 80; 95];
T = table(Names, Age, Score);
% access
T.Age % column as vector
T.(2) % column by index
T{1, 2} % row 1, col 2 (cell-style)
T(1:2, :) % first 2 rows
% add/remove columns
T.Grade = {'A'; 'B'; 'A'};
T.Grade = []; % remove column
% filtering
T(T.Age > 26, :) % rows where Age > 26
find(T.Age > 26);
% sorting
T = sortrows(T, 'Age');
T = sortrows(T, {'Age', 'Score'}, 'descend');
% summary
summary(T)
T.Properties.VariableNames
% read/write
T = readtable('data.csv');
writetable(T, 'out.csv')Timetables
Timetables (R2016b+) are tables with row timestamps. retime resamples/aggregates (e.g., 'hourly', 'daily', or custom TimeStep). synchronize aligns multiple timetables to a common time vector. lag/lead shift columns. Much cleaner than manually managing time indices in matrices.
% create timetable with timestamps
Time = datetime(2024, 1, 1) + hours(0:23)';
Temp = 20 + 5 * randn(24, 1);
TT = timetable(Time, Temp);
% indexing by time
TT.timerange(datetime(2024,1,1,6,0,0), datetime(2024,1,1,12,0,0))
TT(datetime(2024,1,1,10,0,0), :) % row at specific time
TT('2024-01-01 10:00:00', :)
% resample / synchronize
TT_30min = retime(TT, 'regular', 'mean', 'TimeStep', minutes(30));
TT_hourly = retime(TT, 'hourly', 'mean');
% aggregate
TT_daily = retime(TT, 'daily', @mean);
TT_daily_max = retime(TT, 'daily', 'max');
% combine timetables
TT2 = synchronize(TT1, TT2, 'union');
% lagging
TT.PrevTemp = lag(TT.Temp, 1);Maps (dictionaries)
containers.Map is the legacy hash map — works in all MATLAB versions but slower and untyped. dictionary (R2022b+) is the modern replacement: typed, faster, and supports vectorized lookup. Use maps when you need O(1) key lookup instead of searching a struct array or cell.
% containers.Map (pre-R2022b)
m = containers.Map;
m('apple') = 1;
m('banana') = 2;
m('cherry') = 3;
% access
m('apple') % 1
m.Keys % {'apple', 'banana', 'cherry'}
m.Values % [1, 2, 3]
isKey(m, 'apple') % true
remove(m, 'banana');
% iterate
keys = m.keys;
for k = 1:length(keys)
fprintf('%s -> %d\n', keys{k}, m(keys{k}));
end
% R2022b+ dictionary (faster, typed)
d = dictionary({'apple', 'banana'}, [1, 2]);
d('cherry') = 3;
d('apple') % 1
keys(d); values(d)Optimization
fmincon constrained optimization
fmincon is the workhorse for constrained nonlinear minimization. The nonlcon function must return [c, ceq] where c <= 0 (inequality) and ceq = 0 (equality). deal is a clean way to return multiple outputs from an anonymous function. Set Algorithm based on problem type: 'interior-point' (general), 'sqp' (small/medium, often faster).
% minimize objective with constraints
% min f(x) s.t. A*x <= b, Aeq*x = beq, lb <= x <= ub, c(x) <= 0, ceq(x) = 0
fun = @(x) (x(1) - 2)^2 + (x(2) - 3)^2;
% linear inequality: x1 + x2 <= 4
A = [1 1]; b = 4;
% linear equality: x1 - x2 = 0
Aeq = [1 -1]; beq = 0;
% bounds
lb = [0 0]; ub = [5 5];
% nonlinear: x1^2 + x2^2 >= 1 (so -(x1^2 + x2^2 - 1) <= 0)
nonlcon = @(x) deal(-(x(1)^2 + x(2)^2 - 1), []);
x0 = [1 1];
[x, fval, exitflag, output] = fmincon(fun, x0, A, b, Aeq, beq, lb, ub, nonlcon);
% options
opts = optimoptions('fmincon', 'Display', 'iter', ...
'Algorithm', 'interior-point');
[x, fval] = fmincon(fun, x0, A, b, Aeq, beq, lb, ub, nonlcon, opts);fminunc unconstrained
fminunc minimizes unconstrained nonlinear functions. Providing the gradient (via SpecifyObjectiveGradient) dramatically improves speed and accuracy. The default BFGS Hessian approximation works well for smooth problems; for large ones, 'lbfgs' limits memory. Check exitflag (>0 = converged) and firstorderopt (should be tiny).
% unconstrained minimization
fun = @(x) 100*(x(2) - x(1)^2)^2 + (1 - x(1))^2; % Rosenbrock
x0 = [-1.2 1];
[x, fval, flag, out] = fminunc(fun, x0);
% with gradient (faster, more accurate)
syms x1 x2
f = 100*(x2 - x1^2)^2 + (1 - x1)^2;
grad = gradient(f, [x1, x2]);
fun_grad = matlabFunction(f, grad, 'Vars', {x1, x2});
opts = optimoptions('fminunc', 'SpecifyObjectiveGradient', true, ...
'Display', 'iter');
[x, fval] = fminunc(@(x) fun_grad(x(1), x(2)), x0, opts);
% check optimality
disp(out.firstorderopt) % should be near 0
% Hessian option
opts.Hessian = 'bfgs'; % quasi-Newton (default)
opts.Hessian = 'lbfgs'; % for large sparse problemslinprog linear programming
linprog solves linear programs. For integer/binary variables, use intlinprog (replaces the deprecated bintprog). intcon lists which variables are integer-constrained. Set lb=0, ub=1 for binary. The dual-simplex algorithm is the default and fastest for most problems.
% min f'*x s.t. A*x <= b, Aeq*x = beq, lb <= x <= ub
% example: min -x1 - 2*x2
% s.t. x1 + x2 <= 4
% x1 + 3*x2 <= 6
% x1, x2 >= 0
f = [-1; -2];
A = [1 1; 1 3];
b = [4; 6];
lb = [0; 0];
opts = optimoptions('linprog', 'Display', 'iter');
[x, fval, exitflag, output] = linprog(f, A, b, [], [], lb, [], opts);
% integer programming (intlinprog)
intcon = 1:2; % variables 1 and 2 are integers
[x, fval] = intlinprog(f, intcon, A, b, [], [], lb, []);
% binary variables: set lb=0, ub=1, and add to intcon
lb = [0; 0]; ub = [1; 1];
[x, fval] = intlinprog(f, intcon, A, b, [], [], lb, ub);lsqcurvefit and curve fitting
lsqcurvefit fits parametric models to data via least squares. polyfit is the easy choice for polynomials. For R² (coefficient of determination), compute it manually: 1 - SSE/SST. The Levenberg-Marquardt algorithm is good for unconstrained problems; trust-region-reflective handles bounds.
% fit y = a*exp(b*x) to data
xdata = linspace(0, 5, 50)';
ydata = 2.5 * exp(-0.7 * xdata) + 0.05 * randn(50, 1);
model = @(p, x) p(1) * exp(p(2) * x);
x0 = [1, -1];
[params, resnorm, residual, exitflag] = lsqcurvefit(model, x0, xdata, ydata);
% with bounds
lb = [0, -5]; ub = [10, 0];
[params, resnorm] = lsqcurvefit(model, x0, xdata, ydata, lb, ub);
% polyfit for polynomials
p = polyfit(xdata, ydata, 3); % cubic
yfit = polyval(p, xdata);
% fit with custom output
opts = optimoptions('lsqcurvefit', 'Display', 'off', ...
'Algorithm', 'levenberg-marquardt');
[params, resnorm] = lsqcurvefit(model, x0, xdata, ydata, [], [], opts);
% goodness of fit
sse = sum((ydata - model(params, xdata)).^2);
sst = sum((ydata - mean(ydata)).^2);
r2 = 1 - sse / sst;Global optimization
Global optimization tools (in the Global Optimization Toolbox) help with non-convex problems where local solvers get stuck. MultiStart runs a local solver from many random starts. GlobalSearch is smarter — it filters promising starts. ga (genetic algorithm) and simulannealbnd are derivative-free. patternsearch is good for nonsmooth problems.
% MultiStart: run local solver from many points
fun = @(x) x(1)^2 + x(2)^2 + 10*sin(x(1)) + 10*sin(x(2));
ms = MultiStart('Display', 'iter');
opts = optimoptions('fmincon', 'Algorithm', 'interior-point');
problem = createOptimProblem('fmincon', 'objective', fun, ...
'x0', [0 0], 'lb', [-5 -5], 'ub', [5 5]);
[x, fval] = run(ms, problem, 50); % 50 starting points
% GlobalSearch: smarter, fewer starts
gs = GlobalSearch;
[x, fval] = run(gs, problem);
% ga (genetic algorithm)
[x, fval] = ga(fun, 2, [], [], [], [], [-5 -5], [5 5]);
% simulannealbnd (simulated annealing)
[x, fval] = simulannealbnd(fun, [0 0], [-5 -5], [5 5]);
% patternsearch
[x, fval] = patternsearch(fun, [0 0]);Image Processing
Reading and displaying images
imread returns uint8 arrays for most image formats. rgb2gray converts RGB to grayscale. im2double scales to [0, 1] — use this (not double()) before float processing. imshow auto-scales double images: [0, 1] is the expected range. imwrite supports quality/compression options.
% read and display
img = imread('photo.jpg');
imshow(img);
% info
size(img) % rows x cols x channels
class(img) % usually uint8
imfinfo('photo.jpg') % metadata
% convert types
gray = rgb2gray(img); % RGB -> gray
img_double = im2double(img); % uint8 [0,255] -> double [0,1]
img_uint8 = im2uint8(img_double);
% write
imwrite(gray, 'gray.png');
imwrite(img, 'compressed.jpg', 'Quality', 80);
% display multiple
figure;
subplot(1, 2, 1); imshow(img); title('Original');
subplot(1, 2, 2); imshow(gray); title('Grayscale');
% pixel info
impixelinfo; % interactive pixel values
img(100, 200, :) % pixel at (row, col)Filtering and convolution
imgaussfilt is the modern Gaussian blur (replaces fspecial('gaussian') + imfilter). medfilt2 is the right choice for salt-and-pepper noise (mean filter just smears it). fspecial creates common kernels (sobel, prewitt, laplacian, gaussian, disk, motion). imfilter does correlation by default — pass 'conv' for true convolution.
img = imread('cameraman.tif');
img = im2double(img);
% Gaussian blur
blurred = imgaussfilt(img, 2); % sigma = 2
blurred = imgaussfilt(img, 2, 'FilterSize', 7);
% median filter (great for salt-and-pepper noise)
noisy = imnoise(img, 'salt & pepper', 0.05);
denoised = medfilt2(noisy, [3 3]);
% custom kernel
h = fspecial('sobel'); % edge detection
edges = imfilter(img, h);
h = fspecial('laplacian', 0);
sharpened = img - imfilter(img, h);
% 2D convolution vs correlation
out_conv = imfilter(img, h, 'conv');
out_corr = imfilter(img, h, 'corr'); % default
% unsharp masking
sharp = imsharpen(img, 'Amount', 1.5, 'Radius', 2);Morphological operations
Morphological ops work on binary images. Erode shrinks objects; dilate grows them. Open (erode then dilate) removes small noise; close (dilate then erode) fills small gaps. strel creates structuring elements — disk/square/line/octagon. bwareaopen removes small objects; imfill fills holes; bwperim extracts boundaries.
bw = imread('text.png');
bw = imbinarize(bw); % grayscale -> binary
% basic ops
eroded = imerode(bw, strel('square', 3));
dilated = imdilate(bw, strel('disk', 2));
opened = imopen(bw, strel('square', 5));
closed = imclose(bw, strel('square', 5));
% structuring elements
se = strel('square', 3);
se = strel('disk', 5);
se = strel('line', 10, 45); % length 10, angle 45 deg
se = strel('octagon', 3);
% remove small objects
clean = bwareaopen(bw, 50); % remove <50 pixels
% skeleton
skel = bwmorph(bw, 'skel', Inf);
% fill holes
filled = imfill(bw, 'holes');
% boundary
boundary = bwperim(bw);Edge detection and segmentation
edge with 'canny' is the most robust edge detector (specify [low high] thresholds and sigma). imbinarize with 'adaptive' handles uneven lighting. bwconncomp finds connected components; regionprops extracts measurements (Area, Centroid, BoundingBox, etc.). watershed separates touching objects — compute on the gradient to find boundaries.
img = imread('coins.png');
img = im2double(img);
% edges
edges_sobel = edge(img, 'sobel');
edges_canny = edge(img, 'canny', [0.1 0.2], 1.5);
edges_prewitt = edge(img, 'prewitt');
% thresholding
bw = imbinarize(img);
bw_otsu = imbinarize(img, 'adaptive'); % local threshold
% connected components
cc = bwconncomp(bw);
stats = regionprops(cc, 'Area', 'Centroid', 'BoundingBox');
areas = [stats.Area];
[~, idx] = sort(areas, 'descend');
biggest = stats(idx(1));
% watershed segmentation
grad = imgradient(img);
L = watershed(grad);
L(L == 0) = NaN;
imshow(img); hold on; imshow(L, []);Color and transforms
rgb2hsv, rgb2lab convert color spaces — HSV is intuitive for color picking; L*a*b* separates luminance from color (good for color difference). fft2 + fftshift center the spectrum for filtering. imresize/imrotate/imcrop are geometric ops — 'bilinear' (default) is usually best; 'nearest' is fastest but blocky.
img = imread('peppers.png');
% color space conversion
hsv = rgb2hsv(img);
lab = rgb2lab(img);
gray = rgb2gray(img);
rgb = hsv2rgb(hsv);
% extract channels
R = img(:, :, 1);
G = img(:, :, 2);
B = img(:, :, 3);
% Fourier transform
f = fft2(double(gray));
f = fftshift(f); % center zero freq
mag = log(1 + abs(f));
imshow(mag, []);
% inverse
f_filtered = f;
f_filtered(abs(f) < 100) = 0; % low-pass filter
filtered = real(ifft2(ifftshift(f_filtered)));
imshow(filtered, []);
% resize, rotate
small = imresize(img, 0.5);
rotated = imrotate(img, 45, 'bilinear', 'crop');
cropped = imcrop(img, [50 50 200 150]); % [x y w h]GUI/App Designer
App Designer basics
App Designer (R2016a+) is the modern GUI tool, replacing GUIDE. Components are accessed via app.<Name>. Callbacks receive (app, event). Custom properties (in the Code View) share state between callbacks. Save as .mlapp (binary) or export to .m. Run by typing the app name in the command window.
% Open App Designer:
% >> appdesigner
% Drag components from the left, set properties on the right.
% Callback structure (auto-generated):
function ButtonPushed(app, event)
x = linspace(0, 2*pi, 100);
plot(app.UIAxes, x, sin(x));
app.ResultEditField.Value = 'Plot done';
end
% Access components via app.<ComponentName>
% app.UIAxes, app.Button, app.EditField, app.Slider, ...
% Property panel: add custom properties
properties (Access = private)
data; % shared between callbacks
end
% Startup callback:
function startupFcn(app)
app.data = rand(10);
app.Slider.Value = 50;
end
% Save as .mlapp, run with:
% >> myApp (if named myApp.mlapp)
% Or export to a standalone .m file.Programmatic UI with uifigure
uifigure (R2016b+) is the modern programmatic UI framework — supports modern widgets (gauge, knob, switch, tree) that figure doesn't. Set callbacks via the *Fcn properties using anonymous functions @(src, event) .... uiwait blocks until the figure closes; uiresume releases it.
% modern uifigure (R2016b+) — preferred
fig = uifigure('Name', 'My App', 'Position', [100 100 600 400]);
ax = uiaxes(fig, 'Position', [200 100 350 250]);
plot(ax, 1:10);
btn = uibutton(fig, 'Text', 'Plot', 'Position', [50 100 100 30]);
btn.ButtonPushedFcn = @(~,~) plot(ax, rand(1, 10));
slider = uislider(fig, 'Position', [50 200 100 3]);
slider.ValueChangedFcn = @(s,~) disp(s.Value);
% dropdown
dd = uidropdown(fig, 'Items', {'a', 'b', 'c'}, 'Position', [50 250 100 30]);
dd.ValueChangedFcn = @(s,~) fprintf('Selected: %s\n', s.Value);
% list box
lb = uilistbox(fig, 'Items', {'one', 'two', 'three'}, ...
'Multiselect', 'on', 'Position', [50 50 100 80]);
% wait for user to close
uiwait(fig);Common UI components
Modern UI components: uieditfield (text or numeric), uibuttongroup (manages radio buttons), uicheckbox, uitable (binds to a table), uitabgroup/uitab (tabs). All take a parent as the first arg and use Name-Value pairs for properties. Callbacks fire on user interaction; access new values via the source argument.
fig = uifigure;
% label
lbl = uilabel(fig, 'Text', 'Enter value:', 'Position', [20 200 100 22]);
% edit field
ef = uieditfield(fig, 'numeric', 'Value', 42, 'Position', [130 200 100 22]);
ef.ValueChangedFcn = @(s,~) fprintf('New: %g\n', s.Value);
% button group with radio buttons
bg = uibuttongroup(fig, 'Title', 'Mode', 'Position', [20 100 200 80]);
r1 = uiradiobutton(bg, 'Text', 'A', 'Position', [10 40 100 22]);
r2 = uiradiobutton(bg, 'Text', 'B', 'Position', [10 10 100 22]);
r1.Value = true;
% check box
cb = uicheckbox(fig, 'Text', 'Enable', 'Position', [20 50 100 22]);
% table
tdata = table({'A'; 'B'}, [1; 2], 'VariableNames', {'Name', 'Value'});
uit = uitable(fig, 'Data', tdata, 'Position', [250 50 200 150]);
% tab group
tg = uitabgroup(fig);
t1 = uitab(tg, 'Title', 'Tab 1');
t2 = uitab(tg, 'Title', 'Tab 2');
plot(uiaxes(t1), 1:10);Dialogs and prompts
inputdlg collects text input; questdlg for yes/no/cancel; listdlg for selection; uigetfile/uiputfile for file pickers; msgbox/errordlg/warndlg for notifications. fullfile joins paths portably (better than string concatenation). Always check that the user didn't cancel (empty return or ok == false).
% input dialog
answer = inputdlg({'Name:', 'Age:'}, 'User Info', [1 50; 1 10]);
if ~isempty(answer)
name = answer{1};
age = str2double(answer{2});
end
% question dialog
btn = questdlg('Save changes?', 'Confirm', 'Yes', 'No', 'Cancel', 'Yes');
switch btn
case 'Yes', save_data();
case 'No', % discard
case 'Cancel', return;
end
% list dialog
[sel, ok] = listdlg('PromptString', 'Select items:', ...
'ListString', {'Apple', 'Banana', 'Cherry'}, ...
'SelectionMode', 'multiple');
% file dialogs
[file, path] = uigetfile('*.csv', 'Select CSV');
[file, path] = uiputfile('*.mat', 'Save as');
fullpath = fullfile(path, file);
% message dialog
msgbox('Done!', 'Info', 'help');
errordlg('Something went wrong', 'Error');
warndlg('Check this', 'Warning');Sharing and deployment
For sharing: .mlapp files require MATLAB; standalone apps (via MATLAB Compiler) run without MATLAB but need the free MATLAB Runtime; web apps run in a browser via MATLAB Web App Server. Exporting to .m gives you readable source code. Package as a toolbox for distribution via Add-Ons.
% Run as standalone app
% 1. In App Designer: Designer Tab > App Store Details > Save as .mlapp
% 2. Share the .mlapp file — others open it in MATLAB
% Create standalone app (requires MATLAB Compiler)
% >> mcr.build('myApp.mlapp') % R2024a+
% or
% >> deploytool % legacy
% Web App (requires MATLAB Web App Server)
% >> compiler.build.webApp('myApp.mlapp')
% Export to code (readable .m)
% In App Designer: Designer Tab > Export > Export to .m file
% Pack as toolbox (for sharing with colleagues)
% >> matlab.addons.toolbox.packageToolbox('myApp.prj)
% Tips:
% - Use try/catch in callbacks to avoid silent failures
% - Set app.UIFigure.Name to identify your app
% - Test on a clean MATLAB session before deployingFile I/O Advanced
Low-level file I/O
fopen returns -1 on failure — always check. fgetl reads a line without the newline; fgets keeps it. fscanf reads formatted data; fread reads binary. fseek/ftell navigate. Always fclose when done (use onCleanup for safety: c = onCleanup(@() fclose(fid));).
fid = fopen('data.txt', 'r'); % r, w, a, r+, w+
if fid == -1; error('Cannot open file'); end
% read line by line
while ~feof(fid)
line = fgetl(fid); % without newline
fprintf('%s\n', line);
end
% formatted read
% data.txt: "Alice 30 90.5"
A = fscanf(fid, '%s %d %f', [3 1]);
% formatted write
fprintf(fid, '%s, %d, %.2f\n', 'Bob', 25, 85.3);
% binary I/O
data = fread(fid, [10 5], 'double'); % 10x5 doubles
fwrite(fid, data, 'double');
% position
fseek(fid, 0, 'bof'); % beginning
fseek(fid, 0, 'eof'); % end
pos = ftell(fid);
fclose(fid); % ALWAYS closetextscan for mixed data
textscan is more flexible than fscanf — handles mixed types, custom delimiters, and returns a cell array of columns. 'TreatAsEmpty' converts placeholders to NaN. 'CollectOutput' groups same-type columns into one array. fileread slurps the whole file as a string — convenient for small files or regex processing.
fid = fopen('data.csv', 'r');
% skip header line
header = fgetl(fid);
% parse remaining
% Format: Alice,30,90.5,B+
C = textscan(fid, '%s %d %f %s', ...
'Delimiter', ',', ...
'MultipleDelimsAsOne', true, ...
'TreatAsEmpty', {'NA', 'N/A'}, ...
'HeaderLines', 0);
fclose(fid);
names = C{1}; ages = C{2}; scores = C{3}; grades = C{4};
% alternative: read whole file at once
str = fileread('data.txt');
% from string
C = textscan('1 2 3\n4 5 6', '%d %d %d');
% C{1} = [1; 4], C{2} = [2; 5], C{3} = [3; 6]
% collectoutput (group columns of same type)
C = textscan(fid, '%s %d %d %f', 'CollectOutput', true);
% C{2} = [ages, more_ints] as one matrixMAT-files and save/load
save/load with .mat files preserve variable types and structure. -v7.3 supports files > 2GB (and is the default in modern MATLAB). -append adds variables without rewriting. For huge files, load only what you need by name. For text export, use -ascii (limited) or writematrix/writetable for more control.
A = magic(5);
B = struct('name', 'Alice', 'age', 30);
C = rand(100);
% save variables
save('data.mat', 'A', 'B', 'C');
save('data.mat', 'A', 'B', '-v7.3'); % large files > 2GB
save('data.mat', '-append', 'C'); % add to existing
% load
loaded = load('data.mat'); % struct with variables
loaded.A
loaded.B.age
% or load into workspace
load('data.mat'); % A, B, C now in workspace
% partial load (huge files)
info = whos('-file', 'bigdata.mat');
loaded = load('bigdata.mat', 'A'); % only A
% save specific format
save('data.txt', 'A', '-ascii', '-double');
save('data.csv', 'A', '-ascii', '-delimiter', ',');
% compressed
save('data.mat', 'A', '-v7.3', '-nocompression');HDF5 and scientific formats
HDF5 is the standard for large numerical datasets — supports chunking, compression, and extendable dimensions. h5read with start/count lets you read slices without loading the whole file. NetCDF is common in climate/ocean science; FITS in astronomy. MATLAB also supports TIFF, DICOM, audio, and video formats natively.
% HDF5 (great for large scientific datasets)
% write
h5create('data.h5', '/dataset1', [100 50 20]);
data = rand(100, 50, 20);
h5write('data.h5', '/dataset1', data);
% read
info = h5info('data.h5');
data = h5read('data.h5', '/dataset1');
partial = h5read('data.h5', '/dataset1', [1 1 1], [10 10 5]);
% append (extendable datasets)
h5create('data.h5', '/growable', [100 Inf], 'ChunkSize', [100 100]);
for k = 1:5
h5write('data.h5', '/growable', rand(100, 100), [1 (k-1)*100+1]);
end
% NetCDF (climate/ocean data)
ncid = netcdf.open('data.nc', 'NC_NOWRITE');
varid = netcdf.inqVarID(ncid, 'temperature');
data = netcdf.getVar(ncid, varid);
netcdf.close(ncid);
% FITS (astronomy)
fitsdisp('image.fits');
data = fitsread('image.fits');JSON and XML
jsonencode/jsondecode (R2016b+) handle JSON natively. Structs become JSON objects; cell arrays become arrays. For XML, xmlread returns a Java DOM object — use Java methods to traverse. xmlwrite serializes a DOM back to a file. For complex XML, consider the third-party xml2struct or the DOM API directly.
% JSON (R2016b+)
data = struct('name', 'Alice', 'age', 30, 'scores', [90 80 85]);
txt = jsonencode(data, 'PrettyPrint', true);
disp(txt);
decoded = jsondecode(txt);
decoded.name % 'Alice'
% JSON with cell arrays for mixed types
data = struct('items', {{'apple', 42, [1 2 3]}});
txt = jsonencode(data);
% read JSON file
txt = fileread('config.json');
config = jsondecode(txt);
% XML
doc = xmlread('data.xml');
root = doc.getDocumentElement;
children = root.getChildNodes;
for k = 0:children.getLength - 1
node = children.item(k);
if node.getNodeType == doc.ELEMENT_NODE
fprintf('%s: %s\n', node.getNodeName, char(node.getTextContent));
end
end
% write XML
doc = com.mathworks.xml.XMLUtils.createDocument('root');
root = doc.getDocumentElement;
child = doc.createElement('item');
child.appendChild(doc.createTextNode('hello'));
root.appendChild(child);
xmlwrite('out.xml', doc);Parallel Computing
parfor loops
parfor runs loop iterations in parallel across workers. Iterations must be independent. Variables are classified: sliced (each iteration touches a unique index), broadcast (read-only), reduction (combined with an associative op like + or *), and temp (created inside). Classification determines what's allowed.
% requires Parallel Computing Toolbox
% start pool
pool = gcp('nocreate');
if isempty(pool), parpool; end
% parfor: parallel for loop
N = 1000;
results = zeros(1, N);
parfor k = 1:N
results(k) = some_expensive_function(k);
end
% constraints:
% - iterations must be independent (no order dependency)
% - body cannot contain break/return
% - variables classified as sliced, broadcast, reduction, temp
% reduction variables
total = 0;
parfor k = 1:N
total = total + compute(k);
end
% sliced variables (independent indexing)
data = rand(N, 100);
out = zeros(N, 1);
parfor k = 1:N
out(k) = mean(data(k, :));
endspmd and distributed arrays
spmd runs the same code on all workers, with labindex identifying each. Use for data-parallel algorithms where workers communicate (e.g., MPI-style). distributed arrays spread a large matrix across workers — operations on them stay distributed; gather() brings the result back to the client. Composite stores per-worker values.
% spmd: single program, multiple data
spmd
% code runs on every worker
% labindex: this worker's ID (1 to numlabs)
% numlabs: total workers
fprintf('Worker %d of %d\n', labindex, numlabs);
% each worker computes a chunk
local_data = rand(100, 1);
local_sum = sum(local_data);
end
% combine results
total = sum([local_sum{:}]);
% distributed arrays (split across workers)
D = distributed.rand(10000, 10000); % huge matrix
local_size = size(D, 'local') % each worker's chunk
total_size = size(D) % logical total
% operations auto-distribute
S = D * D';
S_local = gather(S); % pull to client (if fits)
% Composite (cell-like, one per worker)
C = Composite();
spmd
C{labindex} = magic(labindex + 1);
end
C{1} % access worker 1's valuegpuArray
gpuArray moves data to the GPU; operations on gpuArrays run on the GPU automatically. gather() brings data back. Element-wise and matrix-multiply operations see the biggest speedup; scalar or branching code does not. arrayfun on gpuArrays lets you run custom element-wise functions on the GPU without writing CUDA.
% requires GPU support (most NVIDIA GPUs)
% move data to GPU
A = gpuArray(rand(10000));
B = gpuArray(rand(10000));
% operations run on GPU
C = A * B; % still on GPU
D = sin(A) + cos(B);
E = sum(A, 1);
% bring back to CPU
C_cpu = gather(C);
% check GPU
gpuDevice % info about current GPU
gpuDeviceCount % number of available GPUs
gpuDevice(1) % select device 1
% element-wise ops are typically fastest on GPU
% matrix multiply also very fast (cuBLAS)
% custom kernels (PTX)
k = parallel.gpu.CUDAKernel('my_kernel.ptx', 'my_kernel.cu');
result = feval(k, A, B);
% arrayfun on GPU (element-wise custom functions)
f = @(x) x^2 + sin(x);
result = arrayfun(f, A);batch and job
batch runs a function or script in the background — useful for long jobs you don't want to block the MATLAB session. wait(job) blocks until done; fetchOutputs retrieves results. Always delete(job) to free resources. 'Pool', N uses N additional workers for parfor inside the batch function.
% run a function in background
job = batch(@my_function, 0, {arg1, arg2});
% check status
job.State % 'queued', 'running', 'finished'
wait(job); % block until done
% get results
results = fetchOutputs(job);
delete(job); % clean up
% batch script
job = batch('my_script.m');
% with pool
job = batch(@my_func, 1, {x}, 'Pool', 4); % 4 extra workers
% batch with attached files
job = batch(@my_func, 1, {x}, ...
'AttachedFiles', {'data.mat', 'helper.m'}, ...
'CurrentFolder', '/path/to/work');
% list jobs
jobs = findJob(pool);
for j = jobs
fprintf('Job %d: %s\n', j.ID, j.State);
end
% parallel pool settings
parpool('local', 4); % 4 workers
delete(gcp('nocreate')); % shut down poolPerformance tips
Preallocate arrays (zeros/ones) — growing arrays in loops is the #1 MATLAB performance killer. Vectorize (sin(x) instead of looping) — clearer and often faster. The JIT makes simple loops fast, but vectorization still wins for math. profile viewer finds bottlenecks. Use single precision for huge data; write MEX files for true hotspots.
% 1. Preallocate arrays
% BAD
for k = 1:1000
x(k) = k^2; % grows array each iteration
end
% GOOD
x = zeros(1, 1000);
for k = 1:1000
x(k) = k^2;
end
% 2. Vectorize instead of looping
% BAD
for k = 1:length(x)
y(k) = sin(x(k));
end
% GOOD
y = sin(x); % one vectorized call
% 3. Use JIT-friendly patterns
% simple loops are now fast (JIT), but vectorize for clarity
% 4. Profile to find bottlenecks
profile on;
my_function();
profile viewer;
% 5. Prefer single precision for huge data
A = rand(10000, 'single'); % half the memory
% 6. MEX for critical sections
% compile C code: mex my_func.cObject-Oriented
Class definition
Save classdef in a file named <ClassName>.m. Properties hold data; methods define behavior. The constructor must be named after the class and handle nargin==0 (called when no args). Dependent properties are computed on access via get.X methods. disp overrides display. Static methods don't take obj.
% file: Point.m
classdef Point
properties
x = 0
y = 0
end
properties (Dependent)
r % computed on access
end
methods
function obj = Point(x, y)
if nargin > 0
obj.x = x;
obj.y = y;
end
end
function r = get.r(obj)
r = sqrt(obj.x^2 + obj.y^2);
end
function obj = move(obj, dx, dy)
obj.x = obj.x + dx;
obj.y = obj.y + dy;
end
function disp(obj)
fprintf('Point(%.2f, %.2f), r=%.2f\n', obj.x, obj.y, obj.r);
end
end
methods (Static)
function p = origin()
p = Point(0, 0);
end
end
endValue vs handle classes
Value classes copy on assignment (like int or struct); handle classes pass by reference (like Java objects). For mutable objects (a database connection, a UI component), use handle. Value classes are simpler and safer for immutable data. Handle classes inherit from handle and support events/listeners and a delete destructor.
% Value class (default) — copied on assignment
classdef VPoint
properties; x; end
methods
function obj = VPoint(x); obj.x = x; end
function obj = setX(obj, x); obj.x = x; end
end
end
p = VPoint(1);
p2 = p; % copy
p2 = setX(p2, 5);
disp(p.x) % still 1 (unchanged)
% Handle class — passed by reference
classdef HPoint < handle
properties; x; end
methods
function obj = HPoint(x); obj.x = x; end
function setX(obj, x); obj.x = x; end % no return needed
end
end
h = HPoint(1);
h2 = h; % same object
h2.setX(5);
disp(h.x) % 5 (shared)
% handle class features:
% - events and listeners
% - destructor (delete method)
% - copy() methodInheritance and polymorphism
Subclass with <. Call superclass constructor with obj@SuperClass(args). Polymorphism works naturally — call the method on the base type, and the right override runs. MATLAB supports multiple inheritance (separate superclasses with &), but only one can be a concrete class; the rest must be interfaces.
% base class
classdef Animal
properties; name; end
methods
function obj = Animal(name); obj.name = name; end
function speak(obj)
error('Abstract: subclass must override');
end
function describe(obj)
fprintf('%s says: ', obj.name);
obj.speak();
fprintf('\n');
end
end
end
% subclass
classdef Dog < Animal
methods
function obj = Dog(name); obj = obj@Animal(name); end
function speak(obj); fprintf('Woof'); end
end
end
classdef Cat < Animal
methods
function obj = Cat(name); obj = obj@Animal(name); end
function speak(obj); fprintf('Meow'); end
end
end
% polymorphism
animals = {Dog('Rex'), Cat('Whiskers'), Dog('Buddy')};
for k = 1:length(animals)
animals{k}.describe();
end
% multiple inheritance
classdef FlyingDog < Dog & IFlyable
...
endEvents and listeners
Events require a handle class. Declare events in an events block. notify triggers an event; addlistener subscribes. Listeners can be functions or anonymous functions @(src, event). Custom event data subclasses event.EventData. Listeners are deleted when the source object is deleted (or you can delete them explicitly).
classdef Thermometer < handle
properties
temperature = 20
end
events
temperatureChanged
overheat
end
methods
function set.temperature(obj, t)
obj.temperature = t;
notify(obj, 'temperatureChanged');
if t > 100
notify(obj, 'overheat');
end
end
function obj = Thermometer()
% add listener to own event
addlistener(obj, 'overheat', @(s,e) disp('WARNING: too hot!'));
end
end
end
% usage
t = Thermometer();
lh = addlistener(t, 'temperatureChanged', @(s,e) ...
fprintf('Now: %.1f\n', s.temperature));
lh2 = addlistener(t, 'overheat', @onOverheat);
t.temperature = 25; % triggers temperatureChanged
t.temperature = 105; % triggers both
% custom event data
classdef OverheatData < event.EventData
properties; temp; end
end
% notify(obj, 'overheat', OverheatData(t));Enumeration and properties
Enumeration classes define fixed instances — useful for state machines, options, and types. Each enum value can carry data via properties. Property attributes control access: SetAccess=private makes read-only from outside; Constant for compile-time constants; Hidden hides from display; Access={?Class1, ?Class2} restricts to specific classes.
% enumeration class
classdef Color
enumeration
Red [1 0 0]
Green [0 1 0]
Blue [0 0 1]
end
properties
rgb
end
methods
function obj = Color(rgb)
obj.rgb = rgb;
end
end
end
c = Color.Red;
disp(c.rgb) % [1 0 0]
% switch on enum
switch c
case Color.Red; disp('red');
case Color.Green; disp('green');
end
% property attributes
classdef Account
properties (SetAccess = private)
balance = 0 % readable outside, settable only inside
end
properties (Access = {?Account, ?Bank})
internal_id % only Account and Bank classes
end
properties (Constant)
PI = 3.14159 % compile-time constant
end
properties (Hidden)
cache % not shown by disp/struct
end
endRelated MATLAB snippets
Copy-paste ready code for common tasks.
Matrix Creation and Operations
Create and operate on matrices in MATLAB.
2D Plotting
Create line plots with labels, legends, and styling.
Functions and Scripts
Define functions in separate files or at end of scripts.
Cell Arrays and Structs
Heterogeneous data containers in MATLAB.
File I/O
Read and write .mat, .csv, and text files.
ODE Solvers
Solve ordinary differential equations with ode45.
Signal Processing (FFT)
Compute and visualize the FFT of a signal.
Struct Arrays and Tables
Work with struct arrays and modern table data type.
Was this helpful?