%% Welcome to MATLAB! %%
%% ================== %%
% 
% This is a brief introduction to MATLAB. We will be around to help you
% with any questions you may have. If you are familiar with programming you
% will still want to skim this document for how MATLAB is different than
% what you already know.
% 
% First we will start with some MATLAB features. MATLAB is not just a
% programming language but an entire development environment. In the main
% MATLAB window you have many seperate parts. In the middle there is a
% large "Command Window" which is where you can type single commands and
% see outputs from commands. On the left there is the "Current Folder" view
% which shows all files in the current folder (which is shown above it). On
% the right you have the "Workspace" view which shows the currently defined
% variables and "Command History" which shows all of the commands you have
% typed in the Command Window.
% 
% This document probably opened in a seperate window called "Editor".
% MATLAB scripts can be split into "cells" or "sections" which are marked
% by "%%" at the beginning of the line. This allows you to break up an
% entire file into smaller parts that can easily be run separately.
% 
% When cells/sections are run they start with the current workspace
% variables and can change them. As you go through this tutorial you should
% try to modify the contents of each cell to explore the features of MATLAB
% - making sure you understand every line. You can run the same cell over
% and over again or you can add new cells by adding new lines with "%%".
% 
% *Note*: Python is similar to MATLAB. If you are used to Python I
% recommend checking out http://www.scipy.org/NumPy_for_Matlab_Users which
% will tell you all of the important differences. Biggest thing to remember
% is that arrays / matrices are 1-based, not 0-based.
% 
% *Note 2*: If you wish to setup MATLAB on your own computer, please talk
% to us.

