%% Lab 1 - September 2nd 2022 - Matlab Basics
%
%% Review of Matlab Basics
% In matlab live you can write text, LaTex equations such as \pi^2\left(\sqrt{\sigma \phi}\right) and also create code in-line.

%In code sections you use the '%' sign to make a comment at the start of
%the line or after a piece of code

% Section breaks can be added in text using the 'Section Break' button or in code using a double percent sign '%%'.
% When you run your script you can use the 'Run' button to run the entire script from top to bottom, or you can run individual sections. A section will run from top to bottom and stop before the next section starts.
%% Basic operations:
% Addition: +, subtraction: -, multiplication: *, division: /, exponent: ^
% NOTE: Matlab will always follow PEMDAS so be sure to use parentheses

%Example:
5+2^2 * 8/10-3 % ans = 5.2
(5+2)^2 * 8/(10-3) % ans = 56

% Conditionals: >, <, >=, <=, ==, ~= (returns true/false output called a logical)

5 > 4 % ans = 1 aka true
6 == 7 % ans = 0 aka false

% Following a line of code with a semicolon supresses the output to this will print:

10e5 / 2

% while this will not:

7*4;

%%
%% Basic math functions:
% For any function in matlab if you type 'help' into the command window followed by the funtion name it pulls up the documentation in the command window. Also Mathworks website has lots of information on each function with example code.

sqrt(15), abs(-56), exp(7), log(5) 
mean([7 9 3]), std([7 9 3]), var([7 9 3])
sum([7 9 3]), sin(pi), length([7 9 3]),rem(20,7)

%%
%% Other useful things
% Pi shorthand:

pi

% Clearing:

 clc, clear all, close all

% Rounding:

 round(pi,4), ceil(pi), floor(pi)

% Random number seed:

 rng(0) %sets your random generator seed to zero
 rng

%
%% Variables
% Variables are used to store information (in the form of a number, or multiple numbers such as vectors or matrices) to be referenced and manipulated by the computer
% Using a decriptive name is so that humans can read your code, the computer does not care what your variable name is. (However variable names cannot start with a number).
% To create a variable write the name you have chosen to the left of an '=' sign and the components that make up the value on the right. If you give another value the same name it will write over the existing variable.

a = 2;
b = 5;
a + b % ans = 7
a = 4;
a + b % ans = 9

% But with a better naming practice:

electricalBill = 60;
gasBill = 30;
totalUtilities = electricalBill + gasBill

% To speed up your coding when using long variable names you can hit the 'tab' key to auto fill from your existing variables as you're typing- this also helps avoid typos!
% It's good practice to assign any variables that are integers early on in your code then only that value by it's variable name in the code. This makes it much easier to change a value without hunting for every place there is a '17' in your code.
%
%% Vectors
% Vectors are ordered lists of numbers, they can be row vectors which are saved laterally:

v = [5 5 5 5 5]

% or column vectors which are saved vertically:

u = [6; 6; 6; 6; 6]

% You can switch and back forth between the vector directions by using an apostrophe after the variable name which rewrites rows to columns and vice versa.

v', u'

% To generate vectors using a range of values use the : sign to separate a start point, step size, and end point. If no step size is listed it will automatically set it to 1.

v3 = 1:55 %all integers between 1 and 55, inclusive 
v4 = 0:10:55 %count by 10's from 0 to 55
v5 = 0:3:55 %count by 3's from 0 to 55 

% These will all produce vectors of different lengths. To make a vector of a set length covering a range between to values use linspace(). The start and end values will always be included in the list. The vectors you create will have differnt values but the same number of elements.

linspace(1,55,10) %This generates 10 linerally seperate values from 0 to 55. 
linspace(1,100,10) %This generates 10 linerally seperate values from 0 to 100. 

