% You can create defaults if no inputs are created
if ~exist('validRange','var') && isempty(validRange)
=0:1
validRangeend
%Sometimes its nice to have variables available outside a function without it being assigned an output
%This is good for me where I have a function that spontaneously crashes before data is saved
%I can send data from function workspace to 'base'/default workspace before I reach that line
%I can then cleanup the data and save it manually
%assignin -> send variable from one workspace to another
assignin('base','A_base',A_fcn)
%Remember how 'plot' has options that can be assigned by a field?
%You can do this same thing with input parsing
varargin) %Varargin is an input variable that allows for an ambiguous number of inputs
functionA(= inputParser('variableA',variableA); %Essentially just reads through all inputs and organizes them
p 'variableA','D',@ischar); %Checks to make sure that variable is is of char type, assigns default 'D' if not present
p.addParameter(=p.Results.variableA; %Optional, but easier to use 'variableA' in this format variableA
Lets build a simple experiment
First lets build a function to act as a template that can run different types of experiments
function R = questionaire(Q,validRange)
%A questionaire that accepts responses in numbers
% Q - Questions to ask
% validRange - range of numbers that are acceptable
% R - Responses
assert(iscell(Q),'Questions are not in cell format.')
=zeros(size(Q));
Rfor i = 1:length(Q)
clc %clear screen with every new question
while true
try
%PROMPT FOR INPUT
=input([Q{i} ': '],'s');
rspi)=str2double(rsp);
R(
%CHECK IF RESPONSE IS WITHIN RANGE
fail=~ismember(R(i),validRange);
catch
fail=1;
end
if fail
clc
disp('Invalid response. Try again.')
else
break
end
end
end
clc
disp('Questionaire Complete. Thank you!')
octave
Now lets build a function to run a specific experiment using the general function
function [] = ADDquestionaire(subj);
if ~exist('subj','var') || isempty(subj)
error('Requires subject initials.');
end
=txt2lines('addquestions.txt');
Q=1:9;
validRangeclc
input(['Welcome.' ...
'Please rate your response with the following questions with numbers ' num2str(validRange(1)) ' to ' num2str(validRange(end)) '.' ...
newline 'Press return to start questionaire: '],'s');
newline =questionaire(Q,validRange);
R='ADDquestionaireResponses';
dnamemkdir(dname);
=[ dname filesep subj '_addQs'];
fnamesave(fname,'R','subj')
%You can run this on your own, but you can generate similar data by running 'makeData'
%Lets build some scripts to analyze this data
%ANALYSIS SCRIPT
try
='ADDquestionaireResponses';
dnamecd(dname);
=dir; %dir returns all contents of a directory
files={files.name}; %the following process removes any files that don't end with .mat
files=contains(files,'mat');
ind=files(ind);
files=zeros(length(files),1);
scores=cell(length(files),1);
Subjs
%PROCESS BY SUBJECT
=[]; %ALL IS A GOOD
Allfor i = 1:length(files)
load(files{i});
i}=subj;
Subjs{=R;
S.(subj).Ri)=sum(num2str(R));
scores(=scores;
S.(subj).score=i;
S.(subj).num=[All; R];
Allend
%Z-SCORES
=zscore(scores);
zscoresfor i = 1:length(Subjs)
i}).zscore=zscores(i);
S.(Subjs{end
figure(1)
plot(zscores)
title('ADD questionare Z-scores')
xlabel('Subject number')
ylabel('Z-Score')
%Correlation
=randn(length(Subjs),1);
n=corr(scores,n);
rho
figure(2)
plot(scores,n,'k.')
title(['rho = ' num2str(rho)])
catch ME
cd ..
rethrow(ME)
end
cd ..
Try using the variable 'All' in your bootstrap function
REPLACE LOOPS WITH FUNS
There are a group of functions that can replace loops and will run faster
They are often less intuitive
ARRAYFUN
arrayfun(function,input1,input2,…,Options)
Apply a function to each element
=1:10
A=arrayfun(@testfun,A) X
EXAMPLE
If I needed to get subscripts of each pixel of a patch 7x7 patch in a 1920x1080 image and all I have is patch centers
SETUP
=[100,200];
s=zeros(s);
A=randi(s(1),50,1); %example subscripts
N=randi(s(2),50,1); %example subscripts
M=@(x,y) x < 1 | y < 1 | x > s(2) | y > s(1);
indfun
=sub2ind(size(A),N(:),M(:));
ind=A;
B=1;
B(indo)
imagesc(B)
Arrayfun is often easier to figure out than a loop
NON LOOP
=@(x,y) meshgrid(x-3:x+3, y-3:y+3);
fun,Y]=arrayfun(fun,M,N,'UniformOutput',false);
[X=[X{:}];
X=[Y{:}];
Y
%Remove values otuside of range
=indfun(X,Y);
ind=[];
X(ind)=[];
Y(ind)
%Convert subs 2 ind
=sub2ind(size(A),Y(:),X(:));
ind
%VISUALIZE
=A;
D=1;
D(ind)imagesc(D);
LOOP
=zeros(length(N),7^2)
X=zeros(length(N),7^2)
Yfor i = 1:length(N)
=N(i)-3:N(i)+3;
Nall=M(i)-3:M(i)+3;
Mall,y]=meshgrid(Mall,Nall);
[xi,:)=x(:);
X(i,:)=y(:);
Y(end
%Remove values otuside of range
=indfun(X,Y)
ind=[];
X(ind)=[];
Y(ind)
%Convert subs 2 ind
=sub2ind(size(A),Y(:),X(:));
indl=A;
C=1;
C(indl)
%VISUALIZE
imagesc(C)
Uniform Output
By default these functions assume that your outputs are matrices. This option assigns to cells instead, allowing for inconsistent dimensions.
The 'UniformOutput' is usually necessary if output is not same size as input
Cells are a pain to deal with
WORKING WITH GROUPS OF STRINGS
1}='This is a string';
data{2}='This is also a string';
data{3}='A third string';
data{=@(x) strsplit(x);
funcellfun(fun,data,'UniformOutput',false);
BSXFUN
Array fun but with explicit expansion
Row wise/column wise operations
Looks for matching sizes
GENERATE DATA
different populations down rows
Samples across columns
=zeros(100,20);
Xfor i = 1:length(X)
=rand(1);
m=rand(1)*3;
si,:)=normrnd(m,s,1,20);
X(end
Zscore
=bsxfun(@minus, X,mean(X,2))
msize(m)
=bsxfun(@rdivide, m,std(X,[],2)) Z
CHECK
mean(Z,2)
std(Z,[],2)
%solve system of linear equations
syms x y z= 2*x + y + z == 2;
eqn1 = -x + y - z == 3;
eqn2 = x + 2*y + 3*z == -10;
eqn3 = solve([eqn1, eqn2, eqn3], [x, y, z]); sol
GET KEY DEFS
while true
waitforbuttonpress
= double(get(gcf,'CurrentCharacter'));
k disp(num2str(k))
drawnow
end
GET KEY DEFS
=rand(100,100,100);
A
=28; %LEFT
keys.L=29; %RIGHT
keys.Ri=1;
while true
imagesc(A(:,:,i))
title(num2str(i))
waitforbuttonpress
= double(get(gcf,'CurrentCharacter'));
k switch k
case keys.L
i=i-1;
case keys.R
i=i+1;
end
if i < 1
i=1;
elseif i > size(A,3)
break
end
end
Objects
Object-oriented programming is a newer way of programming that has potential to make things more organized and
objects - variables created from a class
classes - a template for objects -> call on classes to make objects
properties - variables nested within a class (like fields in structs)
modules - subroutines/functions of a class, usually meant to do something to the object its being called from
Matlab has objects, but is only partially object oriented
for example:
varA="this is a string"
python:
="this is a string"
varA=varA.split()
out#out=["this", "is", "a, "string"]
='some string';
varA=strsplit(varA)
out%out=["this", "is", "a, "string"]
General form for
classdef exampleClassName
properties
var1=1
var2
var3end
methods
function obj = exampleClassName(obj,var1)
%Contructors are methods that create objects
=var1
obj.var1end
function obj = method2(obj,val)
%Contructors are methods that create objects
=3
obj.var3end
end
%To create an object from this class
=exampleClassName(60)
obj
obj.var1
obj.var2
obj.var3
%To call one of its methods
=object1.method2
obj obj.var3
classdef experiment < handle
properties
name
authortype
subjectsend
methods
function obj=expermient(name)
;
obj.name()end
function obj=change_properties(obj,author,type,nblocks)
=author;
obj.author=type;
obj.type=nblocks
obj.nblocks;
obj.save()end
function obj=add_subject2exp(obj,subjName)
end+1}=subjName;
obj.subjName{;
obj.save()end
function subj=get_subject(obj,subjName)
=subject('subjName')
subj;
subj.load()end
function obj=run_subj(obj,subjName)
if ~isfield(obj.subjects,'subjName')
obj.add_subject2exp(subjName)end
=get_subject(subjName);
subj=subj.get_next_block();
block=obj.run(); %notice not in this class
data=data
subj.data.(obj.name).block;
subj.save();
subj.update_completion()end
function obj=save(obj)
save(obj.name,'obj')
end
function obj=load(obj)
load(obj.name)
end
function obj=run(obj)
%SOME EXPERIMENT CODE HERE
end
end
end
function experment1 < handle & experiment
methods
function obj=run(obj)
%SOME EXPERIMENT CODE HERE
end
end
end
classdef subject < handle
properties
age
name
sex
status%blocks
experiments
dataend
methods
function obj=subject(obj)
end
function obj=get_next_exp(obj)
end
function obj=get_next_block(obj,expName)
end
function obj=change_status
end
function obj=change_status_to_train
end
function obj=change_status_to_run
end
function obj=update_completion
end
function obj=load(obj)
obj.check()load(obj.name)
end
function obj=check()
end
function obj=save()
save(obj.name,'obj')
end
function obj=show_completed()
end
end
special objects for figures
gcr
gcf
gca
all graphics functions use get & set implicitly
%Making advanced changes to properties of figure
=figure(1)
f%whether you assign to a variable, your figure is an object with properties
%you can change these through f, or if you havn't assigned a variable, you can use gcf
=gcf %get current figure
fig
%To make some advanced changes to your axes, you need to adjust the properties of your axes object
axes=gca %get current axes
%Not all properties are listed. See "Figure Properties" in online documentation
parfor is a for loop, but will run each iteration on its own processor core
rules:
Only 1 parfor at a time
parfor; parfor; end; end
independent (variables must not depend on previous interation)
parfor t=1:10; x=(t-1); end
increasing, positive, & integer, iterator
no breaks
%You can have code that doesn't error-out if something goes wrong
try
%Run Something that may break
catch ME; %ME is struct that contains the error message
%do something, like save data
rethrow(ME); %rethrows error
end
try
%Warning %Disp with 'Warning:' attached to the beginning & can trigger debugging tools (next section)
%Error - create your own errors!
%assert -> throw error if condition is not met - like an if statement and 'error' combined
=nan;
a=1;
btry
:,:,i)=imresize(A,[a,b])
z(catch
:,:,i)=zeros(a,b);
z(end
%You can tell matlab to run a system command line function
='matlab'
program=['ps aux | grep ' program] %You can pass matlab variables to it;
command,out]=system(command)
[status%On linux/mac, status will return
% 1 if error
% 0 if successful
%If using logical indexing, always use & and |
%When using if statements, && and || are prefferable
% && and || do what is called 'short-circuiting'
if exist('variableA','var') && exist(variableA)
%if statement 1 fails, it will short-circuit, meaning that it won't test statement2
if exist('variableA','var') & exist(variableA)
%if statement 1 fails, it will test statement2 in this case, and error-out
#! commands
path %list path
=genpath('/home') %returns all directiories within /home
gaddpath(g) %add all directiroies within home to path
Startup
There is a file called startup.m located in (Your matlab install directory)/toolbox/local/
This file will run everytime you start matlab