%% Basics %%
%% ------ %%
% First, any text after a `%` symbol is a comment and is ignored by MATLAB.
% You should be in the practice of commenting your code thoroughly so that
% someone else will know what it is doing and so you will know in a couple
% months when you go back and look at it (you think you'll remember but you
% won't).
% 
% In the Editor there are shortcut keys for executing cells:
% 
% * `Ctrl +Shift + Enter` to run the current cell and move to the next one
% * `Ctrl + Enter` to run the current cell in-place
% 
% You can use the toolbar and menus at the top to do this and much more.

%% Simple math is pretty straight forward:
% Note: disp() is a function that display to the Command Window what it was given
% Any line that does not end with ; will also display in the Command Window
disp(2 + 2);        % displays 4
disp((50-5.*6)./4); % displays 5
disp(3.^3);         % displays 27 (3 to the third power)
disp(7./2);         % displays 3.5
disp(abs(-5));      % displays 5
disp(round(5.53));  % displays 6
roundn(5.53, -1)    % displays 5.5 (since we don't have a ; at the end)
% NOTE: the '.' before '*', '/', and '^'. This is critical and if you
% forget it you will run into many problems.

%% At any time if you want to know what a function does you can type
% `help` before the function name. This is best done in the command window.

help round

% You will also notice that while typing you pause after `round(` it will
% give some minimual help information. Try it!

% Also, MATLAB will 'autocomplete' things for you when you press tab.
% Typing `rou` and pressing tab will give you a list of options. This can
% save you from typing long names! Try it below.

%% You can create variables to hold values:

x = 2 + 2;   % assigns 4 to the variable x
y = x .* 3;  % assigns 12 to the variable y
y ./ 2       % displays 6

% Now look at the "Workspace" window and you will see `x` and `y`.


%% Vectors %%
%% ------- %%
% Vectors and matrices are many values rolled into one that have a specific
% order. In fact, in MATLAB most variables are actually matrices - single
% numbers (called 'scalars') are just 1-by-1 matrices. Vectors usually
% refer to 1-by-n or n-by-1 matrices. We will get to matrices soon enough,
% for now lets work on vectors.

row_vec = [5, 0, 2, 6]; % a 1-by-4 vector - a 'row' vector - columns are separated by ,
col_vec = [1; 2; 3; 4]; % a 4-by-1 vector - a 'column' vector - rows are separated by ;

disp(length(row_vec));  % displays 4, the length of the matrix (the longest dimension)
disp(min(row_vec));     % displays 0, the minimum of the vector
disp(max(col_vec));     % displays 4, the maximum of the vector

%% MATLAB vectors are one-based (unlike Python which is zero-based). This
% means that the first item in a list has the index `1`.
% You can retrieve and modify items by index:
x = row_vec(1);       % x is 5, the first element of row_vec
row_vec(2) = 99;      % the second element of row_vec is now 99
% now look at the Workspace to see what values things have

%% To add elements to a vector create a new vector containing the old one:
col_vec = [col_vec; 200] % col_vec is now [1; 2; 3; 4; 200]

% Make sure that if the original was a column vector to use a ; and if the
% original was a row vector to use ,

% Note: this method of adding values to a vector or matrix is very slow.
% Later we will learn methods to pre-initialize variables and replace
% values as needed (only important when dealing with MANY entries).

%% You can convert a row vector into a row vector and vice-a-versa by
% transposing the matrix
now_a_row_vec = col_vec';

%% Vectors support 'slices' which are portions of a vector
row_vec(2:3) % The second through third values in the list
% Note: the range includes the first number and goes through the second
% number (range is inclusive).

%% You can also use the word 'end' in slices meaning the last element:
disp(row_vec(2:end));  % from the second element to the end

%% You can do math with "end" as well:
disp(row_vec(end-1));     % the second to last element
disp(row_vec(2:end-1));   % from the second to the second to last element
disp(row_vec(end-1:end)); % from the second to last element to the end (last 2 elements)


%%  And even more advanced with a third value which is the "increment":
disp(row_vec(1:2:end)); % every other element

%% Slices can be be replaced:
row_vec(1:2) = [1, 2]; 


%% Strings %%
%% ------- %%
% A string is a piece of text enclosed in single quotes:
disp('Hello World');
str = 'It is a beautiful day';

%% In MATLAB strings are simply row vectors of characters instead of
% numbers which means you can concatenate strings to each other:
str = ['How ', 'are you?'];

%% You can convert numbers to a string:
num2str(2+2) % Try: num2str(x) using the value of x

%% You can even concatenate numbers to a string by first converting:
str = ['2 + 2 equals: ', num2str(2+2)];

% For more complicated situations you likely want to use the printf
% function, to find out more type "help printf" or "doc printf".


%% Cell Arrays %%
%% ----------- %%
% Cell arrays are like vectors/matrices except that each element (cell) is
% indepedent of the other values. In vectors/matrices, if one row has 10
% columns, all rows must have 10 columns. This is useful for storing data
% that has a variable length or collections of strings (which are rarely
% the same length). Cell arrays created like vectors, except they use curly
% braces.
cellarr = {'Hi', 'There', 1, 2};

% Just like vectors, they can have rows/columns depending on if you use
% comma or semicolons between items.

%% Access to items in a cell array is slightly different. Using () like for
% vectors gives back a cell-array but using {} (curly) gives the unerlying
% elements.
smaller_cell_array = cellarr(1:2);
number = cellarr{3};
[hi, there] = cellarr{1:2}; % curly braces and ranges gives back multiple values


%% Booleans %%
%% -------- %%
% Booleans/logicals are values that are treated as either `true` or
% `false`. They are typically used in conditional tests (which we will get
% to in the next section). MATLAB treats 0 and empty vectors [] as false
% and basically everything else as true (usually 1). MATLAB also supports
% the words `true` and `false` (but these are just the values 1 and 0).
% 
% __Try__: add `disp()` functions or remove ; to see the outputs below,
% currently nothing below is output.

% The basic boolean operations are not ~, and &&, and or ||:
t = true;
f = ~t;      % false (not switches True to False and False to True)
b = t && t;  % true  (and is True only if both are True)
b = t && f;  % false (and is False if either is False)
b = f && f;  % false
b = t || t;  % true  (or is True if either is True)
b = t || f;  % true
b = f || f;  % false

%% You can also make booleans by comparisons:
x = 5;
b = x >  4; % true (greater than)
b = x >= 4; % true (greater than or equal to)
b = x <  4; % false (less than)
b = x <= 4; % false (less than or equal to)
b = x == 4; % false (equals)
b = x ~= 4; % true (not equals)


%% Conditionals (`if` statements) %%
%% ------------------------------ %%
% We are finally getting to the interesting stuff. If statements let you
% run a chunk of code if and only if something is `true`. First lets set
% some variables to known values:
x = 5;
y = 10;

%% Then, lets check if x is positive:
if x > 0
  disp('x is positive');
end
    
% This will only print "x is positive" if x is positive.
% __Try__ changing the value of x and re-running that cell.
% 
% Your value of x could come from many places, maybe a file, maybe from
% the user, maybe from some really complicated calculations.
 
%% You can also compare two variables to each other:
if x > y
    disp('x is greater than y');
else
    disp('x is less than or equal to y');
end

% We added an `else` there which runs in case the `if` statement was
% `false`.

%% You can chain multiple `if`s together using `elseif`.
if x > 0
    disp('x is positive');
elseif x < 0
    disp('x is negative');
else % at this point x cannot be positive or negative
    disp('x is 0');
end


%% `while` Loops %%
%% ------------- %%
% So now that we have conditional statements down, lets add on loops. The
% simplest loop is a while loop. Below is an example. Do you recongnize the
% pattern of numbers? The while loop will repeatedly run the code inside it
% until its conditional statement is `false`.

x = [0,1];
while x(2) < 20
    disp(x(2));
    x = [x(2), x(1)+x(2)];
end
    
% __TODO__: What happends when you change the conditional to `x(2) < 2000`?


%% `for` Loops %%
%% ----------- %%
% The truth is that you probably won't use while loops too much because
% their big brother the "for loop" is much more convient.

a = [3, 1, 4, 1, 5, 9];
for x = a % x is given each value in a in turn
    disp(x);
end

%% If you need to cover a range of values, then you use the ranges:
for index = 1:length(a) % Goes from index = 1 to length(a) (1 through 6 in this case)
    disp([index, a(index)]);
end

%% Ranges can also be used outside of for loops (we actually already saw
% them with "slices"). They create a row vector of numbers based on what
% you give it. Has a start and end, and possibly an "increment".
disp(1:5);
disp(5:10);
disp(0:3:10);
disp(-10:-30:-100);


%% Functions %%
%% --------- %%
% If you find yourself writing the same lines of code over and over, or if
% you just need to organize your code (always a good thing), you can create
% functions. Functions are mini-programs that take a set of inputs and give
% a set of outputs. In MATLAB functions are a little tricky. Except for
% "one-line" functions they have to be in documents by themselves and the
% file has to be called the name of the function.
%
% Create a new file (look in the top-left), save it as "minimum.m", and
% copy the following code in it (without the % at the start of each line):
% 
% Note: you can also do `edit minimum` in the Command Window (without `) to
% create a new file called minimum.m
%
%function [out] = minimum(a, b)
%if a < b
%    out = a
%else
%    out = b
%end
%
% This function, called "minimum", takes two inputs: 'a' and 'b' and
% outputs the minimum of those two. Note that variables inside functions
% (like out, a, and b in this case) are not available outside that
% function).
%% Once you create the function, you can use it like so:

minimum(5, 10)

% Note: for MATLAB to find custom functions, they must be in your current
% folder (show up in the "Current Folder" window) or be on your MATLAB
% "path". In the main window on the "Home" tab there is a "Set Path" button
% to add extra folders to your MATLAB path.

%% You can also output more than one value. The function below gives both
% the minumum and maximum value. Put it in a new document with the correct
% filename.

%function [mn,mx] = min_max(a, b)
%if a < b
%    mn = a;
%    mx = b;
%    return; % stops the function if reached
%end
%mn = b;
%mx = a;

%% Then run:
[the_min,the_max] = min_max(10, 5);

% Note: this was just a simple example and for minimum and maximum you
% would use the built-in `min()` and `max()` functions.

%% One-line functions can be made without creating a new document. For
% example, if you frequently calculate the area of cirlces a lot, you can
% make a small function for it:
circle_area = @(r) pi.*r.*r; % "r" is the input, "pi.*r.*r" is the output

% And use it like:
one_area = circle_area(5); % radius (r) of 5, get the circle area
many_areas = circle_area([4,5,6,7]); % calculte the areas of many circles (doesn't work for some functions)


%% Errors %%
%% ------ %%
% It is invetible that you will run into errors in your code so you need to
% understand the common errors, what they mean, and how to work on fixing
% them. When an error occurs you will hear a "ding" (if your speakers are
% on) and a red message will show up in the Command Window.
% 
%% Probably the most common error is are 'syntax errors'. These mean you
% tried to run code that doesn't follow the rules of the MATLAB language.
% Some common ones are:

x = [5, 6, 7  % needs to end with ]
x = [5, 6, 7) % ) should be ]
x = 1::2      % extra : with no value between
x = 1+3+      % trailing + sign
x = "hello"   % should be 's not "s
if x = 3      % should be == to compare values not = (which assigns values)
end

% For syntax errors the `|` above the error message indicates where the
% problem is.
% 
% Sometimes a syntax error on a previous line causes MATLAB to complain on
% a future line so make sure to check the line before if you can't find a
% problem with the given line.


%% "Undefined" errors result when you try to use a variable or function
% that does not exist or cannot be find. Examples:

x = var_that_does_not_exist;
not_a_function();

%% Some basic math operations also produce errors when the matrices they
% are working on are not "compatible". For the most part this means they
% are not the same size.

x = (1:3) - (1:4); % "Matrix dimensions must agree"
x = (1:3) * (1:3); % "Inner matrix dimensions must agree" - should be using .* not *
x = (1:3) ^ 2;     % should be .^ not ^

%% When indexing matrices you can get "index" errors means you tried to get
% an element outside the matrix or it didn't make sense.

x = 1:10; 
y = x(100); % "Index exceeds matrix dimensions"
y = x(0);   % "Subscript indices must either be real positive integers or logicals." - must be 1 or more!
y = x(0.5); % Doesn't make sense, must be integral value
x(1:2) = 1:3; % "Subscripted assignment dimension mismatch." - left and right sides must be the same matrix size

%% There are other errors that will come up, but hopefully they are
% self-explanatory or ask us for help.


%% *********************************** %%
%% Exercise: Fibonacci Series Function %%
%% ----------------------------------- %%
% 
% To see that you understand the basics, write a function called "fib" that
% computes the Fibonacci series up to a given value. It should store every
% value in a vector and return that vector (__ not displaying anything
% directly __).
% 
% Tip: the example `while` loops printed the Fibonacci series, so you have
% the algorithm. However it displays results, you want to store results.

%%
disp(fib(20))   % should output 1 1 2 3 5 8 13
disp(fib(2000)) % should output 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987 1597


%% ********** %%
%% Scientific %%
%% ========== %%
% Now we get to the really interesting stuff. So far we have just covered
% basic programming. Now we will get to the scientific parts.


%% Vectors (again) %%
%% --------------- %%
% We only did the basics with vectors before. Let's do some more advanced
% stuff now.
v1 = [1, 2, 3, 4];
v2 = [4, 3, 2, 1];
v3 = v1 + v2;  % add element-wise (so we get a new row vector with 1+4, 2+3, ...)
disp(v3);      % prints [5, 5, 5, 5]
v4 = v1 .* v2; % multiply element-wise (so we get a new row vector with 1*4, 2*3, ...)
v5 = sin(v1);  % computes sin for each element
v6 = log(v2);  % computes natrual log for each element
v7 = exp(v6);  % computes e^(x) for each x in the array
v8 = 10.^v1;   % computes 10^(x) for each x in the array
% Remeber: multiply, divide, and power must be used with .*, ./, and .^

% There are many more available functions, commonly used ones are:
%   sum mean std cumsum min max sort hist round sign unique

%% More ways to make a 1-D array:
r = 0:0.1:50;        % from 0 to 50, in steps of .1
l = linspace(0, 50, 1000); % 1000 element vector from 0 to 50 (inclusive)
z = zeros(50,1);       % a column vector of 50 zeros
o = ones(1,50);        % a row vector of 50 ones
p1 = pi*ones(50,1);    % a column vector of 50 pis
p2 = repmat(pi, 1,50); % a row vector of 50 pis (repmat = repeat matrix)

% It is recommended to pre-allocate your vectors/matrices using functions
% like zeros and filling in data instead of creating an empty one (0-by-0)
% and adding elements. For cell arrays you can pr-eallocate using cell().


%% Matrices %%
%% -------- %%
% So far we have been dealing with 'vectors' (where one dimension was
% length 1). But really in MATLAB everything is a matrix (it is what the
% MAT in MATLAB stands for). For the most part everything works similarly
% on vectors and matrices.

m1 = [1, 2, 3, 4; % 3 rows (seperated by ;) and 4 columns (seperated by ,)
      4, 3, 2, 1;
      v3         ]; % the last row is defined using a row vector from before
m2 = zeros(4, 5); % 4 rows and 5 columns of zeros
m3 = zeros(size(m1)); % zeros same size as m1

%% Get the shape
disp(size(m2)); % displays (4, 5) - all dimensions in MATLAB do rows then columns
[nrows,ncols] = size(m1); % get the size in two variables
disp(nrows); % outputs 4, the number of rows

%% To access elements in a matrix:
m2(4,1) = 5;   % Changes fourth row and first column to 5
disp(m1(2,:)); % displays the entire second row (same as m1(2))
disp(m1(:,3)); % displays the entire third column
% The other slice operations work as well:
m1(2:3,2:3)    % outputs: 3 2 % second row, second and third columns
               %          5 5 % third row, second and third columns

%% A matrix can be 'flattened' into a column vector by using just (:)
disp(m1(:));   % goes down columns first, then across rows
% A generalized form of this is the reshape function

%% Matrices support all the vectors operations, however functions
% "sumarize" data like sum, min, max, mean, ..., will by default operate on
% each column - not the whole matrix! Usually this is solved by using the
% (:) trick above.

disp(min(m1));      % displays 1 2 2 1 because those are the minimum of each column
disp(min(min(m1))); % displays 1 because it takes the minimum of the minimum of each column
disp(min(m1(:)));   % displays 1 because it makes the matrix a single column first

%% You can also transpose matrices. This switches rows for columns.
t = m2';    % switch rows and columns in the array / matrix
t = v1';    % turns a row vector into a column vector


%% Finding %%
%% ------- %%
% Matrices/vectors can easily be searched. You can use the comparison
% operators we learned before to get a matrix of `true` / `false` values
% for each element like so:
a = [-1, 0, 5, -5, 7];
b = [-2, 4, -1, 0, 8];
disp(a > 0); % displays [0 0 1 0 1]
disp(b > a); % displays [0 1 0 1 1]


%% Check if any or all are `true`:
disp(['Are any negative? ', num2str(any(a < 0))]);
disp(['Are all negative? ', num2str(all(a < 0))]);


%% If you need the indices, you can use the `find()` function:
find(a >= 0)

%% To get the values you can use the comparison or the result of `find()` as an index:
a(a >= 0) % equivilent to a(find(a >= 0))

%% Note that && (and) and || (or) from before operate on the matrix as a
% whole and not element-wise. However & and | work element-wise.
a(a >= 0 & a <= 5) % using && here produces and error

%% Using these techniques we can find spike times in voltage data (at the
% moment we don't have any data, so this won't work, so just make a note
% of it):

threshold = 0; % the spike threshold
time = [];     % when we sampled voltage
voltage = [];  % what the voltage was
% find all time points when previous voltage was below threshold and next voltage was above threshold
spikes = time((voltage(1:end-1) < threshold) & (voltage(2:end) >= threshold));


%% Files %%
%% ----- %%
% You will need to be able to get your data into MATLAB to make use of it.
% Matrices can easily be read from and saved to files.

m = rand(100, 100); % big set of random data

%% Save array:
save('test.mat', 'm'); % save matrix 'm' in MATLAB-specific format
save('test.txt', 'm', '-ascii', '-tabs'); % text format (easiest to read as text)
csvwrite('test.csv', m); % comma-seperated values format (easily usable by Excel)

%% Load matrices from file
load('test.mat'); % causes variables to be loaded as they were named before
data = load('test.mat'); % loads the file
m3 = data.m; % gets the variable named 'm' from the file

% From text files
m3 = load('test.txt');
m3 = csvread('test.csv'); % can also use load



%% Plotting %%
%% -------- %%
% You can also make plots with MATLAB.
%% First we create data for a sin wave, just to have something to show
x = linspace(-2*pi, 2*pi, 5000); % create a list of numbers
y = sin(x);                      % calculate the sin for each point

%% Now plot it
figure()           % creates a new figure to plot in
plot(x, y)         % plot y vs x
title('sin curve') % add a title
xlabel('X')        % add an x label
ylabel('sin(x)')   % add a y label

%% There are an incredible number of options for plotting your data just
% the way you want, and you can have multiple plots at the same time.
y2 = cos(x);       % calculate the cos for each point
figure() % label='$\\cos(x)$'label='$\\sin(x)$'
hold on  % lets us plot more than one thing
plot(x, y,  'r-.') % red dash-dot line
plot(x, y2, 'g--') % green dashes line
title('sine and cosine curves')
xlabel('X values')
ylabel('Y values')
legend('sin(x)', ... % label for the first thing plotted  (the ... means continue line of code onto next line)
       'cos(x)', ... % label for the second thing plotted
       'Location', 'NorthEast') % the location of the legend

%% There are also 2D plots
%% Generate some 'interesting' data (just ignore this part)
x = -3.0:0.025:3.0;
y = -2.0:0.025:2.0;
[X,Y] = meshgrid(x, y);
Z1 = reshape(mvnpdf([X(:),Y(:)],[0.0,0.0],[1.0,1.0]),length(y),length(x));
Z2 = reshape(mvnpdf([X(:),Y(:)],[1.0,1.0],[1.5,0.5]),length(y),length(x));
Z = 10.0 * (Z2 - Z1);

%% Contour plot
figure()
title('Contour Plot')
contour(X, Y, Z)
colorbar() % adds a color bar to the image

%% Image plot
figure()
title('Image Plot')
imagesc(Z)
set(gca, 'YDir', 'normal') % makes the +Y axis up (imagesc flips this)
colorbar()

%% Other options to make your plots perfect:
%    axis([XMIN XMAX YMIN YMAX]); % change the X and Y axes scaling
%    caxis([MINVALUE MAXVALUE]);  % change the color scaling
%    colormap('hot'); % change the colormap, see `doc colormap` for choices
%    subplot(2,1,1);  % breaks the figure into multiple plots

%% Other plot types that may be useful:
%  * line plot:    `errorbar`
%  * box plots:    `bar`, `barh`, `hist`, `boxplot`
%  * vector field: `quiver`, `feather`
%  * 2D plots:     `contourf`
%  * spectral:     `spectrogram`, `pwelch`, `cpsd`
%  * other:        `polar`, `scatter`, `xcorr`


%% 3D Plotting %%
%% ----------- %%
% MATLAB has 3D plotting built-in

% Generate some interesting data
n_mer = 6;
n_long = 11;
phi = 0.0:pi./1000.0:2.*pi+0.0005.*pi;
mu = phi.*n_mer;
x = cos(mu).*(1+cos(n_long.*mu./n_mer)*0.5);
y = sin(mu).*(1+cos(n_long.*mu./n_mer)*0.5);
z = sin(n_long.*mu./n_mer).*0.5;

% Plot the 3D Data
figure()
plot3(x, y, z)

% There are other 3D plot types as well, like meshes.


%% Solving Diff Eqs %%
%% ---------------- %%
% MATLAB has an ordinary differential equation solver that we will use for many
% problems in this class.

% We will integrate this system of differential equations:
%   du/dt = v
%   dv/dt = -u
% 
step = @(t,X) [ X(2); -X(1) ];

% Integrate the function named 'step' and going from time 0 to 10 starting from the
% initial conditions u=0.0 and v=1.0
[t,X] = ode45(step, [0, 10], [0.0, 1.0])

u = X(:, 1) % Column one is u values for all times in t
v = X(:, 2) % Column two is v values for all times in t

% Plot the u values as a function of time
figure()
plot(t, u)
title('du/dt = v, dv/dt = -u')
legend('u', 'Location', 'NorthEast')


%% ********* %%
%% Exercises %%
%% --------- %%
% Run the above code for solving a simple ODE and look at the graph and
% understand what is going on. Then change the function to compute the
% following system of equations:
%   du/dt = v-0.1u
%   dv/dt = -u-0.1v
% Also, plot both u and v over time in the same graph instead of just u.

% Now that you have the hang of solving differential equations, recreate the
% Lorenz Attractor (look it up on Wikipedia). Plot the result using a 3D plot.