% You can also create vectors filled with ones, zeros, or placeholders not-a-number or infinity by giving the function the dimensions you want. The dimensions are [# of rows, # of columns]

 zeros(1,5), ones(1,5), nan(1,5), inf(1,5)

% Random numbers can be used to create vectors as well:

 rand(1,5), randn(1,5), randi(100,[1,5]), randperm(10,5)

% Vectors are indexed starting from 1 in matlab so the first element in any vector is place 1, followed by 2,3,4... end. To select a range of values from a vector you can call those specific index values. Remeber that the index of a place in a vector is DIFFERENT from the value at that location in the vector.

 v3(3) %3rd elements in v3
 v3(1:end-30) %all elements except the last 30
 v3(10:20) %the 10th element through the 20th element 
 v3([5:10,20:25]) %the 5th through 10th elements, and the 20th thru 25th. 

% You can also index using logical arrays (1's and 0's). The index will select any element where a 1 is present and ignore the elements with a zero.

 v3(v3<15) %all the elements in v3 who's value is less than 15
 v3(rem(v3,3)==0) %all the elements in v3 which are evenly divisible by 3 

% You can reassign values in the vector by selecting them and setting them equal to a value

 v6 = zeros(5,1)
 v6(3) = 2 %replace the 3rd place with a 2
 v6(4:5) = 8 %replace the 4th and 5th place with an 8
 v6(1) = v6(5) %replace the 1st place with whatever value is in the 8th place

%
%% Vector Math
%% Dimensionality, length and direction
% A vector can be thought of as a list, but in linear algebra we can think of it as a set of coordinates. A vector with one element is the location of a point on a line. A vector with two elements gives you coordinates in 2D space, and X and a Y, this vector then has a length eg. the distance from that point to the origin. This length is different from length() in matlab which returns the number of elemnts. With 3 elements you have a point in 3d space (x,y,z) and a vector from the origin to that point which has a length. You cannot visualize past 3 dimensions but you can assume that as the vector gets longer each element adds a new dimension and the value at that element tells you how much the vector has moved into that new dimension. Vector length is calculated using square root of the sum of squares \sqrt{\sum\limits_{n=1}^N u_n^2}
% Vectors can be added together to generate new vectors that span the whole coordinate space, to access all points in a space you have to have as many vectors as dimensions (e.g. two vectors for a 2D plane, 3 vectors for 3D etc)

 vec1 = [3 7];
 vec2 = [5 4]; 
 vec3 = vec1 + vec2

% You can do element wise operations on vectors as well : .*, ./, .^ (vectors must be the same length)

[4 5].* [2 3] % ans = [8 15]
sqrt(vec1) %performs the function on each element individually

%% Unit Vectors
% Unit vectors are vectors with a length of one (although they could be many elements long ie. exist in multiple dimensions). Unit vectors perserve direction while normalizing length. To get a unit vector you divide a vector by it's length.

vec = [1,5,8,2,6]; %random vector
unit1 = vec/sqrt(sum(vec.^2)) %vector with the same multidimentional angle with a length of 1

%%
%% Dot Products & Vector Multiplication
% Multiplying a vector by a scaler stretches (or shrinks) it out in vector space, changing the distances between the point and the origin but not the direction of the vector.

vec1 = 1:5;
stretched1 = vec1*2; 
%vec1 and stretched1 are differnt lengths but fall along the same line

vec2 = 6:10;

% Outer Product: Multiply a COLUMN vector (v) times a ROW vector (u) of any lengths (nx1 * 1xm) which results in a matrix of values where each row contains the scalar multiple of the row vector with an element of the column vector (eg. v(1)*u, v(2)*u,....)

vec1'*vec2

% Inner Product: When you multiply a ROW vector (u) with a COLUMN vector (v) of equal lengths (1xn * nx1) you get a single scaler value. This value is the sum of all the elements of each vector multiplied together. (eg. u(1)*v(1) + u(2)*v(2) +.....) essentially \sum\limits_{n=1}^N u_nv_n

vec1*vec2'

%
%% Matrices
% A matrix is a stack of vectors and are 2+ dimensions. To create a square matrix, give a function a single element, eg. randn(5), or to specifiy the size give both the rows and columns, eg. randn(5,6)

 mat1 = randi(100,6) %creates a 6x6 matrix

% To check the size of a matrix or vector functions size() and length() come in handy. Do not confuse length for number of elements with the physical length of vector in space

 size(mat1) %gives the # of rows and # of columns
 length(mat1) %gives the length of the LONGEST side, could be rows or columns
 length(mat1(:)) %number of elements in mat1

% To pull out a specific elemnt of a matrix you index with first the row number and then the column number. Rows start at the top with 1 then count up as you down down, columns start with 1 on the left and count up as you travel to the right.

 mat1(3,5) %3rd row down, 5th column over 

% To pull a whole row or column from the matrix you can use the colon :

 mat1(3,:) %all columns in the 3rd row
 mat1(:,3) %all rows in the 3rd column 

% Each element in the matrix also has a unique number associated with it, as if you took all the columns and stacked them up on eachother to make a long vector. You can use this number to call an element as well:

 mat1(9) %calls the 9th element 
 mat1(:) %flattens the matrix into a vector in order of the element numbers. 

% You can remove rows or columns of a matrix by setting it to empty brackets [], but this will not work for indiviual elements. If you want to remove an element set it equal to nan or inf as a place holder.

 mat1(1,:) = [] %removes the first row of the matrix making it's size 5x6

%% Matrix Transpose
% Just like vectors you can flip the direction of a matrix using the apostrophe. The matrix does NOT rotate, the rows become columns and vice versa. It flips accross the upper left to lower right diagonal.

 mat2 = ones(5).*[1:5] 
 mat2' 

% When the matrix is flipped the 1st row becomes the 1st column and so on. The numbers along the diagonal are always the same. The identity matrix is a square matrix with zeros everywhere an 1's along the diagonal (will be very important later in the course). It's important because when you transpose this matrix it will always equal itself.

 eye1 = eye(5)
 eye1' 

% These two matrices are identical! How cool!
%
%% Matrix Math
%% Basic Operations
% Matrices can be operated upon just like integers. You can add, subtract, multiply, divide or power a whole matrix by a single integer.

 mat1 = [1 3 5; 4 5 6; 9 6 8];
 mat1 ^ 2
 mat1 * 3

% Combinging two matrices or vectors is also possible. Adding, subtracting and point-wise operations such as .*, ./ and .^ pair the two elements at the same element locations, thus the matrices have to be the same shape. The output will have the same dimensions as the input.

mat2 = [5 8 4; 6 1 3; 7 5 8];
mat1 + mat2
mat1 .* mat2

% You can also multiply matrices but we'll get to that in a couple weeks.
%
%% Other Variable Types
% The variables we created above are 'double' type variables which contain numberical values.
% Logicals are true/false variables and exists as either 1's or 0's and can fill any data shape.

check1 = magic(5) == magic(5)' %comparing two magic arrays one transposed
eye(5) == check1 %comparing the logical array to an identity matrix 

% Text data is represented as strings by putting quotes around the text. You can change between variable types string and double by using the commands 'str2double' and 'num2str'

subj = 'Anna'
subjNum = 5
['Anna is subject number ' num2str(subjNum)]

% To create a list of names you can't use a vector as they will run together:

subjs = ['Anna', 'Paul','Fred','Sally'] %vectors have square brackets

% Instead you can create a cell array to store multiple separate strings

groceryList = {'bread','milk','kale'} %arrays have curly brackets 

% Cell arrays can contain numbers (and vectors) as well as strings:

pets = {'dogs', 6, 'cats', 2, 'other', [3 4 6]}

% If you want to store several types of data together use a structure, it's similar to a file system.

petsOwned.dogs.pitbull.ages = [3 5 8 2 3];
petsOwned.dogs.pitbull.names = {'Fido','Spot','Burger','Kit','Toby'};
petsOwned.dogs.lab.ages = 2;
petsOwned.dogs.lab.names = 'Obe';

petsOwned.dogs.pitbull

%
%% Plotting
% To open a figure simply type 'figure', once the figure is open you can change physical attribues about it by set(gcf,[attributes]), gcf stands for 'get current figure'.

figure %open a figure
hold on %keep adding to the same figure
set(gcf,'Color','w','Position',[1001 900 500 500]) %change figure properties

% After a figure is open you can plot something on it. There are many different types of graphs to plot in matlab, including plot(), scatter(), bar(), hist(), stem() and many more! Mathworks has lots of samples on it's website. After you plot something you can then change properties of the line after your x,y coordinates (such as color, width, style etc.) and also change properties of the plot itself using set(gca,[attributes]). gca stands for 'get current axis'

%Creating two 2D vectors
v = [2,7];
u = [3 4];

%Plotting the vectors 
plot([0,v(1)],[0,v(2)],'r--','LineWidth',2) %plots a vector from the origin to point (2,7) 
plot([0,u(1)],[0,u(2)],'b-.','LineWidth',2) %plots a vector from the origin to point (2,7) 

set(gca,'Box','off','FontSize',18,'TickDir','out','XLim',[0 5],'YLim',[0 8],...
   'XTick',[0:2:4],'YTick', [0:2:8]) %change axis properties

%additional plot attributes
grid on; grid minor
xlabel('dimension 1')
ylabel('dimension 2')
legend('vec 1','vec 2')

% Color can be set with the matlab standard colors: w, r, b, c, k, y, g or you can provide an RGB triplet. You can quickly get RBG values using the command 'uisetcolor' in your command window to manually click around for the perfect color scheme!
%
%% Exercises
%% Exercise 1
% Open a new figure and try plotting the vectors v = [1; 2] in blue and  u = [3; 1] in red using plot()
% To see both vectors, on the same axes, specify 'hold on':

figure;


% Show vector addition by plotting v + u as a dashed line. To better illustrate the addition, try plotting u as a vector that originates at the endpoint of v



% What is the vector length (L2 norm) of v1 + u? (hint: to square elements of a vector, use .^)



% What about the "city block" length (L1 norm)? Calculate the L1 and L2 norms of v+u and print them to the command window using fprintf, eg: fprintf( 'your text here %.2f\n', your L1 norm), which will print the norm to two decimal places ( the %.2f)



% How can you create a unit vector (a vector with length 1) in the direction of v? On your existing axes, plot the unit vectors in the direction of v and u, in a different color.



% Convince yourself that the unit vectors you calculated have a length of 1 by plotting a circle over your vectors.

r = 1; % radius of the circle 
x = linspace(-r,r,100);
y = sqrt(r^2 - x.^2);
plot([x, flip(x)],[y,-y], 'c')
axis equal 

%
%% Exercise 2
% Now try plotting higher dimension vectors in a figure with multiple subplots!
% The function subplot(m, n, p) creates a m-by-n grid of axes that you can plot on, and specifies the p-th axis for the current plot. You can also plot on multiple axes to suit your aesthetic sensibilities: e.g. subplot(2,3,1:3) creates a 2x3 grid of axes but specifies subplots 1-3 (the top row) as your current axis.
% Create a figure with two subpots. Create two vectors with three elements and plot them in the first subplot using plot3(x,y,z) (type help plot3 in the command window if you are confused about the syntax). Tip: add rotate3d on to your plotting code to allow 3D panning
% In the second subplot, create a vector with ten elements and plot it using stem(vector). Then calcuate the unit vector, and plot it using stem()
% Give both subplots axis labels and titles.
% hint: to plot multiple objects on the same axes, specify 'hold on' after you create the subplot



% Depending on how you chose to orient your subplots, you may find that one of your graphs is squished in a way that makes it harder to read. Try playing with different layouts to get something that looks nice.
%
%% Exercise 3
% In Math Tools, you will make a lot of histograms and scatter plots. Let's practice using these functions to visualize data.
% First, generate two vectors with 100 elements, one using the randn function and one using rand. We will treat these as the x and y values of a data set.
% Create a figure with three subplots.
% In the first, plot the simulated data using scatter(x,y). Scatter is a nice function for scatter plots because you can easily change the size and color of data points with the syntax: scatter(X,Y,Size,Color). Type 'help scatter' to read more about this function



% In subplot 2 create a histogram of the x values using the histogram() function. You can either let the function automatically specify bins, or set the bins yourself (if you have a prefered bin size or number) by specifying a scalar number of bins (e.g. histogram(x,binNumb)) or by specifying a vector of bin edges (e.g. histogram(x,binEdges) where binEdges = -2:.1:2, for example).
% Plot the x values with 10 bins



% Repeat the process in subplot 3 with the y values. What do you notice is different about these two histograms? You will see (and make!) many examples of similar histograms in future sections.



%
%