diff --git a/MisterBiggs/julia-for-matlabbers/intro.jl b/MisterBiggs/julia-for-matlabbers/intro.jl new file mode 100644 index 000000000..83ea35694 --- /dev/null +++ b/MisterBiggs/julia-for-matlabbers/intro.jl @@ -0,0 +1,57 @@ +### A Pluto.jl notebook ### +# v0.14.7 + +using Markdown +using InteractiveUtils + +# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). +macro bind(def, element) + quote + local el = $(esc(element)) + global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing + el + end +end + +# ╔═╡ 7d7820ff-c0f5-41ee-be29-5006e7f4361d +begin + import Pkg + + # Pkg.add("PlutoUI"); + using PlutoUI + # Pkg.add("Plots") + using Plots +end + +# ╔═╡ bb461e00-c0aa-11eb-2c7d-1bd1591779c6 +md""" +# Julia for People That Were Unfortunate Enough to Learn MATLAB + +Julia is an incredily performant _(2 order of magnitude faster than Matlab)_, Dynamic _(Date types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. + +> The code in this notebook is running in something called Pluto.jl. Pluto notebooks are similar to Matlab Livescript but have a stricter focus on cells and are immutable meaning that a variable can only be declared once and cannot be changed in other cells. This feels very restricting at first but guarantees that the code you are currently looking at is correct, and allows reactive updating of dependant code. It's important to note that these are Pluto.jl features and not Julia features. +""" + +# ╔═╡ 11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 +md""" +## Things Matlab Does Really Weirdly that no one Else Does. + +A major pain point for large Matlab projects is managing installed Toolboxes and Packages. In Matlab once something is installed its available globally and doesn't require being added to a file. There are quite a few downsides to this the largest in my opinion being that its very easy to crowd your namespace. To make it even worse Matlab usually doesn't even warn you about the issue so if two packages offer a function of the same name its just going to choose one and hope it works out. Another big issue this can cause is version conflicts, this is why theres so many issues trying to run code between Matlab versions. + +Julia has a very intuitive package manager. For our uses I won't dig into version management or enviroments since they aren't really needed for smaller projects. + +The best way to install packages is to open the Julia REPL (basically Matlabs command window) and press `]` which puts you in Package mode. You can then `add`, `update` or `remove` packages. You can then press backspace to return to the normal REPL. Once a package is added to Julia you have to bring it into your enviroment to use it by using the `using` keyword. Below is an example that add `PlutoUI` to make Pluto more reactive, and `Plots` which is Julias very powerful plotting library. +""" + +# ╔═╡ a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 +@bind x Slider(1:5, show_value=true) + +# ╔═╡ 863587ab-5ead-4ad0-839f-09e798bc6c93 +plot(y -> y^x) + +# ╔═╡ Cell order: +# ╠═bb461e00-c0aa-11eb-2c7d-1bd1591779c6 +# ╠═11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 +# ╠═7d7820ff-c0f5-41ee-be29-5006e7f4361d +# ╟─a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 +# ╟─863587ab-5ead-4ad0-839f-09e798bc6c93 -- 2.51.2 From 5855b5b44f0d8ed5636489e034b4f5618e754104 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Sun, 30 May 2021 12:26:23 -0700 Subject: [PATCH 02/21] added functions and broadcasting --- MisterBiggs/julia-for-matlabbers/intro.jl | 139 +++++++++++++++++++++- 1 file changed, 136 insertions(+), 3 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/intro.jl b/MisterBiggs/julia-for-matlabbers/intro.jl index 83ea35694..a01d2739a 100644 --- a/MisterBiggs/julia-for-matlabbers/intro.jl +++ b/MisterBiggs/julia-for-matlabbers/intro.jl @@ -36,11 +36,20 @@ Julia is an incredily performant _(2 order of magnitude faster than Matlab)_, Dy md""" ## Things Matlab Does Really Weirdly that no one Else Does. +### Enviroments + A major pain point for large Matlab projects is managing installed Toolboxes and Packages. In Matlab once something is installed its available globally and doesn't require being added to a file. There are quite a few downsides to this the largest in my opinion being that its very easy to crowd your namespace. To make it even worse Matlab usually doesn't even warn you about the issue so if two packages offer a function of the same name its just going to choose one and hope it works out. Another big issue this can cause is version conflicts, this is why theres so many issues trying to run code between Matlab versions. Julia has a very intuitive package manager. For our uses I won't dig into version management or enviroments since they aren't really needed for smaller projects. -The best way to install packages is to open the Julia REPL (basically Matlabs command window) and press `]` which puts you in Package mode. You can then `add`, `update` or `remove` packages. You can then press backspace to return to the normal REPL. Once a package is added to Julia you have to bring it into your enviroment to use it by using the `using` keyword. Below is an example that add `PlutoUI` to make Pluto more reactive, and `Plots` which is Julias very powerful plotting library. +The best way to install packages is to open the Julia REPL (basically Matlabs command window) and press `]` which puts you in Package mode. You can then `add`, `update` or `remove` packages. You can then press backspace to return to the normal REPL. Once a package is added to Julia you have to bring it into your enviroment to use it by using the `using` keyword. Below is an example that adds `PlutoUI` to make Pluto more reactive, and `Plots` which is Julias very powerful plotting library. + +> import Pkg and the Pkg.add() code is a way to install packages inside code and is there to make it easy to install the packages in case they weren't already installed on your system. +""" + +# ╔═╡ d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 +md""" +Dragging the bar below automatically updates the plot thanks to Plutos reactivity. """ # ╔═╡ a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 @@ -49,9 +58,133 @@ The best way to install packages is to open the Julia REPL (basically Matlabs co # ╔═╡ 863587ab-5ead-4ad0-839f-09e798bc6c93 plot(y -> y^x) +# ╔═╡ 3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 +md""" +### Growing Arrays + +In Matlab its very common to grow an array in a for loop using `array(end+1)` _(You really should never do this since it creates a new array every loop which gets very inefficent)_. In Julia you use `push!` for adding a single number to the end of a `Vector` and `append!` to add collections to the end of a `Vector`. You'll notice that `!` at the end of the push and append functions. In Julia the exclamation point at the end of a function name means that the function modifies the function inputs in place compared to returning a new copy of the object. +""" + +# ╔═╡ 0a4dc275-04b3-43e3-8a0d-cb921d769a0a +a = [99, 1, 3, 5] + +# ╔═╡ 193c6a29-4f53-4c96-acc7-b5359043b471 +sort(a) + +# ╔═╡ e9a17e1a-652d-452e-8918-86c5adf699eb +a # a is still unsorted since sort(a) doesn't sort in place. + +# ╔═╡ 6fa90db6-9d2b-47bc-9f41-925b447912e8 +sort!(a) + +# ╔═╡ 7ef8ad0b-4724-43d3-86e2-c854c4fab9c4 +a # a is now sorted since sort!(a) sorts in place. + +# ╔═╡ 58c883b6-3682-424d-a1e9-8ac561bb0dbf +a[end+1] = 5 # Can't grow array by indexing like in Matlab + +# ╔═╡ a74e7cad-8dae-41cd-b77a-65ba082956a3 +md""" +### Functions + +Matlab functions have a ton of weird behaviors. The weirdest being that optional function returns are done base on the amount of return values so: + +```matlab +P = polyfit(X,Y,N) +[P,S] = polyfit(X,Y,N) +[P,S,MU] = polyfit(X,Y,N) +``` + +all return different things. In this case its simple to tell what is going on but if you had no idea what the polyfit function did in the first place its totally unintuitive what the extra returned values are. In other languages if a function has optional returns its usually idiomatic to return those values with an optional keyword argument or you just have a completely different function to get the different data. In the case of polyfit calculating S and MU are unrelated to calculating P so its not like the data was already calculated and can be easily returned which is what you would generally expect of optional arguments. To make things even worse `S` is designed to be an input to a different function, `POLYVAL`, so why wouldn't you just make polyval take `X`, `Y`, and `N` as inputs? Matlab is dumb `/endrant`. + +Another weird thing is where functions can be placed in Matlab. In livescripts they can only be placed at the end of the file, and theres also the ability to make files that are only a function. In Julia functions can be anywhere and files can contain as many functions as you want and can be imported by any other file. The function syntax in Julia is also very sane. +""" + +# ╔═╡ f4d655a2-8539-43f7-9356-56a3e3f9de91 +g(x) = x + 1 # Simple functions can be made in one line + +# ╔═╡ 289727e4-fb29-4ba8-97c5-cce62da725bc +function g(x, y) + z = x^2 + y^2 + return z # Returns can either be the last line of a function or use the return keyword. Returning something ends a function so any lines after a return statement would not execute. + +end # Functions have to have an end + +# ╔═╡ ec37197c-f18e-48c2-8266-867e28cfc138 +g() = g(6, 9.1) # Multiple functions can share names. +# This is also the wrong way to have default values for input arguments. +# g(x=6, y=9.1) ... would be the correct way to have default inputs that dont need to be specified. + +# ╔═╡ 3c921f2d-3972-4b88-990d-36ced0764bc5 +# Julia will always use the closest matching function. +function g(x::Int, y::Int) # x and y need to be integers + z = x+y # last line is returned, so really could just be x+y without the z +end + +# ╔═╡ b7ae33bc-5edd-4741-a578-d210521b1698 +g(14) # Since there are 4 different methods for g Julia will find and use the closest match. This is called multiple dispatch and can be very complicated but is incredibly powerful. + +# ╔═╡ 75eeaff0-4fd3-4745-b042-af8ba12a0506 +g(5.0, 6.0) # Normal g function used since inputs are floats + +# ╔═╡ 8688fe79-00ad-497f-a466-dc86af9e03b0 +g() # Uses normal g function since there is no match for g that has a Int and a Float specified as inputs. + +# ╔═╡ 9440e0bc-7920-4b81-b88a-0b1046d24b4c +g(5,6) # Integer method used since inputs are both integers. + +# ╔═╡ e239604f-2926-455b-a20c-0d9c283cc60a +md""" +### Broadcasting + +Matlab generally does broadcasting for you which can be dangerous since sometimes its unclear what a function or operator will do when used on arrays. Julia uses the same `.` syntax to do broadcasting but it has to be used anytime you want broadcasting and is very powerful in Julia. all operators support broadcasting `.+ .* .^ .==` and even functions support broadcasting by placing the `.` at the end of the function name `sqrt.(b)`. This is awesome because you can write your function as you normally would for one number, and then if its needs to run on a vector Julia takes are of making your function into a very fast vectorized function! You can still make your own functions that take in vectors since there may be situations where you can write faster code. This means that almost no function in the Julia standard library accepts vectors unlike Matlab. Obviously functions like `maximum` that find the max value in an array take them, but functions like `sin`, `cos`, or `sqrt` all have to use the `.` syntax to work on vectors. +""" + +# ╔═╡ 011bb616-3752-432f-adfd-edaecc083cf0 +b = 1:5 + +# ╔═╡ 6124f6b4-6315-4d74-9067-4553ce1d54bc +sin(b) # gotta broadcast! + +# ╔═╡ 95e30983-f305-41aa-a1e2-f38fa0d0c1c3 +sin.(b) # Nice! + +# ╔═╡ 384fe37e-a184-4c3f-8b25-3acfee485cfc +b .^ 2 + +# ╔═╡ 3738b701-1ac6-414e-b1c2-57a1b4a2f53e +b .== b # Compares values element by element + +# ╔═╡ ae1134f5-b5cc-49a8-aee0-99ec118299f9 +b == b # Compares the entire objects against eachother + # ╔═╡ Cell order: -# ╠═bb461e00-c0aa-11eb-2c7d-1bd1591779c6 -# ╠═11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 +# ╟─bb461e00-c0aa-11eb-2c7d-1bd1591779c6 +# ╟─11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 # ╠═7d7820ff-c0f5-41ee-be29-5006e7f4361d +# ╟─d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 # ╟─a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 # ╟─863587ab-5ead-4ad0-839f-09e798bc6c93 +# ╠═3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 +# ╠═0a4dc275-04b3-43e3-8a0d-cb921d769a0a +# ╠═193c6a29-4f53-4c96-acc7-b5359043b471 +# ╠═e9a17e1a-652d-452e-8918-86c5adf699eb +# ╠═6fa90db6-9d2b-47bc-9f41-925b447912e8 +# ╠═7ef8ad0b-4724-43d3-86e2-c854c4fab9c4 +# ╠═58c883b6-3682-424d-a1e9-8ac561bb0dbf +# ╠═a74e7cad-8dae-41cd-b77a-65ba082956a3 +# ╠═f4d655a2-8539-43f7-9356-56a3e3f9de91 +# ╠═289727e4-fb29-4ba8-97c5-cce62da725bc +# ╠═ec37197c-f18e-48c2-8266-867e28cfc138 +# ╠═3c921f2d-3972-4b88-990d-36ced0764bc5 +# ╠═b7ae33bc-5edd-4741-a578-d210521b1698 +# ╠═75eeaff0-4fd3-4745-b042-af8ba12a0506 +# ╠═8688fe79-00ad-497f-a466-dc86af9e03b0 +# ╠═9440e0bc-7920-4b81-b88a-0b1046d24b4c +# ╠═e239604f-2926-455b-a20c-0d9c283cc60a +# ╠═011bb616-3752-432f-adfd-edaecc083cf0 +# ╠═6124f6b4-6315-4d74-9067-4553ce1d54bc +# ╠═95e30983-f305-41aa-a1e2-f38fa0d0c1c3 +# ╠═384fe37e-a184-4c3f-8b25-3acfee485cfc +# ╠═3738b701-1ac6-414e-b1c2-57a1b4a2f53e +# ╠═ae1134f5-b5cc-49a8-aee0-99ec118299f9 -- 2.51.2 From 147fc802561c84c89aae1d38f4a133511911d184 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Sun, 30 May 2021 15:35:18 -0700 Subject: [PATCH 03/21] more stuff --- MisterBiggs/julia-for-matlabbers/intro.jl | 50 ++++++++++++++++++++--- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/intro.jl b/MisterBiggs/julia-for-matlabbers/intro.jl index a01d2739a..e43627572 100644 --- a/MisterBiggs/julia-for-matlabbers/intro.jl +++ b/MisterBiggs/julia-for-matlabbers/intro.jl @@ -63,6 +63,8 @@ md""" ### Growing Arrays In Matlab its very common to grow an array in a for loop using `array(end+1)` _(You really should never do this since it creates a new array every loop which gets very inefficent)_. In Julia you use `push!` for adding a single number to the end of a `Vector` and `append!` to add collections to the end of a `Vector`. You'll notice that `!` at the end of the push and append functions. In Julia the exclamation point at the end of a function name means that the function modifies the function inputs in place compared to returning a new copy of the object. + +> Array index syntax uses square brackets `[]` in Julia. """ # ╔═╡ 0a4dc275-04b3-43e3-8a0d-cb921d769a0a @@ -133,15 +135,20 @@ g() # Uses normal g function since there is no match for g that has a Int and a # ╔═╡ 9440e0bc-7920-4b81-b88a-0b1046d24b4c g(5,6) # Integer method used since inputs are both integers. +# ╔═╡ 86c23c4e-ab5b-4404-b248-c980a4098676 +md""" +> Something to note in Julia when an array is passed into a function a copy is not made. This means if array `x` is passed into `f(x)`, any changes made to the array will apply to x outside of the array. If you intend to modify the passed in array be sure to add a bang `!` to the end of function name to keep your code idiomatic. +""" + # ╔═╡ e239604f-2926-455b-a20c-0d9c283cc60a md""" ### Broadcasting -Matlab generally does broadcasting for you which can be dangerous since sometimes its unclear what a function or operator will do when used on arrays. Julia uses the same `.` syntax to do broadcasting but it has to be used anytime you want broadcasting and is very powerful in Julia. all operators support broadcasting `.+ .* .^ .==` and even functions support broadcasting by placing the `.` at the end of the function name `sqrt.(b)`. This is awesome because you can write your function as you normally would for one number, and then if its needs to run on a vector Julia takes are of making your function into a very fast vectorized function! You can still make your own functions that take in vectors since there may be situations where you can write faster code. This means that almost no function in the Julia standard library accepts vectors unlike Matlab. Obviously functions like `maximum` that find the max value in an array take them, but functions like `sin`, `cos`, or `sqrt` all have to use the `.` syntax to work on vectors. +Matlab generally does broadcasting for you which can be dangerous since sometimes its unclear what a function or operator will do when used on arrays. Julia uses the same `.` syntax to do broadcasting but it has to be used anytime you want broadcasting and is very powerful in Julia. all operators support broadcasting `.+ .* .^ .==` and even functions support broadcasting by placing the `.` at the end of the function name `sqrt.(b)`. This is awesome because you can write your function as you normally would for one number, and then if it needs to run on a vector Julia takes care of making your function into a very fast and efficient vectorized function! You can still make your own functions that take in vectors since there may be situations where you can write faster code. This means that almost no function in the Julia standard library accepts vectors unlike Matlab. Obviously functions like `maximum` that find the max value in an array take them, but functions like `sin`, `cos`, or `sqrt` all have to use the `.` syntax to work on vectors. """ # ╔═╡ 011bb616-3752-432f-adfd-edaecc083cf0 -b = 1:5 +b = 1:5 # Ranges are similar to Matlab, but will discussed later in the text # ╔═╡ 6124f6b4-6315-4d74-9067-4553ce1d54bc sin(b) # gotta broadcast! @@ -150,7 +157,7 @@ sin(b) # gotta broadcast! sin.(b) # Nice! # ╔═╡ 384fe37e-a184-4c3f-8b25-3acfee485cfc -b .^ 2 +b .^ 2 # broadcast operators # ╔═╡ 3738b701-1ac6-414e-b1c2-57a1b4a2f53e b .== b # Compares values element by element @@ -158,6 +165,30 @@ b .== b # Compares values element by element # ╔═╡ ae1134f5-b5cc-49a8-aee0-99ec118299f9 b == b # Compares the entire objects against eachother +# ╔═╡ 3ef67004-2f85-4aa1-a1b5-5cbf62b292f7 +md""" +### Strict Evaluation + +Matlab evaluates arrays when they are made which is very common in programming languages, but Julia lazily computes values. This means that when you create a range like `1:.1:10` it doesn't create an array immediatly but waits until the array is needed. This has many memory advantages and many functions in Julia use the same behavior. These lazy objects generally behave as arrays but if they don't the `collect` function will turn them into an array. +""" + +# ╔═╡ 1025e3a8-59c9-4725-bc1a-a0b94e6bd6af +1:10 + +# ╔═╡ e3c28497-29e9-447e-aba0-650aaaa52d88 +typeof(1:10) + +# ╔═╡ 4fd4f72d-45e0-4760-bc0b-5ebb78636e2c +enumerate(1:.25:2) # returns an enumerate object + +# ╔═╡ cf125fe2-c754-4218-92c9-3f491f3109c1 +collect(enumerate(1:.25:2)) # Returns an an array of tuples as expected + +# ╔═╡ 4802d903-e87c-4ef0-a184-e4ae7af69a28 +md""" +### Random Small Differences +""" + # ╔═╡ Cell order: # ╟─bb461e00-c0aa-11eb-2c7d-1bd1591779c6 # ╟─11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 @@ -165,14 +196,14 @@ b == b # Compares the entire objects against eachother # ╟─d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 # ╟─a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 # ╟─863587ab-5ead-4ad0-839f-09e798bc6c93 -# ╠═3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 +# ╟─3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 # ╠═0a4dc275-04b3-43e3-8a0d-cb921d769a0a # ╠═193c6a29-4f53-4c96-acc7-b5359043b471 # ╠═e9a17e1a-652d-452e-8918-86c5adf699eb # ╠═6fa90db6-9d2b-47bc-9f41-925b447912e8 # ╠═7ef8ad0b-4724-43d3-86e2-c854c4fab9c4 # ╠═58c883b6-3682-424d-a1e9-8ac561bb0dbf -# ╠═a74e7cad-8dae-41cd-b77a-65ba082956a3 +# ╟─a74e7cad-8dae-41cd-b77a-65ba082956a3 # ╠═f4d655a2-8539-43f7-9356-56a3e3f9de91 # ╠═289727e4-fb29-4ba8-97c5-cce62da725bc # ╠═ec37197c-f18e-48c2-8266-867e28cfc138 @@ -181,10 +212,17 @@ b == b # Compares the entire objects against eachother # ╠═75eeaff0-4fd3-4745-b042-af8ba12a0506 # ╠═8688fe79-00ad-497f-a466-dc86af9e03b0 # ╠═9440e0bc-7920-4b81-b88a-0b1046d24b4c -# ╠═e239604f-2926-455b-a20c-0d9c283cc60a +# ╟─86c23c4e-ab5b-4404-b248-c980a4098676 +# ╟─e239604f-2926-455b-a20c-0d9c283cc60a # ╠═011bb616-3752-432f-adfd-edaecc083cf0 # ╠═6124f6b4-6315-4d74-9067-4553ce1d54bc # ╠═95e30983-f305-41aa-a1e2-f38fa0d0c1c3 # ╠═384fe37e-a184-4c3f-8b25-3acfee485cfc # ╠═3738b701-1ac6-414e-b1c2-57a1b4a2f53e # ╠═ae1134f5-b5cc-49a8-aee0-99ec118299f9 +# ╟─3ef67004-2f85-4aa1-a1b5-5cbf62b292f7 +# ╠═1025e3a8-59c9-4725-bc1a-a0b94e6bd6af +# ╠═e3c28497-29e9-447e-aba0-650aaaa52d88 +# ╠═4fd4f72d-45e0-4760-bc0b-5ebb78636e2c +# ╠═cf125fe2-c754-4218-92c9-3f491f3109c1 +# ╠═4802d903-e87c-4ef0-a184-e4ae7af69a28 -- 2.51.2 From 52a7cae77af8ca32f12ea5419c03eac5d182e91a Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Tue, 1 Jun 2021 15:51:54 -0700 Subject: [PATCH 04/21] mostly wrapped up intro --- .../julia-for-matlabbers/intro/index.html | 74 +++++++++++++++ .../julia-for-matlabbers/{ => intro}/intro.jl | 91 +++++++++++++++++-- 2 files changed, 156 insertions(+), 9 deletions(-) create mode 100644 MisterBiggs/julia-for-matlabbers/intro/index.html rename MisterBiggs/julia-for-matlabbers/{ => intro}/intro.jl (71%) diff --git a/MisterBiggs/julia-for-matlabbers/intro/index.html b/MisterBiggs/julia-for-matlabbers/intro/index.html new file mode 100644 index 000000000..9b10883eb --- /dev/null +++ b/MisterBiggs/julia-for-matlabbers/intro/index.html @@ -0,0 +1,74 @@ + + + + + + ⚡ Pluto.jl ⚡ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MisterBiggs/julia-for-matlabbers/intro.jl b/MisterBiggs/julia-for-matlabbers/intro/intro.jl similarity index 71% rename from MisterBiggs/julia-for-matlabbers/intro.jl rename to MisterBiggs/julia-for-matlabbers/intro/intro.jl index e43627572..0be2dba9f 100644 --- a/MisterBiggs/julia-for-matlabbers/intro.jl +++ b/MisterBiggs/julia-for-matlabbers/intro/intro.jl @@ -21,6 +21,8 @@ begin using PlutoUI # Pkg.add("Plots") using Plots + Pkg.add("LaTeXStrings") + using LaTeXStrings end # ╔═╡ bb461e00-c0aa-11eb-2c7d-1bd1591779c6 @@ -29,12 +31,17 @@ md""" Julia is an incredily performant _(2 order of magnitude faster than Matlab)_, Dynamic _(Date types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. -> The code in this notebook is running in something called Pluto.jl. Pluto notebooks are similar to Matlab Livescript but have a stricter focus on cells and are immutable meaning that a variable can only be declared once and cannot be changed in other cells. This feels very restricting at first but guarantees that the code you are currently looking at is correct, and allows reactive updating of dependant code. It's important to note that these are Pluto.jl features and not Julia features. +!!! info "Pluto Notebooks" + The code in this notebook is running in something called Pluto.jl. Pluto notebooks are similar to Matlab Livescript but have a stricter focus on cells and are immutable meaning that a variable can only be declared once and cannot be changed in other cells. This feels very restricting at first but guarantees that the code you are currently looking at is correct, and allows reactive updating of dependant code. It's important to note that these are Pluto.jl features and not Julia features. """ # ╔═╡ 11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 md""" -## Things Matlab Does Really Weirdly that no one Else Does. +## Intro - Things Matlab Does Really Weirdly that no one Else Does + +To get started I want to focus on things that Matlab does that are outlandish and make little sense and compare them to things Julia does. Julia is obviously not perfect, but being that it's one of the newest and fastest growing languages it's easy to argue that the syntax and language design of Julia are the most modern and sane currently available in programming especially if you are focussing on engineering or science workloads. + +In future chapters I will focus more on how Julia shines rather than why Matlab doesn't. ### Enviroments @@ -44,7 +51,8 @@ Julia has a very intuitive package manager. For our uses I won't dig into versio The best way to install packages is to open the Julia REPL (basically Matlabs command window) and press `]` which puts you in Package mode. You can then `add`, `update` or `remove` packages. You can then press backspace to return to the normal REPL. Once a package is added to Julia you have to bring it into your enviroment to use it by using the `using` keyword. Below is an example that adds `PlutoUI` to make Pluto more reactive, and `Plots` which is Julias very powerful plotting library. -> import Pkg and the Pkg.add() code is a way to install packages inside code and is there to make it easy to install the packages in case they weren't already installed on your system. +!!! warning "Package Management" + `import Pkg` and the `Pkg.add()` code is a way to install packages inside a script and is there to make it easy to install the packages in case they weren't already installed on your system. """ # ╔═╡ d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 @@ -56,7 +64,9 @@ Dragging the bar below automatically updates the plot thanks to Plutos reactivit @bind x Slider(1:5, show_value=true) # ╔═╡ 863587ab-5ead-4ad0-839f-09e798bc6c93 -plot(y -> y^x) +begin + plot(y -> y^x, title=L"f(x) = x^%$x", label="") +end # ╔═╡ 3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 md""" @@ -64,7 +74,8 @@ md""" In Matlab its very common to grow an array in a for loop using `array(end+1)` _(You really should never do this since it creates a new array every loop which gets very inefficent)_. In Julia you use `push!` for adding a single number to the end of a `Vector` and `append!` to add collections to the end of a `Vector`. You'll notice that `!` at the end of the push and append functions. In Julia the exclamation point at the end of a function name means that the function modifies the function inputs in place compared to returning a new copy of the object. -> Array index syntax uses square brackets `[]` in Julia. +!!! note "Indexing Syntax" + Array index syntax uses square brackets `[]` in Julia as opposed to paranthesis in Matlab `()`. """ # ╔═╡ 0a4dc275-04b3-43e3-8a0d-cb921d769a0a @@ -91,7 +102,7 @@ md""" Matlab functions have a ton of weird behaviors. The weirdest being that optional function returns are done base on the amount of return values so: -```matlab +```julia P = polyfit(X,Y,N) [P,S] = polyfit(X,Y,N) [P,S,MU] = polyfit(X,Y,N) @@ -137,7 +148,8 @@ g(5,6) # Integer method used since inputs are both integers. # ╔═╡ 86c23c4e-ab5b-4404-b248-c980a4098676 md""" -> Something to note in Julia when an array is passed into a function a copy is not made. This means if array `x` is passed into `f(x)`, any changes made to the array will apply to x outside of the array. If you intend to modify the passed in array be sure to add a bang `!` to the end of function name to keep your code idiomatic. +!!! note + In Julia when an array is passed into a function a copy the actual array gets passed in, not a copy. This means if array `x` is passed into `f(x)`, any changes made to the array will apply to `x` outside of the array. If you intend to modify the passed in array be sure to add a bang `!` to the end of function name to keep your code idiomatic. """ # ╔═╡ e239604f-2926-455b-a20c-0d9c283cc60a @@ -187,6 +199,61 @@ collect(enumerate(1:.25:2)) # Returns an an array of tuples as expected # ╔═╡ 4802d903-e87c-4ef0-a184-e4ae7af69a28 md""" ### Random Small Differences + +#### Plotting + +Plots use very similar syntax to Matlab with the exception that there is no `hold` or `figure` keyword the bang `!` syntax is used to modify plots and if a plot method is called without a bang then it creates a new plot object. Its often best practice to wrap everything for a plot in a `begin` and `end` so that the whole plot runs in order every time. + +!!! warning + Pluto only allows one "thing" per cell, but this is a Pluto quirk not Julia. So every cell needs a `begin` or `let` or `function` if there is more than one line but Pluto will also automatically do this for you. +""" + +# ╔═╡ a4665e30-4c64-46d1-8349-a49f40763a0b +plot(sin) + +# ╔═╡ 09303ffe-6cf8-4273-b697-9fbd7cb82cc1 +plot(cos) # Makes a new plot! + +# ╔═╡ e3b51038-2e57-4a5a-9b5d-7bf7148d700b +begin + plot(sin, label="sin") + plot!(cos, label="cos") + title!("sin and cos functions") +end + +# ╔═╡ 55e0d022-faca-40f8-a4a9-3a501eb5d19e +plot!(atan, label="atan") # Returns a new plot with all the elements of the old plot. + +# ╔═╡ dc89d08d-29bf-4e04-8470-c79c88ab4689 +md""" +!!! note + The Julia plotting library is massive and supports many frontends that are useful for various use cases such as printing in the terminal or making interactive plots for websites. This will all be covered in a future post. +""" + +# ╔═╡ b30e6f73-fe46-45e7-898e-dd1205dffe68 +md""" +#### Keyword Arguments + +Matlab uses an odd syntax where a string argument is passed before the value of the optional argument. Julia and most other languages allow passing in the optional keywords by the following syntax: +```julia +plot(x, y, title="y data vs x data", label="Data") +``` + +#### Semicolons + +Julia doesn't automatically print script values except in certain circumstances like in Pluto or in the REPL. This means that lines do not need to be terminated with a semicolon in regular scripts. Semicolons can be used to combine multiple lines into one. `plot(sin); title!("sin function")` + +#### `...` Syntax + +Matlab uses ... to continue lines of code. In Julia this is called the splat operator and is used to pass a collection into arguments of a function: + +```julia +xs = [1 2 3] + +# Following functions are identical! +f(xs...) +f(1, 2, 3) +``` """ # ╔═╡ Cell order: @@ -195,7 +262,7 @@ md""" # ╠═7d7820ff-c0f5-41ee-be29-5006e7f4361d # ╟─d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 # ╟─a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 -# ╟─863587ab-5ead-4ad0-839f-09e798bc6c93 +# ╠═863587ab-5ead-4ad0-839f-09e798bc6c93 # ╟─3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 # ╠═0a4dc275-04b3-43e3-8a0d-cb921d769a0a # ╠═193c6a29-4f53-4c96-acc7-b5359043b471 @@ -225,4 +292,10 @@ md""" # ╠═e3c28497-29e9-447e-aba0-650aaaa52d88 # ╠═4fd4f72d-45e0-4760-bc0b-5ebb78636e2c # ╠═cf125fe2-c754-4218-92c9-3f491f3109c1 -# ╠═4802d903-e87c-4ef0-a184-e4ae7af69a28 +# ╟─4802d903-e87c-4ef0-a184-e4ae7af69a28 +# ╠═a4665e30-4c64-46d1-8349-a49f40763a0b +# ╠═09303ffe-6cf8-4273-b697-9fbd7cb82cc1 +# ╠═e3b51038-2e57-4a5a-9b5d-7bf7148d700b +# ╠═55e0d022-faca-40f8-a4a9-3a501eb5d19e +# ╟─dc89d08d-29bf-4e04-8470-c79c88ab4689 +# ╟─b30e6f73-fe46-45e7-898e-dd1205dffe68 -- 2.51.2 From f1c97658f6fe3cd2180a65fae1257a6982374cbe Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Tue, 1 Jun 2021 16:45:02 -0700 Subject: [PATCH 05/21] intro cleaned up --- MisterBiggs/julia-for-matlabbers/intro/index.html | 4 ++-- MisterBiggs/julia-for-matlabbers/intro/intro.jl | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/intro/index.html b/MisterBiggs/julia-for-matlabbers/intro/index.html index 9b10883eb..8c07d4253 100644 --- a/MisterBiggs/julia-for-matlabbers/intro/index.html +++ b/MisterBiggs/julia-for-matlabbers/intro/index.html @@ -52,11 +52,11 @@ diff --git a/MisterBiggs/julia-for-matlabbers/intro/intro.jl b/MisterBiggs/julia-for-matlabbers/intro/intro.jl index 0be2dba9f..dd5b01c54 100644 --- a/MisterBiggs/julia-for-matlabbers/intro/intro.jl +++ b/MisterBiggs/julia-for-matlabbers/intro/intro.jl @@ -21,7 +21,7 @@ begin using PlutoUI # Pkg.add("Plots") using Plots - Pkg.add("LaTeXStrings") + # Pkg.add("LaTeXStrings") using LaTeXStrings end @@ -35,6 +35,9 @@ Julia is an incredily performant _(2 order of magnitude faster than Matlab)_, Dy The code in this notebook is running in something called Pluto.jl. Pluto notebooks are similar to Matlab Livescript but have a stricter focus on cells and are immutable meaning that a variable can only be declared once and cannot be changed in other cells. This feels very restricting at first but guarantees that the code you are currently looking at is correct, and allows reactive updating of dependant code. It's important to note that these are Pluto.jl features and not Julia features. """ +# ╔═╡ 307cbf7a-1ac5-47a5-8031-3458f9dd1887 +PlutoUI.TableOfContents(aside=true) + # ╔═╡ 11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 md""" ## Intro - Things Matlab Does Really Weirdly that no one Else Does @@ -60,6 +63,12 @@ md""" Dragging the bar below automatically updates the plot thanks to Plutos reactivity. """ +# ╔═╡ 16a7201a-4ce0-4102-9874-96733514ef08 +md""" +!!! warning + This page is just HTML and doesn't have a Julia Backend to allow interactivity. The button in the top right corner has instructions on how to run this notebook yourself. +""" + # ╔═╡ a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 @bind x Slider(1:5, show_value=true) @@ -258,11 +267,13 @@ f(1, 2, 3) # ╔═╡ Cell order: # ╟─bb461e00-c0aa-11eb-2c7d-1bd1591779c6 +# ╟─307cbf7a-1ac5-47a5-8031-3458f9dd1887 # ╟─11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 # ╠═7d7820ff-c0f5-41ee-be29-5006e7f4361d # ╟─d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 +# ╟─16a7201a-4ce0-4102-9874-96733514ef08 # ╟─a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 -# ╠═863587ab-5ead-4ad0-839f-09e798bc6c93 +# ╟─863587ab-5ead-4ad0-839f-09e798bc6c93 # ╟─3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 # ╠═0a4dc275-04b3-43e3-8a0d-cb921d769a0a # ╠═193c6a29-4f53-4c96-acc7-b5359043b471 -- 2.51.2 From 8aabc25fb704bbc243f50c42c35c3929347443d1 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Mon, 14 Jun 2021 14:47:36 -0700 Subject: [PATCH 06/21] more writing --- .../julia-for-matlabbers/intro/intro.jl | 228 +++++++++++++++++- 1 file changed, 227 insertions(+), 1 deletion(-) diff --git a/MisterBiggs/julia-for-matlabbers/intro/intro.jl b/MisterBiggs/julia-for-matlabbers/intro/intro.jl index dd5b01c54..47c20bd6f 100644 --- a/MisterBiggs/julia-for-matlabbers/intro/intro.jl +++ b/MisterBiggs/julia-for-matlabbers/intro/intro.jl @@ -1,5 +1,5 @@ ### A Pluto.jl notebook ### -# v0.14.7 +# v0.14.8 using Markdown using InteractiveUtils @@ -25,6 +25,12 @@ begin using LaTeXStrings end +# ╔═╡ 3228a21e-cab8-4738-bdc5-a6827c764c06 +using Unitful + +# ╔═╡ 2df0563d-054a-4ad0-97af-6e06b31a7b1d +using LinearAlgebra + # ╔═╡ bb461e00-c0aa-11eb-2c7d-1bd1591779c6 md""" # Julia for People That Were Unfortunate Enough to Learn MATLAB @@ -265,6 +271,197 @@ f(1, 2, 3) ``` """ +# ╔═╡ 916f5f09-1aa3-47a7-9c66-c42513eaccea +md""" +## Things Julia Does Well + +There are a few ways that Julia really shines that make it perfect for engineering and science. Below are a few examples. + +## Symbols + +Julia supports a wide variety of unicode symbols in the language that can be accessed with the syntax `\pi{tab}` to get π. This is a great way to make code closer to LaTex or handwritten examples which makes it easier to read or understand. + +* `\theta{tab}` θ +* `q\bar{tab}` q̄ +* `x\ddot{tab}` ẍ + +## List Comprehension + +List comprehensions can be thought of single line for loops and can be very handy in a variety of scenarios. The syntax is: + +```julia +# Add 1 to each number in a list of numbers +[number + 1 for number in numbers] +``` + +and would return a new list of numbers. + +List comprehensions are especially useful instead of one line for loops, or when you need to create an array to pass into a function. List comprehensions can be nested, and also support `if` in order to filter values making them extremely powerful: + +""" + +# ╔═╡ 2172de3a-7dba-4cbc-9c04-444db595c328 +[x for x in 1:12 if x % 3 == 0] + +# ╔═╡ fd0f5cf6-c90b-4492-9c72-9e707803e736 +md""" +Since `append!` is usually very slow you can see below that using a list comprehension to create a vector is almost 10x faster. +""" + +# ╔═╡ a2c7e472-2460-428e-bfec-acf925fad89d +begin + t = [] + for i in 1:1e6 + append!(t,i) + end + t +end + +# ╔═╡ bce2eecc-dc01-4bf6-9eaa-880fd8a69768 +[i for i in 1:1e6] + +# ╔═╡ 9ea4584c-8177-4f69-9739-b2faa93281a8 +md""" +--- + +### Matrix Math +""" + +# ╔═╡ a2df1c35-c0b2-45bb-86b7-57e208287392 +md""" +--- + +### Units + +Julia has an unofficial units library that is incredibly powerful and much easier to use than Matlabs units functionality. It is simply import as `Unitful` +""" + +# ╔═╡ 7b9b11f2-c6d3-4dab-ab30-6e47a3a4bfb3 +md""" +Making a value with a unit is as simple as using the `u` string macro like the following: +""" + +# ╔═╡ 09bc71cd-7bc0-4d5a-bcf8-984abe273375 +mass = 10u"lb" + +# ╔═╡ 744b7e78-0e5b-468d-98b1-a5511f7db311 +gravity = 9.81u"m/s^2" + +# ╔═╡ ea6b28d5-f82b-4a21-9ca4-13215c6912b3 +mass + gravity # The library automatically detects if units can be added to eachother. + +# ╔═╡ 871664ac-5a93-4718-ae1a-c9f59f6b8374 +weight = mass * gravity # You can mix unit systems + +# ╔═╡ dd38ffe4-4efb-4571-b5b2-76b811901387 +md""" +You'll notice that the weight was left as a gross collection of units instead of automatically converting to `N` like we woule expect. This is usually the case but can easily be fixed by using Julias pipe operator, `|>`. + +!!! note "The Pipe Operator" + The pipe operator, or `|>` is a great way to chain function calls in Julia. Using `x |> f` is the exact same as using `f(x)` but in many cases can be much clearer. + +```julia +inv(sum((x->x.^2 .+ 1)(1:10))) # Hard to read +1:10 |> x -> x.^2 .+ 1 |> sum |> inv # Easier to read +``` + +""" + +# ╔═╡ ade2979d-155e-4f20-82db-6da141bb8eaa +weight |> u"N" + +# ╔═╡ 8d4de01a-197f-40cb-942f-bfec335e3844 +md""" +Units can also be stripped to give a normal number again. +""" + +# ╔═╡ 86da848f-1e84-47c8-8a79-373f241b6025 +ustrip(u"N", weight) + +# ╔═╡ f43812d2-9f87-489a-9317-e7aa19ffd3bc +md""" +--- + +### Custom Data Types +""" + +# ╔═╡ 44daff45-f608-47e3-ad6e-fca43532f322 +struct Quaternion + i::Float64 + j::Float64 + k::Float64 + r::Float64 + + Quaternion(i, j, k, r) = norm([i, j, k, r]) ≈ 1 ? new(i, j, k, r) : error("Magnitude not equal to 1.") + Quaternion(q) = Quaternion(q[1], q[2], q[3], q[4]) + Quaternion() = new(0, 0, 0, 1) + + Quaternion(yaw, pitch, roll) = Quaternion([0 0 sin(yaw / 2) cos(yaw / 2)]) * Quaternion([0 sin(pitch / 2) 0 cos(pitch / 2)]) * Quaternion([sin(roll / 2) 0 0 cos(roll / 2)]) + + function Quaternion(ē, ϕ) + if sum(ē) == 0 + return Quaternion([0 0 0 cos(ϕ / 2)]) + end + dir = normalize(ē) * sin(ϕ / 2) + return Quaternion(dir[1], dir[2], dir[3], cos(ϕ / 2)) + end + +end + + +# ╔═╡ 37c4a8ef-d503-497a-a63c-3e43d0ebb2a7 +function QuaternionMultiplication(l::Quaternion, r::Quaternion) + R = [r.r r.k r.j r.i; + -r.k r.r r.i r.j; + r.j -r.i r.r r.k; + -r.i -r.j -r.k r.r] + L = [l.i; l.j; l.k; l.r] + return Quaternion(R * L) + +end + +# ╔═╡ 0d67e350-a87e-4a07-a01c-d348f3e62599 +Base.:*(l::Quaternion, r::Quaternion) = QuaternionMultiplication(l::Quaternion, r::Quaternion) + +# ╔═╡ cbf7d0fb-855b-442b-80c2-cfb6dcabe104 +begin + Base.iterate(q::Quaternion, state=1) = state > 4 ? nothing : (collect(q)[state], state + 1) + Base.length(q::Quaternion) = 4 + Base.collect(q::Quaternion) = [q.i q.j q.k q.r] + Base.getindex(q::Quaternion, i) = collect(q)[i] +end + +# ╔═╡ 84e6fb12-be8c-4e00-bf9c-d45748347def +begin + LinearAlgebra.norm(q::Quaternion) = norm(collect(q)) + LinearAlgebra.normalize(q::Quaternion) = collect(q) / norm(q) +end + +# ╔═╡ 2ba455ff-70f5-47d5-9fe8-bf4ebee9386a +q1 = Quaternion(1,0,0,0) + +# ╔═╡ 6895bcb2-9a11-4f0a-b1c2-6640f6fb509c +q2 = Quaternion([1 2 3], π) + +# ╔═╡ fafa0a8d-5ae5-49e9-8d11-4abb5748431e +q1*q2 + +# ╔═╡ 8924673f-e99c-44b3-be6d-2abf0b2f5e23 +md""" +--- + +### Tabular Data +""" + +# ╔═╡ fbc06121-d53a-4a64-9497-63d7f3583fbb +md""" +## Things Julia Does Poorly + +Performance +Libraries +Still young and breaking things +""" + # ╔═╡ Cell order: # ╟─bb461e00-c0aa-11eb-2c7d-1bd1591779c6 # ╟─307cbf7a-1ac5-47a5-8031-3458f9dd1887 @@ -310,3 +507,32 @@ f(1, 2, 3) # ╠═55e0d022-faca-40f8-a4a9-3a501eb5d19e # ╟─dc89d08d-29bf-4e04-8470-c79c88ab4689 # ╟─b30e6f73-fe46-45e7-898e-dd1205dffe68 +# ╟─916f5f09-1aa3-47a7-9c66-c42513eaccea +# ╠═2172de3a-7dba-4cbc-9c04-444db595c328 +# ╟─fd0f5cf6-c90b-4492-9c72-9e707803e736 +# ╠═a2c7e472-2460-428e-bfec-acf925fad89d +# ╠═bce2eecc-dc01-4bf6-9eaa-880fd8a69768 +# ╠═9ea4584c-8177-4f69-9739-b2faa93281a8 +# ╠═a2df1c35-c0b2-45bb-86b7-57e208287392 +# ╠═3228a21e-cab8-4738-bdc5-a6827c764c06 +# ╠═7b9b11f2-c6d3-4dab-ab30-6e47a3a4bfb3 +# ╠═09bc71cd-7bc0-4d5a-bcf8-984abe273375 +# ╠═744b7e78-0e5b-468d-98b1-a5511f7db311 +# ╠═ea6b28d5-f82b-4a21-9ca4-13215c6912b3 +# ╠═871664ac-5a93-4718-ae1a-c9f59f6b8374 +# ╟─dd38ffe4-4efb-4571-b5b2-76b811901387 +# ╠═ade2979d-155e-4f20-82db-6da141bb8eaa +# ╟─8d4de01a-197f-40cb-942f-bfec335e3844 +# ╠═86da848f-1e84-47c8-8a79-373f241b6025 +# ╟─f43812d2-9f87-489a-9317-e7aa19ffd3bc +# ╠═2df0563d-054a-4ad0-97af-6e06b31a7b1d +# ╠═44daff45-f608-47e3-ad6e-fca43532f322 +# ╠═37c4a8ef-d503-497a-a63c-3e43d0ebb2a7 +# ╠═0d67e350-a87e-4a07-a01c-d348f3e62599 +# ╠═cbf7d0fb-855b-442b-80c2-cfb6dcabe104 +# ╠═84e6fb12-be8c-4e00-bf9c-d45748347def +# ╠═2ba455ff-70f5-47d5-9fe8-bf4ebee9386a +# ╠═6895bcb2-9a11-4f0a-b1c2-6640f6fb509c +# ╠═fafa0a8d-5ae5-49e9-8d11-4abb5748431e +# ╠═8924673f-e99c-44b3-be6d-2abf0b2f5e23 +# ╠═fbc06121-d53a-4a64-9497-63d7f3583fbb -- 2.51.2 From e28f7c0ac9cb88e6dc0e37c7c43065133c1e2efc Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Wed, 14 Jul 2021 14:46:26 -0700 Subject: [PATCH 07/21] proofreading --- .../julia-for-matlabbers/intro/index.html | 37 +- .../julia-for-matlabbers/intro/intro.jl | 1057 +++++++++++++++-- 2 files changed, 992 insertions(+), 102 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/intro/index.html b/MisterBiggs/julia-for-matlabbers/intro/index.html index 8c07d4253..b1052615c 100644 --- a/MisterBiggs/julia-for-matlabbers/intro/index.html +++ b/MisterBiggs/julia-for-matlabbers/intro/index.html @@ -11,14 +11,14 @@ - - - + + + - - + + - + @@ -39,32 +39,33 @@ + - - - - - - + + + + + + - - + + - + diff --git a/MisterBiggs/julia-for-matlabbers/intro/intro.jl b/MisterBiggs/julia-for-matlabbers/intro/intro.jl index 47c20bd6f..8fdb45c31 100644 --- a/MisterBiggs/julia-for-matlabbers/intro/intro.jl +++ b/MisterBiggs/julia-for-matlabbers/intro/intro.jl @@ -1,72 +1,59 @@ ### A Pluto.jl notebook ### -# v0.14.8 +# v0.15.1 using Markdown using InteractiveUtils -# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error). -macro bind(def, element) - quote - local el = $(esc(element)) - global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing - el - end -end - -# ╔═╡ 7d7820ff-c0f5-41ee-be29-5006e7f4361d +# ╔═╡ 307cbf7a-1ac5-47a5-8031-3458f9dd1887 begin - import Pkg - - # Pkg.add("PlutoUI"); using PlutoUI - # Pkg.add("Plots") - using Plots - # Pkg.add("LaTeXStrings") - using LaTeXStrings + PlutoUI.TableOfContents(aside=true) end +# ╔═╡ 7d7820ff-c0f5-41ee-be29-5006e7f4361d +using LinearAlgebra + +# ╔═╡ 52819547-9593-446a-91e7-a08e08723e66 +using Plots + # ╔═╡ 3228a21e-cab8-4738-bdc5-a6827c764c06 using Unitful -# ╔═╡ 2df0563d-054a-4ad0-97af-6e06b31a7b1d -using LinearAlgebra +# ╔═╡ 3f7ae2df-9d4d-46d3-b12e-22107a560b66 +begin + using CSV + using DataFrames + using HTTP +end # ╔═╡ bb461e00-c0aa-11eb-2c7d-1bd1591779c6 md""" # Julia for People That Were Unfortunate Enough to Learn MATLAB -Julia is an incredily performant _(2 order of magnitude faster than Matlab)_, Dynamic _(Date types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. +Julia is an incredily performant _(2 order of magnitude faster than Matlab)_, Dynamic _(Data types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. !!! info "Pluto Notebooks" The code in this notebook is running in something called Pluto.jl. Pluto notebooks are similar to Matlab Livescript but have a stricter focus on cells and are immutable meaning that a variable can only be declared once and cannot be changed in other cells. This feels very restricting at first but guarantees that the code you are currently looking at is correct, and allows reactive updating of dependant code. It's important to note that these are Pluto.jl features and not Julia features. """ -# ╔═╡ 307cbf7a-1ac5-47a5-8031-3458f9dd1887 -PlutoUI.TableOfContents(aside=true) - # ╔═╡ 11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 md""" ## Intro - Things Matlab Does Really Weirdly that no one Else Does -To get started I want to focus on things that Matlab does that are outlandish and make little sense and compare them to things Julia does. Julia is obviously not perfect, but being that it's one of the newest and fastest growing languages it's easy to argue that the syntax and language design of Julia are the most modern and sane currently available in programming especially if you are focussing on engineering or science workloads. +To get started, I want to focus on things that Matlab does that are outlandish and make little sense and compare them to things Julia does. Julia is obviously not perfect, but being that it's one of the newest and fastest-growing languages, it's easy to argue that Julia's syntax and language design are the most modern and sane currently available in programming, primarily if you are focusing on engineering or science workloads. -In future chapters I will focus more on how Julia shines rather than why Matlab doesn't. +In future chapters, I will focus more on how Julia shines rather than why Matlab doesn't. ### Enviroments -A major pain point for large Matlab projects is managing installed Toolboxes and Packages. In Matlab once something is installed its available globally and doesn't require being added to a file. There are quite a few downsides to this the largest in my opinion being that its very easy to crowd your namespace. To make it even worse Matlab usually doesn't even warn you about the issue so if two packages offer a function of the same name its just going to choose one and hope it works out. Another big issue this can cause is version conflicts, this is why theres so many issues trying to run code between Matlab versions. +A significant pain point for large Matlab projects is managing installed Toolboxes and Packages. In Matlab, once something is installed it is available globally and doesn't have to be imported to a script to be used. There are quite a few downsides to this, the largest in my opinion: it is very easy to crowd your namespace. To make it even worse, Matlab usually doesn't even warn you about the issue so if two packages offer a function of the same name, it is just going to choose one and hope it works out. Another big issue this can cause is version conflicts. This is why there are so many issues trying to run code between Matlab versions. -Julia has a very intuitive package manager. For our uses I won't dig into version management or enviroments since they aren't really needed for smaller projects. +Julia has a very intuitive package manager. I won't dig into version management or environments for our uses since they aren't really needed for smaller projects. You can get away with just installing whatever package you need globally until your writing packages or working on production code. -The best way to install packages is to open the Julia REPL (basically Matlabs command window) and press `]` which puts you in Package mode. You can then `add`, `update` or `remove` packages. You can then press backspace to return to the normal REPL. Once a package is added to Julia you have to bring it into your enviroment to use it by using the `using` keyword. Below is an example that adds `PlutoUI` to make Pluto more reactive, and `Plots` which is Julias very powerful plotting library. +The best way to install packages is to open the Julia REPL (basically Matlab's command window) and press `]`, which puts you in Package mode. You can then `add`, `update`, or `remove` packages. You can then press backspace to return to the normal REPL. Once a package is added to Julia, you have to bring it into your environment using the `using` keyword. Below is an example that adds the `LinearAlgebra` library, which is part of the Julia standard library, which means it is included in every Julia installation. !!! warning "Package Management" - `import Pkg` and the `Pkg.add()` code is a way to install packages inside a script and is there to make it easy to install the packages in case they weren't already installed on your system. -""" - -# ╔═╡ d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 -md""" -Dragging the bar below automatically updates the plot thanks to Plutos reactivity. + Pluto will automatically install any of the packages in this notebook that you are missing, but this can take a long time since Julia is still very slow to compile new packages. """ # ╔═╡ 16a7201a-4ce0-4102-9874-96733514ef08 @@ -75,38 +62,24 @@ md""" This page is just HTML and doesn't have a Julia Backend to allow interactivity. The button in the top right corner has instructions on how to run this notebook yourself. """ -# ╔═╡ a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 -@bind x Slider(1:5, show_value=true) - -# ╔═╡ 863587ab-5ead-4ad0-839f-09e798bc6c93 -begin - plot(y -> y^x, title=L"f(x) = x^%$x", label="") -end - # ╔═╡ 3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 md""" ### Growing Arrays -In Matlab its very common to grow an array in a for loop using `array(end+1)` _(You really should never do this since it creates a new array every loop which gets very inefficent)_. In Julia you use `push!` for adding a single number to the end of a `Vector` and `append!` to add collections to the end of a `Vector`. You'll notice that `!` at the end of the push and append functions. In Julia the exclamation point at the end of a function name means that the function modifies the function inputs in place compared to returning a new copy of the object. +In Matlab its very common to grow an array in a for loop using `array(end+1)` _(You really should never do this since it creates a new array every loop which gets very inefficent, but I'm not here to teach you Matlab)_. In Julia, you use `push!` for adding a single number to the end of a `Vector` and `append!` to add collections _(also known as arrays or lists)_ to the end of a `Vector`. You'll notice that `!` at the end of the push and append functions. In Julia the exclamation point at the end of a function name means that the function modifies the function inputs in place compared to returning a new copy of the object. !!! note "Indexing Syntax" - Array index syntax uses square brackets `[]` in Julia as opposed to paranthesis in Matlab `()`. + Array index syntax uses square brackets `[]` in Julia instead of parenthesis in Matlab `()`. """ # ╔═╡ 0a4dc275-04b3-43e3-8a0d-cb921d769a0a a = [99, 1, 3, 5] # ╔═╡ 193c6a29-4f53-4c96-acc7-b5359043b471 -sort(a) - -# ╔═╡ e9a17e1a-652d-452e-8918-86c5adf699eb -a # a is still unsorted since sort(a) doesn't sort in place. +sort(a); a # a is still unsorted since sort(a) doesn't sort in place. # ╔═╡ 6fa90db6-9d2b-47bc-9f41-925b447912e8 -sort!(a) - -# ╔═╡ 7ef8ad0b-4724-43d3-86e2-c854c4fab9c4 -a # a is now sorted since sort!(a) sorts in place. +sort!(a); a # a is now sorted since sort!(a) sorts in place. # ╔═╡ 58c883b6-3682-424d-a1e9-8ac561bb0dbf a[end+1] = 5 # Can't grow array by indexing like in Matlab @@ -115,17 +88,18 @@ a[end+1] = 5 # Can't grow array by indexing like in Matlab md""" ### Functions -Matlab functions have a ton of weird behaviors. The weirdest being that optional function returns are done base on the amount of return values so: +Matlab functions have a ton of weird behaviors. The weirdest being that optional function returns are done based on the amount of return values so: ```julia +% Matlab Example P = polyfit(X,Y,N) [P,S] = polyfit(X,Y,N) [P,S,MU] = polyfit(X,Y,N) ``` -all return different things. In this case its simple to tell what is going on but if you had no idea what the polyfit function did in the first place its totally unintuitive what the extra returned values are. In other languages if a function has optional returns its usually idiomatic to return those values with an optional keyword argument or you just have a completely different function to get the different data. In the case of polyfit calculating S and MU are unrelated to calculating P so its not like the data was already calculated and can be easily returned which is what you would generally expect of optional arguments. To make things even worse `S` is designed to be an input to a different function, `POLYVAL`, so why wouldn't you just make polyval take `X`, `Y`, and `N` as inputs? Matlab is dumb `/endrant`. +all return different things. In this case, it's simple to tell what is going on, but if you had no idea what the `polyfit` function did in the first place it is totally unintuitive what the extra returned values are. If a function has optional returns in other languages, it is usually idiomatic to return those values with an optional keyword argument or just have a completely different function to get the different data. In the case of `polyfit`, calculating S and MU are unrelated to calculating P, so it is not like the data was already calculated and can be quickly returned like you would generally expect to be the case with optional returns. To make things even worse, `S` is designed to be an input to a different function, `POLYVAL`, so why wouldn't you just make polyval take `X`, `Y`, and `N` as inputs? Matlab is dumb `/endrant`. -Another weird thing is where functions can be placed in Matlab. In livescripts they can only be placed at the end of the file, and theres also the ability to make files that are only a function. In Julia functions can be anywhere and files can contain as many functions as you want and can be imported by any other file. The function syntax in Julia is also very sane. +Another weird thing is where functions can be placed in Matlab. In livescripts they can only be placed at the end of the file, and there's also the ability to make files that are only a function. In Julia, functions can be anywhere, and files can contain as many functions as you want and can be imported by any other file. The function syntax in Julia is also very sane. """ # ╔═╡ f4d655a2-8539-43f7-9356-56a3e3f9de91 @@ -136,12 +110,21 @@ function g(x, y) z = x^2 + y^2 return z # Returns can either be the last line of a function or use the return keyword. Returning something ends a function so any lines after a return statement would not execute. -end # Functions have to have an end +end # Multi line functions have to have an end # ╔═╡ ec37197c-f18e-48c2-8266-867e28cfc138 g() = g(6, 9.1) # Multiple functions can share names. -# This is also the wrong way to have default values for input arguments. -# g(x=6, y=9.1) ... would be the correct way to have default inputs that dont need to be specified. + +# ╔═╡ 7fc003bb-bf1f-42fa-94c7-c7e778edda61 +md""" +!!! note + Functions can also have default values. Instead of the case above where g() just calls g(x, y) with some values that would be common you could instead declare g(x, y) with default values: +```julia +function g(x=6, y=9.1) + z = x^2 + 6^2 +end +``` +""" # ╔═╡ 3c921f2d-3972-4b88-990d-36ced0764bc5 # Julia will always use the closest matching function. @@ -159,12 +142,12 @@ g(5.0, 6.0) # Normal g function used since inputs are floats g() # Uses normal g function since there is no match for g that has a Int and a Float specified as inputs. # ╔═╡ 9440e0bc-7920-4b81-b88a-0b1046d24b4c -g(5,6) # Integer method used since inputs are both integers. +g(5, 6) # Integer method used since inputs are both integers. # ╔═╡ 86c23c4e-ab5b-4404-b248-c980a4098676 md""" !!! note - In Julia when an array is passed into a function a copy the actual array gets passed in, not a copy. This means if array `x` is passed into `f(x)`, any changes made to the array will apply to `x` outside of the array. If you intend to modify the passed in array be sure to add a bang `!` to the end of function name to keep your code idiomatic. + In Julia when an array is passed into a function the actual array gets passed in, not a copy. This means if array `x` is passed into `f(x)`, any changes made to the array will apply to `x` outside of the array. If you intend to modify the passed in array be sure to add a bang `!` to the end of function name to keep your code idiomatic. """ # ╔═╡ e239604f-2926-455b-a20c-0d9c283cc60a @@ -242,7 +225,7 @@ plot!(atan, label="atan") # Returns a new plot with all the elements of the old # ╔═╡ dc89d08d-29bf-4e04-8470-c79c88ab4689 md""" !!! note - The Julia plotting library is massive and supports many frontends that are useful for various use cases such as printing in the terminal or making interactive plots for websites. This will all be covered in a future post. + The Julia plotting library is massive and supports many frontends that are useful for various use cases such as printing in the terminal or making interactive plots for websites. """ # ╔═╡ b30e6f73-fe46-45e7-898e-dd1205dffe68 @@ -260,7 +243,7 @@ Julia doesn't automatically print script values except in certain circumstances #### `...` Syntax -Matlab uses ... to continue lines of code. In Julia this is called the splat operator and is used to pass a collection into arguments of a function: +Matlab uses `...` to continue lines of code. In Julia this is called the splat operator and is used to pass a collection into arguments of a function: ```julia xs = [1 2 3] @@ -269,6 +252,8 @@ xs = [1 2 3] f(xs...) f(1, 2, 3) ``` + +If a line of code is multi line no additional syntax is needed, Julia is smart enough to know when a statement of code is complete. """ # ╔═╡ 916f5f09-1aa3-47a7-9c66-c42513eaccea @@ -320,13 +305,6 @@ end # ╔═╡ bce2eecc-dc01-4bf6-9eaa-880fd8a69768 [i for i in 1:1e6] -# ╔═╡ 9ea4584c-8177-4f69-9739-b2faa93281a8 -md""" ---- - -### Matrix Math -""" - # ╔═╡ a2df1c35-c0b2-45bb-86b7-57e208287392 md""" --- @@ -355,7 +333,7 @@ weight = mass * gravity # You can mix unit systems # ╔═╡ dd38ffe4-4efb-4571-b5b2-76b811901387 md""" -You'll notice that the weight was left as a gross collection of units instead of automatically converting to `N` like we woule expect. This is usually the case but can easily be fixed by using Julias pipe operator, `|>`. +You'll notice that the weight was left as a weird collection of units instead of automatically converting to `N` like we woule expect. This is usually the case but can easily be fixed by using Julias pipe operator, `|>`. !!! note "The Pipe Operator" The pipe operator, or `|>` is a great way to chain function calls in Julia. Using `x |> f` is the exact same as using `f(x)` but in many cases can be much clearer. @@ -378,6 +356,18 @@ Units can also be stripped to give a normal number again. # ╔═╡ 86da848f-1e84-47c8-8a79-373f241b6025 ustrip(u"N", weight) +# ╔═╡ dc898d32-b30b-4baa-a595-b83ccd1dc86d +md""" +# Everything below isn't close to being finished +""" + +# ╔═╡ 9ea4584c-8177-4f69-9739-b2faa93281a8 +md""" +--- + +### Matrix Math +""" + # ╔═╡ f43812d2-9f87-489a-9317-e7aa19ffd3bc md""" --- @@ -392,8 +382,7 @@ struct Quaternion k::Float64 r::Float64 - Quaternion(i, j, k, r) = norm([i, j, k, r]) ≈ 1 ? new(i, j, k, r) : error("Magnitude not equal to 1.") - Quaternion(q) = Quaternion(q[1], q[2], q[3], q[4]) + Quaternion(i, j, k, r) = norm([i, j, k, r]) ≈ 1 ? new(i, j, k, r) : error("Magnitude not equal to 1.") Quaternion() = new(0, 0, 0, 1) Quaternion(yaw, pitch, roll) = Quaternion([0 0 sin(yaw / 2) cos(yaw / 2)]) * Quaternion([0 sin(pitch / 2) 0 cos(pitch / 2)]) * Quaternion([sin(roll / 2) 0 0 cos(roll / 2)]) @@ -409,6 +398,9 @@ struct Quaternion end +# ╔═╡ 639fc5f0-1ab8-4d4e-83b5-77a82ae9bdf8 +q() = Quaternion() + # ╔═╡ 37c4a8ef-d503-497a-a63c-3e43d0ebb2a7 function QuaternionMultiplication(l::Quaternion, r::Quaternion) R = [r.r r.k r.j r.i; @@ -443,6 +435,9 @@ q1 = Quaternion(1,0,0,0) # ╔═╡ 6895bcb2-9a11-4f0a-b1c2-6640f6fb509c q2 = Quaternion([1 2 3], π) +# ╔═╡ 045a1898-a3db-4e65-9711-9e4608ce09c6 +q()*q() + # ╔═╡ fafa0a8d-5ae5-49e9-8d11-4abb5748431e q1*q2 @@ -457,31 +452,919 @@ md""" md""" ## Things Julia Does Poorly -Performance +Nothing you nerd + +Time to First Plot Libraries Still young and breaking things """ +# ╔═╡ 00000000-0000-0000-0000-000000000001 +PLUTO_PROJECT_TOML_CONTENTS = """ +[deps] +CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" +LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" +Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[compat] +CSV = "~0.8.5" +DataFrames = "~1.2.0" +HTTP = "~0.9.12" +Plots = "~1.19.0" +PlutoUI = "~0.7.9" +Unitful = "~1.8.0" +""" + +# ╔═╡ 00000000-0000-0000-0000-000000000002 +PLUTO_MANIFEST_TOML_CONTENTS = """ +# This file is machine-generated - editing it directly is not advised + +[[Adapt]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "84918055d15b3114ede17ac6a7182f68870c16f7" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "3.3.1" + +[[ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" + +[[Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" + +[[Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" + +[[Bzip2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "c3598e525718abcc440f69cc6d5f60dda0a1b61e" +uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" +version = "1.0.6+5" + +[[CSV]] +deps = ["Dates", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode"] +git-tree-sha1 = "b83aa3f513be680454437a0eee21001607e5d983" +uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +version = "0.8.5" + +[[Cairo_jll]] +deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "e2f47f6d8337369411569fd45ae5753ca10394c6" +uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a" +version = "1.16.0+6" + +[[ColorSchemes]] +deps = ["ColorTypes", "Colors", "FixedPointNumbers", "Random", "StaticArrays"] +git-tree-sha1 = "ed268efe58512df8c7e224d2e170afd76dd6a417" +uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" +version = "3.13.0" + +[[ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "024fe24d83e4a5bf5fc80501a314ce0d1aa35597" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.0" + +[[Colors]] +deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] +git-tree-sha1 = "417b0ed7b8b838aa6ca0a87aadf1bb9eb111ce40" +uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" +version = "0.12.8" + +[[Compat]] +deps = ["Base64", "Dates", "DelimitedFiles", "Distributed", "InteractiveUtils", "LibGit2", "Libdl", "LinearAlgebra", "Markdown", "Mmap", "Pkg", "Printf", "REPL", "Random", "SHA", "Serialization", "SharedArrays", "Sockets", "SparseArrays", "Statistics", "Test", "UUIDs", "Unicode"] +git-tree-sha1 = "dc7dedc2c2aa9faf59a55c622760a25cbefbe941" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "3.31.0" + +[[CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" + +[[ConstructionBase]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "f74e9d5388b8620b4cee35d4c5a618dd4dc547f4" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.3.0" + +[[Contour]] +deps = ["StaticArrays"] +git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7" +uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" +version = "0.5.7" + +[[Crayons]] +git-tree-sha1 = "3f71217b538d7aaee0b69ab47d9b7724ca8afa0d" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.0.4" + +[[DataAPI]] +git-tree-sha1 = "ee400abb2298bd13bfc3df1c412ed228061a2385" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.7.0" + +[[DataFrames]] +deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +git-tree-sha1 = "1dadfca11c0e08e03ab15b63aaeda55266754bad" +uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +version = "1.2.0" + +[[DataStructures]] +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "4437b64df1e0adccc3e5d1adbc3ac741095e4677" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.18.9" + +[[DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" + +[[DelimitedFiles]] +deps = ["Mmap"] +uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" + +[[Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" + +[[Downloads]] +deps = ["ArgTools", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" + +[[EarCut_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "92d8f9f208637e8d2d28c664051a00569c01493d" +uuid = "5ae413db-bbd1-5e63-b57d-d24a61df00f5" +version = "2.1.5+1" + +[[Expat_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "b3bfd02e98aedfa5cf885665493c5598c350cd2f" +uuid = "2e619515-83b5-522b-bb60-26c02a35a201" +version = "2.2.10+0" + +[[FFMPEG]] +deps = ["FFMPEG_jll"] +git-tree-sha1 = "b57e3acbe22f8484b4b5ff66a7499717fe1a9cc8" +uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" +version = "0.4.1" + +[[FFMPEG_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "LibVPX_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "Pkg", "Zlib_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] +git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f" +uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" +version = "4.3.1+4" + +[[FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.4" + +[[Fontconfig_jll]] +deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Pkg", "Zlib_jll"] +git-tree-sha1 = "35895cf184ceaab11fd778b4590144034a167a2f" +uuid = "a3f928ae-7b40-5064-980b-68af3947d34b" +version = "2.13.1+14" + +[[Formatting]] +deps = ["Printf"] +git-tree-sha1 = "8339d61043228fdd3eb658d86c926cb282ae72a8" +uuid = "59287772-0a20-5a39-b81b-1366585eb4c0" +version = "0.4.2" + +[[FreeType2_jll]] +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] +git-tree-sha1 = "cbd58c9deb1d304f5a245a0b7eb841a2560cfec6" +uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7" +version = "2.10.1+5" + +[[FriBidi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91" +uuid = "559328eb-81f9-559d-9380-de523a88c83c" +version = "1.0.10+0" + +[[Future]] +deps = ["Random"] +uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" + +[[GLFW_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"] +git-tree-sha1 = "dba1e8614e98949abfa60480b13653813d8f0157" +uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89" +version = "3.3.5+0" + +[[GR]] +deps = ["Base64", "DelimitedFiles", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Pkg", "Printf", "Random", "Serialization", "Sockets", "Test", "UUIDs"] +git-tree-sha1 = "b83e3125048a9c3158cbb7ca423790c7b1b57bea" +uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" +version = "0.57.5" + +[[GR_jll]] +deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Pkg", "Qt5Base_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "e14907859a1d3aee73a019e7b3c98e9e7b8b5b3e" +uuid = "d2c73de3-f751-5644-a686-071e5b155ba9" +version = "0.57.3+0" + +[[GeometryBasics]] +deps = ["EarCut_jll", "IterTools", "LinearAlgebra", "StaticArrays", "StructArrays", "Tables"] +git-tree-sha1 = "15ff9a14b9e1218958d3530cc288cf31465d9ae2" +uuid = "5c1252a2-5f33-56bf-86c9-59e7332b4326" +version = "0.3.13" + +[[Gettext_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "9b02998aba7bf074d14de89f9d37ca24a1a0b046" +uuid = "78b55507-aeef-58d4-861c-77aaff3498b1" +version = "0.21.0+0" + +[[Glib_jll]] +deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE_jll", "Pkg", "Zlib_jll"] +git-tree-sha1 = "47ce50b742921377301e15005c96e979574e130b" +uuid = "7746bdde-850d-59dc-9ae8-88ece973131d" +version = "2.68.1+0" + +[[Grisu]] +git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2" +uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe" +version = "1.0.2" + +[[HTTP]] +deps = ["Base64", "Dates", "IniFile", "Logging", "MbedTLS", "NetworkOptions", "Sockets", "URIs"] +git-tree-sha1 = "c6a1fff2fd4b1da29d3dccaffb1e1001244d844e" +uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" +version = "0.9.12" + +[[IniFile]] +deps = ["Test"] +git-tree-sha1 = "098e4d2c533924c921f9f9847274f2ad89e018b8" +uuid = "83e8ac13-25f8-5344-8a64-a9f2b223428f" +version = "0.5.0" + +[[InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" + +[[InvertedIndices]] +deps = ["Test"] +git-tree-sha1 = "15732c475062348b0165684ffe28e85ea8396afc" +uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" +version = "1.0.0" + +[[IterTools]] +git-tree-sha1 = "05110a2ab1fc5f932622ffea2a003221f4782c18" +uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" +version = "1.3.0" + +[[IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[JLLWrappers]] +deps = ["Preferences"] +git-tree-sha1 = "642a199af8b68253517b80bd3bfd17eb4e84df6e" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.3.0" + +[[JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "81690084b6198a2e1da36fcfda16eeca9f9f24e4" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.1" + +[[JpegTurbo_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "d735490ac75c5cb9f1b00d8b5509c11984dc6943" +uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" +version = "2.1.0+0" + +[[LAME_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "f6250b16881adf048549549fba48b1161acdac8c" +uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d" +version = "3.100.1+0" + +[[LZO_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "e5b909bcf985c5e2605737d2ce278ed791b89be6" +uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac" +version = "2.10.1+0" + +[[LaTeXStrings]] +git-tree-sha1 = "c7f1c695e06c01b95a67f0cd1d34994f3e7db104" +uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +version = "1.2.1" + +[[Latexify]] +deps = ["Formatting", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "Printf", "Requires"] +git-tree-sha1 = "a4b12a1bd2ebade87891ab7e36fdbce582301a92" +uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" +version = "0.15.6" + +[[LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" + +[[LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" + +[[LibGit2]] +deps = ["Base64", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" + +[[LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" + +[[LibVPX_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "12ee7e23fa4d18361e7c2cde8f8337d4c3101bc7" +uuid = "dd192d2f-8180-539f-9fb4-cc70b1dcf69a" +version = "1.10.0+0" + +[[Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" + +[[Libffi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "761a393aeccd6aa92ec3515e428c26bf99575b3b" +uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490" +version = "3.2.2+0" + +[[Libgcrypt_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll", "Pkg"] +git-tree-sha1 = "64613c82a59c120435c067c2b809fc61cf5166ae" +uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4" +version = "1.8.7+0" + +[[Libglvnd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"] +git-tree-sha1 = "7739f837d6447403596a75d19ed01fd08d6f56bf" +uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29" +version = "1.3.0+3" + +[[Libgpg_error_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "c333716e46366857753e273ce6a69ee0945a6db9" +uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8" +version = "1.42.0+0" + +[[Libiconv_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "42b62845d70a619f063a7da093d995ec8e15e778" +uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" +version = "1.16.1+1" + +[[Libmount_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "9c30530bf0effd46e15e0fdcf2b8636e78cbbd73" +uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9" +version = "2.35.0+0" + +[[Libtiff_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Pkg", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "340e257aada13f95f98ee352d316c3bed37c8ab9" +uuid = "89763e89-9b03-5906-acba-b20f662cd828" +version = "4.3.0+0" + +[[Libuuid_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "7f3efec06033682db852f8b3bc3c1d2b0a0ab066" +uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700" +version = "2.36.0+0" + +[[LinearAlgebra]] +deps = ["Libdl"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" + +[[Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" + +[[MacroTools]] +deps = ["Markdown", "Random"] +git-tree-sha1 = "6a8a2a625ab0dea913aba95c11370589e0239ff0" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.6" + +[[Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" + +[[MbedTLS]] +deps = ["Dates", "MbedTLS_jll", "Random", "Sockets"] +git-tree-sha1 = "1c38e51c3d08ef2278062ebceade0e46cefc96fe" +uuid = "739be429-bea8-5141-9913-cc70e7f3736d" +version = "1.0.3" + +[[MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" + +[[Measures]] +git-tree-sha1 = "e498ddeee6f9fdb4551ce855a46f54dbd900245f" +uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e" +version = "0.3.1" + +[[Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "4ea90bd5d3985ae1f9a908bd4500ae88921c5ce7" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "1.0.0" + +[[Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" + +[[MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" + +[[NaNMath]] +git-tree-sha1 = "bfe47e760d60b82b66b61d2d44128b62e3a369fb" +uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +version = "0.3.5" + +[[NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" + +[[Ogg_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "7937eda4681660b4d6aeeecc2f7e1c81c8ee4e2f" +uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051" +version = "1.3.5+0" + +[[OpenSSL_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "15003dcb7d8db3c6c857fda14891a539a8f2705a" +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "1.1.10+0" + +[[Opus_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "51a08fb14ec28da2ec7a927c4337e4332c2a4720" +uuid = "91d4177d-7536-5919-b921-800302f37372" +version = "1.3.2+0" + +[[OrderedCollections]] +git-tree-sha1 = "85f8e6578bf1f9ee0d11e7bb1b1456435479d47c" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.4.1" + +[[PCRE_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "b2a7af664e098055a7529ad1a900ded962bca488" +uuid = "2f80f16e-611a-54ab-bc61-aa92de5b98fc" +version = "8.44.0+0" + +[[Parsers]] +deps = ["Dates"] +git-tree-sha1 = "c8abc88faa3f7a3950832ac5d6e690881590d6dc" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "1.1.0" + +[[Pixman_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "b4f5d02549a10e20780a24fce72bea96b6329e29" +uuid = "30392449-352a-5448-841d-b1acce4e97dc" +version = "0.40.1+0" + +[[Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "REPL", "Random", "SHA", "Serialization", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" + +[[PlotThemes]] +deps = ["PlotUtils", "Requires", "Statistics"] +git-tree-sha1 = "a3a964ce9dc7898193536002a6dd892b1b5a6f1d" +uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a" +version = "2.0.1" + +[[PlotUtils]] +deps = ["ColorSchemes", "Colors", "Dates", "Printf", "Random", "Reexport", "Statistics"] +git-tree-sha1 = "501c20a63a34ac1d015d5304da0e645f42d91c9f" +uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043" +version = "1.0.11" + +[[Plots]] +deps = ["Base64", "Contour", "Dates", "FFMPEG", "FixedPointNumbers", "GR", "GeometryBasics", "JSON", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "PlotThemes", "PlotUtils", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "UUIDs"] +git-tree-sha1 = "83c762ddea05f5554e1b04f4a5ecae61990ccc8e" +uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +version = "1.19.0" + +[[PlutoUI]] +deps = ["Base64", "Dates", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "Suppressor"] +git-tree-sha1 = "44e225d5837e2a2345e69a1d1e01ac2443ff9fcb" +uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" +version = "0.7.9" + +[[PooledArrays]] +deps = ["DataAPI", "Future"] +git-tree-sha1 = "cde4ce9d6f33219465b55162811d8de8139c0414" +uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" +version = "1.2.1" + +[[Preferences]] +deps = ["TOML"] +git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.2.2" + +[[PrettyTables]] +deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"] +git-tree-sha1 = "0d1245a357cc61c8cd61934c07447aa569ff22e6" +uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" +version = "1.1.0" + +[[Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" + +[[Qt5Base_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "xkbcommon_jll"] +git-tree-sha1 = "ad368663a5e20dbb8d6dc2fddeefe4dae0781ae8" +uuid = "ea2cea3b-5b76-57ae-a6ef-0a8af62496e1" +version = "5.15.3+0" + +[[REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" + +[[Random]] +deps = ["Serialization"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" + +[[RecipesBase]] +git-tree-sha1 = "b3fb709f3c97bfc6e948be68beeecb55a0b340ae" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +version = "1.1.1" + +[[RecipesPipeline]] +deps = ["Dates", "NaNMath", "PlotUtils", "RecipesBase"] +git-tree-sha1 = "2a7a2469ed5d94a98dea0e85c46fa653d76be0cd" +uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" +version = "0.3.4" + +[[Reexport]] +git-tree-sha1 = "5f6c21241f0f655da3952fd60aa18477cf96c220" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.1.0" + +[[Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "4036a3bd08ac7e968e27c203d45f5fff15020621" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.1.3" + +[[SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" + +[[Scratch]] +deps = ["Dates"] +git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda" +uuid = "6c6a2e73-6563-6170-7368-637461726353" +version = "1.1.0" + +[[SentinelArrays]] +deps = ["Dates", "Random"] +git-tree-sha1 = "ffae887d0f0222a19c406a11c3831776d1383e3d" +uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" +version = "1.3.3" + +[[Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" + +[[SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" + +[[Showoff]] +deps = ["Dates", "Grisu"] +git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de" +uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f" +version = "1.0.3" + +[[Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" + +[[SortingAlgorithms]] +deps = ["DataStructures"] +git-tree-sha1 = "b3363d7460f7d098ca0912c69b082f75625d7508" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "1.0.1" + +[[SparseArrays]] +deps = ["LinearAlgebra", "Random"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + +[[StaticArrays]] +deps = ["LinearAlgebra", "Random", "Statistics"] +git-tree-sha1 = "a43a7b58a6e7dc933b2fa2e0ca653ccf8bb8fd0e" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.2.6" + +[[Statistics]] +deps = ["LinearAlgebra", "SparseArrays"] +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" + +[[StatsAPI]] +git-tree-sha1 = "1958272568dc176a1d881acb797beb909c785510" +uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" +version = "1.0.0" + +[[StatsBase]] +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "2f6792d523d7448bbe2fec99eca9218f06cc746d" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.33.8" + +[[StructArrays]] +deps = ["Adapt", "DataAPI", "StaticArrays", "Tables"] +git-tree-sha1 = "000e168f5cc9aded17b6999a560b7c11dda69095" +uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" +version = "0.6.0" + +[[Suppressor]] +git-tree-sha1 = "a819d77f31f83e5792a76081eee1ea6342ab8787" +uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb" +version = "0.2.0" + +[[TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" + +[[TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "LinearAlgebra", "TableTraits", "Test"] +git-tree-sha1 = "8ed4a3ea724dac32670b062be3ef1c1de6773ae8" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.4.4" + +[[Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" + +[[Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[URIs]] +git-tree-sha1 = "97bbe755a53fe859669cd907f2d96aee8d2c1355" +uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +version = "1.3.0" + +[[UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" + +[[Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" + +[[Unitful]] +deps = ["ConstructionBase", "Dates", "LinearAlgebra", "Random"] +git-tree-sha1 = "b3682a0559219355f1e3c8024e9f97adce2d4623" +uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" +version = "1.8.0" + +[[Wayland_jll]] +deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "3e61f0b86f90dacb0bc0e73a0c5a83f6a8636e23" +uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89" +version = "1.19.0+0" + +[[Wayland_protocols_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll"] +git-tree-sha1 = "2839f1c1296940218e35df0bbb220f2a79686670" +uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91" +version = "1.18.0+4" + +[[XML2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Pkg", "Zlib_jll"] +git-tree-sha1 = "1acf5bdf07aa0907e0a37d3718bb88d4b687b74a" +uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" +version = "2.9.12+0" + +[[XSLT_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "Pkg", "XML2_jll", "Zlib_jll"] +git-tree-sha1 = "91844873c4085240b95e795f692c4cec4d805f8a" +uuid = "aed1982a-8fda-507f-9586-7b0439959a61" +version = "1.1.34+0" + +[[Xorg_libX11_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] +git-tree-sha1 = "5be649d550f3f4b95308bf0183b82e2582876527" +uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc" +version = "1.6.9+4" + +[[Xorg_libXau_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "4e490d5c960c314f33885790ed410ff3a94ce67e" +uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" +version = "1.0.9+4" + +[[Xorg_libXcursor_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXfixes_jll", "Xorg_libXrender_jll"] +git-tree-sha1 = "12e0eb3bc634fa2080c1c37fccf56f7c22989afd" +uuid = "935fb764-8cf2-53bf-bb30-45bb1f8bf724" +version = "1.2.0+4" + +[[Xorg_libXdmcp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "4fe47bd2247248125c428978740e18a681372dd4" +uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05" +version = "1.1.3+4" + +[[Xorg_libXext_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] +git-tree-sha1 = "b7c0aa8c376b31e4852b360222848637f481f8c3" +uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3" +version = "1.3.4+4" + +[[Xorg_libXfixes_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] +git-tree-sha1 = "0e0dc7431e7a0587559f9294aeec269471c991a4" +uuid = "d091e8ba-531a-589c-9de9-94069b037ed8" +version = "5.0.3+4" + +[[Xorg_libXi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXfixes_jll"] +git-tree-sha1 = "89b52bc2160aadc84d707093930ef0bffa641246" +uuid = "a51aa0fd-4e3c-5386-b890-e753decda492" +version = "1.7.10+4" + +[[Xorg_libXinerama_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll"] +git-tree-sha1 = "26be8b1c342929259317d8b9f7b53bf2bb73b123" +uuid = "d1454406-59df-5ea1-beac-c340f2130bc3" +version = "1.1.4+4" + +[[Xorg_libXrandr_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll"] +git-tree-sha1 = "34cea83cb726fb58f325887bf0612c6b3fb17631" +uuid = "ec84b674-ba8e-5d96-8ba1-2a689ba10484" +version = "1.5.2+4" + +[[Xorg_libXrender_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] +git-tree-sha1 = "19560f30fd49f4d4efbe7002a1037f8c43d43b96" +uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" +version = "0.9.10+4" + +[[Xorg_libpthread_stubs_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "6783737e45d3c59a4a4c4091f5f88cdcf0908cbb" +uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74" +version = "0.1.0+3" + +[[Xorg_libxcb_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"] +git-tree-sha1 = "daf17f441228e7a3833846cd048892861cff16d6" +uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b" +version = "1.13.0+3" + +[[Xorg_libxkbfile_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll"] +git-tree-sha1 = "926af861744212db0eb001d9e40b5d16292080b2" +uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a" +version = "1.1.0+4" + +[[Xorg_xcb_util_image_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "0fab0a40349ba1cba2c1da699243396ff8e94b97" +uuid = "12413925-8142-5f55-bb0e-6d7ca50bb09b" +version = "0.4.0+1" + +[[Xorg_xcb_util_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxcb_jll"] +git-tree-sha1 = "e7fd7b2881fa2eaa72717420894d3938177862d1" +uuid = "2def613f-5ad1-5310-b15b-b15d46f528f5" +version = "0.4.0+1" + +[[Xorg_xcb_util_keysyms_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "d1151e2c45a544f32441a567d1690e701ec89b00" +uuid = "975044d2-76e6-5fbe-bf08-97ce7c6574c7" +version = "0.4.0+1" + +[[Xorg_xcb_util_renderutil_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "dfd7a8f38d4613b6a575253b3174dd991ca6183e" +uuid = "0d47668e-0667-5a69-a72c-f761630bfb7e" +version = "0.3.9+1" + +[[Xorg_xcb_util_wm_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xcb_util_jll"] +git-tree-sha1 = "e78d10aab01a4a154142c5006ed44fd9e8e31b67" +uuid = "c22f9ab0-d5fe-5066-847c-f4bb1cd4e361" +version = "0.4.1+1" + +[[Xorg_xkbcomp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libxkbfile_jll"] +git-tree-sha1 = "4bcbf660f6c2e714f87e960a171b119d06ee163b" +uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4" +version = "1.4.2+4" + +[[Xorg_xkeyboard_config_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_xkbcomp_jll"] +git-tree-sha1 = "5c8424f8a67c3f2209646d4425f3d415fee5931d" +uuid = "33bec58e-1273-512f-9401-5d533626f822" +version = "2.27.0+4" + +[[Xorg_xtrans_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "79c31e7844f6ecf779705fbc12146eb190b7d845" +uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10" +version = "1.4.0+3" + +[[Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" + +[[Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "cc4bf3fdde8b7e3e9fa0351bdeedba1cf3b7f6e6" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.0+0" + +[[libass_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] +git-tree-sha1 = "acc685bcf777b2202a904cdcb49ad34c2fa1880c" +uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0" +version = "0.14.0+4" + +[[libfdk_aac_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "7a5780a0d9c6864184b3a2eeeb833a0c871f00ab" +uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280" +version = "0.1.6+4" + +[[libpng_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Zlib_jll"] +git-tree-sha1 = "94d180a6d2b5e55e447e2d27a29ed04fe79eb30c" +uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" +version = "1.6.38+0" + +[[libvorbis_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"] +git-tree-sha1 = "c45f4e40e7aafe9d086379e5578947ec8b95a8fb" +uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a" +version = "1.3.7+0" + +[[nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" + +[[p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" + +[[x264_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "d713c1ce4deac133e3334ee12f4adff07f81778f" +uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a" +version = "2020.7.14+2" + +[[x265_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "487da2f8f2f0c8ee0e83f39d13037d6bbf0a45ab" +uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76" +version = "3.0.0+3" + +[[xkbcommon_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"] +git-tree-sha1 = "ece2350174195bb31de1a63bea3a41ae1aa593b6" +uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd" +version = "0.9.1+5" +""" + # ╔═╡ Cell order: # ╟─bb461e00-c0aa-11eb-2c7d-1bd1591779c6 # ╟─307cbf7a-1ac5-47a5-8031-3458f9dd1887 # ╟─11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 # ╠═7d7820ff-c0f5-41ee-be29-5006e7f4361d -# ╟─d15dbf3e-45a8-454f-83eb-e9ad5eac5d24 # ╟─16a7201a-4ce0-4102-9874-96733514ef08 -# ╟─a6ea55b5-3d1e-4f3c-8b5b-bb6138b6b316 -# ╟─863587ab-5ead-4ad0-839f-09e798bc6c93 # ╟─3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 # ╠═0a4dc275-04b3-43e3-8a0d-cb921d769a0a # ╠═193c6a29-4f53-4c96-acc7-b5359043b471 -# ╠═e9a17e1a-652d-452e-8918-86c5adf699eb # ╠═6fa90db6-9d2b-47bc-9f41-925b447912e8 -# ╠═7ef8ad0b-4724-43d3-86e2-c854c4fab9c4 # ╠═58c883b6-3682-424d-a1e9-8ac561bb0dbf # ╟─a74e7cad-8dae-41cd-b77a-65ba082956a3 # ╠═f4d655a2-8539-43f7-9356-56a3e3f9de91 # ╠═289727e4-fb29-4ba8-97c5-cce62da725bc # ╠═ec37197c-f18e-48c2-8266-867e28cfc138 +# ╟─7fc003bb-bf1f-42fa-94c7-c7e778edda61 # ╠═3c921f2d-3972-4b88-990d-36ced0764bc5 # ╠═b7ae33bc-5edd-4741-a578-d210521b1698 # ╠═75eeaff0-4fd3-4745-b042-af8ba12a0506 @@ -501,6 +1384,7 @@ Still young and breaking things # ╠═4fd4f72d-45e0-4760-bc0b-5ebb78636e2c # ╠═cf125fe2-c754-4218-92c9-3f491f3109c1 # ╟─4802d903-e87c-4ef0-a184-e4ae7af69a28 +# ╠═52819547-9593-446a-91e7-a08e08723e66 # ╠═a4665e30-4c64-46d1-8349-a49f40763a0b # ╠═09303ffe-6cf8-4273-b697-9fbd7cb82cc1 # ╠═e3b51038-2e57-4a5a-9b5d-7bf7148d700b @@ -512,10 +1396,9 @@ Still young and breaking things # ╟─fd0f5cf6-c90b-4492-9c72-9e707803e736 # ╠═a2c7e472-2460-428e-bfec-acf925fad89d # ╠═bce2eecc-dc01-4bf6-9eaa-880fd8a69768 -# ╠═9ea4584c-8177-4f69-9739-b2faa93281a8 -# ╠═a2df1c35-c0b2-45bb-86b7-57e208287392 +# ╟─a2df1c35-c0b2-45bb-86b7-57e208287392 # ╠═3228a21e-cab8-4738-bdc5-a6827c764c06 -# ╠═7b9b11f2-c6d3-4dab-ab30-6e47a3a4bfb3 +# ╟─7b9b11f2-c6d3-4dab-ab30-6e47a3a4bfb3 # ╠═09bc71cd-7bc0-4d5a-bcf8-984abe273375 # ╠═744b7e78-0e5b-468d-98b1-a5511f7db311 # ╠═ea6b28d5-f82b-4a21-9ca4-13215c6912b3 @@ -524,15 +1407,21 @@ Still young and breaking things # ╠═ade2979d-155e-4f20-82db-6da141bb8eaa # ╟─8d4de01a-197f-40cb-942f-bfec335e3844 # ╠═86da848f-1e84-47c8-8a79-373f241b6025 -# ╟─f43812d2-9f87-489a-9317-e7aa19ffd3bc -# ╠═2df0563d-054a-4ad0-97af-6e06b31a7b1d +# ╟─dc898d32-b30b-4baa-a595-b83ccd1dc86d +# ╠═9ea4584c-8177-4f69-9739-b2faa93281a8 +# ╠═f43812d2-9f87-489a-9317-e7aa19ffd3bc # ╠═44daff45-f608-47e3-ad6e-fca43532f322 +# ╠═639fc5f0-1ab8-4d4e-83b5-77a82ae9bdf8 # ╠═37c4a8ef-d503-497a-a63c-3e43d0ebb2a7 # ╠═0d67e350-a87e-4a07-a01c-d348f3e62599 # ╠═cbf7d0fb-855b-442b-80c2-cfb6dcabe104 # ╠═84e6fb12-be8c-4e00-bf9c-d45748347def # ╠═2ba455ff-70f5-47d5-9fe8-bf4ebee9386a # ╠═6895bcb2-9a11-4f0a-b1c2-6640f6fb509c +# ╠═045a1898-a3db-4e65-9711-9e4608ce09c6 # ╠═fafa0a8d-5ae5-49e9-8d11-4abb5748431e # ╠═8924673f-e99c-44b3-be6d-2abf0b2f5e23 +# ╠═3f7ae2df-9d4d-46d3-b12e-22107a560b66 # ╠═fbc06121-d53a-4a64-9497-63d7f3583fbb +# ╟─00000000-0000-0000-0000-000000000001 +# ╟─00000000-0000-0000-0000-000000000002 -- 2.51.2 From 7d8db950144cdd98350dd390ed90b7be75e8a0a9 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Wed, 14 Jul 2021 14:47:18 -0700 Subject: [PATCH 08/21] redone directory structure --- MisterBiggs/julia-for-matlabbers/{intro => }/index.html | 0 MisterBiggs/julia-for-matlabbers/{intro/intro.jl => index.jl} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename MisterBiggs/julia-for-matlabbers/{intro => }/index.html (100%) rename MisterBiggs/julia-for-matlabbers/{intro/intro.jl => index.jl} (100%) diff --git a/MisterBiggs/julia-for-matlabbers/intro/index.html b/MisterBiggs/julia-for-matlabbers/index.html similarity index 100% rename from MisterBiggs/julia-for-matlabbers/intro/index.html rename to MisterBiggs/julia-for-matlabbers/index.html diff --git a/MisterBiggs/julia-for-matlabbers/intro/intro.jl b/MisterBiggs/julia-for-matlabbers/index.jl similarity index 100% rename from MisterBiggs/julia-for-matlabbers/intro/intro.jl rename to MisterBiggs/julia-for-matlabbers/index.jl -- 2.51.2 From ab84aac937570a400c0c0a2c923fef1f84097b2a Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Wed, 14 Jul 2021 21:49:35 +0000 Subject: [PATCH 09/21] add pages --- MisterBiggs/julia-for-matlabbers/.gitlab-ci.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 MisterBiggs/julia-for-matlabbers/.gitlab-ci.yml diff --git a/MisterBiggs/julia-for-matlabbers/.gitlab-ci.yml b/MisterBiggs/julia-for-matlabbers/.gitlab-ci.yml new file mode 100644 index 000000000..063e19d73 --- /dev/null +++ b/MisterBiggs/julia-for-matlabbers/.gitlab-ci.yml @@ -0,0 +1,10 @@ +pages: + stage: deploy + script: + - mkdir .public + - cp -r * .public + - mv .public public + artifacts: + paths: + - public + -- 2.51.2 From 080854551d969820648f64956197f1f6ce9521cb Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Wed, 14 Jul 2021 21:49:45 +0000 Subject: [PATCH 10/21] add pages -- 2.51.2 From 5514d0d98186e0283c007caebb50a1fa59844008 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Wed, 14 Jul 2021 21:50:00 +0000 Subject: [PATCH 11/21] add pages -- 2.51.2 From e52cbd9d1e393d98cf1a486466ebfe4214097499 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Sat, 17 Jul 2021 12:51:23 -0700 Subject: [PATCH 12/21] added some data for tabular example --- .../julia-for-matlabbers/AeroTech_F10.csv | 28 +++++++++++++++++++ .../julia-for-matlabbers/AeroTech_G8ST.csv | 22 +++++++++++++++ .../julia-for-matlabbers/Estes_F15.csv | 28 +++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv create mode 100644 MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv create mode 100644 MisterBiggs/julia-for-matlabbers/Estes_F15.csv diff --git a/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv b/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv new file mode 100644 index 000000000..6a7d98264 --- /dev/null +++ b/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv @@ -0,0 +1,28 @@ +"Time (s)","Thrust (N)" +0.01,16.81 +0.03,22.34 +0.11,22.23 +0.26,21.49 +0.37,20 +0.47,20.21 +0.67,18.09 +0.99,15.74 +1.31,13.4 +1.81,10.85 +2.49,10.21 +3.13,8.94 +3.6,8.83 +4.11,8.62 +4.95,8.62 +5.45,8.62 +5.58,8.51 +5.88,8.72 +6.22,8.51 +6.46,8.51 +6.6,7.77 +6.71,7.02 +6.79,5.64 +6.91,3.83 +6.95,2.23 +7,0.96 +7.05,0 diff --git a/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv b/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv new file mode 100644 index 000000000..a1d00b0ad --- /dev/null +++ b/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv @@ -0,0 +1,22 @@ +"Time (s)","Thrust (N)" +0.024,0.3704 +0.066,0.8746 +0.138,4.5044 +0.246,6.6207 +0.426,6.7351 +1.218,7.3232 +2.082,7.423 +3.306,7.183 +5.322,6.8385 +6.978,6.7193 +8.632,6.5512 +10.144,6.4792 +12.088,6.4254 +15.472,6.3333 +17.632,6.1305 +19.108,6.0385 +19.511,5.9607 +19.804,4.4295 +19.867,1.6687 +19.937,0.3341 +19.964,0 diff --git a/MisterBiggs/julia-for-matlabbers/Estes_F15.csv b/MisterBiggs/julia-for-matlabbers/Estes_F15.csv new file mode 100644 index 000000000..d20085b5c --- /dev/null +++ b/MisterBiggs/julia-for-matlabbers/Estes_F15.csv @@ -0,0 +1,28 @@ +"Time (s)","Thrust (N)" +0,0 +0.148,7.638 +0.228,12.253 +0.294,16.391 +0.353,20.21 +0.382,22.756 +0.419,25.26 +0.477,23.074 +0.52,20.845 +0.593,19.093 +0.688,17.5 +0.855,16.225 +1.037,15.427 +1.205,14.948 +1.423,14.627 +1.452,15.741 +1.503,14.785 +1.736,14.623 +1.955,14.303 +2.21,14.141 +2.494,13.819 +2.763,13.338 +3.12,13.334 +3.382,13.013 +3.404,9.352 +3.418,4.895 +3.45,0 -- 2.51.2 From cf56add46e372668c0141b8c48510fa1ad2f20f7 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Sat, 17 Jul 2021 13:00:05 -0700 Subject: [PATCH 13/21] renaming columns --- MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv b/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv index 6a7d98264..2caa46379 100644 --- a/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv +++ b/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv @@ -1,4 +1,4 @@ -"Time (s)","Thrust (N)" +Time,Thrust 0.01,16.81 0.03,22.34 0.11,22.23 -- 2.51.2 From 62e002a88811f5eccdb62b054ef4ab73fce80867 Mon Sep 17 00:00:00 2001 From: Anson Biggs Date: Tue, 20 Jul 2021 00:07:28 +0000 Subject: [PATCH 14/21] Upload New File --- .../julia-for-matlabbers/copernicus.grib | Bin 0 -> 248760 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 MisterBiggs/julia-for-matlabbers/copernicus.grib diff --git a/MisterBiggs/julia-for-matlabbers/copernicus.grib b/MisterBiggs/julia-for-matlabbers/copernicus.grib new file mode 100644 index 0000000000000000000000000000000000000000..055f0b8db12bed0c7329e0d4c015c6457b9dc2af GIT binary patch literal 248760 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 Date: Sat, 14 Aug 2021 23:28:20 -0700 Subject: [PATCH 15/21] tried swapping quaternions example with orbits --- MisterBiggs/julia-for-matlabbers/index.jl | 110 ++++++++++------------ 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/index.jl b/MisterBiggs/julia-for-matlabbers/index.jl index 8fdb45c31..b0c869376 100644 --- a/MisterBiggs/julia-for-matlabbers/index.jl +++ b/MisterBiggs/julia-for-matlabbers/index.jl @@ -375,71 +375,61 @@ md""" ### Custom Data Types """ +# ╔═╡ f6d87354-ac46-4202-92f8-b39a0db13327 +μ = 3.986004418e14u"m^3/s^2" # Standard Gravitational Parameter for Earth + # ╔═╡ 44daff45-f608-47e3-ad6e-fca43532f322 -struct Quaternion - i::Float64 - j::Float64 - k::Float64 - r::Float64 - - Quaternion(i, j, k, r) = norm([i, j, k, r]) ≈ 1 ? new(i, j, k, r) : error("Magnitude not equal to 1.") - Quaternion() = new(0, 0, 0, 1) +struct Elliptic_Orbit + """Simple 2d elliptic orbit""" + r::typeof(.1u"km") # altitude + a::typeof(.1u"km") # semimajor axis + e::Float64 # eccentricity - Quaternion(yaw, pitch, roll) = Quaternion([0 0 sin(yaw / 2) cos(yaw / 2)]) * Quaternion([0 sin(pitch / 2) 0 cos(pitch / 2)]) * Quaternion([sin(roll / 2) 0 0 cos(roll / 2)]) - - function Quaternion(ē, ϕ) - if sum(ē) == 0 - return Quaternion([0 0 0 cos(ϕ / 2)]) - end - dir = normalize(ē) * sin(ϕ / 2) - return Quaternion(dir[1], dir[2], dir[3], cos(ϕ / 2)) + function Elliptic_Orbit(r, a, e) + @assert e < 1 "Eccentricity must be less than 1!" + new(r, a, e) + end + function Elliptic_Orbit(r) + new(r,r,0) # we'll pretend circular orbits count for this example end - end -# ╔═╡ 639fc5f0-1ab8-4d4e-83b5-77a82ae9bdf8 -q() = Quaternion() +# ╔═╡ efb58b79-24e4-45c6-ad45-aeaa339d82fd +ISS = Elliptic_Orbit(420u"km") -# ╔═╡ 37c4a8ef-d503-497a-a63c-3e43d0ebb2a7 -function QuaternionMultiplication(l::Quaternion, r::Quaternion) - R = [r.r r.k r.j r.i; - -r.k r.r r.i r.j; - r.j -r.i r.r r.k; - -r.i -r.j -r.k r.r] - L = [l.i; l.j; l.k; l.r] - return Quaternion(R * L) - +# ╔═╡ 3efd8a29-6a56-4f5c-9cab-0f08875b2064 +function get_velocity(o::Elliptic_Orbit) + v = sqrt(μ*(2/o.r - 1/o.a)) + return v |> u"km/s" end -# ╔═╡ 0d67e350-a87e-4a07-a01c-d348f3e62599 -Base.:*(l::Quaternion, r::Quaternion) = QuaternionMultiplication(l::Quaternion, r::Quaternion) - -# ╔═╡ cbf7d0fb-855b-442b-80c2-cfb6dcabe104 -begin - Base.iterate(q::Quaternion, state=1) = state > 4 ? nothing : (collect(q)[state], state + 1) - Base.length(q::Quaternion) = 4 - Base.collect(q::Quaternion) = [q.i q.j q.k q.r] - Base.getindex(q::Quaternion, i) = collect(q)[i] +# ╔═╡ 59207a25-fa6d-4369-979d-cd9cc2f094cf +function get_period(o::Elliptic_Orbit) + T = 2*π*sqrt(o.a^3/μ) + return T |> u"s" end -# ╔═╡ 84e6fb12-be8c-4e00-bf9c-d45748347def -begin - LinearAlgebra.norm(q::Quaternion) = norm(collect(q)) - LinearAlgebra.normalize(q::Quaternion) = collect(q) / norm(q) -end +# ╔═╡ 5a4b673b-babb-4e11-a292-d71087fa32bc + + +# ╔═╡ a6c72acc-39fc-4dfc-8126-64c6b35145d1 +get_period(ISS) + +# ╔═╡ d79a6752-77ba-496f-96c3-d9904db0a46b +get_velocity(ISS) + +# ╔═╡ 026321df-6991-4b59-aaba-c467b267a477 +whatsit(u"m") -# ╔═╡ 2ba455ff-70f5-47d5-9fe8-bf4ebee9386a -q1 = Quaternion(1,0,0,0) +# ╔═╡ 3955b9d6-7514-4712-ba22-929afda3c77c +typeof(1.1u"km") -# ╔═╡ 6895bcb2-9a11-4f0a-b1c2-6640f6fb509c -q2 = Quaternion([1 2 3], π) +# ╔═╡ a7bacb81-0f19-4d2d-9588-61e912689001 +Elliptic_Orbit(1,2,.9) -# ╔═╡ 045a1898-a3db-4e65-9711-9e4608ce09c6 -q()*q() +# ╔═╡ c3d943b4-809d-4a96-a99d-be7653ba2c8b -# ╔═╡ fafa0a8d-5ae5-49e9-8d11-4abb5748431e -q1*q2 # ╔═╡ 8924673f-e99c-44b3-be6d-2abf0b2f5e23 md""" @@ -1410,16 +1400,18 @@ version = "0.9.1+5" # ╟─dc898d32-b30b-4baa-a595-b83ccd1dc86d # ╠═9ea4584c-8177-4f69-9739-b2faa93281a8 # ╠═f43812d2-9f87-489a-9317-e7aa19ffd3bc +# ╠═f6d87354-ac46-4202-92f8-b39a0db13327 # ╠═44daff45-f608-47e3-ad6e-fca43532f322 -# ╠═639fc5f0-1ab8-4d4e-83b5-77a82ae9bdf8 -# ╠═37c4a8ef-d503-497a-a63c-3e43d0ebb2a7 -# ╠═0d67e350-a87e-4a07-a01c-d348f3e62599 -# ╠═cbf7d0fb-855b-442b-80c2-cfb6dcabe104 -# ╠═84e6fb12-be8c-4e00-bf9c-d45748347def -# ╠═2ba455ff-70f5-47d5-9fe8-bf4ebee9386a -# ╠═6895bcb2-9a11-4f0a-b1c2-6640f6fb509c -# ╠═045a1898-a3db-4e65-9711-9e4608ce09c6 -# ╠═fafa0a8d-5ae5-49e9-8d11-4abb5748431e +# ╠═efb58b79-24e4-45c6-ad45-aeaa339d82fd +# ╠═3efd8a29-6a56-4f5c-9cab-0f08875b2064 +# ╠═59207a25-fa6d-4369-979d-cd9cc2f094cf +# ╠═5a4b673b-babb-4e11-a292-d71087fa32bc +# ╠═a6c72acc-39fc-4dfc-8126-64c6b35145d1 +# ╠═d79a6752-77ba-496f-96c3-d9904db0a46b +# ╠═026321df-6991-4b59-aaba-c467b267a477 +# ╠═3955b9d6-7514-4712-ba22-929afda3c77c +# ╠═a7bacb81-0f19-4d2d-9588-61e912689001 +# ╠═c3d943b4-809d-4a96-a99d-be7653ba2c8b # ╠═8924673f-e99c-44b3-be6d-2abf0b2f5e23 # ╠═3f7ae2df-9d4d-46d3-b12e-22107a560b66 # ╠═fbc06121-d53a-4a64-9497-63d7f3583fbb -- 2.51.2 From 87aded701c0baab9707465342fa680d9a7b94de1 Mon Sep 17 00:00:00 2001 From: Anson Date: Sun, 15 Aug 2021 23:54:42 -0700 Subject: [PATCH 16/21] more work on orbits example --- MisterBiggs/julia-for-matlabbers/index.html | 4 +- MisterBiggs/julia-for-matlabbers/index.jl | 99 +++++++++++++++------ 2 files changed, 72 insertions(+), 31 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/index.html b/MisterBiggs/julia-for-matlabbers/index.html index b1052615c..f42bbc6e2 100644 --- a/MisterBiggs/julia-for-matlabbers/index.html +++ b/MisterBiggs/julia-for-matlabbers/index.html @@ -53,11 +53,11 @@ diff --git a/MisterBiggs/julia-for-matlabbers/index.jl b/MisterBiggs/julia-for-matlabbers/index.jl index b0c869376..da276e124 100644 --- a/MisterBiggs/julia-for-matlabbers/index.jl +++ b/MisterBiggs/julia-for-matlabbers/index.jl @@ -378,8 +378,24 @@ md""" # ╔═╡ f6d87354-ac46-4202-92f8-b39a0db13327 μ = 3.986004418e14u"m^3/s^2" # Standard Gravitational Parameter for Earth +# ╔═╡ f8039870-2570-47d0-8d46-30922415ec9d +earth_radius = 6378u"km" + +# ╔═╡ 863cd607-a459-49ae-9049-983f3374f523 +abstract type Orbit end + # ╔═╡ 44daff45-f608-47e3-ad6e-fca43532f322 -struct Elliptic_Orbit +struct Circular_Orbit <: Orbit + """Simple 2d circular orbit""" + r::typeof(.1u"km") # altitude +end + + +# ╔═╡ efb58b79-24e4-45c6-ad45-aeaa339d82fd +ISS = Circular_Orbit(420u"km") + +# ╔═╡ ad3a2b19-5639-4d11-8d89-bc54772d639b +struct Elliptic_Orbit <: Orbit """Simple 2d elliptic orbit""" r::typeof(.1u"km") # altitude a::typeof(.1u"km") # semimajor axis @@ -387,48 +403,70 @@ struct Elliptic_Orbit function Elliptic_Orbit(r, a, e) @assert e < 1 "Eccentricity must be less than 1!" + @assert 0 < e "Eccentricity must be greater than 0!" new(r, a, e) end - function Elliptic_Orbit(r) - new(r,r,0) # we'll pretend circular orbits count for this example + + + function Elliptic_Orbit(perigee, apogee) + a = (perigee + apogee) / 2 + e = 1 - (perigee/a) + r = a*((1-e^2)/(1+e)) # Assume θ is 0 since we aren't keeping track of it + Elliptic_Orbit(r,a,e) end end - -# ╔═╡ efb58b79-24e4-45c6-ad45-aeaa339d82fd -ISS = Elliptic_Orbit(420u"km") +# ╔═╡ b4e08868-d48a-4f66-9d20-f45ea4d83f00 +sat = Elliptic_Orbit(earth_radius+537.0u"km", earth_radius+9040.9u"km") # ╔═╡ 3efd8a29-6a56-4f5c-9cab-0f08875b2064 -function get_velocity(o::Elliptic_Orbit) - v = sqrt(μ*(2/o.r - 1/o.a)) +function get_velocity(o::Circular_Orbit) + v = sqrt(μ/o.r) return v |> u"km/s" end # ╔═╡ 59207a25-fa6d-4369-979d-cd9cc2f094cf -function get_period(o::Elliptic_Orbit) - T = 2*π*sqrt(o.a^3/μ) - return T |> u"s" +function get_velocity(o::Elliptic_Orbit) + v = sqrt(μ*(2/o.r - 1/o.a)) + return v |> u"km/s" end -# ╔═╡ 5a4b673b-babb-4e11-a292-d71087fa32bc +# ╔═╡ 11fb3a28-edf3-46ff-8c4a-5286793b6e43 +get_velocity(ISS) +# ╔═╡ 79a9ab94-06a8-4613-8f60-358e08f0f32e +get_velocity(sat) -# ╔═╡ a6c72acc-39fc-4dfc-8126-64c6b35145d1 -get_period(ISS) +# ╔═╡ c3d943b4-809d-4a96-a99d-be7653ba2c8b +begin +function Plots.plot(orbit::Elliptic_Orbit) + a = orbit.a |> u"km" |> ustrip + b = orbit.a*sqrt(1-orbit.e^2) |> u"km" |> ustrip + t = 0:.01:2π + + x_orbit(t) = a*cos(t) + y_orbit(t) = b*sin(t) -# ╔═╡ d79a6752-77ba-496f-96c3-d9904db0a46b -get_velocity(ISS) + plot(x_orbit, y_orbit, t) + + x_earth(t) = ustrip(earth_radius)*cos(t) + a*orbit.e + y_earth(t) = ustrip(earth_radius)*sin(t) + plot!(x_earth,y_earth, t, c=:gray,fill=(0,:blue), legend=false,aspect_ratio=:equal) -# ╔═╡ 026321df-6991-4b59-aaba-c467b267a477 -whatsit(u"m") + title!("Satellite Orbiting Earth") +end +plot(sat) +end -# ╔═╡ 3955b9d6-7514-4712-ba22-929afda3c77c -typeof(1.1u"km") +# ╔═╡ 01ba1742-d26e-4271-ab62-0bd9ce5e291d +function get_ΔV(start::Orbit, final::Orbit) + get_velocity(start) - get_velocity(final) +end -# ╔═╡ a7bacb81-0f19-4d2d-9588-61e912689001 -Elliptic_Orbit(1,2,.9) +# ╔═╡ ad4d24a8-f601-4522-a3eb-c01f6fd68aec +get_ΔV(ISS,sat) -# ╔═╡ c3d943b4-809d-4a96-a99d-be7653ba2c8b +# ╔═╡ 2d0de5db-5558-41e0-96d5-a3317d151aff # ╔═╡ 8924673f-e99c-44b3-be6d-2abf0b2f5e23 @@ -1401,17 +1439,20 @@ version = "0.9.1+5" # ╠═9ea4584c-8177-4f69-9739-b2faa93281a8 # ╠═f43812d2-9f87-489a-9317-e7aa19ffd3bc # ╠═f6d87354-ac46-4202-92f8-b39a0db13327 +# ╠═f8039870-2570-47d0-8d46-30922415ec9d +# ╠═863cd607-a459-49ae-9049-983f3374f523 # ╠═44daff45-f608-47e3-ad6e-fca43532f322 # ╠═efb58b79-24e4-45c6-ad45-aeaa339d82fd +# ╠═ad3a2b19-5639-4d11-8d89-bc54772d639b +# ╠═b4e08868-d48a-4f66-9d20-f45ea4d83f00 # ╠═3efd8a29-6a56-4f5c-9cab-0f08875b2064 # ╠═59207a25-fa6d-4369-979d-cd9cc2f094cf -# ╠═5a4b673b-babb-4e11-a292-d71087fa32bc -# ╠═a6c72acc-39fc-4dfc-8126-64c6b35145d1 -# ╠═d79a6752-77ba-496f-96c3-d9904db0a46b -# ╠═026321df-6991-4b59-aaba-c467b267a477 -# ╠═3955b9d6-7514-4712-ba22-929afda3c77c -# ╠═a7bacb81-0f19-4d2d-9588-61e912689001 +# ╠═11fb3a28-edf3-46ff-8c4a-5286793b6e43 +# ╠═79a9ab94-06a8-4613-8f60-358e08f0f32e # ╠═c3d943b4-809d-4a96-a99d-be7653ba2c8b +# ╠═01ba1742-d26e-4271-ab62-0bd9ce5e291d +# ╠═ad4d24a8-f601-4522-a3eb-c01f6fd68aec +# ╠═2d0de5db-5558-41e0-96d5-a3317d151aff # ╠═8924673f-e99c-44b3-be6d-2abf0b2f5e23 # ╠═3f7ae2df-9d4d-46d3-b12e-22107a560b66 # ╠═fbc06121-d53a-4a64-9497-63d7f3583fbb -- 2.51.2 From 84e624faa193b61001968d897af2dff780e10d4c Mon Sep 17 00:00:00 2001 From: Anson Date: Thu, 19 Aug 2021 01:31:59 -0700 Subject: [PATCH 17/21] fix csv column names --- MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv | 2 +- MisterBiggs/julia-for-matlabbers/Estes_F15.csv | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv b/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv index a1d00b0ad..17db4eba5 100644 --- a/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv +++ b/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv @@ -1,4 +1,4 @@ -"Time (s)","Thrust (N)" +Time,Thrust 0.024,0.3704 0.066,0.8746 0.138,4.5044 diff --git a/MisterBiggs/julia-for-matlabbers/Estes_F15.csv b/MisterBiggs/julia-for-matlabbers/Estes_F15.csv index d20085b5c..f385247ee 100644 --- a/MisterBiggs/julia-for-matlabbers/Estes_F15.csv +++ b/MisterBiggs/julia-for-matlabbers/Estes_F15.csv @@ -1,4 +1,4 @@ -"Time (s)","Thrust (N)" +Time,Thrust 0,0 0.148,7.638 0.228,12.253 -- 2.51.2 From 8ff330ce4dc8a6ba36ea122c49475323457a00b1 Mon Sep 17 00:00:00 2001 From: Anson Date: Thu, 19 Aug 2021 03:03:20 -0700 Subject: [PATCH 18/21] work on tabular data example --- MisterBiggs/julia-for-matlabbers/index.jl | 54 +++++++++++++++++++---- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/index.jl b/MisterBiggs/julia-for-matlabbers/index.jl index da276e124..092d0604d 100644 --- a/MisterBiggs/julia-for-matlabbers/index.jl +++ b/MisterBiggs/julia-for-matlabbers/index.jl @@ -23,7 +23,7 @@ using Unitful begin using CSV using DataFrames - using HTTP + using FileIO end # ╔═╡ bb461e00-c0aa-11eb-2c7d-1bd1591779c6 @@ -476,15 +476,40 @@ md""" ### Tabular Data """ +# ╔═╡ c460478a-db52-4a15-a723-9ff64eed9aec +# download_csv(url) = DataFrame(CSV.File(download(url))) +download_csv(url) = url |> download |> CSV.File |> DataFrame + +# ╔═╡ 9ccbea0d-6463-4533-88a6-0267879eb263 +F10 = download_csv("julia.ansonbiggs.com/AeroTech_F10.csv") + +# ╔═╡ 4ffebbb2-7021-4c08-82ac-95366dab3d48 +G8 = download_csv("julia.ansonbiggs.com/AeroTech_G8ST.csv") + +# ╔═╡ 2e83292e-8e8c-43e4-82ee-951a2f6a98c1 +F15 = download_csv("julia.ansonbiggs.com/Estes_F15.csv") + +# ╔═╡ c7e2a7f8-626f-45d8-b771-6f9e74a86bd8 +let + plot(title = "Rocket Motor Comparison", xlabel="Time (s)", ylabel="Thrust (N)") + plot!(F10.Time, F10.Thrust,label="F10") + plot!(G8.Time, G8.Thrust,label="G8") + plot!(F15.Time, F15.Thrust,label="F15") +end + +# ╔═╡ 8ec4af16-1a19-468e-b097-59985bf28f5c +describe(F10) + +# ╔═╡ 9f886419-7259-442e-b068-d0e4c886a886 +maximum.([F10.Thrust, G8.Thrust, F15.Thrust]) + # ╔═╡ fbc06121-d53a-4a64-9497-63d7f3583fbb md""" ## Things Julia Does Poorly -Nothing you nerd - -Time to First Plot -Libraries -Still young and breaking things +- Time to First Plot +- Libraries +- Still young and breaking things """ # ╔═╡ 00000000-0000-0000-0000-000000000001 @@ -492,7 +517,7 @@ PLUTO_PROJECT_TOML_CONTENTS = """ [deps] CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3" +FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" @@ -501,7 +526,7 @@ Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" [compat] CSV = "~0.8.5" DataFrames = "~1.2.0" -HTTP = "~0.9.12" +FileIO = "~1.11.0" Plots = "~1.19.0" PlutoUI = "~0.7.9" Unitful = "~1.8.0" @@ -651,6 +676,12 @@ git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f" uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" version = "4.3.1+4" +[[FileIO]] +deps = ["Pkg", "Requires", "UUIDs"] +git-tree-sha1 = "937c29268e405b6808d958a9ac41bfe1a31b08e7" +uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +version = "1.11.0" + [[FixedPointNumbers]] deps = ["Statistics"] git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" @@ -1455,6 +1486,13 @@ version = "0.9.1+5" # ╠═2d0de5db-5558-41e0-96d5-a3317d151aff # ╠═8924673f-e99c-44b3-be6d-2abf0b2f5e23 # ╠═3f7ae2df-9d4d-46d3-b12e-22107a560b66 +# ╠═c460478a-db52-4a15-a723-9ff64eed9aec +# ╠═9ccbea0d-6463-4533-88a6-0267879eb263 +# ╠═4ffebbb2-7021-4c08-82ac-95366dab3d48 +# ╠═2e83292e-8e8c-43e4-82ee-951a2f6a98c1 +# ╠═c7e2a7f8-626f-45d8-b771-6f9e74a86bd8 +# ╠═8ec4af16-1a19-468e-b097-59985bf28f5c +# ╠═9f886419-7259-442e-b068-d0e4c886a886 # ╠═fbc06121-d53a-4a64-9497-63d7f3583fbb # ╟─00000000-0000-0000-0000-000000000001 # ╟─00000000-0000-0000-0000-000000000002 -- 2.51.2 From 66eb6d06a01aa1e5a359cc06a8820e5b417d13fc Mon Sep 17 00:00:00 2001 From: Anson Date: Tue, 24 Aug 2021 00:59:25 -0700 Subject: [PATCH 19/21] brought back the scope a ton and finished --- .../julia-for-matlabbers/AeroTech_F10.csv | 28 -- .../julia-for-matlabbers/AeroTech_G8ST.csv | 22 -- .../julia-for-matlabbers/Estes_F15.csv | 28 -- .../julia-for-matlabbers/copernicus.grib | Bin 248760 -> 0 bytes MisterBiggs/julia-for-matlabbers/index.html | 4 +- MisterBiggs/julia-for-matlabbers/index.jl | 347 ++++-------------- 6 files changed, 82 insertions(+), 347 deletions(-) delete mode 100644 MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv delete mode 100644 MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv delete mode 100644 MisterBiggs/julia-for-matlabbers/Estes_F15.csv delete mode 100644 MisterBiggs/julia-for-matlabbers/copernicus.grib diff --git a/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv b/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv deleted file mode 100644 index 2caa46379..000000000 --- a/MisterBiggs/julia-for-matlabbers/AeroTech_F10.csv +++ /dev/null @@ -1,28 +0,0 @@ -Time,Thrust -0.01,16.81 -0.03,22.34 -0.11,22.23 -0.26,21.49 -0.37,20 -0.47,20.21 -0.67,18.09 -0.99,15.74 -1.31,13.4 -1.81,10.85 -2.49,10.21 -3.13,8.94 -3.6,8.83 -4.11,8.62 -4.95,8.62 -5.45,8.62 -5.58,8.51 -5.88,8.72 -6.22,8.51 -6.46,8.51 -6.6,7.77 -6.71,7.02 -6.79,5.64 -6.91,3.83 -6.95,2.23 -7,0.96 -7.05,0 diff --git a/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv b/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv deleted file mode 100644 index 17db4eba5..000000000 --- a/MisterBiggs/julia-for-matlabbers/AeroTech_G8ST.csv +++ /dev/null @@ -1,22 +0,0 @@ -Time,Thrust -0.024,0.3704 -0.066,0.8746 -0.138,4.5044 -0.246,6.6207 -0.426,6.7351 -1.218,7.3232 -2.082,7.423 -3.306,7.183 -5.322,6.8385 -6.978,6.7193 -8.632,6.5512 -10.144,6.4792 -12.088,6.4254 -15.472,6.3333 -17.632,6.1305 -19.108,6.0385 -19.511,5.9607 -19.804,4.4295 -19.867,1.6687 -19.937,0.3341 -19.964,0 diff --git a/MisterBiggs/julia-for-matlabbers/Estes_F15.csv b/MisterBiggs/julia-for-matlabbers/Estes_F15.csv deleted file mode 100644 index f385247ee..000000000 --- a/MisterBiggs/julia-for-matlabbers/Estes_F15.csv +++ /dev/null @@ -1,28 +0,0 @@ -Time,Thrust -0,0 -0.148,7.638 -0.228,12.253 -0.294,16.391 -0.353,20.21 -0.382,22.756 -0.419,25.26 -0.477,23.074 -0.52,20.845 -0.593,19.093 -0.688,17.5 -0.855,16.225 -1.037,15.427 -1.205,14.948 -1.423,14.627 -1.452,15.741 -1.503,14.785 -1.736,14.623 -1.955,14.303 -2.21,14.141 -2.494,13.819 -2.763,13.338 -3.12,13.334 -3.382,13.013 -3.404,9.352 -3.418,4.895 -3.45,0 diff --git a/MisterBiggs/julia-for-matlabbers/copernicus.grib b/MisterBiggs/julia-for-matlabbers/copernicus.grib deleted file mode 100644 index 055f0b8db12bed0c7329e0d4c015c6457b9dc2af..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 248760 zcmZ<{@^oTgC}3n@Flk8o|G!~5BLf2;BO?m~BLf(Sf=L9yD9*&fXkcJq2o_Rc_|L$= z$iT#4d8;vQO9O+&gT}Zm48ItDfn^yO1UMQ5oQ2GG3otM(WM(ioH#dh$FyOG4m74aN zXA3a!&$1=PUN&mlYfvk|z%)C62z!~R8qP9?0t`GGFmwMqW;4GxVCBVSd zBuIq4EYu5UL1!VwM*J$E7ScK+z`(Rwix_*U8qTtp1Q>We+#Q) z7hqst7)Fe})C*?;XCc8E0t~#Jjl|eX)o|u37hn*4R8EAwJX8&59UcJ&?rBGev6rgh ztoU4jfo~o$^&k)R!WmTm9ur{T+A@g<|MF5boGl&;FfjHs5MwX(!Wq=A`y{|1`1=?! z_EI;TnFSa)nm!O=FCX>7SdIx+TAGn@tAdI~UbUQ{B&UO{Sxv*7WS z0t}poT#2!ldf_bKEO_Lo0E56cV)`k9)C*^RXTd$I1sK>n7ZBlJA?k&*ptInQEdmVu z4~ZEk6ryT4e{2z8U~f|-#=q1HXF+Gd-<<*s@|*RDuveIR;Vj@R#HlC1z&(kWez!1H z!})Kl00Z|D3u63By>J$A7Gk<3z`!@@HWBuUP%oSXody4|6ky=^EK7{N)C^}KMo$3- z_Fg|??4@ovZx&!++)hmX6{TJ{3pfjjeH36|oJ!0%gD6$Qndzkf1LKl4M1->_Rl}L} zp8x~X+Ve!%D@MI=7IYSp2@zlr_;ivOd#M`EBG&{MSSMx?V=wi>8Ps2>6JU^fV?u(h@HJrta1sD`= zKPARqs)jS)ECB}jpTw+Zkf3Tf^V}0);NGJ`gnuQe7tR9CLdyRI7+AM45MwX(!WmRA z928(+pPxaDz0?b50cRnp*#Zn)vvY{BSBk3PERrw4z`STWG4@h5oCUQ77#LfLS+62R zy>J$E7UJI~z##fFnh5_&Q#G7LKMOE0wCfXNFIB^t>z4onOB*r$P-*Igvw*V@o4No4 z``Wog_*aIi;cOHoz`%Z)nD(R$Rl`}0TY!PJO@J8xQZ<}aWd#@*Tb2=FuPjx=S(#IS zf$JhM^X#%z4QELM0S5Ma--+=r^}?CoS%~qK00aA74kGN8qh2@*Itv**6krhgP0YBr z9QDFk&{;^cL4ZO0;09v+OTBOwbQaQ?D8L}G>?0BO%2O|#1)PN>!UY(ZJKTt|mwMqW z;4H*1FTlV)k(l{kdFq8T$lgl=42;W&s0W#-xGop8zHXubgTjM0!r{!sNWE|dt#iv0 zU|_z&LX5rC3ulnM`T`7cmy3w7mx}9h`JIJyQUn-S+D(bEm#X0`zgK`k`nokS_EImL zg`I^|jRY8SW``4DFLl@Dnq~+vFkP`D#$M`$vw*XZ(tH61=3`dG*h{@|7H}3)^A=!W z?7u{Wy;NM6%kL~?coo!NSVD}w)C*^RXCaAR0S4AxXNa+vs^P4-S%87#1`+c(OjKN# z%kL~?yikCFz3&7O{$-_VI4gkG)psr=#$Kw1v-%nV2A*Y)h_IKs>vCOE1sJ&R6H_0t zQ7@bYoP}%y1Q?hP5;4Ee#74bv=64p-KLScu*+hghb=Tz@S_v?4J#`?)UaE$(_5}e3 z=9Rp}*h{@|29?iJ0t`HD7l^Qzs_Sxv)WQT9_>K@UUdO~i)o_;nAi%(LiI{xELA`M1 zcNXGr5@2BMBx1b^6Lr_+YIF%OFrN$}B7Qlk8qVrz0t}1?iP#szMBR0{x~T#T{Ob=A z;a}>m%Qa&cU|>B-O#g_A>v9F0g$!m0F!1eSC&s_jOV0w%LWaTu4E#Hdh_IKs>vGLl z1sIrniP(?B#7))oY#1rPz|vbnjDM*b&I(fn7}!n{V=r~r<=S}&FfhEyBf`Ht)C*@p zXCbo(0t|A$h-ueRab2#Evyi2O0E6sLej@x!-F3M!KLr>#&k?a-gNc`V;Vj@Rs6R|shXahI|UdxJ`geP%|zXGxu)#`3>}j<6r89vyiip zQK$d|=fN99*h|HAxq{9@Mk)dfEL(_JKglFO)o|8+EWjXjei||UrCvCL_LW~3VBo(` z#C~Tcs;{p`fFbEvp37c`&pQ-DG6D-rXdOjKQ$ zE2QTkz`%8ri2Za-R9u$}nzynNVBnog#JU0|A*!ZlohJeeq8o_uFLl@DTImTe@O9rM zB0W=aU9Os z7X%nM->oIazf=uplivai%*%-x-=N~UTz+REQyBpU=5y&p_?L?7a`~Nwj4}im*jKG0 z#$M`$vw*XZsipvfz~&Gl?4{zmTz+RE&oluBruk;X*h{_i%LHtJ`G5)1qdIp`3)Fi;b zb%}`eS4>n~m&@-gWb##jfumW62>(h_FPsIOh0I?FFbEtcVqFlEBvr%N>XrZl+hHQs z|Qzb0Zo9TOGTUuo)vGoQ1N`*#5b=C-%Q*h{_i%;zj*H%owlxq*mtFqo*gE?3xDC_znN z(_sc(BK%9mb-5DGLVo!IJW6MXnLm=DUN{Ro3%M!?JhW%1CG1}wDz2{+a28T`7GPkT zHj@~8sh6GworTnO1sGWVaS~%M^}-o6zHvf;f$`l|BJ8E&`Z@t;A*=lY3~XE2h_RP? z;S6fml?X6!Z)PRNUh0LjfU}T=y8r{v8Y0R`9_p^IQ=cHfz`5op5&mVSYB(#i2{15D zCSso#4>MK6S;km^fpI|^5&os(`Z@t;A>nfZ4E$S(7@y=}p=vk_dI~V`Zy}<+!NWq; zaORyUz`)=0o``U!;`%y4XCc*F0u1awxrnisdf_bSETsHifI;D+Gcop3FPuT^y>ALI z@ZE?c!d@z_uLJFyuoGYqfBlyjd#M`EdfNmTnAh?VV=q<1S^JRygTg){)_w6%d3_zI zA9{d@^;bOX)C*?;XCa*i0S1=!M2rLTQ1RSL0cRntlL8Ff%ZQk_;-T*PI!R9f2HtjJ z+LP2>UndeMz`(yvnTYgE#r1Up&O)N=1Q^&`iK&07xV{dwe_vF9L2?c;?F}lfuM>0@ z;{GAP!1rMn5#h{9)pA1!)Sf&sg9v-6xV}!%SxDla0E5il3B=e-y>bH-zYziqoGXbK zZ|C8nYB&oRgZ76Kao#l#71!5+&XWlgVBqT5NklkPaebYjv*2G{0S4YFvx%{nn&B+? z|Aznr=UyVlH+ZPHzE03tNQO~>LE-@s>o$3)yS`53p#X#A$u~rVGZoj@2|5e$eGp&} zI6zE)pNi}21f7LMq68QuPpc8(Un;Jz6Lc05_$t64f1Zf(Ivy&nuLIQ!zXcdLP7pDE z#Y4sQb)f#>DFFuV1;n(ksJp&SR78M*t&^B~pStVo1b74(#8wh9{>($&^>t#-0t}*S zh*-bDL*4atLOTQ)q^A>c?*k7%^~z@+3-K%ZvpW1f~&jULOw?*VhR;3u*rnVBoqcO^ko37tTV?LV7y|7-SzzCc<7SuCD{l zhqenaaIQT>jJ?!L&w|cEQdt5Fq6df>-=O09I?#AdhX4b|Ct}8dskpw5&sj)YQGkJQ zp%W3|Ox^W$nz;fD%zq7uv6p)3S=d=fdZEBiTLvP|L*}94`a015qe1}&v2#SMH{+r1 z`Z^5*(7Y8fja#ISepeH7&mtl5zbUS_fqh)x&Q;)Vx7(z6of$g_=w3zR9s&NYUhLtFmOI1rk_IHb1yBo3ox)vAmTi8 z9_pTZX>mk=fq4os<+CjH%4g8}b`b#v>BB_apTa}Mb1wy)g^affFmP=uCL%pk@!U%R zXCd9M0u21U1;p4()o?bj7hqr_s$WLkb1yaY1Q?ii6LC%vk39AIDWLPc{R9|zH&hc5 z&eT2kQsoKg{$IlN0zZ}SqqhRpgNwEh^e;an70&^~Kx0S3J4j z@-tF*U9MfW00Zy3vqY2|)LoZrJx_pvdBZ7U?4@dYw%ZC?mrMAb8h%D9uFDm07IFaX z^EyKKo(q0PDxP~O;4EZ)Ux0!A7~%N^enwWRhO@b{00ZM4!u#p?8L7A~7qo6OQhaNQbkrZIy*+KaH4Sq)IuFDnsAi%)AknlcDen#r9%LT1tZN@_EImLLFawh2`~u%^dZ7t>aNQ* zc_F|cbu6A3d#M-Bg3dxF&H@aa>jg2wAO1Q^)6 z3E!K>&q&2}xuE=8FTlV!o$&ften#r9%Qcr2U|{*hO+@@scU`V#oB#vw1H$)+@iS6) zT`p+6j{hv-eaHNa)LoYg8jt1vN_gD}KO=S52wP)D7_$jE+Ri871!m0)?H5$VBp_O zcwH_(BX!Tc6h0!rz_F%+h;XLjx?IqCs`Ua4%!i0+$5L@!F2A#ouBHG3%Qa&9zf@e8 z%kM0t90$6eo$&cr{ESpwmn+~bq1QvEaT3ovl(JWPatsk<(hL0*7?cQfI8Tlg8NyDpb`vH$~9b1xD8rQ*6= zL1!V32+)4Iqr})t)q0Texd4OQ24colsJJdy&{^=~1_1`i_H{(~mx}9hLFZs>6JQYA zNcbKienu*;%N1}I{QO0Lfomq=bBg#Gskkmzz*+EZmjDCj0bDx}xg3T*0@e1sFIE5VOvWitBRuodw_P3otOWh7#dl zDz3}rcNTmoAi%(~nwa?%IqKDe{LX?GA_W*2?-9Olk)M&e>vB0S2rzKXBfRg4pOL!j za#;-p7`T@bGoM1$b-99n4+=2wZ|NYMuBdq*y@0cj_*wx5o^B%iOU?V}1)PN>%LEv> z*Ad=F&(B2Nb-5B>1sFKzCKD0PR9u$}3TIXU29|ZQ#Mn#K_J+t!0S2}!2Z*tkdgTUa zKkPCA2Il!h^i!CqxGop8-Yi9cfoYRB5&os(x?BNgA^!OS3@on*?+@i?qT;$-erF-h zZvqU=GvbKwFLl@Ds#gdwa2z6huLnO9b=T!8ND46UUneF#Q}Mi9erF*G(7K?hgwGY{ zr{;b10?tBm?g9+_tHX(iUn;K4<#!hR{a=8Ac`gzACYY$WE|=d~@U5%>1KSb8=bP~} zQFmRg+9Cl4#x5ep>zJsxE*EreUb+B-&^^NEZ}3y|K6;S7pmUkNRuPe|sJkwg*Gzzc zsc|v9F1g_tG@Fi1YzM1+5-x-M7n_eucee{CPLc&b~4AMm0&(6=pP1Sx1 z|4so0_8&y7zha`|x?Fx|A?f#^bwNbT!!l9vyj*@~A+c8i3{0nv5Rsm#xGtC9SxB$| zG*3sw{v#&puFF+?BEZ0Ovyce?Qg>ahXt4kT|Cfox*h{_iEZ{68ut$J_@gp(zQg>ah z;8Fnw=4nK%%VnbCx?E7X!6CpP^|_pgaHj5gxm+g%7&xyGKEIBiiHhrT1)K%{HwrK? zHs2w_zf@e8%kM1sVy*xKb6++w_EIlB^E(SZ1C8f&64P#{?z&voYXS^R%U=@VU#hOl z75rr+z`#CLm>7Gh7tWx0D@_3g){8`pw^Q>zdO>F)wL;Lo3Bu=m@-tC!T`uT+?_;3z zHi_7;!9>M%x%|$8-zEw$u%04jT$GCIa`~Nw93KcUFkdBnJ`z7Q@1y5;7Lwm7z`*oI zi-`10#dW#-&O$;L1sE9q5HT;wMBR0{I-dm?xaJZ*rk@Hxm`tP5Az9ekLle%LSd^E+N3c`)N86 z@k_;ZxuAPIXA3Y0os}oXUh0k4fyRN01Q_H$5V7Bin)lHQIt$5t6<`qSCt_UzmG7f> zloep$zeP+tmWu0gLFc(W6<}bPbAyQZrS7_119kxhroPQY*h|HAxdP5Ye!>C_0@H~& zUxkT^>v9F0h1{A27?|hO5aVBJwx5L@K=;F5B_=&ncU`W!qyPicwm(Gpm%8h66+!FF zw-K>kl*;$fiyszX;Jukjgny~HE?3A|$nBN@gH^*`V(g_}`7Gotq~8O&zl`wxDf~=S zT$c;lzYrwAVEcraaZxI+%jI_#3Y8IHU~D9&zd*(Fa`~NwoZ18!m}Z_KB7Uj3E?2-= z$aR(g1N#9pBJ8E&x?Ipb+Mfg%Sg#Usjtvu4*X0VC2?{W9Z(2=^f2mqN8;J=purlV(g`Axgpyoz`!wsi1Ye*sJOlkbboi20E5J1M6ZU+Oa&;U0W8 z6Ta_>pUU^qn>GqCu+0=DBAlsv?xn$10S18yiNx4T)$&=}P=JAJA`$xsseB*3{yhN( zhM7dn|MF1r+)Gfp5)feEdPzjPorj9+>pN>@_0B`FW^#?j`8HiHQOX!b|;#@GlkD*9kfcx$uMbvlB6{!b8RN zbpp;pb}Rx6JQIo7Pek4?NxV}!vS;#2~bT1w;{RJwnuM>0@3i&I*AaR9=`9Uh*NAIf!+TTsYeFQvI zTwf>XEaW#;fI)C^6cOo}itFnHorOGE1Q>Yd6XRbhuCEhx7IIDm^~;Dj=aZWE(F-{X zc`yqwSloO|L^xA-eO+Ri00ZkpBKEcMP;q^ofU{7HiU0%SM8fyf@bge{eI38EP~tNI z296dY&Xb|$ee`_JLiyVT7?|6Ln0Kb;ee?p(LYW)_44jXNSZ_wn`{?)q$B|bo_#Gu_?L?7>ja#I z!kq*dIF=B;_mH2;_tA&W2F-`I6XRd1re~L(0t_6@`9#=D#r1W9&O&Z01sM2$5pf_`<_7O$n7G0&oVy` z71!4ZI14!n2{3T4NhcybQ*nKrfU}U9o&W>OQ6^&SrD}V__?Z9$`xPS2yXK+pxtFE~ z1Q;xF(KN4~72M-n3*9kZaIf;YXlf<;2seA6F z*>(X2rWPX33FM*T`a013ZwF}Ho0#!BDz2{+a27J1DZs$IhKO};JXBm?C+I9>%q76U zH;I^aP*hxBC+sYwuP?x0cAl925f#_h@i_~H8Gy#kh?%FO;`%y1XCe0`0t`%xO^7J3 zsCe!rzq61BhX4cf3u5LMsCe!rXnYdX-Z;-jgny}c?j^|HNC5`U1|rTW;-TufmqNiZ z0t}qnb&2pV70syGtN)db1#Jq7zG#@b`u^~5uoyY^nO1< z`{)Vx%LJ%-AHATnP^h2)gY-GV=Y9xK^FDe(XQ6<{0t`~u?-EQ`0@S>Z9<3I#dW!Y&O)-G0t}+(3W%|n zdf_bKETjNB7owl=K3oAR-$yT_F2KOjN4S3^K+XH;1)YVYd<7U7UJ_m}DnQNq=t1#2 z5j5{icpg@On)lHQISVQM6kxD@v4eOLxGq=7St!y~;PG7s zNh0i};<{XZXQB9~0u0Q*i77Xzd+ufUTmc5w8HDe-5TNpX^nNP@7`XOY5fRQ*T$jt| zEEIlUph2I3g&2FO*WLiFlUXBhsgS7jOvQ6Ag`9=_A_W)>h`4uHfRVcEay6$4Fz_yK zBO;u+sTar|7 z0Y)mGdkG5X6#@(b4?hqQztmlqYmg(rAa|M=d#SrF*V;&cLF_Hz@n->Q-bXL!EM$H~ zfI;x|eImk{iuchAItyu?5n$kZKzJTjfSUKwgZf811Q?`G^AX`+Dz3{FbQaQ85n$k+ zb(t7@sn<^tau(78#qVyy_bdxAQt{kNVP~Oa1p$WIm4wf~5}@XN^uo?U5laLZ*!Kz& z5zbV+k6y%C$bE~zHw^}2%1P?3%T2WwU|_mTOg^ISy4?5_0S4ytjYNbqb?>7ORu^F4 zUq^VKwE#8mqX(@smlv41il}xS71!nRISVCp2~2KgU?w7*sk<&W^RqzrNe05}RRpMf zAH9~b00ZmVCL;Vx#rx<5orRRo2{1@qb|%JN>Xpxe&O(Y01sJ$@64PIx;<{YWeO}uH z7#JsCB*MQ`T$c+vuYQ{VgYb1*V(g`AIE!8tV366ihX{MAxGq=7SxEYl00ZA=V#a}~ zxGonoj&wwTL9~gO@hd8>%N2GO5@{4*h&fDnU4Z~271!m0&LwUYV32x5%={pA&%KoC z6<`qPCA@A^fSUKwgU*381DzXBcwM~!mG7fh2A`ip_`CuEMk?M%FXSww`bdDm_!Keo z&eUC(E1@R9z%-ZeIyV7E>aNSxv=LxnnASr?c}3lIxr#Fc82A?xUN<5@<@@MmOhEUQ zzazrGR9u%Uf2F5#+ zi3n$^uFDm?Wg@`9K7AT7_EK}aPVmwZ0S2Z$CyB9_n(Yn2Go1nqJP(K&XQ1x7Trp6+ zu!`{heE~-5uFK_^A;7@8otScis_SwE|JMmHFuf&wPM`oI71!nRISU0|6kuTP$RHwJ zQE^=^zq3#X=v<~%oW$5m&Gal}A}7GWxQUo?LMpDy<#!fJ-~ip{MfiMv0czey&+jZ0 zd{%&gc|tG|;Y`JKxdP5Y!R-PJ0?&zAk3`*dx#FPl*oDNbbEEFMT+wF&44hqr_Zah$W8$U&Oe<*#4i=sg6`8? zB*4JB^$QXHrQ*6=(71|-0E5h3V#YXNqmIelk2aR!C7=AJQ z0?RTm2yirj&Tp3$VBp?M#CRQ*@1u9j6kuSV_LFeBqVj$8Hn#*ASXUBW?=8SY#q)Cc zoP}%`f$mA4PlSJ|cwR2Qvyj^{0S4CF(ZtwGz4ivbvyiQT00Z+~!sqn~Q1d=|erF-? z9DzqJ3`CTZOjKN#%kL~?w@siUi z8s&(wmwNRezq63*836{iw?wRCWTN7I^q~EcN&*ZllLd(IFBQ+r6?7J|uNGjC_)YkJ z904XOuFDm07BcA)U|^X_#Ck$%-bW8w?|oB%fo)+O5#dbT^KwO+1Q?ih5Yc|7=6&=6 z&O)4N0t{@Y37<12K+XH;LHBtn3NUaSAYy)yiHi5pgXWJw;|%BBiHKk7uFD18PsjR* zh;>0!zK>pFw*Uj@3SW3jYTx#A&FX$}z*;s&qb1C6{^a9kpk6zGO z@XKid2Cj8ah=^Y*uFDm47JUC(fPwV}5%aK2R6H+N&{^=!dI1LJw?xe2Fi~+`uAsBv zqh0|9ZX)h26`ZJ-Wa9tr{JrXtVqvv-P(&!doVCo=zzPA9C@1vLh zCBVS-iHP<5)Vz-#v@fPkfI;L8;d`|Nn5cVRu8n{I1N&q{BJvRx*X0U03t65KVBl#Y ze9pE26BX~H2i>~_Dxdp^SkFM^`{?bMK82DOk?f$mMj?6;!kee{CPLP0YG7HwuA zVtpMG71!koI}7=!2{7oNB;uSCCaSK>6$+mqz`$~ojfiwb-TUYR3k4WhR}(XiM8)%R z1)PPvKM62!&Ne5)zf@h9EBGf?fPtfxh;sv&sJbp!@b7d12DZtB&m|V1=6&=6&Vqlq zLGAXVM1(UH*X4r7Rc;F~@O17c#$IaHgMzufAR}3@IRbDguPT; zmn-Nj#I{p_f$s@1<7QMmFBdc}nkT@(*hox&kh<$~nZWHUBF^h$qVBp}p)3Igp4CL` zD`%qax?EvT(EKkk<0@2Kmn+~bB+w(kz}!N_dT$=;u462c68NCNK*YWY9!Bbw8v@Qk zDVGG+DiO2pi-(bVigQ1N_GL1!T+X#ob2DMYNl;-TU?M$o6wLk<%XcMkZZR9 zgWOCa))nwjcO9eUPXPx0IYf-B@KA9bqp-733X{M-Rt6&GLwTsUj#0>2C@N2Yf%Ek% zBI1{odg&QtZ;k*1>v3Z0BkHbWOnxiS^PiY=KX}-vm!3iA_9O}H3SuB)A0H1J^}<=$ zS;*^+0E5MHBGv=*P;nh2zq3%JtN;V!RwB;d;GyC=Mt*0ZP*8t=&VM4(GduOd8MN-Y zQ-FbEB{Auls_PhqLazxh@a@eb!oO5p$0+D56sRD;AoYZZb(=g?T*oNrEaV|Cz##LU zhfsjn1Z;5$#mxdA*>JYN*FE+{~Nf$fYw5#db5^F=}Tm{S6*6EbYXMGf;6IBfqndN{Iji>l9xi{7c>QMXl69^S^q;*h{@|2HhjJ zRe*u7nTT@&d8oLK5oGTM0S3`7BIfsbsJo6aaJK*h>o#KgN7P-%==Mf{fw`ZEeLy@^ zUB@V7mjRkjSwuv-qT)J6L1!WV3;_m?`$XL9!9(43jGk@+44hAhI46*Yisy?8ItzKe z7hqtyM9eq?b=NVP9v5KXn@@~?sk@F*XQKcEYujuh(iL^rF)AepFtD@`u@8txkb3Jk z1f7L!Rthl4+`mnPf2nxBD9GNO0u20r2;bKxz(d9JMFpLOO!@^FM6VH(o~gKwQP5e) za)|(g{C^_m%Xp}`j#1EANXJxwfv25_^Xqu1yN*%GQGkJ^n}~HmJk&j3)Z9*hf&DEJ z`$KuCxQ>zES;&Y%fPtms0TKB~n5z9j-7^9VOuv2*VJ~&pG5Qq?FfhN*A;w()X9ixD=ka4L11KR^)`k~Z4U(}#gfPv*L z5%<*ah*C8@>*NVAupJ|&UZCzeM&(Tc3;4GvTCcwbGfS7WFisy?8I14G)2r#g2ksu$f8FbGS=v?s)nM8y$71uF>>{S(D;92{c7<;MOe%72Xz#y=SnDz#B z*DtFR9Ps%z`l%#^Hq4L zc)lno|N09sur4EJo=%Rc=~-nb=ss&A_B-=X@qAGMXCXN=0S2y)DMX|zDxNPY;4H*n zBETT9pNM-dc&K>3D5!nqD!{;VmWXp~c&K>3D8I81^I8E0wr0ZnQUw{QyDpb?GAMqf z3C6D=BNf->3OWn1whJ&Y-Si{IUTW5Zf}g@b_occLVJ{We<$~rVNVku$PMKas`})?0yO`FfJq}oT5MW@QNO)hHAR`smvEl?1Q=MJ5FSSoWTfu8T+n)cmi>hLM}mx0T$c;F zclfjbgYX~1>+1v=sk<)Ms7HW7>I^aM4eGATHOv=a5I#^yM7pBtx?I6Op!2TR-66(a z>XjP;&Vt`S`%ysu4=k&5eb1)PNxwg@n=?j$DvQuTaMA;s$g3`}iWM5Jdb zuFDm07LpJaVBnZccs;)$BNf->g3eK2Bf!A3jF$-iQt^CI(0Pn*0u1uc3D0W?GE#9} zF37+20t}4H3E%f5$VkO?x%|$8|BnhVupT6QzNjE071!nRISYP`7GPj%Abd}pAR`sm zhzMsYuFDm0782$VVBq;zMvT4GY(ER}pAlf-JnKM=z0_3_=q?^N05<<>vDyhg{0mJJebQMNJKuO;<{WRXCb@k0t_+5#jBO;usxGq=FSxA;$fPrbsaboPHUV0XG7UHWF zVBq;c_kKSm)}{)Qc{3{{UG6WGJ=d$T$ju5ETrQi zz`(ken071`*X4rNQS=BfFwXo&M7pBlx?DbIA*%oZ2F8_Y#Mn!{^vvfhr1wsMfpPjl zV(g_}KZV~}NVQggf%ymFeQkn_R9u$}N>^H-d!~$u@GlkD<$~79Lf2{16X5vAk&5eb1)YV|W(Y8dy-Ft{T~T#iuHfej z0t~FPi76+kx-M7nou2>$`$WR$d_26BXCx3ONgL&lg}&`b~J9xgZl2&&w5Z7Gk?Bz@WR#p9ud_aa}HGeft#w24*78 z7Zqfp;<{WxXCbL-0S5VtMD+KWsC!uYb?6mfVD2WoUs8~Xis$8m=5e$I7-YT?zW-N{iHhrTLG}g-FmPNY zVqArZitBPg^JVV@7}$;zF+Rye#dWzL{~i%wU|mVXI0F+E*X0U23+dGfFo@3~VqFju z71!koI14$33ox)QB4T|V6BXCx3OEayhY2w7wG!UPC&)y_b-4o0LRyOi82I-RJ|{tt ziHhrT`JILA96|dgmJ?B4QTM!D8&JJ})rA;)sag-(>I*RNo@^$t`EI3~cr zyN!r_PfS!@mn&qYBf!8opYT0^f=pChmn)=qQhyVn1evJ2F4sDh$oXz2Dz3`~ z-Q$@nz`!(@n0!Rtb-BiJ0u1augzxbbWTNi6TwNOh2F_Qh9-FICs&3c0-i-6ulCdSE6huFD18H<2p9z&Bfg2>()X zT`s?~ki#O-JRLFhJ{8Z)1?}J8AiyAS|0*&5rC#|g;4EabO@M)|k??tpf=pCgmn-Zn z6z3*zWf220{UhqG%MH6H@R^-~i2W%{R9u%U;4I{~THvTIQRM~|*X8m%3;Eg!%vL03 zJs}en*X4rFQ=KBPb~{n!GZok6@;eLZsS6y`A>w{#K_)7$%jI_#iZc~B;zLwDNZob0 zVP6DZFDEK~sk<&WQcYk{JyG^jab2!}vruTK00ZY_V&*ldxGq<~St#PA00Yxc!sjCi zGEs3|F2A#ohpzww>sC!7>IEvU%LUydwpDtzBA9FL@k@Go`O&xGq<~Stu!4V4DmBG4mQ!T$d~0EEIcNV3IWv_gV@v zQE^?afU{6`ivR=Xk#|IdGZoLv6>t^`jul{F+igjVz0@n8LH7V=2rzKnBc^{u-F3N6 z>;eqztwikCV4~u>T+n^iGXxlTjuJE8PTliz^}+=hSdJ1iuR+~)xzRH~_7XEsN8NR~ zuG<6{xGoX1ZiI^Kas`})?3Dx0@Qhy-8pzsvWx#9?W zsT$6T7X%oDcFPcvuBf}dPX4$61NSOC`{?2RrSAGVgUqmou6bcZq$}#KuQPBEVBlI{L5#gr4QEX$0S3-> zcT+I^RZaHit=Iss=Pl^X&K9Ix^8yW#$& z;`%z!y03Qv3>*g|i105J*VhR+3t4&!Fz_wMGtZ9jFICgC@k0Ry-UWE>Ux3?7-Su_e zt^y2vQ}LXqim;ce>Dg(i00YkyJols{?4@crTPcF>1;Dc}25v8P*Vp-r2r#f5yhKEL zrsDcKerF*+djSTPNxz7(mwMsM?=0lb3hMvj*`ERrXX>u6V?HRrz%{L&2>()deH|m{ zoZf{>#Mn!{a29YD{Hr6tz~77KoFaHQQ*nJAzq8-e1o56%L$Cs~NFmx}A__?-oh{Q>RQz_Wh=9?n!;U&rq(c-%>VfpOIq zV*E?J^bGQ^kN^YQGCcG9aQ{+ueVyRXKLQNwi}9Slfv}f)=~>WO@Jo;YgX~da+LKg0 z_fqiPUjYV=*?9I_!Tn3s^>u<@ZwN5(_9haMuBf=aPQY34?OXu{u33%5*h{_iEZ{8o zWTpTE-$6Y0FTlf@itFnHoP{J=1sK@A;5jD&VK4R4vw*XZ&^rMJ&L!$ZgfkV_*9kfc z@pcI?$UL1)guPT;Unk%!qi0%d~@-fBZsh;n(0}{@_+yX z`y4#yY{TuP;`%xPXCcpj0t~FZc<%2;*h|&)>=Z1(Akc|t{WHQ|s)n<@jQ|60(^4YR zGZoj@f#%C>1sGUPzbD3Cs)n=ABLN1^i4%#jm%8D6K!AaD`VAuNrQ-TJ(D=q{0S2}` zb;Q_9)o`{wCcwbA1<(2oczUMd`Z@t;AuG^%*NgD1=ZD)%#r1Wda-&p$fwS)e5#db5 z^>v{2IR*j@>=TlSv6rgp+4j5ugFqXedmiE8OvUwep!Jjg1sIsRyovBH71!7CI}0fv z5MW?#S0%V-4Evykk1(6|bo_0RBdrsDcK0cRmwM*#-@B|Sv=m%8`SJLrMVzapl+ zLEUpNt>y?Y2>!!!uQWWIsk^=owC|W_(`+KbnY!!iEV~651SSwOA4%0K>IWW1Q>W4@a$WJrz`5Nud@{tV3692=e}~d zz0_S_r+Ywvf%g+7V<1Q^)%A0;9^Q+Iuxbguvd-yS^o zT)^X(y6fx29ttqe{}^IxVGWh#|O8UitFn@>nNNA7}zG`+5d~M zm#Xb&sSBX+7xxFfcqLW?oW`g@KU)3`D^sf?yP9Vqr8eFfarQDKPwJU|?imVz9i` z7`LT?!Qw$<+!lsk48Op#3=9Gs4T8=>iirXY5@(3Xzf?T;QqWmQbhQ8j({n>2(ld3> zy%YnDZ!DcfguPTf_fklaLx6#I6EW=^s-Al(B#|Y+z(0EdG5)1$`7BTjnzxE3Xs-~J z@1vJU6ky=H(NB!MRILa31qB%RFA%Qxg&3)L?xldU5TAnp1NTil=RiX1BOylWuFF++ z7hvGIhv)ofguT=YXF+En`6vMf#^;$t#4mN%<*IfIFbHoyM})o9U6-pgMSy{|hwwbR z5F-`Oy%cm7lIRv-kiAW~+z_JXee{CPLSoFId!|+p5zbUxmn-NjB=lNwh5!RwC*k@?h>?YQ<+Gr(5TCLDgV;A)BEp%9>v9F1g;>}H7$mo&a?=ZZ4rs}zug8vT+ zFfg6PbDk=~UTUUi!M`>F41ya^6A{i-U6(8P^D^k1{O82jOU-&v@V6sq9}wYr4IygY zM=$6s_$g0-fqx4z{-xr&T+sc_3k4Y19}r%jBSg*n=mnewf2@29_zrq$?`kN6+sp_>u*5UICtS z65#%&>bhLP&({SQn3pUeB7Uj3E?3Z5@NA_Y!n2;(GxGwi|)O_?LR&44T)-5MW@N5KDx;R9u%U=q&hhi2wuRDPrm)Dz3{F zbQXNJU4Vi6pE5E2rCvA-It$+4Ccq%~awZY>QgK}_zq8=s$pQ>)3yH}`R6O^R-&t_? z4FLw0O-;o3mwMsM?<}~bU4VgcH!0-k%s;O!hLuFDm47QD7Z zfI;d9G4&A@&%G3I7QD3(wEvfw@hd8>%N2AM{Bc@2mln^!Vqvv-P{4_&=fxV6JemWsWDxQ1E z?=1KsL4bj62A=!q;rW-k>vEaB1Q^(V5tE*&cDl0S1;ggy#o^7^%80SMaxt z00ZMIJoga6!cC#7S5?;R{#7NzB zxrWz4`%?(-hZSO^?z&uE6#)j;=FddbgVbG@tIj3B!1A2%IaET7)LoZr@mPRCU>Q3R z{uQTQzZ-O}T8#h$PrE-c_EN9CA>b@z`dffOU^3xz5`-A3yDrz%8gyR4J|g@}-F3NI z9|RcK?-CQgR9u%U;4GxWCcwaX8PEB3@OqHC>vDBY3ox*p$t5D3sk<&$Ggg3scL_21 zm%8h6m1hbtFzxt4gny~KE?3iEfPwo42Ql_iwcOAKt&_P%Ogl%4s^y0KThO_eD~a$g zb=T!8?+{?%J?=@2y;KcnX)Tbw#I$3nd+w!prT_!mRl@rwgs6NUy?T)V1It`u=DVr5 zE*CUDDI~za)j-Vp4Jxk76?7KTxg@|KbBgeJ6hhRzj~-O-CkQZbwH6VPo~gJl7v$d^ z0t`aW+=;Q5dgTVl-gBUPw24`NMa6Zw0?tC(5dsW6eSSpvmx}9hLH8|22`~uEyGe|_ z)C*?;XCV#HJ=*QW)PvMrmn&`|z`*d7nE65KuFDnV6JTJvpG8DCQ}sT2ApuDN2FANY z*h|g(=mngGIKu=O*v=4t{Pj}&0wT$D|Of2nvMJt+U~7GU68CrOOGR4q4Txda&acN0DzScuB^(VKRF#&d`m zXQ1YN^a9R8M&NPaLL$PMy65E@DGM<0bt_ZC>LO0SxiLv%tYP$=;a$h z=Oo~{pB>i!WuoG`Tmfex17`U&865(I!uFJLDE5N`ro0xn=)pfZ-X4L`={4=eH@h|ntXCY@Ht1AKw zs{aY^rxT*)ee?p(LaNLH44kv@+@Au^zf?Rg7qpL0Uw}dI&l4iTnTq$(gU&Yttyfv3 zNQAvqT$d~0Eaamlz`!?!h}M7=|t>nqw;<90S5&bxEK5< z!oO5pmn-Njv9F0g=a<&`5aD+y;SX|7(NzY;QCC&dIlyc-bWAW z@2?YJV7p07y+GA42l_aZxS-29D1} z%)>HKaa}HGp6;Xo1H)p%_gn}uQFUFeklaN92G(DM&sPy*5~N-~1=J6X6ky=}!$d^7 zqUyR_A&ngZ3=Fdf-+v^;M8*5)LF?R(3otOX5HTN0&HLzuoP`wr2{7=kAbg&=5EFIR z<;rmjFmN4cCnA2SyDnGuy8r{*R3hdjnW(rfSI}8V`JVuT&_QCxRj9iz*VtHqfvK06 zaWg8e%N2AMG69XZpA{q`eyMmLy`Zy@wyOXGdp8mLVwkAAF4x&YfPr~EG3`m}uFExg zA;7@9nwW5=;<{WxXCYl<0S1{1MC@N+qVBp}=Q#oljLV40N7P-HYmq9zz%k94i1bXw zb-AE(wqpbs*cbdI!d~jG%eCJqz#y<&lNfuc+D|dLFTlXrl0uBVRBdkaNQ*1nrk>C1O1iHSeS6cNQ|> z5ny0nbc%>@rsBF>(74$$0S1{p#Eh#@ab2#kvykBw0S4RaB}Dj_y6bX{LHklqv=U=4 zRm%+v(0;mxSH##$)pA2WK!AbgH4*#Tn5eiem)}{)yk3BTeG4(`f~a^OJ-@S%DrjBM zZeqq&sJkv#qd5GeoOeiV<9H$uFKW05MW?hNlbf#itBPg z;|$&c3_QQR2!}J3@1u{{E5IOii->VE9!9E`8$KTd7+6*iaqcA#b=|VizJ@-=EL*R8kgA5VrnTqFL@;eKK zDG2PE%|Jvuhlh&iUh+E&IXerioxwoFIW|1hU0-LiOyIU610NCLOvUwee9l7N#{?J{ z7ZcIW;i2yOI)`JRaTOxQ&3LH0zRq>300Tp}3lZT=#r1W9&O$DU0t}+3h?s}vq2hh? zg3dw~Uj!IL_S+HTU+T5%K>IW&2r%$Z(IUcLDz2{+a27Hw6<}cBCq#_BRILY94hS%? zy(WCGmJknh@1xh)Ex^Ek*O&ZNCXXCdkP0t`$|#H42`uCEhx7BYS*z##FMnDop+z4Qzke_kfQ!1wqU5#dbLb1#Lo zCkim|P6{BxUMik@3EJ=cP=JB`_+et~rCvCL_IX_wVBp$G#6A%o>aMR-T_eE2^l&v1 z{-xsjIss=Pbx=NfCrXUHR1IgPb^!+FJ4B4f@=$Sooq)5Dbcp~1<7vY8mXEcoky0E6u0AY$yLUOfo1*G_Xpxe z&O!!N0?ThP5K}KuaebYTvyhmF0E5Yue?<6~itFnHoQ1q~1Q?hfRuN+_^}-pnk6?!Y z1N%H8&iCfwr(U@Mnuo0f-AhZvxtBatJoi$-S@0L900Vam;rrQzc&NC(PQY34i@g8? z`)XpsnTqFL3OWmZzX95RBuzxRqT>2G(7ga%0t~!oiI~^mq2l^F0cXJvnF0*_%|x8P z!9&IMbpp+IT81^ z@KEvGOEG65W?q4rl8nUkyQ#arj`M*41Mhqy&imq_;`%z!Jr~jf4B~A>%>VLGaeW== zo(mQM2BzgioXf;R#r1W<&O%b$0t|d-&k#{wQE`2pu(OchX#s}n!$j==<)PyGIw5Bv z7H0tl-R^lr_?L?7>p<MM3E!70#6!jPbpp;pW)lP$ zxXu%?f1ihn>+ATP1@D6H13FDidZyy~I(}!ttKp#bBr)|q71!7CI}2Xd6<}bzU_eB= zqT>2GL1)4Dp9C0$cWx)fUh1W1(0SMA1sG)JIuc_q_1e!u&VnBv2ry_7RZdd(+)H(1 z0S2CCBF=N;q3-%RwK)O|3{!}>2Z4vW>+579K<6P7v2T%wy60Z1zY<_zx=WP3)Jx9- z&O$2T0t`GimJyMjskpvQz*$KCkN^YY<%vYtOWpN#vN8e;thY0Wv6rghEDv{8 zL$w4L7(NoQkB^6n>+ATOh1_jH<0?d)yTwDr^>zHtLUz6a3{206IA4W_y6fvK(gYYd zw-Iq}Ef00?qqjLAz`#hv{p>V?$zR<;(hd>`OsDY2F_>1jBil!+)F`cAw4Yt z2AOZf%nwrW+)L1Ts;mMGg15biNLN%m_Y!o@Nv8mV{BFYIIl@%Fk6v+`00Zw~!uN;? zGg5b5u2_Ho1Ml;eqRyV{6|Un;K41v9F0g_PU{7`RRoo<9<%@_qEu(*zg<)_o)*eyO`I zSNgR814k?2b0CEoskkl|RR4wxFmTQzd@rpqHSePbo%8uffPr@r;e8^)RKAa1-b{c& z{x9KsTZ9>@yDnEAbgt=~Jw&7{DxP}@>JOe0VBnuY_v9F1g=BXLFz_8Gybem3k&5ebLFbJK3NQ%$CcKYcn40&|gVt}H7htfuMtI&?n30O> zas`})M79esuums^uca_`@1qxD(g)pFPWb!{VMZ#h%N2AM;;a;45c)ZZi2O_4b-9uy z0t`HBnu)QOs_hN&Dgg%WMq=t;Dz3`~jU%ZDFo-=PJboq2NX2!zg3dzn0s;(-KM0>2 zAk0YJb1&si2r%&9xJE?$Qg>ah+AH9&XkerDCgT|LBMEIAA>v9F1 zg~W~tFt9x%d~cdCHSePra268I7hquTCA_Xrn31aMa)ns82r%$&Bc`81)pfZ-EP?_I zvU3T~!wNG}@!U%xXTe{60t{0739o|^W~Ab}T+sfMGyw+D|Jp>PXDY7C1@(`-1Q?iC z5nhKZ%t*y`xuE^swgL>?Q zazXdDJP=^uI!SmxjxZy2*X4?{3NY~PB79G}Fe4Suy%cm7;%gOP5dKGaAAv9kcvYQm@<)bQY2m5ny2XV@Zs?)LSPb;4Gy4K!Ab2v4;qIskkl| z)c@Thz`**F@I9@<)Vz;g&{;_EjsOGu9m4Zg!qmKv9#mc(6JU@#uS7&RQ*m9cu(Oc* zJOKv(-Gt|lgc+&0E?3A|Na~jW1OHaS>tltfc^|!$vye!+z%M=x!uNUzGg5I~F2A#o zzN`QP^9;iKQ-m3*xGtC9SxBZ)fPt-{nuv5o#dWy?&O!n=1sJ$*65dBI%t*y`xdP6D zzc&gnaLp!suZJ)rRnNT?{AL3>ub%MwXJJMvuFDm47W{BafI;p9;rp$Gsd*p0ptIn8 zN6>u}sYIkJDz3`~*{d(Wz()XT`s8It_8Y3l<;~6 zVMeOnM=$u@Sb%~1FX8j9g&D=E+1?QR$S%OZ+v`L`I8$+5F2A#oX@md+^J+6v9F1h0MDI7?}4GvyOtg=U(cA&QU*3 z_vH*>g$%tw=f)Eg&Qx5N zE9@-z|C7M92@Hhy9|<#3ab2#Uv*4G-0t{S-37>N!%t+OBxq|l`1Q=L9ng&C>1E|=d~Na~dU1AB8BG5)1$djqtNg5z-@5%yAXT`uT;oHGIp zTt^9?b0W-0#dWy?&Vqkb1sFI^N)Y2;YKF7m&(i`7ylV*G<0(w#`{XC65bCh zOy&FNrA{@WeypNvWS;)pifPtx>@cGZeOjKN#3%WP0 zO@M*@5fSSNnW(rfSHM|Fqd#wMJA3ez47Xl27J%rD17pC%k^irUG zUN5bQ2xsc9%XJDAVBmN~M1P-&is$9>I}2${2hE4BC&s_jtOtdR`ve&H7ZKhcD$GRP zb-C8T0t`F{h*)38M8$QvpnX6K1sKHt6S1zIiHhrT1)YV|9R(Pqj}ft+ftvTxgVxDB z6kt$zM|j_&FcTHmaNQ*OBG;X`c1?Wx2x*2iuXVBq{r#6ALQ-bW9*?>I_; zfn^#I<8@TNk6t}ZfPw82;rqOVsd*ng=>E_hp!uVlM5JdbuFD0j7o8x$z}P{=I4~0x z*X8m%3q^GcFtA+OK!ks(xGtC9S;%Fg00Y||!sl%YGf{C}F2A#om4^TW$9f{>C7GzZ zF4wqIfPwcR;rn5QnfRzzZtyz`$(jlav|dlRp3%KgBTI% znX2dI3T1l>FtE&NBF0|ol^gudLdl@{vZeCG*h{@~1Jo~57GPkWNsPTzT$ju5ER-21 zz`(qsjtKu!bzQDdin{;<>rZ`R?4@2f3pfkKDGD%fekEr9m%8h6Q-2CDuudnY{Y>5S za$^q(FmRkFd`_=0mG7gEG6T(95phleHSePrbQbav6JX%pevXKAMcs9|uIB_8q+ib_ z#$KwXXR8eY41Ar$^arWCE?4US=zInu&PQUR;<{YWxm!sB49sVVDJQA8E*G?(;S^|H z{Td?Tm%8h6^(F`~aGoM!{~!}}*X6253o!7nBxZh)y6bWkmVoXLC8obm#dWy?&O*k# z0t~FH2;ZYE%tXa?xuALHegOuSt3;d!#YDw*xuA0|1wi-l6%kI)Jd7+1j0|8P3MLT* zqc{@_qk(~eAy`O(;XeZdBLfqI<*mlJEe#A74;tgPF#KZp1(s!C5a4J4jkk*mFo^zB zCB|Orwd(|&h4_C9FtE%fV&5V)@1y5;7X05Nz`)*0_`Fla|)*-rRA z0%0C1uCEhx7P1f$VBmj7#Ce-MR9s&t;4GxK0(9>o5$8_xP{2?p*&PP z_Y!p91h)W#z-3~}E9$PV6R{9r;CV*Gxp_QPTwllUEW~Lfz`)*5#JDIAb=TMF>=j_( znQ(-Na+13D(JS2%U|_mU#C}O0>aMTT?Ga!Qm_x)qTpsG4dnp|yz`)&3#C{DPDz2{+ zbQV%j6krg0O2qy_YTidL=qx1jSAaq2BQf9}gAR*MZg(W(zPd zZjB@&A5r(*OR1Rx3g5@p!*1jSU18$ z-Su^PpnHfe60t9ahl=a#KV?x*Vh^D6JTIF z5kN$`qT>2G&^>_30t_r~i8zOun)lK3I}1q%3NWyC5V7Bxy7$owsbvZ<@SG>6T}Q?B zb)fTOJp~xpPYV+fztlbVQledefo=UXBJ8E^xt9(l0u0Pgi8$wzn)lHQIt$rn3ouBp zASNGC@jiM%XCXU90S4(-V)}zrTwf>PEaY)efPwpXEfMic#rx<5oP})41Q>W{62320 zn40&|3pxu~s|zsjTqUMnpyK*E(D|_`0t`Hx-x3kdR6O?*G@o)yfPsGn5&O!idmp_J zN2mY;LpKroo~U^ry`ZxYV;ZQPL&W-a9xAS{6Lc2*uOYx7beZtI;lk9sk6zGO@L!t% zgTy@|&V%Bi;`%xvXCXlg0S1$sE<~hfDz2{+au(t}4!X~ahaMSo?-5|&>RwDl zI8*W5OVBvs0s#hzSHz5qQgMA9=-#CR0u1bviKz#vyS`4i40OI(E)n5O#rx<%=X+-h zFi3nProBPkb1wy%1Q_@(RTAM}>aMS2bQECVIdXs)d#PG(us#-GVBB?z2z#lxzD~$l zNc^n;gVq*e;+Kl+>ja&Jn2!oDu+AjnUI1#|M-MvxIaYvy;|dY`j(MoKzD~$lh%Zrq z!C(n74yguPT;Unk@&_~(`Y1J6<- z&h4S*ee^=kg1MZUn<^5FX${}^HqR>b0RVQUn-t^$?q&=4?4%DftYm#R6X}n$ndZL1J|o{M1(UH z@1qxR7Se4IU|_v>nxMTRRKAbi{-FQ^Z#UungCf+tj~=uR>ZSk#%h4EO{7cn#onfT_ zgYcVHBJ5?N>iTEZp8|K-h^QAtsCgf~fU}TXt3dBp20mi^OTBOwb`}zSA<)UiAVY+` zR9u%U;w**=z|3Xp4AYse_w>k_t9(E3NY|a zv?U@RQSsbM0cRnpt)O*%7m2Z#dg&Ro?kiq^LFy*q^;aTPzK>qOPJn@ciBR)CdI4u4 z@o54KOp^(pS0KVj-F3MVb^;8X3ka|G7Gb2~x?BNgA+c2g49wFAujdzGr0%(wk`|zI z0tw&WEkfn{=v{URFbF>*yk1m_b({AD82BfDA)>sZ?z&u^bO8pQ#lFPYOTG36Xr4|$fPs4-;q$#ksC*y2-)#W~ zi7$lD$roXy;<{WxXCbe30t{@A3Eyue!bsh9xptuYyQirU5x-PC_Y$-o$xwiSv4QZo zw+JJ3*X7!%fZCIU_f3dU^FDgey03Er3^KRx5)sbSU6<>AMSy|5Lx>oAskgsd&{@c3 ztpJ1EXTs-=h*0xBdeC_6Jdp&eUC(YuPQpz<+D7?>Jn65(I!uFKWu6JTJ!O-wt7itBRuorSc{ zg7yzSBErAaU6*V8Ux0z_9pUpfMHmICS8fP63z=#NFtDF&A;!N{P0wcU1Q@tCEF;2R z>aNRmJ1xM#v5N40Z6egXk6yr8$nApw1INC3#Q2x0;p|u@z`%Ki@cHc`jMQD1YyVMz zfqxF+^MXXEc^|!ivye%F00Z}A!uKGEFbY#OoQ>-Q7`PS?Q!h~Q+)DvxA<%ueOkITU z?-rrvee?p(LJDUE7NMUN3ak5Pn?y6bY)`UDs_{@x=ZJyUUA zF6f*<9svff3xv;g5n-g_x?IqGBKiUhOkao@H>2XZT+q2&q5=#ozX`8n6rtvQ^a9R8 zyxal|jQa@hhZUjnee`Oe^EWz(>6cM=U9NJn00ZytI3m(B70vH*=g~DzKFfcA7 zrrl1(b-8@bLf%^h7#OB3AfmjY?z&vp%>oR(rwE^mD8fj^b-4o0Lg5Dl7#KdhAi}>? zT$d~8EEE$Zz`)QJPmI0P>!%1h3q>3d=*%K!9V0dGqvv-P%DXSX!19@cuz#s}A3dM5 zP!yK{17kDc^Z7-nd>_5Pu>b?pNg~!2Q1d=|L1!WV(*g`qpEeT_&Qv@vSI}9=+e(0e z|2^UTDI!$9kKUzUfPt&wED`>t;<{V`XCc{_0u20n3E!70!bHV&x%|#TLg4}oEFDDj zLz$?1AHBeJ0S5k$*+hghb`IH!YsW+b@=qw~*A;7@Ap76c!BGkN(UeH-c zpiO{5d=e4kW=vE(FIUi6$URDcLEu><5#db5b-6;$LN3Mv3_3H5iLsY@^`MZmkc9xK zzd-oBFA-|qM=#_o6lp8)T%M@!cySW10wDp6rtvQ^n%VpiID>Dix~)?Pbfmo`{;$7g%aWf7<4*`7&oKx zee}Vd0t{T2%!tUpR6H+Nz*)%ev;YJ1TEhGHMW}fnJ!t(T=se`*eMI<|itBRuorRo3 z1Q^(wh*$^3M8$Qv{LVsV4Iq1`6XRd%mCyXnLi*(b4D6jmj88IA_q<%wJD_vLiC8a6 z&HLy<>o$)HFmPNVrhi1;b-5~v0t{TAh}b_!&HLyDorRnj1Q;YA5!0@t;<{WxXCeK& z0t{@gh!|I)=6&=6&O!zP0t_6Ddx*$K)IBdZ;DP{yz;eR(!i!MzK6(LXA*a^@44g}e zvX^@0hM=>MgN^`$z)!;G<%&@AK6*Z9A@|1u3`{GC*k8s(-F3NkodOIzx33V9uBdok zuAsA!>lpzCxoyPMgH&9X%kL}{y;y*Ot@jfV{-xr1xuE*@y#NE-#9zeNOTF~W?<`~o zS|8i*NQAvqJTI5uSxB==fPrz&1Y+!^UcZ~)Sx9N400TqgEn@7YYBnND0xGon|4{8fAuwNslKSXUU|>E?#JLbmRJ@NKbpJw!00ZxR!uPX_Fj041uDgr?1J5BM=GmF3 zdtR>fd;tcY(}d6W7Ga|9x?Iht0u1b{2%nQL!bIJ5x!z0y3`~7NMC2nXo|h}&EM#pd zz`(kdh;tICc^|!ivyc_900YxP!skzlFj4WmTu^`EjQ|7tZ*C&OnTqRj1)PPp>|cq>h)7V`v|5AFfi_!MU1`FOV6P5Rf+`| zWR4PXo(whbqZe`(%2E(m9>icrgny~HE?3A|C~Ca`gXT8E_lJrwNm4bOgH;6>q}B=$ z;a@7Amn+~b6v!tqMV6TJ&8T@FJ!qfx1%WHc3~a>sm#X2cFCx(Jo`LW=kRnXfU6)(X zF2KOtNK8A2itBO(oQ2Y7fzF>KX1tw>=j94G3njS=FmTM=PDK1taa}H`A1W%qz;%L% zbEuf8cpp9JUXS$x3>(lcm1e}(`9%SIyB6Eab8U9Ov9F1h1iM&7#P12ao#2qb=T!GGzlM!7l*@-qvlz_?LR= z8Pq@8AiyBBgNShk9xAS56m=G|VisU@ze>b@D;_GYV-#@~vOFNbpzxE3^(s89R1IgN zH3AG=%|x7g$-_p~deFQ{fI(m)5$Cz_P;nh2XntXt00V0S;q&=Lc-W{K&T19{48lkD z5s{DBsTaGr4L2``_G4@ig+z@gWGBy`rux+R##$M`$v#7I>Dd>KU-9(J%@KEu5 zQ9)-R!-WD2GT&|!;a}>mW7PH#VBlyb;@o&14(f$7sC;e`U||0`n+X3>aUG+evk<$9 z00Ym7Ok(V%UU~-gQ=A1DL{=vgV=q<1nave+t|>A76fSC(8-jle1sHhS3yAP97d69K z@Ta%{gZOD8&Y$F=>N-Zj?=_(F2?^gDF2ci2&2Sdt@E2eZ-$P8jPu+Eloc#g}+}%XX zYw&PWFFgx63$ff6U{JpjLPWZv?m9;9egOvNd9R4EmzwEWi2bzy1Md&Q_brO>Q1N_G z&^?}i1Q?Wd6R|#)hl=Nm3OWm^+Y2zTA19{%rS3XL`9q-cs)>mBrS3XLc?AImzK1qM z*h|HAjH1p$W;+DtL^2R@4h9bu*D-?5-3kS@C;t%RU+R?`{LVtWG6D>2E6Rzmmx}8c zLF?B}=FZIG%z*$J$K!AZ`GvRxsMR=&VjuEu3UQl3{ z0|OEB-8@uW#|XOr_ocw>^Tf;_@lbIcBfqoYzexfNO#MWh%fv&)b&UMZLQY)*46KWZ zsTZiYjuF)Fz9YcE{M&$t^ejl#^sMtmfPw9P1rhdAcO9eNW&sA)^Gk@amwN3D0cRnd zUs$aJr1?bl$~a*P;zsh6HX_3vQ;29EheoS(x(-F1xmmjoCj&k=Es91j)G7X_6Y ztpW@}cZunjQTKdNt-AsY%*{mHgTO<@^F{fcg-oPD_e#$oB3)5&9V5T9kdcl61A8km z;~P|5$0*<|WH?=bf$b9!_X6-xbseMNXHb7(6%psT@lf%6Q2}ScHlg){g_unR7=%~26A{i-T*oNnEW|D^z+gtFWaSrN5We({7<;ML-Vk&aVwfbrAb6OF z^MZJ&c)qBhvk+ex=={3HMEIAA=ZgwD3vp!&FfiOCV!tF070(wHauyO*7hn+jM9e&_ zJXPlh?H3C$u)gynBAlssz9_%5kes9d1JiyY?z!NRr(SyIcNP+#C&0k5K9Qh*MH#8P zF4r|nV0I!A`xitR8L3$h3fcb>xO$0*bBRS6skkmz*jdP-S77-qBFZ~LE|=d~$l;~{1M_sk=YEJXQg>ahbD#hN``rgbq-QFw%LVPzoFu@& zy*88>d#RV61)PO!LHCv}Bqn~TxGooTZqIuG2F~?_*I$V;QgK}_XkEPp=-w8>=g5gN zQgK}_$le$M2CjC(_oRz5vQV#l7IYReJ0ZZp^dyjobVbE=xuA1DA_N$CZW2B(SCo;8 z>vBQ!p@9MnOfLxU-xp=1;<{YW{V5Ux418M&&!>noQg>Z0N0R^p^TJI;#4lCXaNSRt`lJ3*-CgmMU;_> z>v9F0h0LxCFz_rQypK()XU9OO`5TB<2gZ4ba_jijjQgL0bh_eva zLji^t{|KKOFUm;8b-AGZWg!9#QonW+5zai+s|P{nelQ9!2<{`ik3f`>itBPg^JQuR z3{0B|pPMJjNZob0IvWHSWZn}#|5=ogy6bW^KL{`|H4;8IUX+oF>v9F0h2-}LFmUt` z)83%sx?DkLA(a{d2Ib?o3TLjixkSV-KUKq7FKNg3PDB~0yDrybvH%0` z^AsZdOWk$3R)zu$0V-2XAI%qFU|LQ1JVsGQDz3{FbQY4b6ky=mpG1Uzg{T+Kg3dxBA_5E|R|wy8 zA<9U_b-9AhLj1h~3}VZOseh@vF4s^|fPv?n1QFp(-F3N!dIAiL7l~=dQulmO6I%fW zwi|@!e?=LoyDrzHQGkJWjS>;zOx<<4R!;;N7&qk;V=q<94I?Q52KFt4*I$V;QgL0b zfU}TVFzDPZE+YI(-Sb6t90eHoR|FGdFIB@?RZ)O}a|bc=Wz=1lYbXjjABph(GEqkA zuFJLZ5MW@LNBDd*QAR4R%LSdcX(PbE-ABxLI~CXE3OWlZ83-`2>?NjrrsBF>A!i|x zF9HlI2Z>2n)IDF63v|xsI%4Kwskkl|bRU6=00V0~G2@d|T$d~0ETnW*fPwuTG4%p< z*X7E65n$lHMofE>itBPg=T5f@Ffbk`e7>0|BNf->g7PnDAN^Kh$}8%w%Qck{VBkMW z_}&LmMk=n$<#QI&Wf5RtIZjNyPsMe){LVr;NdgRvuL<9OB+5wDb-6-jGXxlTnh39N z7iFa4x?Fx|ArD3Y2BsgZMAZA#Jzvz+N`Qf3jRi6GQnkHd$S=Uab(Qe>W}=K#T$ju5 zEM%!Ez`)W@jDM-PE*EsJ_$>hjhG)d|7pS-{7qp(CRe*tilP3}JOVxF`LK+?d4BY1l zpC=>ANX2!z0?tB;Uj!H!&lM8mU#g~OIXeLc=0k+nsfsdEaa}HG|Ir!&2F4y@+I7@j zm#g$ffI;E`G3$b;xGq<~SxDSQfI(o*2_oW`y6bYaI|Udd`%e*LFIC5p3@?Dj+fNc> zFICgC{&fKc?g>P!b7P|7x?IqG<@*H~*cTDeKVqWdx?Fx|AuiDU-F<}5%@bv!;<{XZ zXTd+bp!>^+Sf9g0#dW!$@n=xIKbP?RN1{wrT$d~0EF@Jcz`#0j*)LoY=CM3YX zznJj(8=_29T$d~8Eckqb0E2WZ5#u>bR6H+N&{^=&PXPw@4I+fg4JN9t%N4wRTY!Q8 z3gPn#M470#E?3Z5@Z38A2H7u!&-)T(qT;$-L1)2hPXrj)FA~w7WTNW2T)|751Q-|( zbr2E1R9u(K?=1LxrvL-v6fa`zrCvQK>@4_at^fn`xm058rCvQK>@4_MLSRob1L1v| zqD<6XmuvJ^V173d=Oc+SQE^?ah_jHai9mM}0}<^yCMuqnE95LBuvUPZEsJJc{v|fcrVDfch_B}CCcU`W% zv;YI|1;Xbti84`fT`p)GsQ}bJ;wK`0skkne-&sgKOn`y4|2h%&QgK}_zq63pasdYB ziE_l)OTF|g;4Gx?Ccwb*-I5r4saHOO#$z=E77+FaHi_ITp?Xc0S2De#Q2wr>v9F0g&Z$|?u92NT~TpeE@*xMH2&O8 z#Ck#|Dz3`~oj)lD+PBzEMEp{5T`r%qkh78i17qJ`V(g_}xxwcwWKk}_z}TWmjJ?z= zH~5`}9LqrSbVQ7+Fi~+`F2A#o{U(9=w~07^Qk02`>vH*>h0KKo_MRhV|1T32*X4rF zu~{PUNRok_i1?-Ax?BNgA)hvZjkQFzpQ*SmSHM}w_nZI&+Y`d)jEOQ)ab2!}vyj(v z(E2MP<|Ub^xGtB^St!{`V3s3M?Pn^k%jI(xiqjBi;bveWB3)5&T`s?~P*AnNfn!9q zpQ*Smm(N)!qC$XyaUtRR7Dbt;xGoozo`VD!*gq1n-kXVv=jDny3wZ?yFkD?v#C~=r zDz3`~%?~yUFfh#jNkqD$?s>V^6#@)weYc3QmwNS}sI!obz5t`wGs5R?i84`fT`uU} z(r$r+j6~H7)LobB>L74yIRi26Sn96Jb@CCIoxni&eppc^Dz3}rcNWT07hvExO-y@| zitBRuorU7p2rw|;B7CoVt@i84`lU9NSo z00aM}>BRV#dgTV_{_d%ubBc(V-)Exgx?I73H3AImyM>7GFLl@DGP?;da4jTapBIxT zHNzR~Uyg0Wj1y9KU9Q|g0S3k{Ng~3Ty6bZJ3k4WhyLS;|FEztii1WJu1KR>$BJ8E& zx?BNgAx$p<29Bph?0aIO;<{XZXCcKV0S3kv9dI3otPD6TX*Ll!?0Qat*Zv7}$D=sTZiYE*Eq!kG}we%oSqtFBRA2 zg6?}V5?~NJPsDm)CMvGW6?7I-J1f8-d}TEe`In08as`})v?mKNFsvtH-6j)t*X8OQ z7GPkTOw2s2H1*02(D<{l00YMYBF;HsqVBp}hkpVLYz?wR#4nZC diff --git a/MisterBiggs/julia-for-matlabbers/index.jl b/MisterBiggs/julia-for-matlabbers/index.jl index 092d0604d..4e43f9f88 100644 --- a/MisterBiggs/julia-for-matlabbers/index.jl +++ b/MisterBiggs/julia-for-matlabbers/index.jl @@ -16,21 +16,17 @@ using LinearAlgebra # ╔═╡ 52819547-9593-446a-91e7-a08e08723e66 using Plots +# ╔═╡ c231f030-5861-4b30-a182-efc06b5c08fe +using BenchmarkTools + # ╔═╡ 3228a21e-cab8-4738-bdc5-a6827c764c06 using Unitful -# ╔═╡ 3f7ae2df-9d4d-46d3-b12e-22107a560b66 -begin - using CSV - using DataFrames - using FileIO -end - # ╔═╡ bb461e00-c0aa-11eb-2c7d-1bd1591779c6 md""" # Julia for People That Were Unfortunate Enough to Learn MATLAB -Julia is an incredily performant _(2 order of magnitude faster than Matlab)_, Dynamic _(Data types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. +Julia is an incredily [performant](https://julialang.org/benchmarks/) _(2 order of magnitude faster than Matlab)_, Dynamic _(Data types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. !!! info "Pluto Notebooks" The code in this notebook is running in something called Pluto.jl. Pluto notebooks are similar to Matlab Livescript but have a stricter focus on cells and are immutable meaning that a variable can only be declared once and cannot be changed in other cells. This feels very restricting at first but guarantees that the code you are currently looking at is correct, and allows reactive updating of dependant code. It's important to note that these are Pluto.jl features and not Julia features. @@ -42,8 +38,6 @@ md""" To get started, I want to focus on things that Matlab does that are outlandish and make little sense and compare them to things Julia does. Julia is obviously not perfect, but being that it's one of the newest and fastest-growing languages, it's easy to argue that Julia's syntax and language design are the most modern and sane currently available in programming, primarily if you are focusing on engineering or science workloads. -In future chapters, I will focus more on how Julia shines rather than why Matlab doesn't. - ### Enviroments A significant pain point for large Matlab projects is managing installed Toolboxes and Packages. In Matlab, once something is installed it is available globally and doesn't have to be imported to a script to be used. There are quite a few downsides to this, the largest in my opinion: it is very easy to crowd your namespace. To make it even worse, Matlab usually doesn't even warn you about the issue so if two packages offer a function of the same name, it is just going to choose one and hope it works out. Another big issue this can cause is version conflicts. This is why there are so many issues trying to run code between Matlab versions. @@ -56,6 +50,11 @@ The best way to install packages is to open the Julia REPL (basically Matlab's c Pluto will automatically install any of the packages in this notebook that you are missing, but this can take a long time since Julia is still very slow to compile new packages. """ +# ╔═╡ 072e459a-1423-45df-b269-8402b1683ea6 +md""" +Since you have to import packages in order to use them there is never any ambiguity as to what package you need to run a script. In Matlab you simply get a warning saying it doesn't know what the function you are trying to use is but with Julia the compiler will even tell you the commands needed to install that package. +""" + # ╔═╡ 16a7201a-4ce0-4102-9874-96733514ef08 md""" !!! warning @@ -69,7 +68,7 @@ md""" In Matlab its very common to grow an array in a for loop using `array(end+1)` _(You really should never do this since it creates a new array every loop which gets very inefficent, but I'm not here to teach you Matlab)_. In Julia, you use `push!` for adding a single number to the end of a `Vector` and `append!` to add collections _(also known as arrays or lists)_ to the end of a `Vector`. You'll notice that `!` at the end of the push and append functions. In Julia the exclamation point at the end of a function name means that the function modifies the function inputs in place compared to returning a new copy of the object. !!! note "Indexing Syntax" - Array index syntax uses square brackets `[]` in Julia instead of parenthesis in Matlab `()`. + Julia uses square brackets `[]` to index compared to parenthesis in Matlab `()`. """ # ╔═╡ 0a4dc275-04b3-43e3-8a0d-cb921d769a0a @@ -84,11 +83,14 @@ sort!(a); a # a is now sorted since sort!(a) sorts in place. # ╔═╡ 58c883b6-3682-424d-a1e9-8ac561bb0dbf a[end+1] = 5 # Can't grow array by indexing like in Matlab +# ╔═╡ a0748b65-171a-49e3-a018-8cb7b8c0bc31 +push!(a, 5) # Correct way to grow the array. + # ╔═╡ a74e7cad-8dae-41cd-b77a-65ba082956a3 md""" ### Functions -Matlab functions have a ton of weird behaviors. The weirdest being that optional function returns are done based on the amount of return values so: +Matlab functions have a ton of weird behaviors. The weirdest being that optional function returns are done based on the amount of return values like the follwing: ```julia % Matlab Example @@ -97,7 +99,7 @@ P = polyfit(X,Y,N) [P,S,MU] = polyfit(X,Y,N) ``` -all return different things. In this case, it's simple to tell what is going on, but if you had no idea what the `polyfit` function did in the first place it is totally unintuitive what the extra returned values are. If a function has optional returns in other languages, it is usually idiomatic to return those values with an optional keyword argument or just have a completely different function to get the different data. In the case of `polyfit`, calculating S and MU are unrelated to calculating P, so it is not like the data was already calculated and can be quickly returned like you would generally expect to be the case with optional returns. To make things even worse, `S` is designed to be an input to a different function, `POLYVAL`, so why wouldn't you just make polyval take `X`, `Y`, and `N` as inputs? Matlab is dumb `/endrant`. +All of those function calls to `polyfit` return different things. In this case, it's simple to tell what is going on, but if you had no idea what the `polyfit` function did in the first place it is totally unintuitive what the extra returned values are. If a function has optional returns in other languages, it is usually idiomatic to return those values with an optional keyword argument or just have a completely different function to get the different data. In the case of `polyfit`, calculating S and MU are unrelated to calculating P, so it is not like the data was already calculated and can be quickly returned like you would generally expect to be the case with optional returns. To make things even worse, `S` is designed to be an input to a different function, `POLYVAL`, so why wouldn't you just make polyval take `X`, `Y`, and `N` as inputs? Matlab is dumb `/endrant`. Another weird thing is where functions can be placed in Matlab. In livescripts they can only be placed at the end of the file, and there's also the ability to make files that are only a function. In Julia, functions can be anywhere, and files can contain as many functions as you want and can be imported by any other file. The function syntax in Julia is also very sane. """ @@ -129,7 +131,7 @@ end # ╔═╡ 3c921f2d-3972-4b88-990d-36ced0764bc5 # Julia will always use the closest matching function. function g(x::Int, y::Int) # x and y need to be integers - z = x+y # last line is returned, so really could just be x+y without the z + x + y # last line in a function gets returned end # ╔═╡ b7ae33bc-5edd-4741-a578-d210521b1698 @@ -139,7 +141,7 @@ g(14) # Since there are 4 different methods for g Julia will find and use the cl g(5.0, 6.0) # Normal g function used since inputs are floats # ╔═╡ 8688fe79-00ad-497f-a466-dc86af9e03b0 -g() # Uses normal g function since there is no match for g that has a Int and a Float specified as inputs. +g(4, 2.1) # Uses most generic g function since there is no match for g that has a Int and a Float specified as inputs. # ╔═╡ 9440e0bc-7920-4b81-b88a-0b1046d24b4c g(5, 6) # Integer method used since inputs are both integers. @@ -161,7 +163,7 @@ Matlab generally does broadcasting for you which can be dangerous since sometime b = 1:5 # Ranges are similar to Matlab, but will discussed later in the text # ╔═╡ 6124f6b4-6315-4d74-9067-4553ce1d54bc -sin(b) # gotta broadcast! +sin(b) # Error, gotta broadcast! # ╔═╡ 95e30983-f305-41aa-a1e2-f38fa0d0c1c3 sin.(b) # Nice! @@ -188,11 +190,11 @@ Matlab evaluates arrays when they are made which is very common in programming l # ╔═╡ e3c28497-29e9-447e-aba0-650aaaa52d88 typeof(1:10) -# ╔═╡ 4fd4f72d-45e0-4760-bc0b-5ebb78636e2c -enumerate(1:.25:2) # returns an enumerate object +# ╔═╡ cc419cd3-75fc-4ae6-b41f-17bf5b537771 +collect(1:10) -# ╔═╡ cf125fe2-c754-4218-92c9-3f491f3109c1 -collect(enumerate(1:.25:2)) # Returns an an array of tuples as expected +# ╔═╡ 4fd4f72d-45e0-4760-bc0b-5ebb78636e2c +enumerate([5 4 3 2 1]) # enumeration is also lazy # ╔═╡ 4802d903-e87c-4ef0-a184-e4ae7af69a28 md""" @@ -207,10 +209,10 @@ Plots use very similar syntax to Matlab with the exception that there is no `hol """ # ╔═╡ a4665e30-4c64-46d1-8349-a49f40763a0b -plot(sin) +plot(sin) # We can plot functions # ╔═╡ 09303ffe-6cf8-4273-b697-9fbd7cb82cc1 -plot(cos) # Makes a new plot! +plot(cos) # Makes a new plot since we didnt use plot! # ╔═╡ e3b51038-2e57-4a5a-9b5d-7bf7148d700b begin @@ -222,6 +224,23 @@ end # ╔═╡ 55e0d022-faca-40f8-a4a9-3a501eb5d19e plot!(atan, label="atan") # Returns a new plot with all the elements of the old plot. +# ╔═╡ 4cd38b1c-e85c-49c7-9871-b893bc53c686 +let + x = -10:10 + y = x.^2 + plot(x, y, title="We can also plot x-y data", label="") +end + +# ╔═╡ 2f3b1426-5e16-4d24-9ade-e5c88d8cb9b7 +let + t = 0:.001:2π + x = sin.(t) + y = cos.(t) + z = sin.(4t) + + plot(x,y,z, title="We can even do 3d plots!", label="3 Dimensions!") +end + # ╔═╡ dc89d08d-29bf-4e04-8470-c79c88ab4689 md""" !!! note @@ -262,20 +281,20 @@ md""" There are a few ways that Julia really shines that make it perfect for engineering and science. Below are a few examples. -## Symbols +### Symbols -Julia supports a wide variety of unicode symbols in the language that can be accessed with the syntax `\pi{tab}` to get π. This is a great way to make code closer to LaTex or handwritten examples which makes it easier to read or understand. +Julia supports a wide variety of unicode symbols in the language that can be accessed with the syntax `\pi{tab}` to get π. This is a great way to make code closer to $\LaTeX$ or handwritten examples which makes it easier to read or understand. * `\theta{tab}` θ * `q\bar{tab}` q̄ * `x\ddot{tab}` ẍ -## List Comprehension +### List Comprehension List comprehensions can be thought of single line for loops and can be very handy in a variety of scenarios. The syntax is: ```julia -# Add 1 to each number in a list of numbers +# Add 1 to each number in the list called numbers [number + 1 for number in numbers] ``` @@ -288,6 +307,9 @@ List comprehensions are especially useful instead of one line for loops, or when # ╔═╡ 2172de3a-7dba-4cbc-9c04-444db595c328 [x for x in 1:12 if x % 3 == 0] +# ╔═╡ b519ad43-dd1f-41f2-8b6c-f6196ae1df76 +@benchmark 1+1; # This just makes sure benchmark is precompiled to ensure the tests below are accurate + # ╔═╡ fd0f5cf6-c90b-4492-9c72-9e707803e736 md""" Since `append!` is usually very slow you can see below that using a list comprehension to create a vector is almost 10x faster. @@ -295,15 +317,22 @@ Since `append!` is usually very slow you can see below that using a list compreh # ╔═╡ a2c7e472-2460-428e-bfec-acf925fad89d begin + function f() t = [] for i in 1:1e6 append!(t,i) end - t + end + @benchmark f() end # ╔═╡ bce2eecc-dc01-4bf6-9eaa-880fd8a69768 -[i for i in 1:1e6] +@benchmark [i for i in 1:1e6] + +# ╔═╡ 881367d3-a247-4bdc-92d4-f3e205982837 +md""" +Note that not only is it much faster, but the memory usage and allocations are much lower aswell. +""" # ╔═╡ a2df1c35-c0b2-45bb-86b7-57e208287392 md""" @@ -350,183 +379,32 @@ weight |> u"N" # ╔═╡ 8d4de01a-197f-40cb-942f-bfec335e3844 md""" -Units can also be stripped to give a normal number again. +Units can also be stripped to give a normal number again. This is important since most other packages don't have support for units. Yet. """ # ╔═╡ 86da848f-1e84-47c8-8a79-373f241b6025 ustrip(u"N", weight) -# ╔═╡ dc898d32-b30b-4baa-a595-b83ccd1dc86d -md""" -# Everything below isn't close to being finished -""" - -# ╔═╡ 9ea4584c-8177-4f69-9739-b2faa93281a8 -md""" ---- - -### Matrix Math -""" - -# ╔═╡ f43812d2-9f87-489a-9317-e7aa19ffd3bc -md""" ---- - -### Custom Data Types -""" - -# ╔═╡ f6d87354-ac46-4202-92f8-b39a0db13327 -μ = 3.986004418e14u"m^3/s^2" # Standard Gravitational Parameter for Earth - -# ╔═╡ f8039870-2570-47d0-8d46-30922415ec9d -earth_radius = 6378u"km" - -# ╔═╡ 863cd607-a459-49ae-9049-983f3374f523 -abstract type Orbit end - -# ╔═╡ 44daff45-f608-47e3-ad6e-fca43532f322 -struct Circular_Orbit <: Orbit - """Simple 2d circular orbit""" - r::typeof(.1u"km") # altitude -end - - -# ╔═╡ efb58b79-24e4-45c6-ad45-aeaa339d82fd -ISS = Circular_Orbit(420u"km") - -# ╔═╡ ad3a2b19-5639-4d11-8d89-bc54772d639b -struct Elliptic_Orbit <: Orbit - """Simple 2d elliptic orbit""" - r::typeof(.1u"km") # altitude - a::typeof(.1u"km") # semimajor axis - e::Float64 # eccentricity - - function Elliptic_Orbit(r, a, e) - @assert e < 1 "Eccentricity must be less than 1!" - @assert 0 < e "Eccentricity must be greater than 0!" - new(r, a, e) - end - - - function Elliptic_Orbit(perigee, apogee) - a = (perigee + apogee) / 2 - e = 1 - (perigee/a) - r = a*((1-e^2)/(1+e)) # Assume θ is 0 since we aren't keeping track of it - Elliptic_Orbit(r,a,e) - end -end - -# ╔═╡ b4e08868-d48a-4f66-9d20-f45ea4d83f00 -sat = Elliptic_Orbit(earth_radius+537.0u"km", earth_radius+9040.9u"km") - -# ╔═╡ 3efd8a29-6a56-4f5c-9cab-0f08875b2064 -function get_velocity(o::Circular_Orbit) - v = sqrt(μ/o.r) - return v |> u"km/s" -end - -# ╔═╡ 59207a25-fa6d-4369-979d-cd9cc2f094cf -function get_velocity(o::Elliptic_Orbit) - v = sqrt(μ*(2/o.r - 1/o.a)) - return v |> u"km/s" -end - -# ╔═╡ 11fb3a28-edf3-46ff-8c4a-5286793b6e43 -get_velocity(ISS) - -# ╔═╡ 79a9ab94-06a8-4613-8f60-358e08f0f32e -get_velocity(sat) - -# ╔═╡ c3d943b4-809d-4a96-a99d-be7653ba2c8b -begin -function Plots.plot(orbit::Elliptic_Orbit) - a = orbit.a |> u"km" |> ustrip - b = orbit.a*sqrt(1-orbit.e^2) |> u"km" |> ustrip - t = 0:.01:2π - - x_orbit(t) = a*cos(t) - y_orbit(t) = b*sin(t) - - plot(x_orbit, y_orbit, t) - - x_earth(t) = ustrip(earth_radius)*cos(t) + a*orbit.e - y_earth(t) = ustrip(earth_radius)*sin(t) - plot!(x_earth,y_earth, t, c=:gray,fill=(0,:blue), legend=false,aspect_ratio=:equal) - - title!("Satellite Orbiting Earth") -end -plot(sat) -end - -# ╔═╡ 01ba1742-d26e-4271-ab62-0bd9ce5e291d -function get_ΔV(start::Orbit, final::Orbit) - get_velocity(start) - get_velocity(final) -end - -# ╔═╡ ad4d24a8-f601-4522-a3eb-c01f6fd68aec -get_ΔV(ISS,sat) - -# ╔═╡ 2d0de5db-5558-41e0-96d5-a3317d151aff - - -# ╔═╡ 8924673f-e99c-44b3-be6d-2abf0b2f5e23 +# ╔═╡ ee5aad93-0437-429d-969e-fee239e6a577 md""" ---- - -### Tabular Data -""" - -# ╔═╡ c460478a-db52-4a15-a723-9ff64eed9aec -# download_csv(url) = DataFrame(CSV.File(download(url))) -download_csv(url) = url |> download |> CSV.File |> DataFrame +## Conclusion -# ╔═╡ 9ccbea0d-6463-4533-88a6-0267879eb263 -F10 = download_csv("julia.ansonbiggs.com/AeroTech_F10.csv") +This is only scratching the surface of the differences between the two languages, but I hope this can serve as a starting point. In the future, I would like to dig more into the differences since I do think that Julia will eclipse Matlab in use in engineering before too long. -# ╔═╡ 4ffebbb2-7021-4c08-82ac-95366dab3d48 -G8 = download_csv("julia.ansonbiggs.com/AeroTech_G8ST.csv") - -# ╔═╡ 2e83292e-8e8c-43e4-82ee-951a2f6a98c1 -F15 = download_csv("julia.ansonbiggs.com/Estes_F15.csv") - -# ╔═╡ c7e2a7f8-626f-45d8-b771-6f9e74a86bd8 -let - plot(title = "Rocket Motor Comparison", xlabel="Time (s)", ylabel="Thrust (N)") - plot!(F10.Time, F10.Thrust,label="F10") - plot!(G8.Time, G8.Thrust,label="G8") - plot!(F15.Time, F15.Thrust,label="F15") -end - -# ╔═╡ 8ec4af16-1a19-468e-b097-59985bf28f5c -describe(F10) - -# ╔═╡ 9f886419-7259-442e-b068-d0e4c886a886 -maximum.([F10.Thrust, G8.Thrust, F15.Thrust]) - -# ╔═╡ fbc06121-d53a-4a64-9497-63d7f3583fbb -md""" -## Things Julia Does Poorly - -- Time to First Plot -- Libraries -- Still young and breaking things +I am currently rewriting large amounts of code from Matlab to Julia, so hopefully, through that experience, I can provide a more detailed explanation and, ideally, some information that will be useful to other people making the same transition. """ # ╔═╡ 00000000-0000-0000-0000-000000000001 PLUTO_PROJECT_TOML_CONTENTS = """ [deps] -CSV = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" +BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" [compat] -CSV = "~0.8.5" -DataFrames = "~1.2.0" -FileIO = "~1.11.0" +BenchmarkTools = "~1.1.3" Plots = "~1.19.0" PlutoUI = "~0.7.9" Unitful = "~1.8.0" @@ -551,18 +429,18 @@ uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" [[Base64]] uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +[[BenchmarkTools]] +deps = ["JSON", "Logging", "Printf", "Statistics", "UUIDs"] +git-tree-sha1 = "aa3aba5ed8f882ed01b71e09ca2ba0f77f44a99e" +uuid = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" +version = "1.1.3" + [[Bzip2_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] git-tree-sha1 = "c3598e525718abcc440f69cc6d5f60dda0a1b61e" uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" version = "1.0.6+5" -[[CSV]] -deps = ["Dates", "Mmap", "Parsers", "PooledArrays", "SentinelArrays", "Tables", "Unicode"] -git-tree-sha1 = "b83aa3f513be680454437a0eee21001607e5d983" -uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" -version = "0.8.5" - [[Cairo_jll]] deps = ["Artifacts", "Bzip2_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Pkg", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] git-tree-sha1 = "e2f47f6d8337369411569fd45ae5753ca10394c6" @@ -609,22 +487,11 @@ git-tree-sha1 = "9f02045d934dc030edad45944ea80dbd1f0ebea7" uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" version = "0.5.7" -[[Crayons]] -git-tree-sha1 = "3f71217b538d7aaee0b69ab47d9b7724ca8afa0d" -uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" -version = "4.0.4" - [[DataAPI]] git-tree-sha1 = "ee400abb2298bd13bfc3df1c412ed228061a2385" uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" version = "1.7.0" -[[DataFrames]] -deps = ["Compat", "DataAPI", "Future", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrettyTables", "Printf", "REPL", "Reexport", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] -git-tree-sha1 = "1dadfca11c0e08e03ab15b63aaeda55266754bad" -uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" -version = "1.2.0" - [[DataStructures]] deps = ["Compat", "InteractiveUtils", "OrderedCollections"] git-tree-sha1 = "4437b64df1e0adccc3e5d1adbc3ac741095e4677" @@ -676,12 +543,6 @@ git-tree-sha1 = "3cc57ad0a213808473eafef4845a74766242e05f" uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" version = "4.3.1+4" -[[FileIO]] -deps = ["Pkg", "Requires", "UUIDs"] -git-tree-sha1 = "937c29268e405b6808d958a9ac41bfe1a31b08e7" -uuid = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" -version = "1.11.0" - [[FixedPointNumbers]] deps = ["Statistics"] git-tree-sha1 = "335bfdceacc84c5cdf16aadc768aa5ddfc5383cc" @@ -712,10 +573,6 @@ git-tree-sha1 = "aa31987c2ba8704e23c6c8ba8a4f769d5d7e4f91" uuid = "559328eb-81f9-559d-9380-de523a88c83c" version = "1.0.10+0" -[[Future]] -deps = ["Random"] -uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" - [[GLFW_jll]] deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pkg", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll"] git-tree-sha1 = "dba1e8614e98949abfa60480b13653813d8f0157" @@ -773,12 +630,6 @@ version = "0.5.0" deps = ["Markdown"] uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" -[[InvertedIndices]] -deps = ["Test"] -git-tree-sha1 = "15732c475062348b0165684ffe28e85ea8396afc" -uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" -version = "1.0.0" - [[IterTools]] git-tree-sha1 = "05110a2ab1fc5f932622ffea2a003221f4782c18" uuid = "c8e1da08-722c-5040-9ed9-7db0dc04731e" @@ -1024,24 +875,12 @@ git-tree-sha1 = "44e225d5837e2a2345e69a1d1e01ac2443ff9fcb" uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" version = "0.7.9" -[[PooledArrays]] -deps = ["DataAPI", "Future"] -git-tree-sha1 = "cde4ce9d6f33219465b55162811d8de8139c0414" -uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" -version = "1.2.1" - [[Preferences]] deps = ["TOML"] git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a" uuid = "21216c6a-2e73-6563-6e65-726566657250" version = "1.2.2" -[[PrettyTables]] -deps = ["Crayons", "Formatting", "Markdown", "Reexport", "Tables"] -git-tree-sha1 = "0d1245a357cc61c8cd61934c07447aa569ff22e6" -uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" -version = "1.1.0" - [[Printf]] deps = ["Unicode"] uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" @@ -1091,12 +930,6 @@ git-tree-sha1 = "0b4b7f1393cff97c33891da2a0bf69c6ed241fda" uuid = "6c6a2e73-6563-6170-7368-637461726353" version = "1.1.0" -[[SentinelArrays]] -deps = ["Dates", "Random"] -git-tree-sha1 = "ffae887d0f0222a19c406a11c3831776d1383e3d" -uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" -version = "1.3.3" - [[Serialization]] uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" @@ -1413,12 +1246,14 @@ version = "0.9.1+5" # ╟─307cbf7a-1ac5-47a5-8031-3458f9dd1887 # ╟─11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 # ╠═7d7820ff-c0f5-41ee-be29-5006e7f4361d +# ╟─072e459a-1423-45df-b269-8402b1683ea6 # ╟─16a7201a-4ce0-4102-9874-96733514ef08 # ╟─3cad3f5f-f6a5-405b-aeb0-495ebd8cca45 # ╠═0a4dc275-04b3-43e3-8a0d-cb921d769a0a # ╠═193c6a29-4f53-4c96-acc7-b5359043b471 # ╠═6fa90db6-9d2b-47bc-9f41-925b447912e8 # ╠═58c883b6-3682-424d-a1e9-8ac561bb0dbf +# ╠═a0748b65-171a-49e3-a018-8cb7b8c0bc31 # ╟─a74e7cad-8dae-41cd-b77a-65ba082956a3 # ╠═f4d655a2-8539-43f7-9356-56a3e3f9de91 # ╠═289727e4-fb29-4ba8-97c5-cce62da725bc @@ -1440,22 +1275,27 @@ version = "0.9.1+5" # ╟─3ef67004-2f85-4aa1-a1b5-5cbf62b292f7 # ╠═1025e3a8-59c9-4725-bc1a-a0b94e6bd6af # ╠═e3c28497-29e9-447e-aba0-650aaaa52d88 +# ╠═cc419cd3-75fc-4ae6-b41f-17bf5b537771 # ╠═4fd4f72d-45e0-4760-bc0b-5ebb78636e2c -# ╠═cf125fe2-c754-4218-92c9-3f491f3109c1 # ╟─4802d903-e87c-4ef0-a184-e4ae7af69a28 # ╠═52819547-9593-446a-91e7-a08e08723e66 # ╠═a4665e30-4c64-46d1-8349-a49f40763a0b # ╠═09303ffe-6cf8-4273-b697-9fbd7cb82cc1 # ╠═e3b51038-2e57-4a5a-9b5d-7bf7148d700b # ╠═55e0d022-faca-40f8-a4a9-3a501eb5d19e +# ╠═4cd38b1c-e85c-49c7-9871-b893bc53c686 +# ╠═2f3b1426-5e16-4d24-9ade-e5c88d8cb9b7 # ╟─dc89d08d-29bf-4e04-8470-c79c88ab4689 # ╟─b30e6f73-fe46-45e7-898e-dd1205dffe68 # ╟─916f5f09-1aa3-47a7-9c66-c42513eaccea # ╠═2172de3a-7dba-4cbc-9c04-444db595c328 +# ╠═c231f030-5861-4b30-a182-efc06b5c08fe +# ╟─b519ad43-dd1f-41f2-8b6c-f6196ae1df76 # ╟─fd0f5cf6-c90b-4492-9c72-9e707803e736 # ╠═a2c7e472-2460-428e-bfec-acf925fad89d # ╠═bce2eecc-dc01-4bf6-9eaa-880fd8a69768 -# ╟─a2df1c35-c0b2-45bb-86b7-57e208287392 +# ╠═881367d3-a247-4bdc-92d4-f3e205982837 +# ╠═a2df1c35-c0b2-45bb-86b7-57e208287392 # ╠═3228a21e-cab8-4738-bdc5-a6827c764c06 # ╟─7b9b11f2-c6d3-4dab-ab30-6e47a3a4bfb3 # ╠═09bc71cd-7bc0-4d5a-bcf8-984abe273375 @@ -1466,33 +1306,6 @@ version = "0.9.1+5" # ╠═ade2979d-155e-4f20-82db-6da141bb8eaa # ╟─8d4de01a-197f-40cb-942f-bfec335e3844 # ╠═86da848f-1e84-47c8-8a79-373f241b6025 -# ╟─dc898d32-b30b-4baa-a595-b83ccd1dc86d -# ╠═9ea4584c-8177-4f69-9739-b2faa93281a8 -# ╠═f43812d2-9f87-489a-9317-e7aa19ffd3bc -# ╠═f6d87354-ac46-4202-92f8-b39a0db13327 -# ╠═f8039870-2570-47d0-8d46-30922415ec9d -# ╠═863cd607-a459-49ae-9049-983f3374f523 -# ╠═44daff45-f608-47e3-ad6e-fca43532f322 -# ╠═efb58b79-24e4-45c6-ad45-aeaa339d82fd -# ╠═ad3a2b19-5639-4d11-8d89-bc54772d639b -# ╠═b4e08868-d48a-4f66-9d20-f45ea4d83f00 -# ╠═3efd8a29-6a56-4f5c-9cab-0f08875b2064 -# ╠═59207a25-fa6d-4369-979d-cd9cc2f094cf -# ╠═11fb3a28-edf3-46ff-8c4a-5286793b6e43 -# ╠═79a9ab94-06a8-4613-8f60-358e08f0f32e -# ╠═c3d943b4-809d-4a96-a99d-be7653ba2c8b -# ╠═01ba1742-d26e-4271-ab62-0bd9ce5e291d -# ╠═ad4d24a8-f601-4522-a3eb-c01f6fd68aec -# ╠═2d0de5db-5558-41e0-96d5-a3317d151aff -# ╠═8924673f-e99c-44b3-be6d-2abf0b2f5e23 -# ╠═3f7ae2df-9d4d-46d3-b12e-22107a560b66 -# ╠═c460478a-db52-4a15-a723-9ff64eed9aec -# ╠═9ccbea0d-6463-4533-88a6-0267879eb263 -# ╠═4ffebbb2-7021-4c08-82ac-95366dab3d48 -# ╠═2e83292e-8e8c-43e4-82ee-951a2f6a98c1 -# ╠═c7e2a7f8-626f-45d8-b771-6f9e74a86bd8 -# ╠═8ec4af16-1a19-468e-b097-59985bf28f5c -# ╠═9f886419-7259-442e-b068-d0e4c886a886 -# ╠═fbc06121-d53a-4a64-9497-63d7f3583fbb +# ╟─ee5aad93-0437-429d-969e-fee239e6a577 # ╟─00000000-0000-0000-0000-000000000001 # ╟─00000000-0000-0000-0000-000000000002 -- 2.51.2 From 854cfae9a401a39643a59648a4038baa46279553 Mon Sep 17 00:00:00 2001 From: Anson Date: Tue, 24 Aug 2021 02:48:39 -0700 Subject: [PATCH 20/21] fixed a typo --- MisterBiggs/julia-for-matlabbers/index.html | 4 ++-- MisterBiggs/julia-for-matlabbers/index.jl | 26 +++------------------ 2 files changed, 5 insertions(+), 25 deletions(-) diff --git a/MisterBiggs/julia-for-matlabbers/index.html b/MisterBiggs/julia-for-matlabbers/index.html index 9001f9d4f..65b37e0fb 100644 --- a/MisterBiggs/julia-for-matlabbers/index.html +++ b/MisterBiggs/julia-for-matlabbers/index.html @@ -53,11 +53,11 @@ diff --git a/MisterBiggs/julia-for-matlabbers/index.jl b/MisterBiggs/julia-for-matlabbers/index.jl index 4e43f9f88..585a6c886 100644 --- a/MisterBiggs/julia-for-matlabbers/index.jl +++ b/MisterBiggs/julia-for-matlabbers/index.jl @@ -4,12 +4,6 @@ using Markdown using InteractiveUtils -# ╔═╡ 307cbf7a-1ac5-47a5-8031-3458f9dd1887 -begin - using PlutoUI - PlutoUI.TableOfContents(aside=true) -end - # ╔═╡ 7d7820ff-c0f5-41ee-be29-5006e7f4361d using LinearAlgebra @@ -26,7 +20,7 @@ using Unitful md""" # Julia for People That Were Unfortunate Enough to Learn MATLAB -Julia is an incredily [performant](https://julialang.org/benchmarks/) _(2 order of magnitude faster than Matlab)_, Dynamic _(Data types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. +Julia is an incredibly [performant](https://julialang.org/benchmarks/) _(2 order of magnitude faster than Matlab)_, Dynamic _(Data types dont need to be declared unlike C)_, Composable _(The compiler is smart enough to allow functions you write to work for multiple different types of data)_, and most importantly for our use case Julia has very simple syntax that focuses on engineering / science applications. !!! info "Pluto Notebooks" The code in this notebook is running in something called Pluto.jl. Pluto notebooks are similar to Matlab Livescript but have a stricter focus on cells and are immutable meaning that a variable can only be declared once and cannot be changed in other cells. This feels very restricting at first but guarantees that the code you are currently looking at is correct, and allows reactive updating of dependant code. It's important to note that these are Pluto.jl features and not Julia features. @@ -400,13 +394,11 @@ PLUTO_PROJECT_TOML_CONTENTS = """ BenchmarkTools = "6e4b80f9-dd63-53aa-95a3-0cdb28fa8baf" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" Plots = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" -PlutoUI = "7f904dfe-b85e-4ff6-b463-dae2292396a8" Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" [compat] BenchmarkTools = "~1.1.3" Plots = "~1.19.0" -PlutoUI = "~0.7.9" Unitful = "~1.8.0" """ @@ -869,12 +861,6 @@ git-tree-sha1 = "83c762ddea05f5554e1b04f4a5ecae61990ccc8e" uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" version = "1.19.0" -[[PlutoUI]] -deps = ["Base64", "Dates", "InteractiveUtils", "JSON", "Logging", "Markdown", "Random", "Reexport", "Suppressor"] -git-tree-sha1 = "44e225d5837e2a2345e69a1d1e01ac2443ff9fcb" -uuid = "7f904dfe-b85e-4ff6-b463-dae2292396a8" -version = "0.7.9" - [[Preferences]] deps = ["TOML"] git-tree-sha1 = "00cfd92944ca9c760982747e9a1d0d5d86ab1e5a" @@ -983,11 +969,6 @@ git-tree-sha1 = "000e168f5cc9aded17b6999a560b7c11dda69095" uuid = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" version = "0.6.0" -[[Suppressor]] -git-tree-sha1 = "a819d77f31f83e5792a76081eee1ea6342ab8787" -uuid = "fd094767-a336-5f1f-9728-57cf17d0bbfb" -version = "0.2.0" - [[TOML]] deps = ["Dates"] uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" @@ -1243,7 +1224,6 @@ version = "0.9.1+5" # ╔═╡ Cell order: # ╟─bb461e00-c0aa-11eb-2c7d-1bd1591779c6 -# ╟─307cbf7a-1ac5-47a5-8031-3458f9dd1887 # ╟─11ed58ac-1289-4b64-88a8-17cb7f0b6cd2 # ╠═7d7820ff-c0f5-41ee-be29-5006e7f4361d # ╟─072e459a-1423-45df-b269-8402b1683ea6 @@ -1294,8 +1274,8 @@ version = "0.9.1+5" # ╟─fd0f5cf6-c90b-4492-9c72-9e707803e736 # ╠═a2c7e472-2460-428e-bfec-acf925fad89d # ╠═bce2eecc-dc01-4bf6-9eaa-880fd8a69768 -# ╠═881367d3-a247-4bdc-92d4-f3e205982837 -# ╠═a2df1c35-c0b2-45bb-86b7-57e208287392 +# ╟─881367d3-a247-4bdc-92d4-f3e205982837 +# ╟─a2df1c35-c0b2-45bb-86b7-57e208287392 # ╠═3228a21e-cab8-4738-bdc5-a6827c764c06 # ╟─7b9b11f2-c6d3-4dab-ab30-6e47a3a4bfb3 # ╠═09bc71cd-7bc0-4d5a-bcf8-984abe273375 -- 2.51.2 From 46ad0b602df64bedee347b8598ab83bb636d2d3b Mon Sep 17 00:00:00 2001 From: Anson Date: Tue, 24 Aug 2021 02:54:15 -0700 Subject: [PATCH 21/21] added a readme --- MisterBiggs/julia-for-matlabbers/readme.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 MisterBiggs/julia-for-matlabbers/readme.md diff --git a/MisterBiggs/julia-for-matlabbers/readme.md b/MisterBiggs/julia-for-matlabbers/readme.md new file mode 100644 index 000000000..94b6fd65d --- /dev/null +++ b/MisterBiggs/julia-for-matlabbers/readme.md @@ -0,0 +1 @@ +This article is live at https://projects.ansonbiggs.com/posts/2021-08-24-julia-for-matlabbers/ \ No newline at end of file