diff --git a/.gitignore b/.gitignore index 30ce227..8107067 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,6 @@ # MacOS nonsense .DS_Store -Manifest.toml - # quarto docs/ diff --git a/9_experiments_end.qmd b/9_experiments_end.qmd index b060603..8c7ad5b 100644 --- a/9_experiments_end.qmd +++ b/9_experiments_end.qmd @@ -8,6 +8,7 @@ format: title-block-banner: true engine: julia --- + In the previous chapter, we learned how to make networks and run a simulation. We did this for a simple tri-trophic chain where we specified the network with a matrix of ones and zeros, and for a more complex network defined by the niche model where we specified species richness and connectance. We also learned how to visualise the simulations and to collect several metrics about the simulations, including detail on biomass, diversity and stability. In this tutorial, we are going to learn how to do experiments. We'll learn first how to generate multiple networks and collect information on how network structure impacts our metrics. Then we'll learn how to manipulate parameters in the model, again collecting information on how variation in these parameters impacts our metrics. diff --git a/Manifest.toml b/Manifest.toml new file mode 100644 index 0000000..6dd6f19 --- /dev/null +++ b/Manifest.toml @@ -0,0 +1,3075 @@ +# This file is machine-generated - editing it directly is not advised + +julia_version = "1.11.1" +manifest_format = "2.0" +project_hash = "b3838a2c9f5911bc19243043766e954754ba3821" + +[[deps.ADTypes]] +git-tree-sha1 = "eea5d80188827b35333801ef97a40c2ed653b081" +uuid = "47edcb42-4c32-4615-8424-f2b9edc5f35b" +version = "1.9.0" +weakdeps = ["ChainRulesCore", "EnzymeCore"] + + [deps.ADTypes.extensions] + ADTypesChainRulesCoreExt = "ChainRulesCore" + ADTypesEnzymeCoreExt = "EnzymeCore" + +[[deps.ANSIColoredPrinters]] +git-tree-sha1 = "574baf8110975760d391c710b6341da1afa48d8c" +uuid = "a4c015fc-c6ff-483c-b24f-f7ea428134e9" +version = "0.0.1" + +[[deps.AbstractFFTs]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "d92ad398961a3ed262d8bf04a1a2b8340f915fef" +uuid = "621f4979-c628-5d54-868e-fcf4e3e8185c" +version = "1.5.0" +weakdeps = ["ChainRulesCore", "Test"] + + [deps.AbstractFFTs.extensions] + AbstractFFTsChainRulesCoreExt = "ChainRulesCore" + AbstractFFTsTestExt = "Test" + +[[deps.AbstractTrees]] +git-tree-sha1 = "2d9c9a55f9c93e8887ad391fbae72f8ef55e1177" +uuid = "1520ce14-60c1-5f80-bbc7-55ef81b5835c" +version = "0.4.5" + +[[deps.Accessors]] +deps = ["CompositionsBase", "ConstructionBase", "InverseFunctions", "LinearAlgebra", "MacroTools", "Markdown"] +git-tree-sha1 = "b392ede862e506d451fc1616e79aa6f4c673dab8" +uuid = "7d9f7c33-5ae7-4f3b-8dc6-eff91059b697" +version = "0.1.38" + + [deps.Accessors.extensions] + AccessorsAxisKeysExt = "AxisKeys" + AccessorsDatesExt = "Dates" + AccessorsIntervalSetsExt = "IntervalSets" + AccessorsStaticArraysExt = "StaticArrays" + AccessorsStructArraysExt = "StructArrays" + AccessorsTestExt = "Test" + AccessorsUnitfulExt = "Unitful" + + [deps.Accessors.weakdeps] + AxisKeys = "94b1ba4f-4ee9-5380-92f1-94cde586c3c5" + Dates = "ade2ca70-3891-5945-98fb-dc099432e06a" + IntervalSets = "8197267c-284f-5f27-9208-e0e47529a953" + Requires = "ae029012-a4dd-5104-9daa-d747884805df" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + StructArrays = "09ab397b-f2b6-538f-b94a-2f83cf4a842a" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.Adapt]] +deps = ["LinearAlgebra", "Requires"] +git-tree-sha1 = "50c3c56a52972d78e8be9fd135bfb91c9574c140" +uuid = "79e6a3ab-5dfb-504d-930d-738a2a938a0e" +version = "4.1.1" +weakdeps = ["StaticArrays"] + + [deps.Adapt.extensions] + AdaptStaticArraysExt = "StaticArrays" + +[[deps.AliasTables]] +deps = ["PtrArrays", "Random"] +git-tree-sha1 = "9876e1e164b144ca45e9e3198d0b689cadfed9ff" +uuid = "66dad0bd-aa9a-41b7-9441-69ab47430ed8" +version = "1.1.3" + +[[deps.ArgTools]] +uuid = "0dad84c5-d112-42e6-8d28-ef12dabb789f" +version = "1.1.2" + +[[deps.ArnoldiMethod]] +deps = ["LinearAlgebra", "Random", "StaticArrays"] +git-tree-sha1 = "d57bd3762d308bded22c3b82d033bff85f6195c6" +uuid = "ec485272-7323-5ecc-a04f-4719b315124d" +version = "0.4.0" + +[[deps.Arpack]] +deps = ["Arpack_jll", "Libdl", "LinearAlgebra", "Logging"] +git-tree-sha1 = "9b9b347613394885fd1c8c7729bfc60528faa436" +uuid = "7d9fca2a-8960-54d3-9f78-7d1dccf2cb97" +version = "0.5.4" + +[[deps.Arpack_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "OpenBLAS_jll", "Pkg"] +git-tree-sha1 = "5ba6c757e8feccf03a1554dfaf3e26b3cfc7fd5e" +uuid = "68821587-b530-5797-8361-c406ea357684" +version = "3.5.1+1" + +[[deps.ArrayInterface]] +deps = ["Adapt", "LinearAlgebra"] +git-tree-sha1 = "3640d077b6dafd64ceb8fd5c1ec76f7ca53bcf76" +uuid = "4fba245c-0d91-5ea0-9b3e-6abc04ee57a9" +version = "7.16.0" + + [deps.ArrayInterface.extensions] + ArrayInterfaceBandedMatricesExt = "BandedMatrices" + ArrayInterfaceBlockBandedMatricesExt = "BlockBandedMatrices" + ArrayInterfaceCUDAExt = "CUDA" + ArrayInterfaceCUDSSExt = "CUDSS" + ArrayInterfaceChainRulesExt = "ChainRules" + ArrayInterfaceGPUArraysCoreExt = "GPUArraysCore" + ArrayInterfaceReverseDiffExt = "ReverseDiff" + ArrayInterfaceSparseArraysExt = "SparseArrays" + ArrayInterfaceStaticArraysCoreExt = "StaticArraysCore" + ArrayInterfaceTrackerExt = "Tracker" + + [deps.ArrayInterface.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e" + ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" + GPUArraysCore = "46192b85-c4d5-4398-a991-12ede77f4527" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + StaticArraysCore = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + +[[deps.ArrayLayouts]] +deps = ["FillArrays", "LinearAlgebra"] +git-tree-sha1 = "492681bc44fac86804706ddb37da10880a2bd528" +uuid = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" +version = "1.10.4" +weakdeps = ["SparseArrays"] + + [deps.ArrayLayouts.extensions] + ArrayLayoutsSparseArraysExt = "SparseArrays" + +[[deps.Artifacts]] +uuid = "56f22d72-fd6d-98f1-02f0-08ddc0907c33" +version = "1.11.0" + +[[deps.AxisAlgorithms]] +deps = ["LinearAlgebra", "Random", "SparseArrays", "WoodburyMatrices"] +git-tree-sha1 = "01b8ccb13d68535d73d2b0c23e39bd23155fb712" +uuid = "13072b0f-2c55-5437-9ae7-d433b7a33950" +version = "1.1.0" + +[[deps.BandedMatrices]] +deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "PrecompileTools"] +git-tree-sha1 = "a2c85f53ddcb15b4099da59867868bd40f005579" +uuid = "aae01518-5342-5314-be14-df237901396f" +version = "1.7.5" +weakdeps = ["SparseArrays"] + + [deps.BandedMatrices.extensions] + BandedMatricesSparseArraysExt = "SparseArrays" + +[[deps.Base64]] +uuid = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f" +version = "1.11.0" + +[[deps.Bijections]] +git-tree-sha1 = "d8b0439d2be438a5f2cd68ec158fe08a7b2595b7" +uuid = "e2ed5e7c-b2de-5872-ae92-c73ca462fb04" +version = "0.1.9" + +[[deps.BitFlags]] +git-tree-sha1 = "0691e34b3bb8be9307330f88d1a3c3f25466c24d" +uuid = "d1d4a3ce-64b1-5f1a-9ba4-7e7e69966f35" +version = "0.1.9" + +[[deps.BitTwiddlingConvenienceFunctions]] +deps = ["Static"] +git-tree-sha1 = "f21cfd4950cb9f0587d5067e69405ad2acd27b87" +uuid = "62783981-4cbd-42fc-bca8-16325de8dc4b" +version = "0.1.6" + +[[deps.BoundaryValueDiffEq]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "BoundaryValueDiffEqFIRK", "BoundaryValueDiffEqMIRK", "BoundaryValueDiffEqShooting", "ConcreteStructs", "DiffEqBase", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LineSearch", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "NonlinearSolve", "OrdinaryDiffEq", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays", "SparseDiffTools"] +git-tree-sha1 = "98da8bd76b89a4ae1b8dde9fc6dcd75dcd6b5282" +uuid = "764a87c0-6b3e-53db-9096-fe964310641d" +version = "5.12.0" + + [deps.BoundaryValueDiffEq.extensions] + BoundaryValueDiffEqODEInterfaceExt = "ODEInterface" + + [deps.BoundaryValueDiffEq.weakdeps] + ODEInterface = "54ca160b-1b9f-5127-a996-1867f4bc2a2c" + +[[deps.BoundaryValueDiffEqCore]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "ForwardDiff", "LineSearch", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "NonlinearSolve", "PreallocationTools", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays", "SparseDiffTools"] +git-tree-sha1 = "768423f5fa51adc47ea5bd2540497fc785c2f0cc" +uuid = "56b672f2-a5fe-4263-ab2d-da677488eb3a" +version = "1.0.1" + +[[deps.BoundaryValueDiffEqFIRK]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LineSearch", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "NonlinearSolve", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays", "SparseDiffTools"] +git-tree-sha1 = "35e1e7822d1c77d85ecf568606ca64d60fbd39de" +uuid = "85d9eb09-370e-4000-bb32-543851f73618" +version = "1.0.2" + +[[deps.BoundaryValueDiffEqMIRK]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LineSearch", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "NonlinearSolve", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays", "SparseDiffTools"] +git-tree-sha1 = "e1fa0dee3d8eca528ab96e765a52760fd7466ffa" +uuid = "1a22d4ce-7765-49ea-b6f2-13c8438986a6" +version = "1.0.1" + +[[deps.BoundaryValueDiffEqShooting]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "BandedMatrices", "BoundaryValueDiffEqCore", "ConcreteStructs", "DiffEqBase", "FastAlmostBandedMatrices", "FastClosures", "ForwardDiff", "LineSearch", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "NonlinearSolve", "OrdinaryDiffEq", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "SparseArrays", "SparseDiffTools"] +git-tree-sha1 = "fac04445ab0fdfa29b62d84e1af6b21334753a94" +uuid = "ed55bfe0-3725-4db6-871e-a1dc9f42a757" +version = "1.0.2" + +[[deps.Bzip2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "8873e196c2eb87962a2048b3b8e08946535864a1" +uuid = "6e34b625-4abd-537c-b88f-471c36dfa7a0" +version = "1.0.8+2" + +[[deps.CEnum]] +git-tree-sha1 = "389ad5c84de1ae7cf0e28e381131c98ea87d54fc" +uuid = "fa961155-64e5-5f13-b03f-caf6b980ea82" +version = "0.5.0" + +[[deps.CPUSummary]] +deps = ["CpuId", "IfElse", "PrecompileTools", "Static"] +git-tree-sha1 = "5a97e67919535d6841172016c9530fd69494e5ec" +uuid = "2a0fbf3d-bb9c-48f3-b0a9-814d99fd7ab9" +version = "0.2.6" + +[[deps.CSV]] +deps = ["CodecZlib", "Dates", "FilePathsBase", "InlineStrings", "Mmap", "Parsers", "PooledArrays", "PrecompileTools", "SentinelArrays", "Tables", "Unicode", "WeakRefStrings", "WorkerUtilities"] +git-tree-sha1 = "deddd8725e5e1cc49ee205a1964256043720a6c3" +uuid = "336ed68f-0bac-5ca0-87d4-7b16caf5d00b" +version = "0.10.15" + +[[deps.Cairo_jll]] +deps = ["Artifacts", "Bzip2_jll", "CompilerSupportLibraries_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "JLLWrappers", "LZO_jll", "Libdl", "Pixman_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "009060c9a6168704143100f36ab08f06c2af4642" +uuid = "83423d85-b0ee-5818-9007-b63ccbeb887a" +version = "1.18.2+1" + +[[deps.ChainRulesCore]] +deps = ["Compat", "LinearAlgebra"] +git-tree-sha1 = "3e4b134270b372f2ed4d4d0e936aabaefc1802bc" +uuid = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" +version = "1.25.0" +weakdeps = ["SparseArrays"] + + [deps.ChainRulesCore.extensions] + ChainRulesCoreSparseArraysExt = "SparseArrays" + +[[deps.CloseOpenIntervals]] +deps = ["Static", "StaticArrayInterface"] +git-tree-sha1 = "05ba0d07cd4fd8b7a39541e31a7b0254704ea581" +uuid = "fb6a15b2-703c-40df-9091-08a04967cfa9" +version = "0.1.13" + +[[deps.Clustering]] +deps = ["Distances", "LinearAlgebra", "NearestNeighbors", "Printf", "Random", "SparseArrays", "Statistics", "StatsBase"] +git-tree-sha1 = "9ebb045901e9bbf58767a9f34ff89831ed711aae" +uuid = "aaaa29a8-35af-508c-8bc3-b662a17a0fe5" +version = "0.15.7" + +[[deps.CodeTracking]] +deps = ["InteractiveUtils", "UUIDs"] +git-tree-sha1 = "7eee164f122511d3e4e1ebadb7956939ea7e1c77" +uuid = "da1fd8a2-8d9e-5ec2-8556-3022fb5608a2" +version = "1.3.6" + +[[deps.CodecZlib]] +deps = ["TranscodingStreams", "Zlib_jll"] +git-tree-sha1 = "bce6804e5e6044c6daab27bb533d1295e4a2e759" +uuid = "944b1d66-785c-5afd-91f1-9de20f533193" +version = "0.7.6" + +[[deps.ColorSchemes]] +deps = ["ColorTypes", "ColorVectorSpace", "Colors", "FixedPointNumbers", "PrecompileTools", "Random"] +git-tree-sha1 = "13951eb68769ad1cd460cdb2e64e5e95f1bf123d" +uuid = "35d6a980-a343-548e-a6ea-1d62b119f2f4" +version = "3.27.0" + +[[deps.ColorTypes]] +deps = ["FixedPointNumbers", "Random"] +git-tree-sha1 = "b10d0b65641d57b8b4d5e234446582de5047050d" +uuid = "3da002f7-5984-5a60-b8a6-cbb66c0b333f" +version = "0.11.5" + +[[deps.ColorVectorSpace]] +deps = ["ColorTypes", "FixedPointNumbers", "LinearAlgebra", "Requires", "Statistics", "TensorCore"] +git-tree-sha1 = "a1f44953f2382ebb937d60dafbe2deea4bd23249" +uuid = "c3611d14-8923-5661-9e6a-0046d554d3a4" +version = "0.10.0" +weakdeps = ["SpecialFunctions"] + + [deps.ColorVectorSpace.extensions] + SpecialFunctionsExt = "SpecialFunctions" + +[[deps.Colors]] +deps = ["ColorTypes", "FixedPointNumbers", "Reexport"] +git-tree-sha1 = "362a287c3aa50601b0bc359053d5c2468f0e7ce0" +uuid = "5ae59095-9a9b-59fe-a467-6f913c188581" +version = "0.12.11" + +[[deps.Combinatorics]] +git-tree-sha1 = "08c8b6831dc00bfea825826be0bc8336fc369860" +uuid = "861a8166-3701-5b0c-9a16-15d98fcdc6aa" +version = "1.0.2" + +[[deps.CommonSolve]] +git-tree-sha1 = "0eee5eb66b1cf62cd6ad1b460238e60e4b09400c" +uuid = "38540f10-b2f7-11e9-35d8-d573e4eb0ff2" +version = "0.2.4" + +[[deps.CommonSubexpressions]] +deps = ["MacroTools"] +git-tree-sha1 = "cda2cfaebb4be89c9084adaca7dd7333369715c5" +uuid = "bbf7d656-a473-5ed7-a52c-81e309532950" +version = "0.3.1" + +[[deps.CommonWorldInvalidations]] +git-tree-sha1 = "ae52d1c52048455e85a387fbee9be553ec2b68d0" +uuid = "f70d9fcc-98c5-4d4a-abd7-e4cdeebd8ca8" +version = "1.0.0" + +[[deps.Compat]] +deps = ["TOML", "UUIDs"] +git-tree-sha1 = "8ae8d32e09f0dcf42a36b90d4e17f5dd2e4c4215" +uuid = "34da2185-b29b-5c13-b0c7-acf172513d20" +version = "4.16.0" +weakdeps = ["Dates", "LinearAlgebra"] + + [deps.Compat.extensions] + CompatLinearAlgebraExt = "LinearAlgebra" + +[[deps.CompilerSupportLibraries_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "e66e0078-7015-5450-92f7-15fbd957f2ae" +version = "1.1.1+0" + +[[deps.CompositeTypes]] +git-tree-sha1 = "bce26c3dab336582805503bed209faab1c279768" +uuid = "b152e2b5-7a66-4b01-a709-34e65c35f657" +version = "0.1.4" + +[[deps.CompositionsBase]] +git-tree-sha1 = "802bb88cd69dfd1509f6670416bd4434015693ad" +uuid = "a33af91c-f02d-484b-be07-31d278c5ca2b" +version = "0.1.2" +weakdeps = ["InverseFunctions"] + + [deps.CompositionsBase.extensions] + CompositionsBaseInverseFunctionsExt = "InverseFunctions" + +[[deps.ConcreteStructs]] +git-tree-sha1 = "f749037478283d372048690eb3b5f92a79432b34" +uuid = "2569d6c7-a4a2-43d3-a901-331e8e4be471" +version = "0.2.3" + +[[deps.ConcurrentUtilities]] +deps = ["Serialization", "Sockets"] +git-tree-sha1 = "ea32b83ca4fefa1768dc84e504cc0a94fb1ab8d1" +uuid = "f0e56b4a-5159-44fe-b623-3e5288b988bb" +version = "2.4.2" + +[[deps.Conda]] +deps = ["Downloads", "JSON", "VersionParsing"] +git-tree-sha1 = "b19db3927f0db4151cb86d073689f2428e524576" +uuid = "8f4d0f93-b110-5947-807f-2305c1781a2d" +version = "1.10.2" + +[[deps.ConstructionBase]] +git-tree-sha1 = "76219f1ed5771adbb096743bff43fb5fdd4c1157" +uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" +version = "1.5.8" +weakdeps = ["IntervalSets", "LinearAlgebra", "StaticArrays"] + + [deps.ConstructionBase.extensions] + ConstructionBaseIntervalSetsExt = "IntervalSets" + ConstructionBaseLinearAlgebraExt = "LinearAlgebra" + ConstructionBaseStaticArraysExt = "StaticArrays" + +[[deps.Contour]] +git-tree-sha1 = "439e35b0b36e2e5881738abc8857bd92ad6ff9a8" +uuid = "d38c429a-6771-53c6-b99e-75d170b6e991" +version = "0.6.3" + +[[deps.CpuId]] +deps = ["Markdown"] +git-tree-sha1 = "fcbb72b032692610bfbdb15018ac16a36cf2e406" +uuid = "adafc99b-e345-5852-983c-f28acb93d879" +version = "0.3.1" + +[[deps.Crayons]] +git-tree-sha1 = "249fe38abf76d48563e2f4556bebd215aa317e15" +uuid = "a8cc5b0e-0ffa-5ad4-8c14-923d3ee1735f" +version = "4.1.1" + +[[deps.DataAPI]] +git-tree-sha1 = "abe83f3a2f1b857aac70ef8b269080af17764bbe" +uuid = "9a962f9c-6df0-11e9-0e5d-c546b8b5ee8a" +version = "1.16.0" + +[[deps.DataFrames]] +deps = ["Compat", "DataAPI", "DataStructures", "Future", "InlineStrings", "InvertedIndices", "IteratorInterfaceExtensions", "LinearAlgebra", "Markdown", "Missings", "PooledArrays", "PrecompileTools", "PrettyTables", "Printf", "Random", "Reexport", "SentinelArrays", "SortingAlgorithms", "Statistics", "TableTraits", "Tables", "Unicode"] +git-tree-sha1 = "fb61b4812c49343d7ef0b533ba982c46021938a6" +uuid = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" +version = "1.7.0" + +[[deps.DataStructures]] +deps = ["Compat", "InteractiveUtils", "OrderedCollections"] +git-tree-sha1 = "1d0a14036acb104d9e89698bd408f63ab58cdc82" +uuid = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8" +version = "0.18.20" + +[[deps.DataValueInterfaces]] +git-tree-sha1 = "bfc1187b79289637fa0ef6d4436ebdfe6905cbd6" +uuid = "e2d170a0-9d28-54be-80f0-106bbe20a464" +version = "1.0.0" + +[[deps.Dates]] +deps = ["Printf"] +uuid = "ade2ca70-3891-5945-98fb-dc099432e06a" +version = "1.11.0" + +[[deps.Dbus_jll]] +deps = ["Artifacts", "Expat_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "fc173b380865f70627d7dd1190dc2fce6cc105af" +uuid = "ee1fde0b-3d02-5ea6-8484-8dfef6360eab" +version = "1.14.10+0" + +[[deps.Decimals]] +git-tree-sha1 = "e98abef36d02a0ec385d68cd7dadbce9b28cbd88" +uuid = "abce61dc-4473-55a0-ba07-351d65e31d42" +version = "0.4.1" + +[[deps.DelayDiffEq]] +deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "LinearAlgebra", "Logging", "OrdinaryDiffEq", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SimpleNonlinearSolve", "SimpleUnPack"] +git-tree-sha1 = "066f60231c1b0ae2905ffd2651e207accd91f627" +uuid = "bcd4f6db-9728-5f36-b5f7-82caef46ccdb" +version = "5.48.1" + +[[deps.DelimitedFiles]] +deps = ["Mmap"] +git-tree-sha1 = "9e2f36d3c96a820c678f2f1f1782582fcf685bae" +uuid = "8bb1440f-4735-579b-a4ab-409b98df4dab" +version = "1.9.1" + +[[deps.DiffEqBase]] +deps = ["ArrayInterface", "ConcreteStructs", "DataStructures", "DocStringExtensions", "EnumX", "EnzymeCore", "FastBroadcast", "FastClosures", "ForwardDiff", "FunctionWrappers", "FunctionWrappersWrappers", "LinearAlgebra", "Logging", "Markdown", "MuladdMacro", "Parameters", "PreallocationTools", "PrecompileTools", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SciMLStructures", "Setfield", "Static", "StaticArraysCore", "Statistics", "TruncatedStacktraces"] +git-tree-sha1 = "f8eefbb7e910f59087c4bb09ce670f235758ee4a" +uuid = "2b5f629d-d688-5b77-993f-72d75c75574e" +version = "6.158.3" + + [deps.DiffEqBase.extensions] + DiffEqBaseCUDAExt = "CUDA" + DiffEqBaseChainRulesCoreExt = "ChainRulesCore" + DiffEqBaseDistributionsExt = "Distributions" + DiffEqBaseEnzymeExt = ["ChainRulesCore", "Enzyme"] + DiffEqBaseGeneralizedGeneratedExt = "GeneralizedGenerated" + DiffEqBaseMPIExt = "MPI" + DiffEqBaseMeasurementsExt = "Measurements" + DiffEqBaseMonteCarloMeasurementsExt = "MonteCarloMeasurements" + DiffEqBaseReverseDiffExt = "ReverseDiff" + DiffEqBaseSparseArraysExt = "SparseArrays" + DiffEqBaseTrackerExt = "Tracker" + DiffEqBaseUnitfulExt = "Unitful" + + [deps.DiffEqBase.weakdeps] + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Distributions = "31c24e10-a181-5473-b8eb-7969acd0382f" + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + GeneralizedGenerated = "6b9d7cbe-bcb9-11e9-073f-15a7a543e2eb" + MPI = "da04e1cc-30fd-572f-bb4f-1f8673147195" + Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.DiffEqCallbacks]] +deps = ["DataStructures", "DiffEqBase", "ForwardDiff", "Functors", "LinearAlgebra", "Markdown", "NonlinearSolve", "Parameters", "RecipesBase", "RecursiveArrayTools", "SciMLBase", "StaticArraysCore"] +git-tree-sha1 = "19dbd44d18bbfdfcf5e56c99cea9b0ed23df350a" +uuid = "459566f4-90b8-5000-8ac3-15dfb0a30def" +version = "3.9.1" +weakdeps = ["OrdinaryDiffEq", "OrdinaryDiffEqCore", "Sundials"] + +[[deps.DiffEqNoiseProcess]] +deps = ["DiffEqBase", "Distributions", "GPUArraysCore", "LinearAlgebra", "Markdown", "Optim", "PoissonRandom", "QuadGK", "Random", "Random123", "RandomNumbers", "RecipesBase", "RecursiveArrayTools", "ResettableStacks", "SciMLBase", "StaticArraysCore", "Statistics"] +git-tree-sha1 = "ab1e6515ce15f01316a9825b02729fefa51726bd" +uuid = "77a26b50-5914-5dd7-bc55-306e6241c503" +version = "5.23.0" + + [deps.DiffEqNoiseProcess.extensions] + DiffEqNoiseProcessReverseDiffExt = "ReverseDiff" + + [deps.DiffEqNoiseProcess.weakdeps] + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + +[[deps.DiffResults]] +deps = ["StaticArraysCore"] +git-tree-sha1 = "782dd5f4561f5d267313f23853baaaa4c52ea621" +uuid = "163ba53b-c6d8-5494-b064-1a9d43ac40c5" +version = "1.1.0" + +[[deps.DiffRules]] +deps = ["IrrationalConstants", "LogExpFunctions", "NaNMath", "Random", "SpecialFunctions"] +git-tree-sha1 = "23163d55f885173722d1e4cf0f6110cdbaf7e272" +uuid = "b552c78f-8df3-52c6-915a-8e097449b14b" +version = "1.15.1" + +[[deps.DifferentialEquations]] +deps = ["BoundaryValueDiffEq", "DelayDiffEq", "DiffEqBase", "DiffEqCallbacks", "DiffEqNoiseProcess", "JumpProcesses", "LinearAlgebra", "LinearSolve", "NonlinearSolve", "OrdinaryDiffEq", "Random", "RecursiveArrayTools", "Reexport", "SciMLBase", "SteadyStateDiffEq", "StochasticDiffEq", "Sundials"] +git-tree-sha1 = "d55af9d6b51c54f81ae30d1a463206d32cc4c24a" +uuid = "0c46a032-eb83-5123-abaf-570d42b7fbaa" +version = "7.15.0" + +[[deps.DifferentiationInterface]] +deps = ["ADTypes", "LinearAlgebra"] +git-tree-sha1 = "ba137efeddd4b6e6a7154f2a92d2922a0057486f" +uuid = "a0c0ee7d-e4b9-4e03-894e-1c5f64a51d63" +version = "0.6.21" + + [deps.DifferentiationInterface.extensions] + DifferentiationInterfaceChainRulesCoreExt = "ChainRulesCore" + DifferentiationInterfaceDiffractorExt = "Diffractor" + DifferentiationInterfaceEnzymeExt = "Enzyme" + DifferentiationInterfaceFastDifferentiationExt = "FastDifferentiation" + DifferentiationInterfaceFiniteDiffExt = "FiniteDiff" + DifferentiationInterfaceFiniteDifferencesExt = "FiniteDifferences" + DifferentiationInterfaceForwardDiffExt = "ForwardDiff" + DifferentiationInterfaceMooncakeExt = "Mooncake" + DifferentiationInterfacePolyesterForwardDiffExt = "PolyesterForwardDiff" + DifferentiationInterfaceReverseDiffExt = "ReverseDiff" + DifferentiationInterfaceSparseArraysExt = "SparseArrays" + DifferentiationInterfaceSparseMatrixColoringsExt = "SparseMatrixColorings" + DifferentiationInterfaceStaticArraysExt = "StaticArrays" + DifferentiationInterfaceSymbolicsExt = "Symbolics" + DifferentiationInterfaceTrackerExt = "Tracker" + DifferentiationInterfaceZygoteExt = ["Zygote", "ForwardDiff"] + + [deps.DifferentiationInterface.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Diffractor = "9f5e2b26-1114-432f-b630-d3fe2085c51c" + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + FastDifferentiation = "eb9bf01b-bf85-4b60-bf87-ee5de06c00be" + FiniteDiff = "6a86dc24-6348-571c-b903-95158fe2bd41" + FiniteDifferences = "26cc04aa-876d-5657-8c51-4c34ba976000" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + Mooncake = "da2b9cff-9c12-43a0-ae48-6db2b0edb7d6" + PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + SparseMatrixColorings = "0a514795-09f3-496d-8182-132a7b665d35" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.Distances]] +deps = ["LinearAlgebra", "Statistics", "StatsAPI"] +git-tree-sha1 = "c7e3a542b999843086e2f29dac96a618c105be1d" +uuid = "b4f34e82-e78d-54a5-968a-f98e89d6e8f7" +version = "0.10.12" +weakdeps = ["ChainRulesCore", "SparseArrays"] + + [deps.Distances.extensions] + DistancesChainRulesCoreExt = "ChainRulesCore" + DistancesSparseArraysExt = "SparseArrays" + +[[deps.Distributed]] +deps = ["Random", "Serialization", "Sockets"] +uuid = "8ba89e20-285c-5b6f-9357-94700520ee1b" +version = "1.11.0" + +[[deps.Distributions]] +deps = ["AliasTables", "FillArrays", "LinearAlgebra", "PDMats", "Printf", "QuadGK", "Random", "SpecialFunctions", "Statistics", "StatsAPI", "StatsBase", "StatsFuns"] +git-tree-sha1 = "3101c32aab536e7a27b1763c0797dba151b899ad" +uuid = "31c24e10-a181-5473-b8eb-7969acd0382f" +version = "0.25.113" + + [deps.Distributions.extensions] + DistributionsChainRulesCoreExt = "ChainRulesCore" + DistributionsDensityInterfaceExt = "DensityInterface" + DistributionsTestExt = "Test" + + [deps.Distributions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + DensityInterface = "b429d917-457f-4dbc-8f4c-0cc954292b1d" + Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" + +[[deps.DocStringExtensions]] +deps = ["LibGit2"] +git-tree-sha1 = "2fb1e02f2b635d0845df5d7c167fec4dd739b00d" +uuid = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae" +version = "0.9.3" + +[[deps.Documenter]] +deps = ["ANSIColoredPrinters", "AbstractTrees", "Base64", "CodecZlib", "Dates", "DocStringExtensions", "Downloads", "Git", "IOCapture", "InteractiveUtils", "JSON", "LibGit2", "Logging", "Markdown", "MarkdownAST", "Pkg", "PrecompileTools", "REPL", "RegistryInstances", "SHA", "TOML", "Test", "Unicode"] +git-tree-sha1 = "5a1ee886566f2fa9318df1273d8b778b9d42712d" +uuid = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +version = "1.7.0" + +[[deps.DomainSets]] +deps = ["CompositeTypes", "IntervalSets", "LinearAlgebra", "Random", "StaticArrays"] +git-tree-sha1 = "490392af2c7d63183bfa2c8aaa6ab981c5ba7561" +uuid = "5b8099bc-c8ec-5219-889f-1d9e522a28bf" +version = "0.7.14" + + [deps.DomainSets.extensions] + DomainSetsMakieExt = "Makie" + + [deps.DomainSets.weakdeps] + Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + +[[deps.Downloads]] +deps = ["ArgTools", "FileWatching", "LibCURL", "NetworkOptions"] +uuid = "f43a241f-c20a-4ad4-852c-f6b1247861c6" +version = "1.6.0" + +[[deps.DynamicPolynomials]] +deps = ["Future", "LinearAlgebra", "MultivariatePolynomials", "MutableArithmetics", "Reexport", "Test"] +git-tree-sha1 = "bbf1ace0781d9744cb697fb856bd2c3f6568dadb" +uuid = "7c1d4256-1411-5781-91ec-d7bc3513ac07" +version = "0.6.0" + +[[deps.EcologicalNetworks]] +deps = ["Combinatorics", "DataStructures", "DelimitedFiles", "Distributions", "LinearAlgebra", "Random", "Requires", "SparseArrays", "Statistics", "StatsBase"] +git-tree-sha1 = "3c9c82d9d8d2e7a66695561c6a6f316cdebad74f" +uuid = "f03a62fe-f8ab-5b77-a061-bb599b765229" +version = "0.5.2" + +[[deps.EcologicalNetworksDynamics]] +deps = ["Crayons", "Decimals", "DiffEqBase", "DiffEqCallbacks", "DifferentialEquations", "Distributions", "Documenter", "Graphs", "LinearAlgebra", "MacroTools", "Mangal", "OrderedCollections", "SciMLBase", "SparseArrays", "Statistics", "StringCases"] +git-tree-sha1 = "6578bfbfef3cbc42cf5752461ec81bf68d34f130" +uuid = "2fd9189a-c387-4076-88b7-22b33b5a4388" +version = "0.2.0" + +[[deps.EcologicalNetworksPlots]] +deps = ["EcologicalNetworks", "Random", "RecipesBase", "SparseArrays", "Statistics", "StatsBase"] +git-tree-sha1 = "67896918c157e0909ade42b5b0fba3964a6bfc27" +uuid = "9f7a259d-73a7-556d-a7a2-3eb122d3865b" +version = "0.1.0" + +[[deps.EnumX]] +git-tree-sha1 = "bdb1942cd4c45e3c678fd11569d5cccd80976237" +uuid = "4e289a0a-7415-4d19-859d-a7e5c4648b56" +version = "1.0.4" + +[[deps.EnzymeCore]] +git-tree-sha1 = "04c777af6ef65530a96ab68f0a81a4608113aa1d" +uuid = "f151be2c-9106-41f4-ab19-57ee4f262869" +version = "0.8.5" +weakdeps = ["Adapt"] + + [deps.EnzymeCore.extensions] + AdaptExt = "Adapt" + +[[deps.EpollShim_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8e9441ee83492030ace98f9789a654a6d0b1f643" +uuid = "2702e6a9-849d-5ed8-8c21-79e8b8f9ee43" +version = "0.0.20230411+0" + +[[deps.ExceptionUnwrapping]] +deps = ["Test"] +git-tree-sha1 = "dcb08a0d93ec0b1cdc4af184b26b591e9695423a" +uuid = "460bff9d-24e4-43bc-9d9f-a8973cb893f4" +version = "0.1.10" + +[[deps.Expat_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1c6317308b9dc757616f0b5cb379db10494443a7" +uuid = "2e619515-83b5-522b-bb60-26c02a35a201" +version = "2.6.2+0" + +[[deps.ExponentialUtilities]] +deps = ["Adapt", "ArrayInterface", "GPUArraysCore", "GenericSchur", "LinearAlgebra", "PrecompileTools", "Printf", "SparseArrays", "libblastrampoline_jll"] +git-tree-sha1 = "8e18940a5ba7f4ddb41fe2b79b6acaac50880a86" +uuid = "d4d017d3-3776-5f7e-afef-a10c40355c18" +version = "1.26.1" + +[[deps.ExprTools]] +git-tree-sha1 = "27415f162e6028e81c72b82ef756bf321213b6ec" +uuid = "e2ba6199-217a-4e67-a87a-7c52f15ade04" +version = "0.1.10" + +[[deps.Expronicon]] +deps = ["MLStyle", "Pkg", "TOML"] +git-tree-sha1 = "fc3951d4d398b5515f91d7fe5d45fc31dccb3c9b" +uuid = "6b7a57c9-7cc1-4fdf-b7f5-e857abae3636" +version = "0.8.5" + +[[deps.Extents]] +git-tree-sha1 = "81023caa0021a41712685887db1fc03db26f41f5" +uuid = "411431e0-e8b7-467b-b5e0-f676ba4f2910" +version = "0.1.4" + +[[deps.FFMPEG]] +deps = ["FFMPEG_jll"] +git-tree-sha1 = "53ebe7511fa11d33bec688a9178fac4e49eeee00" +uuid = "c87230d0-a227-11e9-1b43-d7ebe4e7570a" +version = "0.4.2" + +[[deps.FFMPEG_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "JLLWrappers", "LAME_jll", "Libdl", "Ogg_jll", "OpenSSL_jll", "Opus_jll", "PCRE2_jll", "Zlib_jll", "libaom_jll", "libass_jll", "libfdk_aac_jll", "libvorbis_jll", "x264_jll", "x265_jll"] +git-tree-sha1 = "466d45dc38e15794ec7d5d63ec03d776a9aff36e" +uuid = "b22a6f82-2f65-5046-a5b2-351ab43fb4e5" +version = "4.4.4+1" + +[[deps.FFTW]] +deps = ["AbstractFFTs", "FFTW_jll", "LinearAlgebra", "MKL_jll", "Preferences", "Reexport"] +git-tree-sha1 = "4820348781ae578893311153d69049a93d05f39d" +uuid = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" +version = "1.8.0" + +[[deps.FFTW_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "4d81ed14783ec49ce9f2e168208a12ce1815aa25" +uuid = "f5851436-0d7a-5f13-b9de-f02708fd171a" +version = "3.3.10+1" + +[[deps.FastAlmostBandedMatrices]] +deps = ["ArrayInterface", "ArrayLayouts", "BandedMatrices", "ConcreteStructs", "LazyArrays", "LinearAlgebra", "MatrixFactorizations", "PrecompileTools", "Reexport"] +git-tree-sha1 = "3f03d94c71126b6cfe20d3cbcc41c5cd27e1c419" +uuid = "9d29842c-ecb8-4973-b1e9-a27b1157504e" +version = "0.1.4" + +[[deps.FastBroadcast]] +deps = ["ArrayInterface", "LinearAlgebra", "Polyester", "Static", "StaticArrayInterface", "StrideArraysCore"] +git-tree-sha1 = "ab1b34570bcdf272899062e1a56285a53ecaae08" +uuid = "7034ab61-46d4-4ed7-9d0f-46aef9175898" +version = "0.3.5" + +[[deps.FastClosures]] +git-tree-sha1 = "acebe244d53ee1b461970f8910c235b259e772ef" +uuid = "9aa1b823-49e4-5ca5-8b0f-3971ec8bab6a" +version = "0.3.2" + +[[deps.FastLapackInterface]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "cbf5edddb61a43669710cbc2241bc08b36d9e660" +uuid = "29a986be-02c6-4525-aec4-84b980013641" +version = "2.0.4" + +[[deps.FastPower]] +git-tree-sha1 = "58c3431137131577a7c379d00fea00be524338fb" +uuid = "a4df4552-cc26-4903-aec0-212e50a0e84b" +version = "1.1.1" + + [deps.FastPower.extensions] + FastPowerEnzymeExt = "Enzyme" + FastPowerForwardDiffExt = "ForwardDiff" + FastPowerMeasurementsExt = "Measurements" + FastPowerMonteCarloMeasurementsExt = "MonteCarloMeasurements" + FastPowerReverseDiffExt = "ReverseDiff" + FastPowerTrackerExt = "Tracker" + + [deps.FastPower.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + +[[deps.FilePathsBase]] +deps = ["Compat", "Dates"] +git-tree-sha1 = "7878ff7172a8e6beedd1dea14bd27c3c6340d361" +uuid = "48062228-2e41-5def-b9a4-89aafe57970f" +version = "0.9.22" +weakdeps = ["Mmap", "Test"] + + [deps.FilePathsBase.extensions] + FilePathsBaseMmapExt = "Mmap" + FilePathsBaseTestExt = "Test" + +[[deps.FileWatching]] +uuid = "7b1f6079-737a-58dc-b8bc-7a2ca5c1b5ee" +version = "1.11.0" + +[[deps.FillArrays]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "6a70198746448456524cb442b8af316927ff3e1a" +uuid = "1a297f60-69ca-5386-bcde-b61e274b549b" +version = "1.13.0" +weakdeps = ["PDMats", "SparseArrays", "Statistics"] + + [deps.FillArrays.extensions] + FillArraysPDMatsExt = "PDMats" + FillArraysSparseArraysExt = "SparseArrays" + FillArraysStatisticsExt = "Statistics" + +[[deps.FiniteDiff]] +deps = ["ArrayInterface", "LinearAlgebra", "Setfield"] +git-tree-sha1 = "b10bdafd1647f57ace3885143936749d61638c3b" +uuid = "6a86dc24-6348-571c-b903-95158fe2bd41" +version = "2.26.0" + + [deps.FiniteDiff.extensions] + FiniteDiffBandedMatricesExt = "BandedMatrices" + FiniteDiffBlockBandedMatricesExt = "BlockBandedMatrices" + FiniteDiffSparseArraysExt = "SparseArrays" + FiniteDiffStaticArraysExt = "StaticArrays" + + [deps.FiniteDiff.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.FixedPointNumbers]] +deps = ["Statistics"] +git-tree-sha1 = "05882d6995ae5c12bb5f36dd2ed3f61c98cbb172" +uuid = "53c48c17-4a7d-5ca2-90c5-79b7896eea93" +version = "0.8.5" + +[[deps.Fontconfig_jll]] +deps = ["Artifacts", "Bzip2_jll", "Expat_jll", "FreeType2_jll", "JLLWrappers", "Libdl", "Libuuid_jll", "Zlib_jll"] +git-tree-sha1 = "db16beca600632c95fc8aca29890d83788dd8b23" +uuid = "a3f928ae-7b40-5064-980b-68af3947d34b" +version = "2.13.96+0" + +[[deps.Format]] +git-tree-sha1 = "9c68794ef81b08086aeb32eeaf33531668d5f5fc" +uuid = "1fa38f19-a742-5d3f-a2b9-30dd87b9d5f8" +version = "1.3.7" + +[[deps.ForwardDiff]] +deps = ["CommonSubexpressions", "DiffResults", "DiffRules", "LinearAlgebra", "LogExpFunctions", "NaNMath", "Preferences", "Printf", "Random", "SpecialFunctions"] +git-tree-sha1 = "a9ce73d3c827adab2d70bf168aaece8cce196898" +uuid = "f6369f11-7733-5829-9624-2563aa707210" +version = "0.10.37" +weakdeps = ["StaticArrays"] + + [deps.ForwardDiff.extensions] + ForwardDiffStaticArraysExt = "StaticArrays" + +[[deps.FreeType2_jll]] +deps = ["Artifacts", "Bzip2_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "5c1d8ae0efc6c2e7b1fc502cbe25def8f661b7bc" +uuid = "d7e528f0-a631-5988-bf34-fe36492bcfd7" +version = "2.13.2+0" + +[[deps.FriBidi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1ed150b39aebcc805c26b93a8d0122c940f64ce2" +uuid = "559328eb-81f9-559d-9380-de523a88c83c" +version = "1.0.14+0" + +[[deps.FunctionWrappers]] +git-tree-sha1 = "d62485945ce5ae9c0c48f124a84998d755bae00e" +uuid = "069b7b12-0de2-55c6-9aab-29f3d0a68a2e" +version = "1.1.3" + +[[deps.FunctionWrappersWrappers]] +deps = ["FunctionWrappers"] +git-tree-sha1 = "b104d487b34566608f8b4e1c39fb0b10aa279ff8" +uuid = "77dc65aa-8811-40c2-897b-53d922fa7daf" +version = "0.1.3" + +[[deps.Functors]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "64d8e93700c7a3f28f717d265382d52fac9fa1c1" +uuid = "d9f16b24-f501-4c13-a1f2-28368ffc5196" +version = "0.4.12" + +[[deps.Future]] +deps = ["Random"] +uuid = "9fa8497b-333b-5362-9e8d-4d0656e87820" +version = "1.11.0" + +[[deps.GLFW_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libglvnd_jll", "Xorg_libXcursor_jll", "Xorg_libXi_jll", "Xorg_libXinerama_jll", "Xorg_libXrandr_jll", "libdecor_jll", "xkbcommon_jll"] +git-tree-sha1 = "532f9126ad901533af1d4f5c198867227a7bb077" +uuid = "0656b61e-2033-5cc2-a64a-77c0f6c09b89" +version = "3.4.0+1" + +[[deps.GPUArraysCore]] +deps = ["Adapt"] +git-tree-sha1 = "ec632f177c0d990e64d955ccc1b8c04c485a0950" +uuid = "46192b85-c4d5-4398-a991-12ede77f4527" +version = "0.1.6" + +[[deps.GR]] +deps = ["Artifacts", "Base64", "DelimitedFiles", "Downloads", "GR_jll", "HTTP", "JSON", "Libdl", "LinearAlgebra", "Preferences", "Printf", "Qt6Wayland_jll", "Random", "Serialization", "Sockets", "TOML", "Tar", "Test", "p7zip_jll"] +git-tree-sha1 = "ee28ddcd5517d54e417182fec3886e7412d3926f" +uuid = "28b8d3ca-fb5f-59d9-8090-bfdbd6d07a71" +version = "0.73.8" + +[[deps.GR_jll]] +deps = ["Artifacts", "Bzip2_jll", "Cairo_jll", "FFMPEG_jll", "Fontconfig_jll", "FreeType2_jll", "GLFW_jll", "JLLWrappers", "JpegTurbo_jll", "Libdl", "Libtiff_jll", "Pixman_jll", "Qt6Base_jll", "Zlib_jll", "libpng_jll"] +git-tree-sha1 = "f31929b9e67066bee48eec8b03c0df47d31a74b3" +uuid = "d2c73de3-f751-5644-a686-071e5b155ba9" +version = "0.73.8+0" + +[[deps.GenericLinearAlgebra]] +deps = ["LinearAlgebra", "Printf", "Random", "libblastrampoline_jll"] +git-tree-sha1 = "c4f9c87b74aedf20920034bd4db81d0bffc527d2" +uuid = "14197337-ba66-59df-a3e3-ca00e7dcff7a" +version = "0.3.14" + +[[deps.GenericSchur]] +deps = ["LinearAlgebra", "Printf"] +git-tree-sha1 = "af49a0851f8113fcfae2ef5027c6d49d0acec39b" +uuid = "c145ed77-6b09-5dd9-b285-bf645a82121e" +version = "0.5.4" + +[[deps.GeoFormatTypes]] +git-tree-sha1 = "59107c179a586f0fe667024c5eb7033e81333271" +uuid = "68eda718-8dee-11e9-39e7-89f7f65f511f" +version = "0.4.2" + +[[deps.GeoInterface]] +deps = ["Extents", "GeoFormatTypes"] +git-tree-sha1 = "826b4fd69438d9ce4d2b19de6bc2f970f45f0f88" +uuid = "cf35fbd7-0cd7-5166-be24-54bfbe79505f" +version = "1.3.8" + +[[deps.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" + +[[deps.Git]] +deps = ["Git_jll"] +git-tree-sha1 = "04eff47b1354d702c3a85e8ab23d539bb7d5957e" +uuid = "d7ba0133-e1db-5d97-8f8c-041e4b3a1eb2" +version = "1.3.1" + +[[deps.Git_jll]] +deps = ["Artifacts", "Expat_jll", "JLLWrappers", "LibCURL_jll", "Libdl", "Libiconv_jll", "OpenSSL_jll", "PCRE2_jll", "Zlib_jll"] +git-tree-sha1 = "ea372033d09e4552a04fd38361cd019f9003f4f4" +uuid = "f8c6e375-362e-5223-8a59-34ff63f689eb" +version = "2.46.2+0" + +[[deps.Glib_jll]] +deps = ["Artifacts", "Gettext_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Libiconv_jll", "Libmount_jll", "PCRE2_jll", "Zlib_jll"] +git-tree-sha1 = "674ff0db93fffcd11a3573986e550d66cd4fd71f" +uuid = "7746bdde-850d-59dc-9ae8-88ece973131d" +version = "2.80.5+0" + +[[deps.Graphite2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "344bf40dcab1073aca04aa0df4fb092f920e4011" +uuid = "3b182d85-2403-5c21-9c21-1e1f0cc25472" +version = "1.3.14+0" + +[[deps.Graphs]] +deps = ["ArnoldiMethod", "Compat", "DataStructures", "Distributed", "Inflate", "LinearAlgebra", "Random", "SharedArrays", "SimpleTraits", "SparseArrays", "Statistics"] +git-tree-sha1 = "1dc470db8b1131cfc7fb4c115de89fe391b9e780" +uuid = "86223c79-3864-5bf0-83f7-82e725a168b6" +version = "1.12.0" + +[[deps.Grisu]] +git-tree-sha1 = "53bb909d1151e57e2484c3d1b53e19552b887fb2" +uuid = "42e2da0e-8278-4e71-bc24-59509adca0fe" +version = "1.0.2" + +[[deps.HTTP]] +deps = ["Base64", "CodecZlib", "ConcurrentUtilities", "Dates", "ExceptionUnwrapping", "Logging", "LoggingExtras", "MbedTLS", "NetworkOptions", "OpenSSL", "Random", "SimpleBufferStream", "Sockets", "URIs", "UUIDs"] +git-tree-sha1 = "bc3f416a965ae61968c20d0ad867556367f2817d" +uuid = "cd3eb016-35fb-5094-929b-558a96fad6f3" +version = "1.10.9" + +[[deps.HarfBuzz_jll]] +deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "Glib_jll", "Graphite2_jll", "JLLWrappers", "Libdl", "Libffi_jll"] +git-tree-sha1 = "401e4f3f30f43af2c8478fc008da50096ea5240f" +uuid = "2e76f6c2-a576-52d4-95c1-20adfe4de566" +version = "8.3.1+0" + +[[deps.HostCPUFeatures]] +deps = ["BitTwiddlingConvenienceFunctions", "IfElse", "Libdl", "Static"] +git-tree-sha1 = "8e070b599339d622e9a081d17230d74a5c473293" +uuid = "3e5b6fbb-0976-4d2c-9146-d79de83f2fb0" +version = "0.1.17" + +[[deps.HypergeometricFunctions]] +deps = ["LinearAlgebra", "OpenLibm_jll", "SpecialFunctions"] +git-tree-sha1 = "7c4195be1649ae622304031ed46a2f4df989f1eb" +uuid = "34004b35-14d8-5ef3-9330-4cdb6864b03a" +version = "0.3.24" + +[[deps.IJulia]] +deps = ["Base64", "Conda", "Dates", "InteractiveUtils", "JSON", "Libdl", "Logging", "Markdown", "MbedTLS", "Pkg", "Printf", "REPL", "Random", "SoftGlobalScope", "Test", "UUIDs", "ZMQ"] +git-tree-sha1 = "1b1299f7d6617291f3d260e9f5b0250afdaac8c0" +uuid = "7073ff75-c697-5162-941a-fcdaad2a7d2a" +version = "1.26.0" + +[[deps.IOCapture]] +deps = ["Logging", "Random"] +git-tree-sha1 = "b6d6bfdd7ce25b0f9b2f6b3dd56b2673a66c8770" +uuid = "b5f81e59-6552-4d32-b1f0-c071b021bf89" +version = "0.2.5" + +[[deps.IfElse]] +git-tree-sha1 = "debdd00ffef04665ccbb3e150747a77560e8fad1" +uuid = "615f187c-cbe4-4ef1-ba3b-2fcf58d6d173" +version = "0.1.1" + +[[deps.Inflate]] +git-tree-sha1 = "d1b1b796e47d94588b3757fe84fbf65a5ec4a80d" +uuid = "d25df0c9-e2be-5dd7-82c8-3ad0b3e990b9" +version = "0.1.5" + +[[deps.InlineStrings]] +git-tree-sha1 = "45521d31238e87ee9f9732561bfee12d4eebd52d" +uuid = "842dd82b-1e85-43dc-bf29-5d0ee9dffc48" +version = "1.4.2" + + [deps.InlineStrings.extensions] + ArrowTypesExt = "ArrowTypes" + ParsersExt = "Parsers" + + [deps.InlineStrings.weakdeps] + ArrowTypes = "31f734f8-188a-4ce0-8406-c8a06bd891cd" + Parsers = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" + +[[deps.IntegerMathUtils]] +git-tree-sha1 = "b8ffb903da9f7b8cf695a8bead8e01814aa24b30" +uuid = "18e54dd8-cb9d-406c-a71d-865a43cbb235" +version = "0.1.2" + +[[deps.IntelOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "LazyArtifacts", "Libdl"] +git-tree-sha1 = "10bd689145d2c3b2a9844005d01087cc1194e79e" +uuid = "1d5cc7b8-4909-519e-a0f8-d0f5ad9712d0" +version = "2024.2.1+0" + +[[deps.InteractiveUtils]] +deps = ["Markdown"] +uuid = "b77e0a4c-d291-57a0-90e8-8db25a27a240" +version = "1.11.0" + +[[deps.Interpolations]] +deps = ["Adapt", "AxisAlgorithms", "ChainRulesCore", "LinearAlgebra", "OffsetArrays", "Random", "Ratios", "Requires", "SharedArrays", "SparseArrays", "StaticArrays", "WoodburyMatrices"] +git-tree-sha1 = "88a101217d7cb38a7b481ccd50d21876e1d1b0e0" +uuid = "a98d9a8b-a2ab-59e6-89dd-64a1c18fca59" +version = "0.15.1" +weakdeps = ["Unitful"] + + [deps.Interpolations.extensions] + InterpolationsUnitfulExt = "Unitful" + +[[deps.IntervalSets]] +git-tree-sha1 = "dba9ddf07f77f60450fe5d2e2beb9854d9a49bd0" +uuid = "8197267c-284f-5f27-9208-e0e47529a953" +version = "0.7.10" +weakdeps = ["Random", "RecipesBase", "Statistics"] + + [deps.IntervalSets.extensions] + IntervalSetsRandomExt = "Random" + IntervalSetsRecipesBaseExt = "RecipesBase" + IntervalSetsStatisticsExt = "Statistics" + +[[deps.InverseFunctions]] +git-tree-sha1 = "a779299d77cd080bf77b97535acecd73e1c5e5cb" +uuid = "3587e190-3f89-42d0-90ee-14403ec27112" +version = "0.1.17" +weakdeps = ["Dates", "Test"] + + [deps.InverseFunctions.extensions] + InverseFunctionsDatesExt = "Dates" + InverseFunctionsTestExt = "Test" + +[[deps.InvertedIndices]] +git-tree-sha1 = "0dc7b50b8d436461be01300fd8cd45aa0274b038" +uuid = "41ab1584-1d38-5bbf-9106-f11c6c58b48f" +version = "1.3.0" + +[[deps.IrrationalConstants]] +git-tree-sha1 = "630b497eafcc20001bba38a4651b327dcfc491d2" +uuid = "92d709cd-6900-40b7-9082-c6be49f344b6" +version = "0.2.2" + +[[deps.IteratorInterfaceExtensions]] +git-tree-sha1 = "a3f24677c21f5bbe9d2a714f95dcd58337fb2856" +uuid = "82899510-4779-5014-852e-03e436cf321d" +version = "1.0.0" + +[[deps.JLFzf]] +deps = ["Pipe", "REPL", "Random", "fzf_jll"] +git-tree-sha1 = "39d64b09147620f5ffbf6b2d3255be3c901bec63" +uuid = "1019f520-868f-41f5-a6de-eb00f4b6a39c" +version = "0.1.8" + +[[deps.JLLWrappers]] +deps = ["Artifacts", "Preferences"] +git-tree-sha1 = "be3dc50a92e5a386872a493a10050136d4703f9b" +uuid = "692b3bcd-3c85-4b1f-b108-f13ce0eb3210" +version = "1.6.1" + +[[deps.JSON]] +deps = ["Dates", "Mmap", "Parsers", "Unicode"] +git-tree-sha1 = "31e996f0a15c7b280ba9f76636b3ff9e2ae58c9a" +uuid = "682c06a0-de6a-54ab-a142-c8b1cf79cde6" +version = "0.21.4" + +[[deps.JpegTurbo_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "25ee0be4d43d0269027024d75a24c24d6c6e590c" +uuid = "aacddb02-875f-59d6-b918-886e6ef4fbf8" +version = "3.0.4+0" + +[[deps.JuliaInterpreter]] +deps = ["CodeTracking", "InteractiveUtils", "Random", "UUIDs"] +git-tree-sha1 = "2984284a8abcfcc4784d95a9e2ea4e352dd8ede7" +uuid = "aa1ae85d-cabe-5617-a682-6adf51b2e16a" +version = "0.9.36" + +[[deps.JumpProcesses]] +deps = ["ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "FunctionWrappers", "Graphs", "LinearAlgebra", "Markdown", "PoissonRandom", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SciMLBase", "Setfield", "StaticArrays", "SymbolicIndexingInterface", "UnPack"] +git-tree-sha1 = "c3a2cb6f968404ed3b1d5382bbdd7b7d83966598" +uuid = "ccbc3e58-028d-4f4c-8cd5-9ae44345cda5" +version = "9.14.0" +weakdeps = ["FastBroadcast"] + +[[deps.KLU]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse_jll"] +git-tree-sha1 = "07649c499349dad9f08dde4243a4c597064663e9" +uuid = "ef3ab10e-7fda-4108-b977-705223b18434" +version = "0.6.0" + +[[deps.KernelDensity]] +deps = ["Distributions", "DocStringExtensions", "FFTW", "Interpolations", "StatsBase"] +git-tree-sha1 = "7d703202e65efa1369de1279c162b915e245eed1" +uuid = "5ab0869b-81aa-558d-bb23-cbf5423bbe9b" +version = "0.6.9" + +[[deps.Krylov]] +deps = ["LinearAlgebra", "Printf", "SparseArrays"] +git-tree-sha1 = "4f20a2df85a9e5d55c9e84634bbf808ed038cabd" +uuid = "ba0b0d4f-ebba-5204-a429-3ac8c609bfb7" +version = "0.9.8" + +[[deps.LAME_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "170b660facf5df5de098d866564877e119141cbd" +uuid = "c1c5ebd0-6772-5130-a774-d5fcae4a789d" +version = "3.100.2+0" + +[[deps.LERC_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "36bdbc52f13a7d1dcb0f3cd694e01677a515655b" +uuid = "88015f11-f218-50d7-93a8-a6af411a945d" +version = "4.0.0+0" + +[[deps.LLVMOpenMP_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "78211fb6cbc872f77cad3fc0b6cf647d923f4929" +uuid = "1d63c593-3942-5779-bab2-d838dc0a180e" +version = "18.1.7+0" + +[[deps.LZO_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "854a9c268c43b77b0a27f22d7fab8d33cdb3a731" +uuid = "dd4b983a-f0e5-5f8d-a1b7-129d4a5fb1ac" +version = "2.10.2+1" + +[[deps.LaTeXStrings]] +git-tree-sha1 = "dda21b8cbd6a6c40d9d02a73230f9d70fed6918c" +uuid = "b964fa9f-0449-5b57-a5c2-d3ea65f4040f" +version = "1.4.0" + +[[deps.Latexify]] +deps = ["Format", "InteractiveUtils", "LaTeXStrings", "MacroTools", "Markdown", "OrderedCollections", "Requires"] +git-tree-sha1 = "ce5f5621cac23a86011836badfedf664a612cee4" +uuid = "23fbe1c1-3f47-55db-b15f-69d7ec21a316" +version = "0.16.5" + + [deps.Latexify.extensions] + DataFramesExt = "DataFrames" + SparseArraysExt = "SparseArrays" + SymEngineExt = "SymEngine" + + [deps.Latexify.weakdeps] + DataFrames = "a93c6f00-e57d-5684-b7b6-d8193f3e46c0" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + SymEngine = "123dc426-2d89-5057-bbad-38513e3affd8" + +[[deps.LayoutPointers]] +deps = ["ArrayInterface", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface"] +git-tree-sha1 = "a9eaadb366f5493a5654e843864c13d8b107548c" +uuid = "10f19ff3-798f-405d-979b-55457f8fc047" +version = "0.1.17" + +[[deps.LazilyInitializedFields]] +git-tree-sha1 = "0f2da712350b020bc3957f269c9caad516383ee0" +uuid = "0e77f7df-68c5-4e49-93ce-4cd80f5598bf" +version = "1.3.0" + +[[deps.LazyArrays]] +deps = ["ArrayLayouts", "FillArrays", "LinearAlgebra", "MacroTools", "SparseArrays"] +git-tree-sha1 = "360f6039babd6e4d6364eff0d4fc9120834a2d9a" +uuid = "5078a376-72f3-5289-bfd5-ec5146d43c02" +version = "2.2.1" + + [deps.LazyArrays.extensions] + LazyArraysBandedMatricesExt = "BandedMatrices" + LazyArraysBlockArraysExt = "BlockArrays" + LazyArraysBlockBandedMatricesExt = "BlockBandedMatrices" + LazyArraysStaticArraysExt = "StaticArrays" + + [deps.LazyArrays.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" + BlockBandedMatrices = "ffab5731-97b5-5995-9138-79e8c1846df0" + StaticArrays = "90137ffa-7385-5640-81b9-e52037218182" + +[[deps.LazyArtifacts]] +deps = ["Artifacts", "Pkg"] +uuid = "4af54fe1-eca0-43a8-85a7-787d91b784e3" +version = "1.11.0" + +[[deps.LevyArea]] +deps = ["LinearAlgebra", "Random", "SpecialFunctions"] +git-tree-sha1 = "56513a09b8e0ae6485f34401ea9e2f31357958ec" +uuid = "2d8b4e74-eb68-11e8-0fb9-d5eb67b50637" +version = "1.0.0" + +[[deps.LibCURL]] +deps = ["LibCURL_jll", "MozillaCACerts_jll"] +uuid = "b27032c2-a3e7-50c8-80cd-2d36dbcbfd21" +version = "0.6.4" + +[[deps.LibCURL_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll", "Zlib_jll", "nghttp2_jll"] +uuid = "deac9b47-8bc7-5906-a0fe-35ac56dc84c0" +version = "8.6.0+0" + +[[deps.LibGit2]] +deps = ["Base64", "LibGit2_jll", "NetworkOptions", "Printf", "SHA"] +uuid = "76f85450-5226-5b5a-8eaa-529ad045b433" +version = "1.11.0" + +[[deps.LibGit2_jll]] +deps = ["Artifacts", "LibSSH2_jll", "Libdl", "MbedTLS_jll"] +uuid = "e37daf67-58a4-590a-8e99-b0245dd2ffc5" +version = "1.7.2+0" + +[[deps.LibSSH2_jll]] +deps = ["Artifacts", "Libdl", "MbedTLS_jll"] +uuid = "29816b5a-b9ab-546f-933c-edad1886dfa8" +version = "1.11.0+1" + +[[deps.Libdl]] +uuid = "8f399da3-3557-5675-b5ff-fb832c97cbdb" +version = "1.11.0" + +[[deps.Libffi_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "0b4a5d71f3e5200a7dff793393e09dfc2d874290" +uuid = "e9f186c6-92d2-5b65-8a66-fee21dc1b490" +version = "3.2.2+1" + +[[deps.Libgcrypt_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgpg_error_jll"] +git-tree-sha1 = "8be878062e0ffa2c3f67bb58a595375eda5de80b" +uuid = "d4300ac3-e22c-5743-9152-c294e39db1e4" +version = "1.11.0+0" + +[[deps.Libglvnd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Xorg_libX11_jll", "Xorg_libXext_jll"] +git-tree-sha1 = "6f73d1dd803986947b2c750138528a999a6c7733" +uuid = "7e76a0d4-f3c7-5321-8279-8d96eeed0f29" +version = "1.6.0+0" + +[[deps.Libgpg_error_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "c6ce1e19f3aec9b59186bdf06cdf3c4fc5f5f3e6" +uuid = "7add5ba3-2f88-524e-9cd5-f83b8a55f7b8" +version = "1.50.0+0" + +[[deps.Libiconv_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "61dfdba58e585066d8bce214c5a51eaa0539f269" +uuid = "94ce4f54-9a6c-5748-9c1c-f9c7231a4531" +version = "1.17.0+1" + +[[deps.Libmount_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "0c4f9c4f1a50d8f35048fa0532dabbadf702f81e" +uuid = "4b2f31a3-9ecc-558c-b454-b3730dcb73e9" +version = "2.40.1+0" + +[[deps.Libtiff_jll]] +deps = ["Artifacts", "JLLWrappers", "JpegTurbo_jll", "LERC_jll", "Libdl", "XZ_jll", "Zlib_jll", "Zstd_jll"] +git-tree-sha1 = "b404131d06f7886402758c9ce2214b636eb4d54a" +uuid = "89763e89-9b03-5906-acba-b20f662cd828" +version = "4.7.0+0" + +[[deps.Libuuid_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "5ee6203157c120d79034c748a2acba45b82b8807" +uuid = "38a345b3-de98-5d2b-a5d3-14cd9215e700" +version = "2.40.1+0" + +[[deps.LineSearch]] +deps = ["ADTypes", "CommonSolve", "ConcreteStructs", "FastClosures", "LinearAlgebra", "MaybeInplace", "SciMLBase", "SciMLJacobianOperators", "StaticArraysCore"] +git-tree-sha1 = "97d502765cc5cf3a722120f50da03c2474efce04" +uuid = "87fe0de2-c867-4266-b59a-2f0a94fc965b" +version = "0.1.4" +weakdeps = ["LineSearches"] + + [deps.LineSearch.extensions] + LineSearchLineSearchesExt = "LineSearches" + +[[deps.LineSearches]] +deps = ["LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "Printf"] +git-tree-sha1 = "e4c3be53733db1051cc15ecf573b1042b3a712a1" +uuid = "d3d80556-e9d4-5f37-9878-2ab0fcc64255" +version = "7.3.0" + +[[deps.LinearAlgebra]] +deps = ["Libdl", "OpenBLAS_jll", "libblastrampoline_jll"] +uuid = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +version = "1.11.0" + +[[deps.LinearSolve]] +deps = ["ArrayInterface", "ChainRulesCore", "ConcreteStructs", "DocStringExtensions", "EnumX", "FastLapackInterface", "GPUArraysCore", "InteractiveUtils", "KLU", "Krylov", "LazyArrays", "Libdl", "LinearAlgebra", "MKL_jll", "Markdown", "PrecompileTools", "Preferences", "RecursiveFactorization", "Reexport", "SciMLBase", "SciMLOperators", "Setfield", "SparseArrays", "Sparspak", "StaticArraysCore", "UnPack"] +git-tree-sha1 = "591de175461afd8323aa24b7686062574527aa3a" +uuid = "7ed4a6bd-45f5-4d41-b270-4a48e9bafcae" +version = "2.36.2" + + [deps.LinearSolve.extensions] + LinearSolveBandedMatricesExt = "BandedMatrices" + LinearSolveBlockDiagonalsExt = "BlockDiagonals" + LinearSolveCUDAExt = "CUDA" + LinearSolveCUDSSExt = "CUDSS" + LinearSolveEnzymeExt = "EnzymeCore" + LinearSolveFastAlmostBandedMatricesExt = "FastAlmostBandedMatrices" + LinearSolveHYPREExt = "HYPRE" + LinearSolveIterativeSolversExt = "IterativeSolvers" + LinearSolveKernelAbstractionsExt = "KernelAbstractions" + LinearSolveKrylovKitExt = "KrylovKit" + LinearSolveMetalExt = "Metal" + LinearSolvePardisoExt = "Pardiso" + LinearSolveRecursiveArrayToolsExt = "RecursiveArrayTools" + + [deps.LinearSolve.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + BlockDiagonals = "0a1fb500-61f7-11e9-3c65-f5ef3456f9f0" + CUDA = "052768ef-5323-5732-b1bb-66c8b64840ba" + CUDSS = "45b445bb-4962-46a0-9369-b4df9d0f772e" + EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869" + FastAlmostBandedMatrices = "9d29842c-ecb8-4973-b1e9-a27b1157504e" + HYPRE = "b5ffcf37-a2bd-41ab-a3da-4bd9bc8ad771" + IterativeSolvers = "42fd0dbc-a981-5370-80f2-aaf504508153" + KernelAbstractions = "63c18a36-062a-441e-b654-da1e3ab1ce7c" + KrylovKit = "0b1a1467-8014-51b9-945f-bf0ae24f4b77" + Metal = "dde4c033-4e86-420c-a63e-0dd931031962" + Pardiso = "46dd5b70-b6fb-5a00-ae2d-e8fea33afaf2" + RecursiveArrayTools = "731186ca-8d62-57ce-b412-fbd966d074cd" + +[[deps.LogExpFunctions]] +deps = ["DocStringExtensions", "IrrationalConstants", "LinearAlgebra"] +git-tree-sha1 = "a2d09619db4e765091ee5c6ffe8872849de0feea" +uuid = "2ab3a3ac-af41-5b50-aa03-7779005ae688" +version = "0.3.28" + + [deps.LogExpFunctions.extensions] + LogExpFunctionsChainRulesCoreExt = "ChainRulesCore" + LogExpFunctionsChangesOfVariablesExt = "ChangesOfVariables" + LogExpFunctionsInverseFunctionsExt = "InverseFunctions" + + [deps.LogExpFunctions.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ChangesOfVariables = "9e997f8a-9a97-42d5-a9f1-ce6bfc15e2c0" + InverseFunctions = "3587e190-3f89-42d0-90ee-14403ec27112" + +[[deps.Logging]] +uuid = "56ddb016-857b-54e1-b83d-db4d58db5568" +version = "1.11.0" + +[[deps.LoggingExtras]] +deps = ["Dates", "Logging"] +git-tree-sha1 = "f02b56007b064fbfddb4c9cd60161b6dd0f40df3" +uuid = "e6f89c97-d47a-5376-807f-9c37f3926c36" +version = "1.1.0" + +[[deps.LoopVectorization]] +deps = ["ArrayInterface", "CPUSummary", "CloseOpenIntervals", "DocStringExtensions", "HostCPUFeatures", "IfElse", "LayoutPointers", "LinearAlgebra", "OffsetArrays", "PolyesterWeave", "PrecompileTools", "SIMDTypes", "SLEEFPirates", "Static", "StaticArrayInterface", "ThreadingUtilities", "UnPack", "VectorizationBase"] +git-tree-sha1 = "8084c25a250e00ae427a379a5b607e7aed96a2dd" +uuid = "bdcacae8-1622-11e9-2a5c-532679323890" +version = "0.12.171" +weakdeps = ["ChainRulesCore", "ForwardDiff", "SpecialFunctions"] + + [deps.LoopVectorization.extensions] + ForwardDiffExt = ["ChainRulesCore", "ForwardDiff"] + SpecialFunctionsExt = "SpecialFunctions" + +[[deps.LoweredCodeUtils]] +deps = ["JuliaInterpreter"] +git-tree-sha1 = "260dc274c1bc2cb839e758588c63d9c8b5e639d1" +uuid = "6f1432cf-f94c-5a45-995e-cdbf5db27b0b" +version = "3.0.5" + +[[deps.MKL_jll]] +deps = ["Artifacts", "IntelOpenMP_jll", "JLLWrappers", "LazyArtifacts", "Libdl", "oneTBB_jll"] +git-tree-sha1 = "f046ccd0c6db2832a9f639e2c669c6fe867e5f4f" +uuid = "856f044c-d86e-5d09-b602-aeab76dc8ba7" +version = "2024.2.0+0" + +[[deps.MLStyle]] +git-tree-sha1 = "bc38dff0548128765760c79eb7388a4b37fae2c8" +uuid = "d8e11817-5142-5d16-987a-aa16d5891078" +version = "0.4.17" + +[[deps.MacroTools]] +deps = ["Markdown", "Random"] +git-tree-sha1 = "2fa9ee3e63fd3a4f7a9a4f4744a52f4856de82df" +uuid = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09" +version = "0.5.13" + +[[deps.Mangal]] +deps = ["Dates", "GeoInterface", "HTTP", "JSON", "TestItems"] +git-tree-sha1 = "7e042dcd60513a5e2607da15e0788041daa1b840" +uuid = "b8b640a6-63d9-51e6-b784-5033db27bef2" +version = "0.5.1" + +[[deps.ManualMemory]] +git-tree-sha1 = "bcaef4fc7a0cfe2cba636d84cda54b5e4e4ca3cd" +uuid = "d125e4d3-2237-4719-b19c-fa641b8a4667" +version = "0.1.8" + +[[deps.Markdown]] +deps = ["Base64"] +uuid = "d6f4376e-aef5-505a-96c1-9c027394607a" +version = "1.11.0" + +[[deps.MarkdownAST]] +deps = ["AbstractTrees", "Markdown"] +git-tree-sha1 = "465a70f0fc7d443a00dcdc3267a497397b8a3899" +uuid = "d0879d2d-cac2-40c8-9cee-1863dc0c7391" +version = "0.1.2" + +[[deps.MatrixFactorizations]] +deps = ["ArrayLayouts", "LinearAlgebra", "Printf", "Random"] +git-tree-sha1 = "16a726dba99685d9e94c8d0a8f655383121fc608" +uuid = "a3b82374-2e81-5b9e-98ce-41277c0e4c87" +version = "3.0.1" +weakdeps = ["BandedMatrices"] + + [deps.MatrixFactorizations.extensions] + MatrixFactorizationsBandedMatricesExt = "BandedMatrices" + +[[deps.MaybeInplace]] +deps = ["ArrayInterface", "LinearAlgebra", "MacroTools"] +git-tree-sha1 = "54e2fdc38130c05b42be423e90da3bade29b74bd" +uuid = "bb5d69b7-63fc-4a16-80bd-7e42200c7bdb" +version = "0.1.4" +weakdeps = ["SparseArrays"] + + [deps.MaybeInplace.extensions] + MaybeInplaceSparseArraysExt = "SparseArrays" + +[[deps.MbedTLS]] +deps = ["Dates", "MbedTLS_jll", "MozillaCACerts_jll", "NetworkOptions", "Random", "Sockets"] +git-tree-sha1 = "c067a280ddc25f196b5e7df3877c6b226d390aaf" +uuid = "739be429-bea8-5141-9913-cc70e7f3736d" +version = "1.1.9" + +[[deps.MbedTLS_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "c8ffd9c3-330d-5841-b78e-0817d7145fa1" +version = "2.28.6+0" + +[[deps.Measures]] +git-tree-sha1 = "c13304c81eec1ed3af7fc20e75fb6b26092a1102" +uuid = "442fdcdd-2543-5da2-b0f3-8c86c306513e" +version = "0.3.2" + +[[deps.Missings]] +deps = ["DataAPI"] +git-tree-sha1 = "ec4f7fbeab05d7747bdf98eb74d130a2a2ed298d" +uuid = "e1d29d7a-bbdc-5cf2-9ac0-f12de2c33e28" +version = "1.2.0" + +[[deps.Mmap]] +uuid = "a63ad114-7e13-5084-954f-fe012c677804" +version = "1.11.0" + +[[deps.MozillaCACerts_jll]] +uuid = "14a3606d-f60d-562e-9121-12d972cd8159" +version = "2023.12.12" + +[[deps.MuladdMacro]] +git-tree-sha1 = "cac9cc5499c25554cba55cd3c30543cff5ca4fab" +uuid = "46d2c3a1-f734-5fdb-9937-b9b9aeba4221" +version = "0.2.4" + +[[deps.MultivariatePolynomials]] +deps = ["ChainRulesCore", "DataStructures", "LinearAlgebra", "MutableArithmetics"] +git-tree-sha1 = "8d39779e29f80aa6c071e7ac17101c6e31f075d7" +uuid = "102ac46a-7ee4-5c85-9060-abc95bfdeaa3" +version = "0.5.7" + +[[deps.MultivariateStats]] +deps = ["Arpack", "Distributions", "LinearAlgebra", "SparseArrays", "Statistics", "StatsAPI", "StatsBase"] +git-tree-sha1 = "816620e3aac93e5b5359e4fdaf23ca4525b00ddf" +uuid = "6f286f6a-111f-5878-ab1e-185364afe411" +version = "0.10.3" + +[[deps.MutableArithmetics]] +deps = ["LinearAlgebra", "SparseArrays", "Test"] +git-tree-sha1 = "90077f1e79de8c9c7c8a90644494411111f4e07b" +uuid = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" +version = "1.5.2" + +[[deps.NLSolversBase]] +deps = ["DiffResults", "Distributed", "FiniteDiff", "ForwardDiff"] +git-tree-sha1 = "a0b464d183da839699f4c79e7606d9d186ec172c" +uuid = "d41bc354-129a-5804-8e4c-c37616107c6c" +version = "7.8.3" + +[[deps.NLsolve]] +deps = ["Distances", "LineSearches", "LinearAlgebra", "NLSolversBase", "Printf", "Reexport"] +git-tree-sha1 = "019f12e9a1a7880459d0173c182e6a99365d7ac1" +uuid = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" +version = "4.5.1" + +[[deps.NaNMath]] +deps = ["OpenLibm_jll"] +git-tree-sha1 = "0877504529a3e5c3343c6f8b4c0381e57e4387e4" +uuid = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" +version = "1.0.2" + +[[deps.NearestNeighbors]] +deps = ["Distances", "StaticArrays"] +git-tree-sha1 = "3cebfc94a0754cc329ebc3bab1e6c89621e791ad" +uuid = "b8a86587-4115-5ab1-83bc-aa920d37bbce" +version = "0.4.20" + +[[deps.NetworkOptions]] +uuid = "ca575930-c2e3-43a9-ace4-1e988b2c1908" +version = "1.2.0" + +[[deps.NonlinearSolve]] +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "DifferentiationInterface", "FastBroadcast", "FastClosures", "FiniteDiff", "ForwardDiff", "LazyArrays", "LineSearch", "LineSearches", "LinearAlgebra", "LinearSolve", "MaybeInplace", "PrecompileTools", "Preferences", "Printf", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLJacobianOperators", "SciMLOperators", "Setfield", "SimpleNonlinearSolve", "SparseArrays", "SparseConnectivityTracer", "SparseMatrixColorings", "StaticArraysCore", "SymbolicIndexingInterface", "TimerOutputs"] +git-tree-sha1 = "4d8944f32db2b07a2bdf8477e878bcb9c9ea2308" +uuid = "8913a72c-1f9b-4ce2-8d82-65094dcecaec" +version = "3.15.1" + + [deps.NonlinearSolve.extensions] + NonlinearSolveBandedMatricesExt = "BandedMatrices" + NonlinearSolveFastLevenbergMarquardtExt = "FastLevenbergMarquardt" + NonlinearSolveFixedPointAccelerationExt = "FixedPointAcceleration" + NonlinearSolveLeastSquaresOptimExt = "LeastSquaresOptim" + NonlinearSolveMINPACKExt = "MINPACK" + NonlinearSolveNLSolversExt = "NLSolvers" + NonlinearSolveNLsolveExt = "NLsolve" + NonlinearSolveSIAMFANLEquationsExt = "SIAMFANLEquations" + NonlinearSolveSpeedMappingExt = "SpeedMapping" + + [deps.NonlinearSolve.weakdeps] + BandedMatrices = "aae01518-5342-5314-be14-df237901396f" + FastLevenbergMarquardt = "7a0df574-e128-4d35-8cbd-3d84502bf7ce" + FixedPointAcceleration = "817d07cb-a79a-5c30-9a31-890123675176" + LeastSquaresOptim = "0fc2ff8b-aaa3-5acd-a817-1944a5e08891" + MINPACK = "4854310b-de5a-5eb6-a2a5-c1dee2bd17f9" + NLSolvers = "337daf1e-9722-11e9-073e-8b9effe078ba" + NLsolve = "2774e3e8-f4cf-5e23-947b-6d7e65073b56" + SIAMFANLEquations = "084e46ad-d928-497d-ad5e-07fa361a48c4" + SpeedMapping = "f1835b91-879b-4a3f-a438-e4baacf14412" + +[[deps.Observables]] +git-tree-sha1 = "7438a59546cf62428fc9d1bc94729146d37a7225" +uuid = "510215fc-4207-5dde-b226-833fc4488ee2" +version = "0.5.5" + +[[deps.OffsetArrays]] +git-tree-sha1 = "1a27764e945a152f7ca7efa04de513d473e9542e" +uuid = "6fe1bfb0-de20-5000-8ca7-80f57d26f881" +version = "1.14.1" +weakdeps = ["Adapt"] + + [deps.OffsetArrays.extensions] + OffsetArraysAdaptExt = "Adapt" + +[[deps.Ogg_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "887579a3eb005446d514ab7aeac5d1d027658b8f" +uuid = "e7412a2a-1a6e-54c0-be00-318e2571c051" +version = "1.3.5+1" + +[[deps.OpenBLAS_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Libdl"] +uuid = "4536629a-c528-5b80-bd46-f80d51c5b363" +version = "0.3.27+1" + +[[deps.OpenLibm_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "05823500-19ac-5b8b-9628-191a04bc5112" +version = "0.8.1+2" + +[[deps.OpenSSL]] +deps = ["BitFlags", "Dates", "MozillaCACerts_jll", "OpenSSL_jll", "Sockets"] +git-tree-sha1 = "38cb508d080d21dc1128f7fb04f20387ed4c0af4" +uuid = "4d8831e6-92b7-49fb-bdf8-b643e874388c" +version = "1.4.3" + +[[deps.OpenSSL_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "7493f61f55a6cce7325f197443aa80d32554ba10" +uuid = "458c3c95-2e84-50aa-8efc-19380b2a3a95" +version = "3.0.15+1" + +[[deps.OpenSpecFun_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "13652491f6856acfd2db29360e1bbcd4565d04f1" +uuid = "efe28fd5-8261-553b-a9e1-b2916fc3738e" +version = "0.5.5+0" + +[[deps.Optim]] +deps = ["Compat", "FillArrays", "ForwardDiff", "LineSearches", "LinearAlgebra", "NLSolversBase", "NaNMath", "Parameters", "PositiveFactorizations", "Printf", "SparseArrays", "StatsBase"] +git-tree-sha1 = "d9b79c4eed437421ac4285148fcadf42e0700e89" +uuid = "429524aa-4258-5aef-a3af-852621145aeb" +version = "1.9.4" + + [deps.Optim.extensions] + OptimMOIExt = "MathOptInterface" + + [deps.Optim.weakdeps] + MathOptInterface = "b8f27783-ece8-5eb3-8dc8-9495eed66fee" + +[[deps.Opus_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6703a85cb3781bd5909d48730a67205f3f31a575" +uuid = "91d4177d-7536-5919-b921-800302f37372" +version = "1.3.3+0" + +[[deps.OrderedCollections]] +git-tree-sha1 = "dfdf5519f235516220579f949664f1bf44e741c5" +uuid = "bac558e1-5e72-5ebc-8fee-abe8a469f55d" +version = "1.6.3" + +[[deps.OrdinaryDiffEq]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "EnumX", "ExponentialUtilities", "FastBroadcast", "FastClosures", "FillArrays", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "InteractiveUtils", "LineSearches", "LinearAlgebra", "LinearSolve", "Logging", "MacroTools", "MuladdMacro", "NonlinearSolve", "OrdinaryDiffEqAdamsBashforthMoulton", "OrdinaryDiffEqBDF", "OrdinaryDiffEqCore", "OrdinaryDiffEqDefault", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqExplicitRK", "OrdinaryDiffEqExponentialRK", "OrdinaryDiffEqExtrapolation", "OrdinaryDiffEqFIRK", "OrdinaryDiffEqFeagin", "OrdinaryDiffEqFunctionMap", "OrdinaryDiffEqHighOrderRK", "OrdinaryDiffEqIMEXMultistep", "OrdinaryDiffEqLinear", "OrdinaryDiffEqLowOrderRK", "OrdinaryDiffEqLowStorageRK", "OrdinaryDiffEqNonlinearSolve", "OrdinaryDiffEqNordsieck", "OrdinaryDiffEqPDIRK", "OrdinaryDiffEqPRK", "OrdinaryDiffEqQPRK", "OrdinaryDiffEqRKN", "OrdinaryDiffEqRosenbrock", "OrdinaryDiffEqSDIRK", "OrdinaryDiffEqSSPRK", "OrdinaryDiffEqStabilizedIRK", "OrdinaryDiffEqStabilizedRK", "OrdinaryDiffEqSymplecticRK", "OrdinaryDiffEqTsit5", "OrdinaryDiffEqVerner", "Polyester", "PreallocationTools", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SciMLStructures", "SimpleNonlinearSolve", "SimpleUnPack", "SparseArrays", "SparseDiffTools", "Static", "StaticArrayInterface", "StaticArrays", "TruncatedStacktraces"] +git-tree-sha1 = "cd892f12371c287dc50d6ad3af075b088b6f2d48" +uuid = "1dea7af3-3e70-54e6-95c3-0bf5283fa5ed" +version = "6.89.0" + +[[deps.OrdinaryDiffEqAdamsBashforthMoulton]] +deps = ["ADTypes", "DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqLowOrderRK", "Polyester", "RecursiveArrayTools", "Reexport", "Static"] +git-tree-sha1 = "8e3c5978d0531a961f70d2f2730d1d16ed3bbd12" +uuid = "89bda076-bce5-4f1c-845f-551c83cdda9a" +version = "1.1.0" + +[[deps.OrdinaryDiffEqBDF]] +deps = ["ArrayInterface", "DiffEqBase", "FastBroadcast", "LinearAlgebra", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "OrdinaryDiffEqSDIRK", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "StaticArrays", "TruncatedStacktraces"] +git-tree-sha1 = "b4498d40bf35da0b6d22652ff2e9d8820590b3c6" +uuid = "6ad6398a-0878-4a85-9266-38940aa047c8" +version = "1.1.2" + +[[deps.OrdinaryDiffEqCore]] +deps = ["ADTypes", "Accessors", "Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DocStringExtensions", "EnumX", "FastBroadcast", "FastClosures", "FastPower", "FillArrays", "FunctionWrappersWrappers", "InteractiveUtils", "LinearAlgebra", "Logging", "MacroTools", "MuladdMacro", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SciMLStructures", "SimpleUnPack", "Static", "StaticArrayInterface", "StaticArraysCore", "SymbolicIndexingInterface", "TruncatedStacktraces"] +git-tree-sha1 = "5e8c500a80674850543394ce3c745b73ad51fea0" +uuid = "bbf590c4-e513-4bbe-9b18-05decba2e5d8" +version = "1.10.0" +weakdeps = ["EnzymeCore"] + + [deps.OrdinaryDiffEqCore.extensions] + OrdinaryDiffEqCoreEnzymeCoreExt = "EnzymeCore" + +[[deps.OrdinaryDiffEqDefault]] +deps = ["DiffEqBase", "EnumX", "LinearAlgebra", "LinearSolve", "OrdinaryDiffEqBDF", "OrdinaryDiffEqCore", "OrdinaryDiffEqRosenbrock", "OrdinaryDiffEqTsit5", "OrdinaryDiffEqVerner", "PrecompileTools", "Preferences", "Reexport"] +git-tree-sha1 = "c8223e487d58bef28a3535b33ddf8ffdb44f46fb" +uuid = "50262376-6c5a-4cf5-baba-aaf4f84d72d7" +version = "1.1.0" + +[[deps.OrdinaryDiffEqDifferentiation]] +deps = ["ADTypes", "ArrayInterface", "DiffEqBase", "FastBroadcast", "FiniteDiff", "ForwardDiff", "FunctionWrappersWrappers", "LinearAlgebra", "LinearSolve", "OrdinaryDiffEqCore", "SciMLBase", "SparseArrays", "SparseDiffTools", "StaticArrayInterface", "StaticArrays"] +git-tree-sha1 = "e63ec633b1efa99e3caa2e26a01faaa88ba6cef9" +uuid = "4302a76b-040a-498a-8c04-15b101fed76b" +version = "1.1.0" + +[[deps.OrdinaryDiffEqExplicitRK]] +deps = ["DiffEqBase", "FastBroadcast", "LinearAlgebra", "MuladdMacro", "OrdinaryDiffEqCore", "RecursiveArrayTools", "Reexport", "TruncatedStacktraces"] +git-tree-sha1 = "4dbce3f9e6974567082ce5176e21aab0224a69e9" +uuid = "9286f039-9fbf-40e8-bf65-aa933bdc4db0" +version = "1.1.0" + +[[deps.OrdinaryDiffEqExponentialRK]] +deps = ["DiffEqBase", "ExponentialUtilities", "FastBroadcast", "LinearAlgebra", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqSDIRK", "OrdinaryDiffEqVerner", "RecursiveArrayTools", "Reexport", "SciMLBase"] +git-tree-sha1 = "f63938b8e9e5d3a05815defb3ebdbdcf61ec0a74" +uuid = "e0540318-69ee-4070-8777-9e2de6de23de" +version = "1.1.0" + +[[deps.OrdinaryDiffEqExtrapolation]] +deps = ["DiffEqBase", "FastBroadcast", "FastPower", "LinearSolve", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "Polyester", "RecursiveArrayTools", "Reexport"] +git-tree-sha1 = "048bcccc8f59c20d5b4ad268eef4d7d21c005a94" +uuid = "becaefa8-8ca2-5cf9-886d-c06f3d2bd2c4" +version = "1.2.1" + +[[deps.OrdinaryDiffEqFIRK]] +deps = ["DiffEqBase", "FastBroadcast", "FastPower", "GenericLinearAlgebra", "GenericSchur", "LinearAlgebra", "LinearSolve", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "Polynomials", "RecursiveArrayTools", "Reexport", "RootedTrees", "SciMLOperators", "Symbolics"] +git-tree-sha1 = "5735f4c094dff311f5064d1a351da9669e4647e3" +uuid = "5960d6e9-dd7a-4743-88e7-cf307b64f125" +version = "1.2.0" + +[[deps.OrdinaryDiffEqFeagin]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "Polyester", "RecursiveArrayTools", "Reexport", "Static"] +git-tree-sha1 = "a7cc74d3433db98e59dc3d58bc28174c6c290adf" +uuid = "101fe9f7-ebb6-4678-b671-3a81e7194747" +version = "1.1.0" + +[[deps.OrdinaryDiffEqFunctionMap]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "RecursiveArrayTools", "Reexport", "SciMLBase", "Static"] +git-tree-sha1 = "925a91583d1ab84f1f0fea121be1abf1179c5926" +uuid = "d3585ca7-f5d3-4ba6-8057-292ed1abd90f" +version = "1.1.1" + +[[deps.OrdinaryDiffEqHighOrderRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "RecursiveArrayTools", "Reexport", "Static"] +git-tree-sha1 = "103e017ff186ac39d731904045781c9bacfca2b0" +uuid = "d28bc4f8-55e1-4f49-af69-84c1a99f0f58" +version = "1.1.0" + +[[deps.OrdinaryDiffEqIMEXMultistep]] +deps = ["DiffEqBase", "FastBroadcast", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "Reexport"] +git-tree-sha1 = "9f8f52aad2399d7714b400ff9d203254b0a89c4a" +uuid = "9f002381-b378-40b7-97a6-27a27c83f129" +version = "1.1.0" + +[[deps.OrdinaryDiffEqLinear]] +deps = ["DiffEqBase", "ExponentialUtilities", "LinearAlgebra", "OrdinaryDiffEqCore", "OrdinaryDiffEqTsit5", "OrdinaryDiffEqVerner", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators"] +git-tree-sha1 = "0f81a77ede3da0dc714ea61e81c76b25db4ab87a" +uuid = "521117fe-8c41-49f8-b3b6-30780b3f0fb5" +version = "1.1.0" + +[[deps.OrdinaryDiffEqLowOrderRK]] +deps = ["DiffEqBase", "FastBroadcast", "LinearAlgebra", "MuladdMacro", "OrdinaryDiffEqCore", "RecursiveArrayTools", "Reexport", "SciMLBase", "Static"] +git-tree-sha1 = "d4bb32e09d6b68ce2eb45fb81001eab46f60717a" +uuid = "1344f307-1e59-4825-a18e-ace9aa3fa4c6" +version = "1.2.0" + +[[deps.OrdinaryDiffEqLowStorageRK]] +deps = ["Adapt", "DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "Static", "StaticArrays"] +git-tree-sha1 = "590561f3af623d5485d070b4d7044f8854535f5a" +uuid = "b0944070-b475-4768-8dec-fb6eb410534d" +version = "1.2.1" + +[[deps.OrdinaryDiffEqNonlinearSolve]] +deps = ["ADTypes", "ArrayInterface", "DiffEqBase", "FastBroadcast", "FastClosures", "ForwardDiff", "LinearAlgebra", "LinearSolve", "MuladdMacro", "NonlinearSolve", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "PreallocationTools", "RecursiveArrayTools", "SciMLBase", "SciMLOperators", "SciMLStructures", "SimpleNonlinearSolve", "StaticArrays"] +git-tree-sha1 = "e4be6539f4aaae8db1f29fcfdf6ef817df1f25cf" +uuid = "127b3ac7-2247-4354-8eb6-78cf4e7c58e8" +version = "1.2.2" + +[[deps.OrdinaryDiffEqNordsieck]] +deps = ["DiffEqBase", "FastBroadcast", "LinearAlgebra", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqTsit5", "Polyester", "RecursiveArrayTools", "Reexport", "Static"] +git-tree-sha1 = "ef44754f10e0dfb9bb55ded382afed44cd94ab57" +uuid = "c9986a66-5c92-4813-8696-a7ec84c806c8" +version = "1.1.0" + +[[deps.OrdinaryDiffEqPDIRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "Polyester", "Reexport", "StaticArrays"] +git-tree-sha1 = "a8b7f8107c477e07c6a6c00d1d66cac68b801bbc" +uuid = "5dd0a6cf-3d4b-4314-aa06-06d4e299bc89" +version = "1.1.0" + +[[deps.OrdinaryDiffEqPRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "Polyester", "Reexport"] +git-tree-sha1 = "da525d277962a1b76102c79f30cb0c31e13fe5b9" +uuid = "5b33eab2-c0f1-4480-b2c3-94bc1e80bda1" +version = "1.1.0" + +[[deps.OrdinaryDiffEqQPRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "RecursiveArrayTools", "Reexport", "Static"] +git-tree-sha1 = "332f9d17d0229218f66a73492162267359ba85e9" +uuid = "04162be5-8125-4266-98ed-640baecc6514" +version = "1.1.0" + +[[deps.OrdinaryDiffEqRKN]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "Polyester", "RecursiveArrayTools", "Reexport"] +git-tree-sha1 = "41c09d9c20877546490f907d8dffdd52690dd65f" +uuid = "af6ede74-add8-4cfd-b1df-9a4dbb109d7a" +version = "1.1.0" + +[[deps.OrdinaryDiffEqRosenbrock]] +deps = ["ADTypes", "DiffEqBase", "FastBroadcast", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "LinearSolve", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "Static"] +git-tree-sha1 = "96b47cdd12cb4ce8f70d701b49f855271a462bd4" +uuid = "43230ef6-c299-4910-a778-202eb28ce4ce" +version = "1.2.0" + +[[deps.OrdinaryDiffEqSDIRK]] +deps = ["DiffEqBase", "FastBroadcast", "LinearAlgebra", "MacroTools", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "RecursiveArrayTools", "Reexport", "SciMLBase", "TruncatedStacktraces"] +git-tree-sha1 = "f6683803a58de600ab7a26d2f49411c9923e9721" +uuid = "2d112036-d095-4a1e-ab9a-08536f3ecdbf" +version = "1.1.0" + +[[deps.OrdinaryDiffEqSSPRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "Static", "StaticArrays"] +git-tree-sha1 = "7dbe4ac56f930df5e9abd003cedb54e25cbbea86" +uuid = "669c94d9-1f4b-4b64-b377-1aa079aa2388" +version = "1.2.0" + +[[deps.OrdinaryDiffEqStabilizedIRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "OrdinaryDiffEqDifferentiation", "OrdinaryDiffEqNonlinearSolve", "RecursiveArrayTools", "Reexport", "StaticArrays"] +git-tree-sha1 = "348fd6def9a88518715425025eadd58517017325" +uuid = "e3e12d00-db14-5390-b879-ac3dd2ef6296" +version = "1.1.0" + +[[deps.OrdinaryDiffEqStabilizedRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "RecursiveArrayTools", "Reexport", "StaticArrays"] +git-tree-sha1 = "1b0d894c880e25f7d0b022d7257638cf8ce5b311" +uuid = "358294b1-0aab-51c3-aafe-ad5ab194a2ad" +version = "1.1.0" + +[[deps.OrdinaryDiffEqSymplecticRK]] +deps = ["DiffEqBase", "FastBroadcast", "MuladdMacro", "OrdinaryDiffEqCore", "Polyester", "RecursiveArrayTools", "Reexport"] +git-tree-sha1 = "4e8b8c8b81df3df17e2eb4603115db3b30a88235" +uuid = "fa646aed-7ef9-47eb-84c4-9443fc8cbfa8" +version = "1.1.0" + +[[deps.OrdinaryDiffEqTsit5]] +deps = ["DiffEqBase", "FastBroadcast", "LinearAlgebra", "MuladdMacro", "OrdinaryDiffEqCore", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "Static", "TruncatedStacktraces"] +git-tree-sha1 = "96552f7d4619fabab4038a29ed37dd55e9eb513a" +uuid = "b1df2697-797e-41e3-8120-5422d3b24e4a" +version = "1.1.0" + +[[deps.OrdinaryDiffEqVerner]] +deps = ["DiffEqBase", "FastBroadcast", "LinearAlgebra", "MuladdMacro", "OrdinaryDiffEqCore", "Polyester", "PrecompileTools", "Preferences", "RecursiveArrayTools", "Reexport", "Static", "TruncatedStacktraces"] +git-tree-sha1 = "81d7841e73e385b9925d5c8e4427f2adcdda55db" +uuid = "79d7bb75-1356-48c1-b8c0-6832512096c2" +version = "1.1.1" + +[[deps.PCRE2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "efcefdf7-47ab-520b-bdef-62a2eaa19f15" +version = "10.42.0+1" + +[[deps.PDMats]] +deps = ["LinearAlgebra", "SparseArrays", "SuiteSparse"] +git-tree-sha1 = "949347156c25054de2db3b166c52ac4728cbad65" +uuid = "90014a1f-27ba-587c-ab20-58faa44d9150" +version = "0.11.31" + +[[deps.PackageExtensionCompat]] +git-tree-sha1 = "fb28e33b8a95c4cee25ce296c817d89cc2e53518" +uuid = "65ce6f38-6b18-4e1d-a461-8949797d7930" +version = "1.0.2" +weakdeps = ["Requires", "TOML"] + +[[deps.Pango_jll]] +deps = ["Artifacts", "Cairo_jll", "Fontconfig_jll", "FreeType2_jll", "FriBidi_jll", "Glib_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e127b609fb9ecba6f201ba7ab753d5a605d53801" +uuid = "36c8627f-9965-5494-a995-c6b170f724f3" +version = "1.54.1+0" + +[[deps.Parameters]] +deps = ["OrderedCollections", "UnPack"] +git-tree-sha1 = "34c0e9ad262e5f7fc75b10a9952ca7692cfc5fbe" +uuid = "d96e819e-fc66-5662-9728-84c9c7592b0a" +version = "0.12.3" + +[[deps.Parsers]] +deps = ["Dates", "PrecompileTools", "UUIDs"] +git-tree-sha1 = "8489905bcdbcfac64d1daa51ca07c0d8f0283821" +uuid = "69de0a69-1ddd-5017-9359-2bf0b02dc9f0" +version = "2.8.1" + +[[deps.Pipe]] +git-tree-sha1 = "6842804e7867b115ca9de748a0cf6b364523c16d" +uuid = "b98c9c47-44ae-5843-9183-064241ee97a0" +version = "1.3.0" + +[[deps.Pixman_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "LLVMOpenMP_jll", "Libdl"] +git-tree-sha1 = "35621f10a7531bc8fa58f74610b1bfb70a3cfc6b" +uuid = "30392449-352a-5448-841d-b1acce4e97dc" +version = "0.43.4+0" + +[[deps.Pkg]] +deps = ["Artifacts", "Dates", "Downloads", "FileWatching", "LibGit2", "Libdl", "Logging", "Markdown", "Printf", "Random", "SHA", "TOML", "Tar", "UUIDs", "p7zip_jll"] +uuid = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f" +version = "1.11.0" +weakdeps = ["REPL"] + + [deps.Pkg.extensions] + REPLExt = "REPL" + +[[deps.PlotThemes]] +deps = ["PlotUtils", "Statistics"] +git-tree-sha1 = "41031ef3a1be6f5bbbf3e8073f210556daeae5ca" +uuid = "ccf2f8ad-2431-5c83-bf29-c5338b663b6a" +version = "3.3.0" + +[[deps.PlotUtils]] +deps = ["ColorSchemes", "Colors", "Dates", "PrecompileTools", "Printf", "Random", "Reexport", "StableRNGs", "Statistics"] +git-tree-sha1 = "3ca9a356cd2e113c420f2c13bea19f8d3fb1cb18" +uuid = "995b91a9-d308-5afd-9ec6-746e21dbc043" +version = "1.4.3" + +[[deps.Plots]] +deps = ["Base64", "Contour", "Dates", "Downloads", "FFMPEG", "FixedPointNumbers", "GR", "JLFzf", "JSON", "LaTeXStrings", "Latexify", "LinearAlgebra", "Measures", "NaNMath", "Pkg", "PlotThemes", "PlotUtils", "PrecompileTools", "Printf", "REPL", "Random", "RecipesBase", "RecipesPipeline", "Reexport", "RelocatableFolders", "Requires", "Scratch", "Showoff", "SparseArrays", "Statistics", "StatsBase", "TOML", "UUIDs", "UnicodeFun", "UnitfulLatexify", "Unzip"] +git-tree-sha1 = "45470145863035bb124ca51b320ed35d071cc6c2" +uuid = "91a5bcdd-55d7-5caf-9e0b-520d859cae80" +version = "1.40.8" + + [deps.Plots.extensions] + FileIOExt = "FileIO" + GeometryBasicsExt = "GeometryBasics" + IJuliaExt = "IJulia" + ImageInTerminalExt = "ImageInTerminal" + UnitfulExt = "Unitful" + + [deps.Plots.weakdeps] + FileIO = "5789e2e9-d7fb-5bc7-8068-2c6fae9b9549" + GeometryBasics = "5c1252a2-5f33-56bf-86c9-59e7332b4326" + IJulia = "7073ff75-c697-5162-941a-fcdaad2a7d2a" + ImageInTerminal = "d8c32880-2388-543b-8c61-d9f865259254" + Unitful = "1986cc42-f94f-5a68-af5c-568840ba703d" + +[[deps.PoissonRandom]] +deps = ["Random"] +git-tree-sha1 = "a0f1159c33f846aa77c3f30ebbc69795e5327152" +uuid = "e409e4f3-bfea-5376-8464-e040bb5c01ab" +version = "0.4.4" + +[[deps.Polyester]] +deps = ["ArrayInterface", "BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "ManualMemory", "PolyesterWeave", "Static", "StaticArrayInterface", "StrideArraysCore", "ThreadingUtilities"] +git-tree-sha1 = "6d38fea02d983051776a856b7df75b30cf9a3c1f" +uuid = "f517fe37-dbe3-4b94-8317-1923a5111588" +version = "0.7.16" + +[[deps.PolyesterWeave]] +deps = ["BitTwiddlingConvenienceFunctions", "CPUSummary", "IfElse", "Static", "ThreadingUtilities"] +git-tree-sha1 = "645bed98cd47f72f67316fd42fc47dee771aefcd" +uuid = "1d0040c9-8b98-4ee7-8388-3f51789ca0ad" +version = "0.2.2" + +[[deps.Polynomials]] +deps = ["LinearAlgebra", "RecipesBase", "Requires", "Setfield", "SparseArrays"] +git-tree-sha1 = "1a9cfb2dc2c2f1bd63f1906d72af39a79b49b736" +uuid = "f27b6e38-b328-58d1-80ce-0feddd5e7a45" +version = "4.0.11" + + [deps.Polynomials.extensions] + PolynomialsChainRulesCoreExt = "ChainRulesCore" + PolynomialsFFTWExt = "FFTW" + PolynomialsMakieCoreExt = "MakieCore" + PolynomialsMutableArithmeticsExt = "MutableArithmetics" + + [deps.Polynomials.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341" + MakieCore = "20f20a25-4f0e-4fdf-b5d1-57303727442b" + MutableArithmetics = "d8a4904e-b15c-11e9-3269-09a3773c0cb0" + +[[deps.PooledArrays]] +deps = ["DataAPI", "Future"] +git-tree-sha1 = "36d8b4b899628fb92c2749eb488d884a926614d3" +uuid = "2dfb63ee-cc39-5dd5-95bd-886bf059d720" +version = "1.4.3" + +[[deps.PositiveFactorizations]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "17275485f373e6673f7e7f97051f703ed5b15b20" +uuid = "85a6dd25-e78a-55b7-8502-1745935b8125" +version = "0.2.4" + +[[deps.PreallocationTools]] +deps = ["Adapt", "ArrayInterface", "ForwardDiff"] +git-tree-sha1 = "6c62ce45f268f3f958821a1e5192cf91c75ae89c" +uuid = "d236fae5-4411-538c-8e31-a6e3d9e00b46" +version = "0.4.24" + + [deps.PreallocationTools.extensions] + PreallocationToolsReverseDiffExt = "ReverseDiff" + + [deps.PreallocationTools.weakdeps] + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + +[[deps.PrecompileTools]] +deps = ["Preferences"] +git-tree-sha1 = "5aa36f7049a63a1528fe8f7c3f2113413ffd4e1f" +uuid = "aea7be01-6a6a-4083-8856-8a6e6704d82a" +version = "1.2.1" + +[[deps.Preferences]] +deps = ["TOML"] +git-tree-sha1 = "9306f6085165d270f7e3db02af26a400d580f5c6" +uuid = "21216c6a-2e73-6563-6e65-726566657250" +version = "1.4.3" + +[[deps.PrettyTables]] +deps = ["Crayons", "LaTeXStrings", "Markdown", "PrecompileTools", "Printf", "Reexport", "StringManipulation", "Tables"] +git-tree-sha1 = "1101cd475833706e4d0e7b122218257178f48f34" +uuid = "08abe8d2-0d0c-5749-adfa-8a2ac140af0d" +version = "2.4.0" + +[[deps.Primes]] +deps = ["IntegerMathUtils"] +git-tree-sha1 = "cb420f77dc474d23ee47ca8d14c90810cafe69e7" +uuid = "27ebfcd6-29c5-5fa9-bf4b-fb8fc14df3ae" +version = "0.5.6" + +[[deps.Printf]] +deps = ["Unicode"] +uuid = "de0858da-6303-5e67-8744-51eddeeeb8d7" +version = "1.11.0" + +[[deps.PtrArrays]] +git-tree-sha1 = "77a42d78b6a92df47ab37e177b2deac405e1c88f" +uuid = "43287f4e-b6f4-7ad1-bb20-aadabca52c3d" +version = "1.2.1" + +[[deps.Qt6Base_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "Fontconfig_jll", "Glib_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "OpenSSL_jll", "Vulkan_Loader_jll", "Xorg_libSM_jll", "Xorg_libXext_jll", "Xorg_libXrender_jll", "Xorg_libxcb_jll", "Xorg_xcb_util_cursor_jll", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_keysyms_jll", "Xorg_xcb_util_renderutil_jll", "Xorg_xcb_util_wm_jll", "Zlib_jll", "libinput_jll", "xkbcommon_jll"] +git-tree-sha1 = "492601870742dcd38f233b23c3ec629628c1d724" +uuid = "c0090381-4147-56d7-9ebc-da0b1113ec56" +version = "6.7.1+1" + +[[deps.Qt6Declarative_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll", "Qt6ShaderTools_jll"] +git-tree-sha1 = "e5dd466bf2569fe08c91a2cc29c1003f4797ac3b" +uuid = "629bc702-f1f5-5709-abd5-49b8460ea067" +version = "6.7.1+2" + +[[deps.Qt6ShaderTools_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll"] +git-tree-sha1 = "1a180aeced866700d4bebc3120ea1451201f16bc" +uuid = "ce943373-25bb-56aa-8eca-768745ed7b5a" +version = "6.7.1+1" + +[[deps.Qt6Wayland_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Qt6Base_jll", "Qt6Declarative_jll"] +git-tree-sha1 = "729927532d48cf79f49070341e1d918a65aba6b0" +uuid = "e99dba38-086e-5de3-a5b1-6e4c66e897c3" +version = "6.7.1+1" + +[[deps.QuadGK]] +deps = ["DataStructures", "LinearAlgebra"] +git-tree-sha1 = "cda3b045cf9ef07a08ad46731f5a3165e56cf3da" +uuid = "1fd47b50-473d-5c70-9696-f719f8f3bcdc" +version = "2.11.1" + + [deps.QuadGK.extensions] + QuadGKEnzymeExt = "Enzyme" + + [deps.QuadGK.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + +[[deps.REPL]] +deps = ["InteractiveUtils", "Markdown", "Sockets", "StyledStrings", "Unicode"] +uuid = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb" +version = "1.11.0" + +[[deps.Random]] +deps = ["SHA"] +uuid = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" +version = "1.11.0" + +[[deps.Random123]] +deps = ["Random", "RandomNumbers"] +git-tree-sha1 = "4743b43e5a9c4a2ede372de7061eed81795b12e7" +uuid = "74087812-796a-5b5d-8853-05524746bad3" +version = "1.7.0" + +[[deps.RandomNumbers]] +deps = ["Random"] +git-tree-sha1 = "c6ec94d2aaba1ab2ff983052cf6a606ca5985902" +uuid = "e6cf234a-135c-5ec9-84dd-332b85af5143" +version = "1.6.0" + +[[deps.Ratios]] +deps = ["Requires"] +git-tree-sha1 = "1342a47bf3260ee108163042310d26f2be5ec90b" +uuid = "c84ed2f1-dad5-54f0-aa8e-dbefe2724439" +version = "0.4.5" +weakdeps = ["FixedPointNumbers"] + + [deps.Ratios.extensions] + RatiosFixedPointNumbersExt = "FixedPointNumbers" + +[[deps.RecipesBase]] +deps = ["PrecompileTools"] +git-tree-sha1 = "5c3d09cc4f31f5fc6af001c250bf1278733100ff" +uuid = "3cdcf5f2-1ef4-517c-9805-6587b60abb01" +version = "1.3.4" + +[[deps.RecipesPipeline]] +deps = ["Dates", "NaNMath", "PlotUtils", "PrecompileTools", "RecipesBase"] +git-tree-sha1 = "45cf9fd0ca5839d06ef333c8201714e888486342" +uuid = "01d81517-befc-4cb6-b9ec-a95719d0359c" +version = "0.6.12" + +[[deps.RecursiveArrayTools]] +deps = ["Adapt", "ArrayInterface", "DocStringExtensions", "GPUArraysCore", "IteratorInterfaceExtensions", "LinearAlgebra", "RecipesBase", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface", "Tables"] +git-tree-sha1 = "6f4dca5fd8e97087a76b7ab8384d1c3086ace0b7" +uuid = "731186ca-8d62-57ce-b412-fbd966d074cd" +version = "3.27.3" + + [deps.RecursiveArrayTools.extensions] + RecursiveArrayToolsFastBroadcastExt = "FastBroadcast" + RecursiveArrayToolsForwardDiffExt = "ForwardDiff" + RecursiveArrayToolsMeasurementsExt = "Measurements" + RecursiveArrayToolsMonteCarloMeasurementsExt = "MonteCarloMeasurements" + RecursiveArrayToolsReverseDiffExt = ["ReverseDiff", "Zygote"] + RecursiveArrayToolsSparseArraysExt = ["SparseArrays"] + RecursiveArrayToolsTrackerExt = "Tracker" + RecursiveArrayToolsZygoteExt = "Zygote" + + [deps.RecursiveArrayTools.weakdeps] + FastBroadcast = "7034ab61-46d4-4ed7-9d0f-46aef9175898" + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + Measurements = "eff96d63-e80a-5855-80a2-b1b0885c5ab7" + MonteCarloMeasurements = "0987c9cc-fe09-11e8-30f0-b96dd679fdca" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.RecursiveFactorization]] +deps = ["LinearAlgebra", "LoopVectorization", "Polyester", "PrecompileTools", "StrideArraysCore", "TriangularSolve"] +git-tree-sha1 = "6db1a75507051bc18bfa131fbc7c3f169cc4b2f6" +uuid = "f2c3362d-daeb-58d1-803e-2bc74f2840b4" +version = "0.2.23" + +[[deps.Reexport]] +git-tree-sha1 = "45e428421666073eab6f2da5c9d310d99bb12f9b" +uuid = "189a3867-3050-52da-a836-e630ba90ab69" +version = "1.2.2" + +[[deps.RegistryInstances]] +deps = ["LazilyInitializedFields", "Pkg", "TOML", "Tar"] +git-tree-sha1 = "ffd19052caf598b8653b99404058fce14828be51" +uuid = "2792f1a3-b283-48e8-9a74-f99dce5104f3" +version = "0.1.0" + +[[deps.RelocatableFolders]] +deps = ["SHA", "Scratch"] +git-tree-sha1 = "ffdaf70d81cf6ff22c2b6e733c900c3321cab864" +uuid = "05181044-ff0b-4ac5-8273-598c1e38db00" +version = "1.0.1" + +[[deps.Requires]] +deps = ["UUIDs"] +git-tree-sha1 = "838a3a4188e2ded87a4f9f184b4b0d78a1e91cb7" +uuid = "ae029012-a4dd-5104-9daa-d747884805df" +version = "1.3.0" + +[[deps.ResettableStacks]] +deps = ["StaticArrays"] +git-tree-sha1 = "256eeeec186fa7f26f2801732774ccf277f05db9" +uuid = "ae5879a3-cd67-5da8-be7f-38c6eb64a37b" +version = "1.1.1" + +[[deps.Revise]] +deps = ["CodeTracking", "Distributed", "FileWatching", "JuliaInterpreter", "LibGit2", "LoweredCodeUtils", "OrderedCollections", "REPL", "Requires", "UUIDs", "Unicode"] +git-tree-sha1 = "7f4228017b83c66bd6aa4fddeb170ce487e53bc7" +uuid = "295af30f-e4ad-537b-8983-00126c2a3abe" +version = "3.6.2" + +[[deps.Rmath]] +deps = ["Random", "Rmath_jll"] +git-tree-sha1 = "852bd0f55565a9e973fcfee83a84413270224dc4" +uuid = "79098fc4-a85e-5d69-aa6a-4863f24498fa" +version = "0.8.0" + +[[deps.Rmath_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "58cdd8fb2201a6267e1db87ff148dd6c1dbd8ad8" +uuid = "f50d1b31-88e8-58de-be2c-1cc44531875f" +version = "0.5.1+0" + +[[deps.RootedTrees]] +deps = ["LaTeXStrings", "Latexify", "LinearAlgebra", "Preferences", "RecipesBase", "Requires"] +git-tree-sha1 = "c0c464d3063e46e4128d21fd677ca575ace44fdc" +uuid = "47965b36-3f3e-11e9-0dcf-4570dfd42a8c" +version = "2.23.1" +weakdeps = ["Plots"] + + [deps.RootedTrees.extensions] + PlotsExt = "Plots" + +[[deps.RuntimeGeneratedFunctions]] +deps = ["ExprTools", "SHA", "Serialization"] +git-tree-sha1 = "04c968137612c4a5629fa531334bb81ad5680f00" +uuid = "7e49a35a-f44a-4d26-94aa-eba1b4ca6b47" +version = "0.5.13" + +[[deps.SHA]] +uuid = "ea8e919c-243c-51af-8825-aaa63cd721ce" +version = "0.7.0" + +[[deps.SIMDTypes]] +git-tree-sha1 = "330289636fb8107c5f32088d2741e9fd7a061a5c" +uuid = "94e857df-77ce-4151-89e5-788b33177be4" +version = "0.1.0" + +[[deps.SLEEFPirates]] +deps = ["IfElse", "Static", "VectorizationBase"] +git-tree-sha1 = "456f610ca2fbd1c14f5fcf31c6bfadc55e7d66e0" +uuid = "476501e8-09a2-5ece-8869-fb82de89a1fa" +version = "0.6.43" + +[[deps.SciMLBase]] +deps = ["ADTypes", "Accessors", "ArrayInterface", "CommonSolve", "ConstructionBase", "Distributed", "DocStringExtensions", "EnumX", "Expronicon", "FunctionWrappersWrappers", "IteratorInterfaceExtensions", "LinearAlgebra", "Logging", "Markdown", "PrecompileTools", "Preferences", "Printf", "RecipesBase", "RecursiveArrayTools", "Reexport", "RuntimeGeneratedFunctions", "SciMLOperators", "SciMLStructures", "StaticArraysCore", "Statistics", "SymbolicIndexingInterface"] +git-tree-sha1 = "f102316e5c958b425ef530ee51c7c8a1def55d1f" +uuid = "0bca4576-84f4-4d90-8ffe-ffa030f20462" +version = "2.58.1" + + [deps.SciMLBase.extensions] + SciMLBaseChainRulesCoreExt = "ChainRulesCore" + SciMLBaseMakieExt = "Makie" + SciMLBasePartialFunctionsExt = "PartialFunctions" + SciMLBasePyCallExt = "PyCall" + SciMLBasePythonCallExt = "PythonCall" + SciMLBaseRCallExt = "RCall" + SciMLBaseZygoteExt = "Zygote" + + [deps.SciMLBase.weakdeps] + ChainRules = "082447d4-558c-5d27-93f4-14fc19e9eca2" + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + Makie = "ee78f7c6-11fb-53f2-987a-cfe4a2b5a57a" + PartialFunctions = "570af359-4316-4cb7-8c74-252c00c2016b" + PyCall = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" + PythonCall = "6099a3de-0909-46bc-b1f4-468b9a2dfc0d" + RCall = "6f49c342-dc21-5d91-9882-a32aef131414" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.SciMLJacobianOperators]] +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "ConstructionBase", "DifferentiationInterface", "FastClosures", "LinearAlgebra", "SciMLBase", "SciMLOperators"] +git-tree-sha1 = "f66048bb969e67bd7d1bdd03cd0b81219642bbd0" +uuid = "19f34311-ddf3-4b8b-af20-060888a46c0e" +version = "0.1.1" + +[[deps.SciMLOperators]] +deps = ["Accessors", "ArrayInterface", "DocStringExtensions", "LinearAlgebra", "MacroTools"] +git-tree-sha1 = "6149620767866d4b0f0f7028639b6e661b6a1e44" +uuid = "c0aeaf25-5076-4817-a8d5-81caf7dfa961" +version = "0.3.12" +weakdeps = ["SparseArrays", "StaticArraysCore"] + + [deps.SciMLOperators.extensions] + SciMLOperatorsSparseArraysExt = "SparseArrays" + SciMLOperatorsStaticArraysCoreExt = "StaticArraysCore" + +[[deps.SciMLStructures]] +deps = ["ArrayInterface"] +git-tree-sha1 = "25514a6f200219cd1073e4ff23a6324e4a7efe64" +uuid = "53ae85a6-f571-4167-b2af-e1d143709226" +version = "1.5.0" + +[[deps.Scratch]] +deps = ["Dates"] +git-tree-sha1 = "3bac05bc7e74a75fd9cba4295cde4045d9fe2386" +uuid = "6c6a2e73-6563-6170-7368-637461726353" +version = "1.2.1" + +[[deps.SentinelArrays]] +deps = ["Dates", "Random"] +git-tree-sha1 = "d0553ce4031a081cc42387a9b9c8441b7d99f32d" +uuid = "91c51154-3ec4-41a3-a24f-3f23e20d615c" +version = "1.4.7" + +[[deps.Serialization]] +uuid = "9e88b42a-f829-5b0c-bbe9-9e923198166b" +version = "1.11.0" + +[[deps.Setfield]] +deps = ["ConstructionBase", "Future", "MacroTools", "StaticArraysCore"] +git-tree-sha1 = "e2cc6d8c88613c05e1defb55170bf5ff211fbeac" +uuid = "efcf1570-3423-57d1-acb7-fd33fddbac46" +version = "1.1.1" + +[[deps.SharedArrays]] +deps = ["Distributed", "Mmap", "Random", "Serialization"] +uuid = "1a1011a3-84de-559e-8e89-a11a2f7dc383" +version = "1.11.0" + +[[deps.Showoff]] +deps = ["Dates", "Grisu"] +git-tree-sha1 = "91eddf657aca81df9ae6ceb20b959ae5653ad1de" +uuid = "992d4aef-0814-514b-bc4d-f2e9a6c4116f" +version = "1.0.3" + +[[deps.SimpleBufferStream]] +git-tree-sha1 = "f305871d2f381d21527c770d4788c06c097c9bc1" +uuid = "777ac1f9-54b0-4bf8-805c-2214025038e7" +version = "1.2.0" + +[[deps.SimpleNonlinearSolve]] +deps = ["ADTypes", "ArrayInterface", "ConcreteStructs", "DiffEqBase", "DiffResults", "DifferentiationInterface", "FastClosures", "FiniteDiff", "ForwardDiff", "LinearAlgebra", "MaybeInplace", "PrecompileTools", "Reexport", "SciMLBase", "Setfield", "StaticArraysCore"] +git-tree-sha1 = "44021f3efc023be3871195d8ad98b865001a2fa1" +uuid = "727e6d20-b764-4bd8-a329-72de5adea6c7" +version = "1.12.3" + + [deps.SimpleNonlinearSolve.extensions] + SimpleNonlinearSolveChainRulesCoreExt = "ChainRulesCore" + SimpleNonlinearSolveReverseDiffExt = "ReverseDiff" + SimpleNonlinearSolveTrackerExt = "Tracker" + SimpleNonlinearSolveZygoteExt = "Zygote" + + [deps.SimpleNonlinearSolve.weakdeps] + ChainRulesCore = "d360d2e6-b24c-11e9-a2a3-2a2ae2dbcce4" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + Tracker = "9f7883ad-71c0-57eb-9f7f-b5c9e6d3789c" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.SimpleTraits]] +deps = ["InteractiveUtils", "MacroTools"] +git-tree-sha1 = "5d7e3f4e11935503d3ecaf7186eac40602e7d231" +uuid = "699a6c99-e7fa-54fc-8d76-47d257e15c1d" +version = "0.9.4" + +[[deps.SimpleUnPack]] +git-tree-sha1 = "58e6353e72cde29b90a69527e56df1b5c3d8c437" +uuid = "ce78b400-467f-4804-87d8-8f486da07d0a" +version = "1.1.0" + +[[deps.Sockets]] +uuid = "6462fe0b-24de-5631-8697-dd941f90decc" +version = "1.11.0" + +[[deps.SoftGlobalScope]] +deps = ["REPL"] +git-tree-sha1 = "986ec2b6162ccb95de5892ed17832f95badf770c" +uuid = "b85f4697-e234-5449-a836-ec8e2f98b302" +version = "1.1.0" + +[[deps.SortingAlgorithms]] +deps = ["DataStructures"] +git-tree-sha1 = "66e0a8e672a0bdfca2c3f5937efb8538b9ddc085" +uuid = "a2af1166-a08f-5f64-846c-94a0d3cef48c" +version = "1.2.1" + +[[deps.SparseArrays]] +deps = ["Libdl", "LinearAlgebra", "Random", "Serialization", "SuiteSparse_jll"] +uuid = "2f01184e-e22b-5df5-ae63-d93ebab69eaf" +version = "1.11.0" + +[[deps.SparseConnectivityTracer]] +deps = ["ADTypes", "DocStringExtensions", "FillArrays", "LinearAlgebra", "Random", "SparseArrays"] +git-tree-sha1 = "6914df6005bab9940e2a96879a97a43e1fb1ce78" +uuid = "9f842d2f-2579-4b1d-911e-f412cf18a3f5" +version = "0.6.8" + + [deps.SparseConnectivityTracer.extensions] + SparseConnectivityTracerDataInterpolationsExt = "DataInterpolations" + SparseConnectivityTracerLogExpFunctionsExt = "LogExpFunctions" + SparseConnectivityTracerNNlibExt = "NNlib" + SparseConnectivityTracerNaNMathExt = "NaNMath" + SparseConnectivityTracerSpecialFunctionsExt = "SpecialFunctions" + + [deps.SparseConnectivityTracer.weakdeps] + DataInterpolations = "82cc6244-b520-54b8-b5a6-8a565e85f1d0" + LogExpFunctions = "2ab3a3ac-af41-5b50-aa03-7779005ae688" + NNlib = "872c559c-99b0-510c-b3b7-b6c96a88d5cd" + NaNMath = "77ba4419-2d1f-58cd-9bb1-8ffee604a2e3" + SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" + +[[deps.SparseDiffTools]] +deps = ["ADTypes", "Adapt", "ArrayInterface", "Compat", "DataStructures", "FiniteDiff", "ForwardDiff", "Graphs", "LinearAlgebra", "PackageExtensionCompat", "Random", "Reexport", "SciMLOperators", "Setfield", "SparseArrays", "StaticArrayInterface", "StaticArrays", "UnPack", "VertexSafeGraphs"] +git-tree-sha1 = "b906758c107b049b6b71599b9f928d9b14e5554a" +uuid = "47a9eef4-7e08-11e9-0b38-333d64bd3804" +version = "2.23.0" + + [deps.SparseDiffTools.extensions] + SparseDiffToolsEnzymeExt = "Enzyme" + SparseDiffToolsPolyesterExt = "Polyester" + SparseDiffToolsPolyesterForwardDiffExt = "PolyesterForwardDiff" + SparseDiffToolsSymbolicsExt = "Symbolics" + SparseDiffToolsZygoteExt = "Zygote" + + [deps.SparseDiffTools.weakdeps] + Enzyme = "7da242da-08ed-463a-9acd-ee780be4f1d9" + Polyester = "f517fe37-dbe3-4b94-8317-1923a5111588" + PolyesterForwardDiff = "98d1487c-24ca-40b6-b7ab-df2af84e126b" + Symbolics = "0c5d862f-8b57-4792-8d23-62f2024744c7" + Zygote = "e88e6eb3-aa80-5325-afca-941959d7151f" + +[[deps.SparseMatrixColorings]] +deps = ["ADTypes", "DataStructures", "DocStringExtensions", "LinearAlgebra", "Random", "SparseArrays"] +git-tree-sha1 = "f37f046636f8dc353a39279abfefe296db212171" +uuid = "0a514795-09f3-496d-8182-132a7b665d35" +version = "0.4.8" +weakdeps = ["Colors"] + + [deps.SparseMatrixColorings.extensions] + SparseMatrixColoringsColorsExt = "Colors" + +[[deps.Sparspak]] +deps = ["Libdl", "LinearAlgebra", "Logging", "OffsetArrays", "Printf", "SparseArrays", "Test"] +git-tree-sha1 = "342cf4b449c299d8d1ceaf00b7a49f4fbc7940e7" +uuid = "e56a9233-b9d6-4f03-8d0f-1825330902ac" +version = "0.3.9" + +[[deps.SpecialFunctions]] +deps = ["IrrationalConstants", "LogExpFunctions", "OpenLibm_jll", "OpenSpecFun_jll"] +git-tree-sha1 = "2f5d4697f21388cbe1ff299430dd169ef97d7e14" +uuid = "276daf66-3868-5448-9aa4-cd146d93841b" +version = "2.4.0" +weakdeps = ["ChainRulesCore"] + + [deps.SpecialFunctions.extensions] + SpecialFunctionsChainRulesCoreExt = "ChainRulesCore" + +[[deps.StableRNGs]] +deps = ["Random"] +git-tree-sha1 = "83e6cce8324d49dfaf9ef059227f91ed4441a8e5" +uuid = "860ef19b-820b-49d6-a774-d7a799459cd3" +version = "1.0.2" + +[[deps.Static]] +deps = ["CommonWorldInvalidations", "IfElse", "PrecompileTools"] +git-tree-sha1 = "87d51a3ee9a4b0d2fe054bdd3fc2436258db2603" +uuid = "aedffcd0-7271-4cad-89d0-dc628f76c6d3" +version = "1.1.1" + +[[deps.StaticArrayInterface]] +deps = ["ArrayInterface", "Compat", "IfElse", "LinearAlgebra", "PrecompileTools", "Static"] +git-tree-sha1 = "96381d50f1ce85f2663584c8e886a6ca97e60554" +uuid = "0d7ed370-da01-4f52-bd93-41d350b8b718" +version = "1.8.0" +weakdeps = ["OffsetArrays", "StaticArrays"] + + [deps.StaticArrayInterface.extensions] + StaticArrayInterfaceOffsetArraysExt = "OffsetArrays" + StaticArrayInterfaceStaticArraysExt = "StaticArrays" + +[[deps.StaticArrays]] +deps = ["LinearAlgebra", "PrecompileTools", "Random", "StaticArraysCore"] +git-tree-sha1 = "777657803913ffc7e8cc20f0fd04b634f871af8f" +uuid = "90137ffa-7385-5640-81b9-e52037218182" +version = "1.9.8" +weakdeps = ["ChainRulesCore", "Statistics"] + + [deps.StaticArrays.extensions] + StaticArraysChainRulesCoreExt = "ChainRulesCore" + StaticArraysStatisticsExt = "Statistics" + +[[deps.StaticArraysCore]] +git-tree-sha1 = "192954ef1208c7019899fbf8049e717f92959682" +uuid = "1e83bf80-4336-4d27-bf5d-d5a4f845583c" +version = "1.4.3" + +[[deps.Statistics]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "ae3bb1eb3bba077cd276bc5cfc337cc65c3075c0" +uuid = "10745b16-79ce-11e8-11f9-7d13ad32a3b2" +version = "1.11.1" +weakdeps = ["SparseArrays"] + + [deps.Statistics.extensions] + SparseArraysExt = ["SparseArrays"] + +[[deps.StatsAPI]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1ff449ad350c9c4cbc756624d6f8a8c3ef56d3ed" +uuid = "82ae8749-77ed-4fe6-ae5f-f523153014b0" +version = "1.7.0" + +[[deps.StatsBase]] +deps = ["DataAPI", "DataStructures", "LinearAlgebra", "LogExpFunctions", "Missings", "Printf", "Random", "SortingAlgorithms", "SparseArrays", "Statistics", "StatsAPI"] +git-tree-sha1 = "d1bf48bfcc554a3761a133fe3a9bb01488e06916" +uuid = "2913bbd2-ae8a-5f71-8c99-4fb6c76f3a91" +version = "0.33.21" + +[[deps.StatsFuns]] +deps = ["HypergeometricFunctions", "IrrationalConstants", "LogExpFunctions", "Reexport", "Rmath", "SpecialFunctions"] +git-tree-sha1 = "b423576adc27097764a90e163157bcfc9acf0f46" +uuid = "4c63d2b9-4356-54db-8cca-17b64c39e42c" +version = "1.3.2" +weakdeps = ["ChainRulesCore", "InverseFunctions"] + + [deps.StatsFuns.extensions] + StatsFunsChainRulesCoreExt = "ChainRulesCore" + StatsFunsInverseFunctionsExt = "InverseFunctions" + +[[deps.StatsPlots]] +deps = ["AbstractFFTs", "Clustering", "DataStructures", "Distributions", "Interpolations", "KernelDensity", "LinearAlgebra", "MultivariateStats", "NaNMath", "Observables", "Plots", "RecipesBase", "RecipesPipeline", "Reexport", "StatsBase", "TableOperations", "Tables", "Widgets"] +git-tree-sha1 = "3b1dcbf62e469a67f6733ae493401e53d92ff543" +uuid = "f3b207a7-027a-5e70-b257-86293d7955fd" +version = "0.15.7" + +[[deps.SteadyStateDiffEq]] +deps = ["ConcreteStructs", "DiffEqBase", "DiffEqCallbacks", "LinearAlgebra", "Reexport", "SciMLBase"] +git-tree-sha1 = "920acf6ae36c86f23969fea1d317e040dbfccf53" +uuid = "9672c7b4-1e72-59bd-8a11-6ac3964bc41f" +version = "2.4.1" + +[[deps.StochasticDiffEq]] +deps = ["Adapt", "ArrayInterface", "DataStructures", "DiffEqBase", "DiffEqNoiseProcess", "DocStringExtensions", "FastPower", "FiniteDiff", "ForwardDiff", "JumpProcesses", "LevyArea", "LinearAlgebra", "Logging", "MuladdMacro", "NLsolve", "OrdinaryDiffEq", "Random", "RandomNumbers", "RecursiveArrayTools", "Reexport", "SciMLBase", "SciMLOperators", "SparseArrays", "SparseDiffTools", "StaticArrays", "UnPack"] +git-tree-sha1 = "bf4bad73c80e058b1d53788ff520e10c8bad7c9d" +uuid = "789caeaf-c7a9-5a7d-9973-96adeb23e2a0" +version = "6.70.0" + +[[deps.StrideArraysCore]] +deps = ["ArrayInterface", "CloseOpenIntervals", "IfElse", "LayoutPointers", "LinearAlgebra", "ManualMemory", "SIMDTypes", "Static", "StaticArrayInterface", "ThreadingUtilities"] +git-tree-sha1 = "f35f6ab602df8413a50c4a25ca14de821e8605fb" +uuid = "7792a7ef-975c-4747-a70f-980b88e8d1da" +version = "0.5.7" + +[[deps.StringCases]] +git-tree-sha1 = "9d2c2ff94838df91866a16832cb0de4449abd54c" +uuid = "f22f4433-750e-5048-95f9-cae576f2c120" +version = "0.1.0" + +[[deps.StringManipulation]] +deps = ["PrecompileTools"] +git-tree-sha1 = "a6b1675a536c5ad1a60e5a5153e1fee12eb146e3" +uuid = "892a3eda-7b42-436c-8928-eab12a02cf0e" +version = "0.4.0" + +[[deps.StyledStrings]] +uuid = "f489334b-da3d-4c2e-b8f0-e476e12c162b" +version = "1.11.0" + +[[deps.SuiteSparse]] +deps = ["Libdl", "LinearAlgebra", "Serialization", "SparseArrays"] +uuid = "4607b0f0-06f3-5cda-b6b1-a6196a1729e9" + +[[deps.SuiteSparse_jll]] +deps = ["Artifacts", "Libdl", "libblastrampoline_jll"] +uuid = "bea87d4a-7f5b-5778-9afe-8cc45184846c" +version = "7.7.0+0" + +[[deps.Sundials]] +deps = ["CEnum", "DataStructures", "DiffEqBase", "Libdl", "LinearAlgebra", "Logging", "PrecompileTools", "Reexport", "SciMLBase", "SparseArrays", "Sundials_jll"] +git-tree-sha1 = "56661ac133ea6df96fea8d6bb4eb18875b002206" +uuid = "c3572dad-4567-51f8-b174-8c6c989267f4" +version = "4.26.1" + +[[deps.Sundials_jll]] +deps = ["Artifacts", "CompilerSupportLibraries_jll", "JLLWrappers", "Libdl", "SuiteSparse_jll", "libblastrampoline_jll"] +git-tree-sha1 = "91db7ed92c66f81435fe880947171f1212936b14" +uuid = "fb77eaff-e24c-56d4-86b1-d163f2edb164" +version = "5.2.3+0" + +[[deps.SymbolicIndexingInterface]] +deps = ["Accessors", "ArrayInterface", "RuntimeGeneratedFunctions", "StaticArraysCore"] +git-tree-sha1 = "20cf607cafb31f922bce84d60379203e7a126911" +uuid = "2efcf032-c050-4f8e-a9bb-153293bab1f5" +version = "0.3.34" + +[[deps.SymbolicLimits]] +deps = ["SymbolicUtils"] +git-tree-sha1 = "fabf4650afe966a2ba646cabd924c3fd43577fc3" +uuid = "19f23fe9-fdab-4a78-91af-e7b7767979c3" +version = "0.2.2" + +[[deps.SymbolicUtils]] +deps = ["AbstractTrees", "ArrayInterface", "Bijections", "ChainRulesCore", "Combinatorics", "ConstructionBase", "DataStructures", "DocStringExtensions", "DynamicPolynomials", "IfElse", "LinearAlgebra", "MultivariatePolynomials", "NaNMath", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArrays", "SymbolicIndexingInterface", "TermInterface", "TimerOutputs", "Unityper"] +git-tree-sha1 = "04e9157537ba51dad58336976f8d04b9ab7122f0" +uuid = "d1185830-fcd6-423d-90d6-eec64667417b" +version = "3.7.2" + + [deps.SymbolicUtils.extensions] + SymbolicUtilsLabelledArraysExt = "LabelledArrays" + SymbolicUtilsReverseDiffExt = "ReverseDiff" + + [deps.SymbolicUtils.weakdeps] + LabelledArrays = "2ee39098-c373-598a-b85f-a56591580800" + ReverseDiff = "37e2e3b7-166d-5795-8a7a-e32c996b4267" + +[[deps.Symbolics]] +deps = ["ADTypes", "ArrayInterface", "Bijections", "CommonWorldInvalidations", "ConstructionBase", "DataStructures", "DiffRules", "Distributions", "DocStringExtensions", "DomainSets", "DynamicPolynomials", "IfElse", "LaTeXStrings", "Latexify", "Libdl", "LinearAlgebra", "LogExpFunctions", "MacroTools", "Markdown", "NaNMath", "PrecompileTools", "Primes", "RecipesBase", "Reexport", "RuntimeGeneratedFunctions", "SciMLBase", "Setfield", "SparseArrays", "SpecialFunctions", "StaticArraysCore", "SymbolicIndexingInterface", "SymbolicLimits", "SymbolicUtils", "TermInterface"] +git-tree-sha1 = "0caef7687abf7094132fa3112bf5514c36a99226" +uuid = "0c5d862f-8b57-4792-8d23-62f2024744c7" +version = "6.18.3" + + [deps.Symbolics.extensions] + SymbolicsForwardDiffExt = "ForwardDiff" + SymbolicsGroebnerExt = "Groebner" + SymbolicsLuxExt = "Lux" + SymbolicsNemoExt = "Nemo" + SymbolicsPreallocationToolsExt = ["PreallocationTools", "ForwardDiff"] + SymbolicsSymPyExt = "SymPy" + + [deps.Symbolics.weakdeps] + ForwardDiff = "f6369f11-7733-5829-9624-2563aa707210" + Groebner = "0b43b601-686d-58a3-8a1c-6623616c7cd4" + Lux = "b2108857-7c20-44ae-9111-449ecde12c47" + Nemo = "2edaba10-b0f1-5616-af89-8c11ac63239a" + PreallocationTools = "d236fae5-4411-538c-8e31-a6e3d9e00b46" + SymPy = "24249f21-da20-56a4-8eb1-6a02cf4ae2e6" + +[[deps.TOML]] +deps = ["Dates"] +uuid = "fa267f1f-6049-4f14-aa54-33bafae1ed76" +version = "1.0.3" + +[[deps.TableOperations]] +deps = ["SentinelArrays", "Tables", "Test"] +git-tree-sha1 = "e383c87cf2a1dc41fa30c093b2a19877c83e1bc1" +uuid = "ab02a1b2-a7df-11e8-156e-fb1833f50b87" +version = "1.2.0" + +[[deps.TableTraits]] +deps = ["IteratorInterfaceExtensions"] +git-tree-sha1 = "c06b2f539df1c6efa794486abfb6ed2022561a39" +uuid = "3783bdb8-4a98-5b6b-af9a-565f29a5fe9c" +version = "1.0.1" + +[[deps.Tables]] +deps = ["DataAPI", "DataValueInterfaces", "IteratorInterfaceExtensions", "OrderedCollections", "TableTraits"] +git-tree-sha1 = "598cd7c1f68d1e205689b1c2fe65a9f85846f297" +uuid = "bd369af6-aec1-5ad0-b16a-f7cc5008161c" +version = "1.12.0" + +[[deps.Tar]] +deps = ["ArgTools", "SHA"] +uuid = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e" +version = "1.10.0" + +[[deps.TensorCore]] +deps = ["LinearAlgebra"] +git-tree-sha1 = "1feb45f88d133a655e001435632f019a9a1bcdb6" +uuid = "62fd8b95-f654-4bbd-a8a5-9c27f68ccd50" +version = "0.1.1" + +[[deps.TermInterface]] +git-tree-sha1 = "d673e0aca9e46a2f63720201f55cc7b3e7169b16" +uuid = "8ea1fca8-c5ef-4a55-8b96-4e9afe9c9a3c" +version = "2.0.0" + +[[deps.Test]] +deps = ["InteractiveUtils", "Logging", "Random", "Serialization"] +uuid = "8dfed614-e22c-5e08-85e1-65c5234f0b40" +version = "1.11.0" + +[[deps.TestItems]] +git-tree-sha1 = "42fd9023fef18b9b78c8343a4e2f3813ffbcefcb" +uuid = "1c621080-faea-4a02-84b6-bbd5e436b8fe" +version = "1.0.0" + +[[deps.ThreadingUtilities]] +deps = ["ManualMemory"] +git-tree-sha1 = "eda08f7e9818eb53661b3deb74e3159460dfbc27" +uuid = "8290d209-cae3-49c0-8002-c8c24d57dab5" +version = "0.5.2" + +[[deps.TimerOutputs]] +deps = ["ExprTools", "Printf"] +git-tree-sha1 = "3a6f063d690135f5c1ba351412c82bae4d1402bf" +uuid = "a759f4b9-e2f1-59dc-863e-4aeb61b1ea8f" +version = "0.5.25" + +[[deps.TranscodingStreams]] +git-tree-sha1 = "0c45878dcfdcfa8480052b6ab162cdd138781742" +uuid = "3bb67fe8-82b1-5028-8e26-92a6c54297fa" +version = "0.11.3" + +[[deps.TriangularSolve]] +deps = ["CloseOpenIntervals", "IfElse", "LayoutPointers", "LinearAlgebra", "LoopVectorization", "Polyester", "Static", "VectorizationBase"] +git-tree-sha1 = "be986ad9dac14888ba338c2554dcfec6939e1393" +uuid = "d5829a12-d9aa-46ab-831f-fb7c9ab06edf" +version = "0.2.1" + +[[deps.TruncatedStacktraces]] +deps = ["InteractiveUtils", "MacroTools", "Preferences"] +git-tree-sha1 = "ea3e54c2bdde39062abf5a9758a23735558705e1" +uuid = "781d530d-4396-4725-bb49-402e4bee1e77" +version = "1.4.0" + +[[deps.URIs]] +git-tree-sha1 = "67db6cc7b3821e19ebe75791a9dd19c9b1188f2b" +uuid = "5c2747f8-b7ea-4ff2-ba2e-563bfd36b1d4" +version = "1.5.1" + +[[deps.UUIDs]] +deps = ["Random", "SHA"] +uuid = "cf7118a7-6976-5b1a-9a39-7adc72f591a4" +version = "1.11.0" + +[[deps.UnPack]] +git-tree-sha1 = "387c1f73762231e86e0c9c5443ce3b4a0a9a0c2b" +uuid = "3a884ed6-31ef-47d7-9d2a-63182c4928ed" +version = "1.0.2" + +[[deps.Unicode]] +uuid = "4ec0a83e-493e-50e2-b9ac-8f72acf5a8f5" +version = "1.11.0" + +[[deps.UnicodeFun]] +deps = ["REPL"] +git-tree-sha1 = "53915e50200959667e78a92a418594b428dffddf" +uuid = "1cfade01-22cf-5700-b092-accc4b62d6e1" +version = "0.4.1" + +[[deps.Unitful]] +deps = ["Dates", "LinearAlgebra", "Random"] +git-tree-sha1 = "d95fe458f26209c66a187b1114df96fd70839efd" +uuid = "1986cc42-f94f-5a68-af5c-568840ba703d" +version = "1.21.0" +weakdeps = ["ConstructionBase", "InverseFunctions"] + + [deps.Unitful.extensions] + ConstructionBaseUnitfulExt = "ConstructionBase" + InverseFunctionsUnitfulExt = "InverseFunctions" + +[[deps.UnitfulLatexify]] +deps = ["LaTeXStrings", "Latexify", "Unitful"] +git-tree-sha1 = "975c354fcd5f7e1ddcc1f1a23e6e091d99e99bc8" +uuid = "45397f5d-5981-4c77-b2b3-fc36d6e9b728" +version = "1.6.4" + +[[deps.Unityper]] +deps = ["ConstructionBase"] +git-tree-sha1 = "25008b734a03736c41e2a7dc314ecb95bd6bbdb0" +uuid = "a7c27f48-0311-42f6-a7f8-2c11e75eb415" +version = "0.1.6" + +[[deps.Unzip]] +git-tree-sha1 = "ca0969166a028236229f63514992fc073799bb78" +uuid = "41fe7b60-77ed-43a1-b4f0-825fd5a5650d" +version = "0.2.0" + +[[deps.VectorizationBase]] +deps = ["ArrayInterface", "CPUSummary", "HostCPUFeatures", "IfElse", "LayoutPointers", "Libdl", "LinearAlgebra", "SIMDTypes", "Static", "StaticArrayInterface"] +git-tree-sha1 = "4ab62a49f1d8d9548a1c8d1a75e5f55cf196f64e" +uuid = "3d5dd08c-fd9d-11e8-17fa-ed2836048c2f" +version = "0.21.71" + +[[deps.VersionParsing]] +git-tree-sha1 = "58d6e80b4ee071f5efd07fda82cb9fbe17200868" +uuid = "81def892-9a0e-5fdd-b105-ffc91e053289" +version = "1.3.0" + +[[deps.VertexSafeGraphs]] +deps = ["Graphs"] +git-tree-sha1 = "8351f8d73d7e880bfc042a8b6922684ebeafb35c" +uuid = "19fa3120-7c27-5ec5-8db8-b0b0aa330d6f" +version = "0.2.0" + +[[deps.Vulkan_Loader_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Wayland_jll", "Xorg_libX11_jll", "Xorg_libXrandr_jll", "xkbcommon_jll"] +git-tree-sha1 = "2f0486047a07670caad3a81a075d2e518acc5c59" +uuid = "a44049a8-05dd-5a78-86c9-5fde0876e88c" +version = "1.3.243+0" + +[[deps.Wayland_jll]] +deps = ["Artifacts", "EpollShim_jll", "Expat_jll", "JLLWrappers", "Libdl", "Libffi_jll", "Pkg", "XML2_jll"] +git-tree-sha1 = "7558e29847e99bc3f04d6569e82d0f5c54460703" +uuid = "a2964d1f-97da-50d4-b82a-358c7fce9d89" +version = "1.21.0+1" + +[[deps.Wayland_protocols_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "93f43ab61b16ddfb2fd3bb13b3ce241cafb0e6c9" +uuid = "2381bf8a-dfd0-557d-9999-79630e7b1b91" +version = "1.31.0+0" + +[[deps.WeakRefStrings]] +deps = ["DataAPI", "InlineStrings", "Parsers"] +git-tree-sha1 = "b1be2855ed9ed8eac54e5caff2afcdb442d52c23" +uuid = "ea10d353-3f73-51f8-a26c-33c1cb351aa5" +version = "1.4.2" + +[[deps.Widgets]] +deps = ["Colors", "Dates", "Observables", "OrderedCollections"] +git-tree-sha1 = "fcdae142c1cfc7d89de2d11e08721d0f2f86c98a" +uuid = "cc8bc4a8-27d6-5769-a93b-9d913e69aa62" +version = "0.6.6" + +[[deps.WoodburyMatrices]] +deps = ["LinearAlgebra", "SparseArrays"] +git-tree-sha1 = "c1a7aa6219628fcd757dede0ca95e245c5cd9511" +uuid = "efce3f68-66dc-5838-9240-27a6d6f5f9b6" +version = "1.0.0" + +[[deps.WorkerUtilities]] +git-tree-sha1 = "cd1659ba0d57b71a464a29e64dbc67cfe83d54e7" +uuid = "76eceee3-57b5-4d4a-8e66-0e911cebbf60" +version = "1.6.1" + +[[deps.XML2_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libiconv_jll", "Zlib_jll"] +git-tree-sha1 = "6a451c6f33a176150f315726eba8b92fbfdb9ae7" +uuid = "02c8fc9c-b97f-50b9-bbe4-9be30ff0a78a" +version = "2.13.4+0" + +[[deps.XSLT_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Libgcrypt_jll", "Libgpg_error_jll", "Libiconv_jll", "XML2_jll", "Zlib_jll"] +git-tree-sha1 = "a54ee957f4c86b526460a720dbc882fa5edcbefc" +uuid = "aed1982a-8fda-507f-9586-7b0439959a61" +version = "1.1.41+0" + +[[deps.XZ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "15e637a697345f6743674f1322beefbc5dcd5cfc" +uuid = "ffd25f8a-64ca-5728-b0f7-c24cf3aae800" +version = "5.6.3+0" + +[[deps.Xorg_libICE_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "326b4fea307b0b39892b3e85fa451692eda8d46c" +uuid = "f67eecfb-183a-506d-b269-f58e52b52d7c" +version = "1.1.1+0" + +[[deps.Xorg_libSM_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libICE_jll"] +git-tree-sha1 = "3796722887072218eabafb494a13c963209754ce" +uuid = "c834827a-8449-5923-a945-d239c165b7dd" +version = "1.2.4+0" + +[[deps.Xorg_libX11_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxcb_jll", "Xorg_xtrans_jll"] +git-tree-sha1 = "afead5aba5aa507ad5a3bf01f58f82c8d1403495" +uuid = "4f6342f7-b3d2-589e-9d20-edeb45f2b2bc" +version = "1.8.6+0" + +[[deps.Xorg_libXau_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "6035850dcc70518ca32f012e46015b9beeda49d8" +uuid = "0c0b7dd1-d40b-584c-a123-a41640f87eec" +version = "1.0.11+0" + +[[deps.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" + +[[deps.Xorg_libXdmcp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "34d526d318358a859d7de23da945578e8e8727b7" +uuid = "a3789734-cfe1-5b06-b2d0-1dd0d9d62d05" +version = "1.1.4+0" + +[[deps.Xorg_libXext_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "d2d1a5c49fae4ba39983f63de6afcbea47194e85" +uuid = "1082639a-0dae-5f34-9b06-72781eeb8cb3" +version = "1.3.6+0" + +[[deps.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" + +[[deps.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" + +[[deps.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" + +[[deps.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" + +[[deps.Xorg_libXrender_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "47e45cd78224c53109495b3e324df0c37bb61fbe" +uuid = "ea2f1a96-1ddc-540d-b46f-429655e07cfa" +version = "0.9.11+0" + +[[deps.Xorg_libpthread_stubs_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8fdda4c692503d44d04a0603d9ac0982054635f9" +uuid = "14d82f49-176c-5ed1-bb49-ad3f5cbd8c74" +version = "0.1.1+0" + +[[deps.Xorg_libxcb_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "XSLT_jll", "Xorg_libXau_jll", "Xorg_libXdmcp_jll", "Xorg_libpthread_stubs_jll"] +git-tree-sha1 = "bcd466676fef0878338c61e655629fa7bbc69d8e" +uuid = "c7cfdc94-dc32-55de-ac96-5a1b8d977c5b" +version = "1.17.0+0" + +[[deps.Xorg_libxkbfile_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libX11_jll"] +git-tree-sha1 = "730eeca102434283c50ccf7d1ecdadf521a765a4" +uuid = "cc61e674-0454-545c-8b26-ed2c68acab7a" +version = "1.1.2+0" + +[[deps.Xorg_xcb_util_cursor_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_xcb_util_image_jll", "Xorg_xcb_util_jll", "Xorg_xcb_util_renderutil_jll"] +git-tree-sha1 = "04341cb870f29dcd5e39055f895c39d016e18ccd" +uuid = "e920d4aa-a673-5f3a-b3d7-f755a4d47c43" +version = "0.1.4+0" + +[[deps.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" + +[[deps.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" + +[[deps.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" + +[[deps.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" + +[[deps.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" + +[[deps.Xorg_xkbcomp_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_libxkbfile_jll"] +git-tree-sha1 = "330f955bc41bb8f5270a369c473fc4a5a4e4d3cb" +uuid = "35661453-b289-5fab-8a00-3d9160c6a3a4" +version = "1.4.6+0" + +[[deps.Xorg_xkeyboard_config_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Xorg_xkbcomp_jll"] +git-tree-sha1 = "691634e5453ad362044e2ad653e79f3ee3bb98c3" +uuid = "33bec58e-1273-512f-9401-5d533626f822" +version = "2.39.0+0" + +[[deps.Xorg_xtrans_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "e92a1a012a10506618f10b7047e478403a046c77" +uuid = "c5fb5394-a638-5e4d-96e5-b29de1b5cf10" +version = "1.5.0+0" + +[[deps.ZMQ]] +deps = ["FileWatching", "PrecompileTools", "Sockets", "ZeroMQ_jll"] +git-tree-sha1 = "18cfd00df3cbbebf8ea4ec7ea6bbceb3af716bd0" +uuid = "c2297ded-f4af-51ae-bb23-16f91089e4e1" +version = "1.3.0" + +[[deps.ZeroMQ_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "libsodium_jll"] +git-tree-sha1 = "f02ce8f0fda1ed40f4d0d59a2ad05e35e8ac9b0e" +uuid = "8f1865be-045e-5c20-9c9f-bfbfb0764568" +version = "4.3.5+1" + +[[deps.Zlib_jll]] +deps = ["Libdl"] +uuid = "83775a58-1f1d-513f-b197-d71354ab007a" +version = "1.2.13+1" + +[[deps.Zstd_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "555d1076590a6cc2fdee2ef1469451f872d8b41b" +uuid = "3161d3a3-bdf6-5164-811a-617609db77b4" +version = "1.5.6+1" + +[[deps.eudev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "gperf_jll"] +git-tree-sha1 = "431b678a28ebb559d224c0b6b6d01afce87c51ba" +uuid = "35ca27e7-8b34-5b7f-bca9-bdc33f59eb06" +version = "3.2.9+0" + +[[deps.fzf_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "936081b536ae4aa65415d869287d43ef3cb576b2" +uuid = "214eeab7-80f7-51ab-84ad-2988db7cef09" +version = "0.53.0+0" + +[[deps.gperf_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "3516a5630f741c9eecb3720b1ec9d8edc3ecc033" +uuid = "1a1c6b14-54f6-533d-8383-74cd7377aa70" +version = "3.1.1+0" + +[[deps.libaom_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "1827acba325fdcdf1d2647fc8d5301dd9ba43a9d" +uuid = "a4ae2306-e953-59d6-aa16-d00cac43593b" +version = "3.9.0+0" + +[[deps.libass_jll]] +deps = ["Artifacts", "Bzip2_jll", "FreeType2_jll", "FriBidi_jll", "HarfBuzz_jll", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "e17c115d55c5fbb7e52ebedb427a0dca79d4484e" +uuid = "0ac62f75-1d6f-5e53-bd7c-93b484bb37c0" +version = "0.15.2+0" + +[[deps.libblastrampoline_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850b90-86db-534c-a0d3-1478176c7d93" +version = "5.11.0+0" + +[[deps.libdecor_jll]] +deps = ["Artifacts", "Dbus_jll", "JLLWrappers", "Libdl", "Libglvnd_jll", "Pango_jll", "Wayland_jll", "xkbcommon_jll"] +git-tree-sha1 = "9bf7903af251d2050b467f76bdbe57ce541f7f4f" +uuid = "1183f4f0-6f2a-5f1a-908b-139f9cdfea6f" +version = "0.2.2+0" + +[[deps.libevdev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "141fe65dc3efabb0b1d5ba74e91f6ad26f84cc22" +uuid = "2db6ffa8-e38f-5e21-84af-90c45d0032cc" +version = "1.11.0+0" + +[[deps.libfdk_aac_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "8a22cf860a7d27e4f3498a0fe0811a7957badb38" +uuid = "f638f0a6-7fb0-5443-88ba-1cc74229b280" +version = "2.0.3+0" + +[[deps.libinput_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "eudev_jll", "libevdev_jll", "mtdev_jll"] +git-tree-sha1 = "ad50e5b90f222cfe78aa3d5183a20a12de1322ce" +uuid = "36db933b-70db-51c0-b978-0f229ee0e533" +version = "1.18.0+0" + +[[deps.libpng_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Zlib_jll"] +git-tree-sha1 = "b70c870239dc3d7bc094eb2d6be9b73d27bef280" +uuid = "b53b4c65-9356-5827-b1ea-8c7a1a84506f" +version = "1.6.44+0" + +[[deps.libsodium_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "f76d682d87eefadd3f165d8d9fda436464213142" +uuid = "a9144af2-ca23-56d9-984f-0d03f7b5ccf8" +version = "1.0.20+1" + +[[deps.libvorbis_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Ogg_jll", "Pkg"] +git-tree-sha1 = "490376214c4721cdaca654041f635213c6165cb3" +uuid = "f27f6e37-5d2b-51aa-960f-b287f2bc3b7a" +version = "1.3.7+2" + +[[deps.mtdev_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "814e154bdb7be91d78b6802843f76b6ece642f11" +uuid = "009596ad-96f7-51b1-9f1b-5ce2d5e8a71e" +version = "1.1.6+0" + +[[deps.nghttp2_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "8e850ede-7688-5339-a07c-302acd2aaf8d" +version = "1.59.0+0" + +[[deps.oneTBB_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl"] +git-tree-sha1 = "7d0ea0f4895ef2f5cb83645fa689e52cb55cf493" +uuid = "1317d2d5-d96f-522e-a858-c73665f53c3e" +version = "2021.12.0+0" + +[[deps.p7zip_jll]] +deps = ["Artifacts", "Libdl"] +uuid = "3f19e933-33d8-53b3-aaab-bd5110c3b7a0" +version = "17.4.0+2" + +[[deps.x264_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "4fea590b89e6ec504593146bf8b988b2c00922b2" +uuid = "1270edf5-f2f9-52d2-97e9-ab00b5d0237a" +version = "2021.5.5+0" + +[[deps.x265_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg"] +git-tree-sha1 = "ee567a171cce03570d77ad3a43e90218e38937a9" +uuid = "dfaa095f-4041-5dcd-9319-2fabd8486b76" +version = "3.5.0+0" + +[[deps.xkbcommon_jll]] +deps = ["Artifacts", "JLLWrappers", "Libdl", "Pkg", "Wayland_jll", "Wayland_protocols_jll", "Xorg_libxcb_jll", "Xorg_xkeyboard_config_jll"] +git-tree-sha1 = "9c304562909ab2bab0262639bd4f444d7bc2be37" +uuid = "d8fb68d0-12a3-5cfd-a85a-d49703b185fd" +version = "1.4.1+1" \ No newline at end of file diff --git a/_freeze/10_complex_experiments_end/execute-results/html.json b/_freeze/10_complex_experiments_end/execute-results/html.json index e24f799..4904082 100644 --- a/_freeze/10_complex_experiments_end/execute-results/html.json +++ b/_freeze/10_complex_experiments_end/execute-results/html.json @@ -1,8 +1,8 @@ { "hash": "93f6b735a5eb08313674e48cf128e6df", "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 10: Complex Experiments with the END\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\n\n\n::: {.callout-caution}\n## Warning\n\nStability was replaced by Shannon diversity - need to review context as well as if we want that or rather re-integrate stability\n:::\n\nThe previous tutorial focused on experiments where we manipulated the number of networks and various network parameters. This is one set of things we can change/vary in an _in silico_ experiment. The other set of things we can change are features of the model, such as the shape of the functional response (see Tutorial 7), features of the environment such as the carrying capacity, or even empirical relationships that drive trophic structure and interaction strengths, such as the predator-prey mass ratio.\n\nIn this tutorial, we are going to implement three experiments. The first two will be 'simple' in that they vary only two things. The final example will implement a large experiment changing five features of the model.\n\nYou may want to start a new script in the project. We'll need the following packages (they are already installed... so we just need `using`).\n\n::: {#6c9caa58 .cell execution_count=1}\n``` {.julia .cell-code}\nusing Random, Plots, Distributions, DataFrames, StatsPlots\nusing EcologicalNetworksDynamics\n```\n:::\n\n\n### Experiment 1: Carrying Capacity and the Predator Prey Mass Ratio\n\nNow we are set for our first experiment. Lets first establish the parameters we need to make the food web and do the experiment. We fix `S` at 20 and `C` at 0.15. We then create vectors of Z and K. \n\nZ is the predator - prey mass ratio, and defines how much bigger or smaller the predators are from their prey. The data suggest it is between predators are between 10 and 100 times bigger than their prey [see Brose et al 2006](https://doi.org/10.1890/0012-9658(2006)87[2411:CBRINF]2.0.CO;2). This value interacts with setting trophic levels in the model. \n\nThe default setting for the models is 1 - i.e. all species are within the same order of magnitude, predators are not bigger than their prey. Here, we create a vector of values to explore, from predators being smaller, to them being 10 or 100 x larger as the data suggests.\n\n::: {#7aeb281d .cell execution_count=2}\n``` {.julia .cell-code}\n#Fixed Parameters\nS = 20\nC = 0.15\n\n# Variable Parameters\nZ_levels = [0.1, 1, 10, 100]\nK_levels = [0.1, 1, 10, 100]\n\n# run this to get same results as in the document\nRandom.seed!(123)\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\nTaskLocalRNG()\n```\n:::\n:::\n\n\nNow, lets set up the collecting data frame.\n\n::: {#37e1e107 .cell execution_count=3}\n``` {.julia .cell-code}\ndf_collect = DataFrame(Z = [], K = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```{=html}\n
0×5 DataFrame
RowZKFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAnyAny
\n```\n:::\n:::\n\n\nNow, set up the loop to use these variables and generate outputs. Notice that we use `for z in Z_levels` - this is a clever trick of the looping method, where `z` simply iterates over the values of `Z_levels` without having to specify the index value (e.g. no use of `Z_levels[i]` etc).\n\nThe significant BIG thing here is the LogisticGrowth function which allows us to set things like the carrying capacity (K) of the resources. Here we use it to define custom values of the K paramter for carrying capacity, drawing on the values in the `K_levels` above. Here, `pg` stands for Producer Growth function, and the paramter set in the food web is K.\n\nNote too our use of `println` and the values of `Z` and `K` to produce an informative _break_ between each combination.\n\n::: {.callout-note icon=false}\n\nCan you guess what increasing K will do to the biomass and richness of the community at equilibrium? How about Z? Will higher Z make things more or less stable?\n:::\n\n::: {#62075ef2 .cell execution_count=4}\n``` {.julia .cell-code}\nfor z in Z_levels\n for k in K_levels\n\n println(\" ***> This is iteration with Z = $z and K = $k\\n\")\n\n # Define the food web\n fw = Foodweb(:niche; S = S, C = C)\n # specify the K value of the producer growth function\n\n B0 = rand(S)\n # specify model to simulate logistic growth as well as BM ratio\n params = default_model(fw, BodyMass(; Z = z), LogisticGrowth(; K = k))\n \n # number of timestamps\n t = 300\n\n out = simulate(params, B0, t)\n\n # calculate metrics\n fin_rich = richness(out)\n fin_biomass = total_biomass(out)\n s_div = shannon_diversity(out)\n\n push!(df_collect, [z, k, fin_rich, fin_biomass, s_div])\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n ***> This is iteration with Z = 0.1 and K = 0.1\n\n ***> This is iteration with Z = 0.1 and K = 1.0\n\n ***> This is iteration with Z = 0.1 and K = 10.0\n\n ***> This is iteration with Z = 0.1 and K = 100.0\n\n ***> This is iteration with Z = 1.0 and K = 0.1\n\n ***> This is iteration with Z = 1.0 and K = 1.0\n\n ***> This is iteration with Z = 1.0 and K = 10.0\n\n ***> This is iteration with Z = 1.0 and K = 100.0\n\n ***> This is iteration with Z = 10.0 and K = 0.1\n\n ***> This is iteration with Z = 10.0 and K = 1.0\n\n ***> This is iteration with Z = 10.0 and K = 10.0\n\n ***> This is iteration with Z = 10.0 and K = 100.0\n\n ***> This is iteration with Z = 100.0 and K = 0.1\n\n ***> This is iteration with Z = 100.0 and K = 1.0\n\n ***> This is iteration with Z = 100.0 and K = 10.0\n\n ***> This is iteration with Z = 100.0 and K = 100.0\n\n```\n:::\n:::\n\n\nWonderful. Now we are in a position to learn about two new plotting methods. First, let's look at the data frame we've created.\n\n::: {#85639f0b .cell execution_count=5}\n``` {.julia .cell-code}\ndf_collect\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```{=html}\n
16×5 DataFrame
RowZKFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAnyAny
10.10.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 5, 5, 5, 5, 5, 5, 5, 5, 5, 5][8.15104, 7.35599, 6.86766, 6.20173, 5.62064, 4.93607, 4.31825, 3.63121, 3.00669, 2.39632 … 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.3][16.6229, 16.7342, 16.5646, 16.1151, 15.6393, 15.1269, 14.7861, 14.5788, 14.548, 14.6324 … 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00005]
20.11.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 11, 11, 11, 11, 11, 11, 11, 11, 11, 11][12.4772, 11.4754, 10.7631, 9.95902, 9.14621, 8.41858, 7.61812, 6.84285, 6.08118, 5.33149 … 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616][17.742, 17.8484, 17.6835, 17.2513, 16.4331, 15.4516, 14.5648, 14.1409, 13.9903, 13.8445 … 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.38235]
30.110.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 13, 13, 13, 13, 13, 13, 13, 13, 13, 13][9.25026, 8.51092, 8.00559, 7.44123, 6.91671, 6.27631, 5.65377, 4.94222, 4.26539, 3.54824 … 2.25548, 2.2559, 2.25643, 2.25698, 2.25747, 2.25783, 2.25806, 2.25819, 2.25825, 2.25825][14.6862, 14.6468, 14.2896, 13.6899, 12.9845, 12.0663, 11.3051, 10.7473, 10.5693, 10.7805 … 9.57129, 9.59447, 9.62346, 9.6528, 9.67659, 9.69307, 9.70369, 9.71014, 9.71404, 9.71427]
40.1100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][11.7083, 11.0424, 10.5769, 9.93713, 9.4234, 8.80592, 8.23005, 7.54626, 6.97782, 6.26384 … 3.48233, 3.48295, 3.48399, 3.48495, 3.48596, 3.48667, 3.48716, 3.48743, 3.48757, 3.48759][18.2061, 17.7393, 17.1158, 15.8476, 14.5755, 13.1387, 12.2288, 11.7098, 11.6218, 11.8449 … 14.6644, 14.6766, 14.6955, 14.7124, 14.7303, 14.7429, 14.7523, 14.7579, 14.7612, 14.762]
51.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 14, 11, 11, 7, 7, 7, 7, 6, 6, 6][9.94865, 9.31694, 8.91556, 8.37917, 7.98085, 7.48504, 7.05457, 6.53892, 6.03007, 5.45877 … 0.599995, 0.599995, 0.600001, 0.600001, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6][16.9057, 16.7928, 16.5411, 15.9674, 15.4178, 14.6761, 13.9969, 13.1036, 12.1136, 10.9472 … 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0]
61.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 16, 16, 16, 16, 15, 15, 14, 14][8.18822, 7.87201, 7.51513, 7.09849, 6.67715, 6.24736, 5.77386, 5.30732, 4.78624, 4.26858 … 2.1041, 2.1036, 2.1036, 2.10339, 2.10338, 2.10338, 2.10338, 2.1034, 2.1034, 2.10341][17.8751, 17.9835, 17.9691, 17.7811, 17.4596, 17.0672, 16.6213, 16.2204, 15.8747, 15.676 … 9.70326, 9.70168, 9.70168, 9.70046, 9.7004, 9.7004, 9.7004, 9.70055, 9.70055, 9.70071]
71.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 18, 18, 18, 18, 17, 17, 17, 17, 17, 17][11.9214, 11.5912, 11.2096, 10.7345, 10.2291, 9.65051, 9.08087, 8.50293, 7.95285, 7.4397 … 12.5097, 12.5097, 12.5097, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098][17.7631, 17.8918, 17.8487, 17.5309, 16.9389, 15.9573, 14.662, 13.1789, 11.9185, 11.0675 … 4.62639, 4.61727, 4.60955, 4.60285, 4.60285, 4.59699, 4.59175, 4.58698, 4.58255, 4.57863]
81.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][9.81854, 9.78941, 9.7508, 9.70287, 9.63915, 9.53889, 9.36204, 9.09799, 8.78533, 8.50462 … 7.83776, 7.83881, 7.83874, 7.83824, 7.83785, 7.8378, 7.83791, 7.83792, 7.83791, 7.83792][15.8542, 15.9962, 16.1459, 16.2131, 16.1391, 15.9368, 15.6428, 15.2171, 14.6976, 14.3231 … 14.8658, 14.8748, 14.8756, 14.873, 14.8704, 14.8698, 14.8703, 14.8705, 14.8704, 14.8705]
910.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 13, 13, 12, 12, 10, 10, 10, 9, 9, 8][12.3589, 11.1366, 10.528, 9.73548, 9.28095, 8.70753, 8.38507, 7.92468, 7.6241, 7.16456 … 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7][17.9611, 18.047, 17.9192, 17.5077, 17.121, 16.4637, 16.0159, 15.3056, 14.8254, 14.13 … 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0]
1010.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 19, 19, 19, 19, 19, 19, 19, 19][8.42215, 8.20465, 7.99326, 7.76301, 7.53365, 7.30894, 7.04805, 6.82182, 6.50908, 6.21272 … 2.86069, 2.86431, 2.86431, 2.86744, 2.87126, 2.87422, 2.87704, 2.87913, 2.88089, 2.88177][15.0882, 15.2155, 15.2234, 15.0786, 14.8185, 14.5613, 14.3405, 14.2066, 14.0631, 13.9396 … 13.2383, 13.2133, 13.2133, 13.1887, 13.1531, 13.1189, 13.0773, 13.0366, 12.9906, 12.9603]
1110.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 17, 17, 17, 17, 16, 16, 16, 16][8.76005, 8.6219, 8.45014, 8.27291, 8.03749, 7.83254, 7.54527, 7.26893, 6.89872, 6.5367 … 4.352, 4.37513, 4.3948, 4.41157, 4.4259, 4.43803, 4.43803, 4.44812, 4.45638, 4.45893][16.3521, 16.3257, 16.2454, 16.1206, 15.8993, 15.6612, 15.275, 14.8714, 14.3179, 13.7872 … 5.58795, 5.46404, 5.36072, 5.2744, 5.20203, 5.14192, 5.14192, 5.09276, 5.0532, 5.04108]
1210.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.25211, 8.29101, 8.4592, 8.87757, 9.76632, 11.7568, 16.001, 25.5672, 46.8751, 88.1647 … 243.87, 243.868, 243.863, 243.857, 243.852, 243.848, 243.845, 243.843, 243.841, 243.84][15.4288, 15.4367, 15.3683, 14.9952, 14.0388, 12.1209, 9.40314, 6.56688, 4.55697, 3.55452 … 6.58682, 6.58612, 6.58472, 6.58295, 6.58118, 6.57958, 6.57821, 6.57708, 6.57618, 6.57556]
13100.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 19, 19, 18, 18, 18, 18, 18, 18, 18, 18][11.5095, 10.9511, 10.7168, 10.3916, 10.2152, 9.9237, 9.78424, 9.46529, 9.30356, 8.92472 … 0.472889, 0.463688, 0.463688, 0.455691, 0.448684, 0.442486, 0.436958, 0.431991, 0.427513, 0.425609][17.231, 17.3743, 17.335, 17.1761, 17.0496, 16.8121, 16.6962, 16.4432, 16.324, 16.0738 … 5.95521, 5.74108, 5.74108, 5.5499, 5.37858, 5.22417, 5.08415, 4.95644, 4.83969, 4.78959]
14100.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.94845, 8.84267, 8.70565, 8.58269, 8.46112, 8.33459, 8.2076, 8.07545, 7.93311, 7.80568 … 8.84776, 8.83373, 8.82279, 8.81646, 8.81702, 8.82562, 8.83778, 8.84947, 8.8573, 8.85948][16.8594, 16.831, 16.7339, 16.6093, 16.4917, 16.4208, 16.4238, 16.5015, 16.6608, 16.8785 … 11.6325, 11.5115, 11.4211, 11.3514, 11.3021, 11.2653, 11.2375, 11.2081, 11.1754, 11.1534]
15100.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][9.0416, 9.1737, 9.5697, 10.2502, 11.3574, 13.2685, 16.0394, 20.0685, 25.3442, 31.3042 … 79.4917, 79.5051, 79.498, 79.4849, 79.4774, 79.4781, 79.4801, 79.4797, 79.4785, 79.4782][15.9684, 16.1206, 16.4693, 16.7484, 16.6086, 15.5647, 13.7709, 11.8335, 10.3515, 9.58567 … 11.1015, 11.0926, 11.0865, 11.0856, 11.0869, 11.0872, 11.0863, 11.0855, 11.0854, 11.0854]
16100.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][11.5292, 11.6221, 11.8303, 12.2001, 12.9034, 14.2178, 16.6995, 21.3803, 29.102, 40.6004 … 466.619, 464.416, 463.06, 460.625, 457.236, 453.504, 450.831, 452.672, 465.621, 471.999][18.3089, 18.2607, 18.15, 17.9446, 17.542, 16.8141, 15.6206, 13.9258, 12.0175, 9.86971 … 7.06769, 7.20399, 7.09213, 6.94422, 6.80881, 6.70295, 6.69553, 6.94315, 7.66919, 7.96389]
\n```\n:::\n:::\n\n\n#### Visualising the experiment\n\nOne option here is to plot one of our `Final` Objects as the response variable against the valuse of Z and K. In R, we'd use ggplot2. Here we'll use `StatsPlots` as we learned about in Tutorial 5. Can you make this work in the regular `Plots` syntax?\n\nLet's first look at a single plot of stability\n\n::: {#9159766f .cell execution_count=6}\n``` {.julia .cell-code}\n@df df_collect plot(:K, [:FinalStability], group = :Z, \n ylabel = \"Stabilty\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line],\n legend = false)\n```\n:::\n\n\nNow some new ploting tricks... 3 plots in a layout.\n\n::: {#50bb5a5c .cell execution_count=7}\n``` {.julia .cell-code}\np1 = @df df_collect plot(:K, [:FinalStability], group = :Z, \n legend = :bottomright,\n ylabel = \"Stabilty\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n\np2 = @df df_collect plot(:K, [:FinalBiomass], group = :Z, \n legend = :bottomright,\n ylabel = \"Biomass\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n \np3 = @df df_collect plot(:K, [:FinalRichness], group = :Z, \n legend = :bottomright,\n ylabel = \"Richness\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n\n# create a layout of 3 graphs stacked on top of each other.\nplot(p1, p2, p3, layout=(3,1), legend = false)\n```\n:::\n\n\n### Interpretation!\n\n#### Challenge - can you get the number of extinctions into the data frame?\n\n### Experiment 2: The Functional Response\n\nThe functional response is the relationship between how much a consumer eats and the 'density' of the prey items. If you can recall from your ecology courses/classes/modules, there are three classic shapes: The Type I, Type II and Type III.\n\nA predator feeding with a Type I delivers to the prey a 'constant mortality rate' (the slope of the Type I line). This means that the effect of predation is density _independent_ because prey mortality rate does not vary by prey density. Remember, density dependence (negative feedback that stabilises communities) is defined by survival decreasing with increasing density, or in this case, mortality rates _increasing_ with increasing density.\n\nA predator feeding with the Type II delivers an _inverse density dependent_ mortality rate. The slope of the Type II line actually goes down as density of the prey goes up meaning that mortality rates for the prey, caused by the predator, are going down with prey density. This means that the effect of predation is _inverse density dependent_ in the Type II. This is **destabilising**.\n\nFinally, a predator feeding via a Type III can deliver a _density dependent_ mortality rate to the prey, but only at low prey densities. This is an S shaped curve. Below the inflection point, the slope is actually getting steeper. This means that as prey density increases up to the inflection, their mortality rate from predation increases (survival goes down with density going up). This is the hallmark of density dependence and can **stabilise** consumer-resource interactions.\n\n::: {.callout-tip icon=false}\n\nRemember that the logistic growth equation, with a carying capacity specified, is also a source of _density dependent negative feedback_\n:::\n\n::: {.callout-tip icon=false}\n\nThe Type II is the MOST common. Type I is rare and even non-existent because it suggests there are no limits to how much a consumer can eat. Type III is also rare, but it is at least plausible and interesting.\n:::\n\n::: {#5eeb3011 .cell execution_count=8}\n``` {.julia .cell-code}\nf_t1(n) = 0.5*n\nf_t2(n) = 0.5*n/(0.2+0.01*n)\nf_t3(n) = 0.5*n^2/(10 + 0.01*n^2)\n\nplot(f_t1, 0, 100, label = \"Type I\")\nplot!(f_t2, 0, 100, label = \"Type II\")\nplot!(f_t3, 0, 100, label = \"Type III\")\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n#### How does the BEFW make a functional response?\n\nThere are two formulations of the functional response. One of them is called the _Bioenergetic_ response and the other is called the _Classic_. In both cases, we ignore the Type I.\n\nThe Bioenergetic functional response is deeply phenomenological in that the parameters that make the shapes move between Type II and III have no deliberate biological interpretation. They function is defined by a 1/2 saturation point, an asymptote (which is nominally a maxiumum feeding rate) and an exponent, which is called the _hill exponent_. The value of the exponent moves the model from Type II (h = 1) to Type III (h = 2). The other variables define the overall shape.\n\nThe Classic functional less phenomenological in that the response is defined more by 'traits': the attack rate of a consumer on a prey and the handling time of that prey. But it also moves between the Type II and Type III shape based on an exponent.\n\n#### Creating Type II vs. Type III with the Bioenergetic response\n\nLet's look at using the Bioenergetic functional response, and see here how we can vary the shape between Type II and Type III. We can do this by modifying the *hill_exponent* after we have specified the model (*i.e.,* after the `default_model` call). We will look at how Richness, Biomass and Shannon Diversity are affected by the hill exponent.\n\n::: {#55111e82 .cell execution_count=9}\n``` {.julia .cell-code}\nRandom.seed!(12352)\n\n# fixed parameters\nS = 20\nC = 0.15\n\n# set the hill exponent to move from Type II to Type III)\nh_levels = [1.0, 1.1, 1.25, 2.0]\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_h = DataFrame(h = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\n# create look across values of h\nfor h in h_levels \n println(\"***> This is iteration with h = $h\\n\")\n \n # make the network\n # Note that we specify the Environment, but there is no K or T set (using defaults)\n # Note the new BioenergeticResponse function\n fw_h = Foodweb(:niche; S = S, C = C)\n \n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_h)\n\n # here we now update the exponent of the hill function\n params.hill_exponent = h\n\n # specify number of time steps\n t = 300\n\n # simulate\n sim_niche = simulate(params, B0, t)\n\n # collect data \n fin_rich = richness(sim_niche)\n fin_bio = total_biomass(sim_niche)\n s_div = shannon_diversity(sim_niche)\n\n push!(df_collect_h, [h, fin_rich, fin_bio, s_div])\nend\n\ndf_collect_h\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n***> This is iteration with h = 1.0\n\n***> This is iteration with h = 1.1\n\n***> This is iteration with h = 1.25\n\n***> This is iteration with h = 2.0\n\n```\n:::\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n
4×4 DataFrame
RowhFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAny
11.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 16, 16, 15, 15, 15, 15, 15, 15, 15, 15][14.0154, 13.7814, 13.4658, 13.1783, 12.8834, 12.6007, 12.3015, 11.9503, 11.7107, 11.4361 … 6.42979, 6.44208, 6.44208, 6.44436, 6.43148, 6.44421, 6.44068, 6.43311, 6.44545, 6.44344][18.7295, 18.6847, 18.5806, 18.4524, 18.2893, 18.0832, 17.7706, 17.2078, 16.6571, 15.8173 … 7.82943, 7.8319, 7.8319, 7.84614, 7.82841, 7.83428, 7.84109, 7.82605, 7.83731, 7.84078]
21.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 17, 17, 17, 17, 16, 16, 16, 16][11.3827, 11.1345, 10.7624, 10.3913, 9.99559, 9.59857, 9.16844, 8.74251, 8.37833, 8.02815 … 5.77289, 5.7729, 5.77293, 5.77292, 5.7729, 5.77291, 5.77291, 5.77291, 5.77291, 5.77291][17.2879, 17.2245, 17.0354, 16.7364, 16.3009, 15.7385, 14.957, 13.9498, 12.8428, 11.4674 … 8.05783, 8.05797, 8.05789, 8.05783, 8.0578, 8.05778, 8.05778, 8.05775, 8.05773, 8.05772]
31.25[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][7.95051, 7.71008, 7.36973, 7.05915, 6.81253, 6.60547, 6.33242, 6.20856, 5.90247, 5.79213 … 5.73092, 5.7267, 5.72288, 5.71981, 5.71723, 5.71558, 5.71443, 5.71385, 5.71357, 5.71354][14.8364, 15.0814, 15.2094, 15.0455, 14.7772, 14.5307, 14.2246, 14.1041, 13.874, 13.816 … 12.4849, 12.445, 12.4101, 12.3868, 12.3692, 12.3593, 12.3531, 12.3504, 12.3493, 12.3492]
42.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.38822, 8.15315, 7.90496, 7.74148, 7.54947, 7.42629, 7.21904, 7.06338, 6.82622, 6.62508 … 5.63687, 5.63973, 5.64247, 5.64441, 5.64568, 5.64631, 5.64656, 5.64657, 5.64648, 5.64641][13.7108, 13.8974, 13.9356, 13.9101, 13.8971, 13.9043, 13.9225, 13.9274, 13.9095, 13.8705 … 13.7105, 13.7429, 13.7652, 13.7748, 13.7762, 13.7723, 13.7654, 13.7572, 13.7488, 13.7434]
\n```\n:::\n:::\n\n\nNow, we can visualise these data\n\n::: {#be0fe852 .cell execution_count=10}\n``` {.julia .cell-code}\n# Visualize the results\np1_h = @df df_collect_h plot(:h, [:FinalStability],\n legend = :bottomright,\n ylabel = \"Stability\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\np2_h = @df df_collect_h plot(:h, [:FinalBiomass],\n legend = :bottomright,\n ylabel = \"Biomass\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\np3_h = @df df_collect_h plot(:h, [:FinalRichness],\n legend = :bottomright,\n ylabel = \"Richness\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\nplot(p1_h, p2_h, p3_h, layout=(3,1), legend = false, size = (1000, 1000))\n```\n:::\n\n\n#### INTERPRETATION?\n\nWhat can you see happening as we move away from the destabilising Type II functional response?\n\nCan you modify this code to explore what happens at different values of K? You'll need to modify this section, and the collection data frame.\n\n::: {#f8aca1ed .cell execution_count=11}\n``` {.julia .cell-code}\n # make the network\n fw_h = Foodweb(:niche; S = S, C = C)\n\n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_h, LogisticGrowth(; K = k))\n\n # update the exponent of the hill function\n params.hill_exponent = h\n```\n:::\n\n\n### Experiment 3: What is Z\n\nOne of the central features of the link between the Bioenergetic Food Web model and the structure of a foodweb created by models like the Niche Model is the organisation of trophic levels. At the heart of this is a _data driven_ assumption about the ratio of predator size to prey size. This is called the _Predator Prey Mass Ratio_, or `PPMR` for short. \n\nIn 2006, Uli Brose and team collated hundreds of data [to reveal that](https://esajournals.onlinelibrary.wiley.com/doi/10.1890/0012-9658%282006%2987%5B2411%3ACBRINF%5D2.0.CO%3B2), on average, predators were between 10 and 100x bigger than their prey.\n\nIn our modelling framework, we use this ratio to help organise species into trophic levels. This is done by organising the bodymass vector, and via a parameter called `Z`. The body mass of consumers is a function of their mean trophic level (T), and it increases with trophic level when Z ≥ 1 and decreases when Z ≤ 1 via this relationship (see Delmas et al 2017 and Williams et al 2007):\n\n$M_C = Z^(T-1)$\n\n[Brose et al 2006](https://onlinelibrary.wiley.com/doi/10.1111/j.1461-0248.2006.00978.x) explored the impact of the _PPMR_ on stability and dynamics as part of their wider exploration of scaling and allometry in the bioenergetic model. Here we show you how to manipulate `Z` and it's effect on stability. `Z` is specified in the call to FoodWeb as the allocation of species with specific sizes is central to the trophic structure of the model. This argument is interfaced with the bodysize vector in `model_parameters()`\n\n::: {#b1b7b1ce .cell execution_count=12}\n``` {.julia .cell-code}\nRandom.seed!(12352)\n\n# fixed parameters\nS = 20\nC = 0.15\n\n# set the PPRM\nz_levels= [0.1, 1, 10, 100]\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_z = DataFrame(z = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\n# create look across values of h\nfor z in z_levels \n println(\"***> This is iteration with z = $z\\n\")\n \n # make the network\n # Note that we specify the Environment, but there is no K or T set (using defaults)\n # Note Z is specified when building the FoodWeb() network\n fw_z = Foodweb(:niche; S = S, C = C)\n \n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_z, BodyMass(; Z = z))\n\n # specify number of time steps\n t = 300\n\n # simulate\n out_z = simulate(params, B0, t)\n\n # collect data \n fin_rich = richness(out_z)\n fin_bio = total_biomass(out_z)\n s_div = shannon_diversity(out_z)\n\n push!(df_collect_z, [z, fin_rich, fin_bio, s_div])\nend\n\ndf_collect_z\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n***> This is iteration with z = 0.1\n\n***> This is iteration with z = 1.0\n\n***> This is iteration with z = 10.0\n\n***> This is iteration with z = 100.0\n\n```\n:::\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n
4×4 DataFrame
RowzFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAny
10.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 14, 14, 14, 14, 14, 13, 13, 12, 12, 12][14.0154, 13.1242, 12.5054, 11.7867, 11.1144, 10.4411, 9.65219, 8.81407, 7.85734, 6.85837 … 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144][18.7295, 18.6017, 18.0408, 17.0915, 16.2886, 15.7357, 15.3028, 14.9264, 14.5273, 14.1848 … 9.01235, 9.01233, 9.01232, 9.01231, 9.01231, 9.01231, 9.01231, 9.01231, 9.0123, 9.0123]
21.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 19, 19, 17, 17, 16, 16, 16, 16, 16, 16][11.3827, 11.0237, 10.6428, 10.1558, 9.68492, 9.08034, 8.44996, 7.73821, 7.12812, 6.50964 … 4.04905, 4.04904, 4.04904, 4.04904, 4.04904, 4.04903, 4.04903, 4.04902, 4.04902, 4.04902][17.2879, 17.2885, 17.2049, 16.9595, 16.5593, 15.7827, 14.6068, 12.8519, 11.257, 9.97863 … 12.411, 12.411, 12.411, 12.411, 12.411, 12.4109, 12.4109, 12.4108, 12.4108, 12.4108]
310.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][7.95051, 7.71606, 7.43686, 7.21154, 7.03513, 6.86424, 6.73195, 6.58726, 6.478, 6.39076 … 6.19265, 6.19575, 6.19649, 6.19564, 6.19442, 6.19361, 6.19319, 6.19306, 6.19304, 6.19304][14.8364, 15.1738, 15.4241, 15.5023, 15.5318, 15.5827, 15.6634, 15.816, 15.987, 16.1622 … 17.1402, 17.1371, 17.1269, 17.1157, 17.1054, 17.0988, 17.0953, 17.0943, 17.0942, 17.0942]
4100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.38822, 8.25788, 8.10381, 7.99055, 7.9029, 7.81458, 7.76517, 7.70146, 7.67839, 7.69968 … 10.4944, 10.5011, 10.5112, 10.5238, 10.5387, 10.553, 10.5648, 10.5725, 10.5769, 10.5779][13.7108, 13.8452, 13.9135, 13.9026, 13.8919, 13.9322, 13.9969, 14.1639, 14.3154, 14.5913 … 12.0742, 12.1247, 12.1854, 12.2463, 12.3038, 12.3476, 12.3764, 12.3919, 12.3991, 12.4006]
\n```\n:::\n:::\n\n\nAs with the variation in `h`, we can create a set of figures too! Perhaps it's worth your time to consult [Brose et al 2006](https://onlinelibrary.wiley.com/doi/10.1111/j.1461-0248.2006.00978.x) and [Reger et al 2017](https://besjournals.onlinelibrary.wiley.com/doi/10.1111/2041-210X.12713) to make sure you understand how Z works and particularly how stability is expected to vary with Z! One of the most important things to understanding is why the stability metric is negative and what values of stability close, or far away, from zero mean.\n\n::: {#ab493d43 .cell execution_count=13}\n``` {.julia .cell-code}\n# Visualize the results\np1_z = @df df_collect_z plot(:z, [:FinalStability],\n legend = :bottomright,\n ylabel = \"Stability\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\np2_z = @df df_collect_z plot(:z, [:FinalBiomass],\n legend = :bottomright,\n ylabel = \"Biomass\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\np3_z = @df df_collect_z plot(:z, [:FinalRichness],\n legend = :bottomright,\n ylabel = \"Richness\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\nplot(p1_z, p2_z, p3_z, layout=(3,1), legend = false, size = (1000, 1000))\n```\n:::\n\n\n#### Challenge\n\nCould you modify this to ask about the interaction between Z and K? This would be asking the question of whether the effect of PPMR on stability varies by system productivity. Or you could ask about the interaction between the functional response, which we know also has a direct effect on stability by the assumption we make of a Type II or Type III shape, and the value of Z, which we also know impacts stability from Brose et al's work.\n\n### Experiment 4: Manipulating Competition among producers\n\nOur final experiment for this section involves manipulating how the basal producers compete with each other. The default paramterisation of the model has each producer growing via the logistic equation and competing with itself via density dependence. There is only intraspecific competition, no interspecific competition.\n\nWe can modify this assumption by invoking another function called `ProducerCompetition`. This function acts like `Environment` that we use to set `K` and `BioenergeticResponse` that we used to modify the functional response between Type II and Type III.\n\nThe theory to recall is that coexistence among species is mediated by the balance between intraspecific and interspecific competition. When intraspecific competition is greater than interspecific competition, there is coexistence. However, when interspecific competition is greater than intraspecific competition, there will be compeitive exclusion and no coexistence. \n\nWe call the competition parameters $\\alpha$. $\\alpha~ii$ defines intraspecific competition and $\\alpha~ij$ defines interspecific competition. The $\\alpha~ij$ defines how the species $j$ reduces the carrying capacity (equilibrium) of species $i$. \n\nWhat we can do is set $\\alpha~ii = 1$ and then vary $\\alpha~ij$ from $<1$ to $>1$. We can expect that there will a dramatic change in biomass and species richness as we move from $alpha~ii > alpha~ij$ to $alpha~ii < alpha~ij$.\n\n::: {#12de3283 .cell execution_count=14}\n``` {.julia .cell-code}\nS = 20 # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\nZ = 100 # Predator Prey Mass Ratio\n\n# here we set the \ninterspecific_vals = 0.8:0.05:1.2 # a set of (9) values between 0.8 and 1.2 in steps of 0.05\n# collect(0.8:0.05:1.2) # see them if you want to\n\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_comp = DataFrame(InterComp = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\nfor alpha_ij in interspecific_vals\n println(\"***> This is iteration with alpha_ij = $alpha_ij\\n\")\n \n # this will make always the same network and body mass\n Random.seed!(123)\n foodweb = Foodweb(:niche; S = S, C = C, Z = Z)\n\n # enhance detail in the network\n # specify K\n LogisticGrowth(foodweb; K = 10)\n # we fix intraspecific = 1 and vary interspecific\n ProducerCompetiton(foodweb; αii = 1.0, αij = 1)\n # set the hill exponent to 1 (type II Functional Response)\n BioenergeticResponse(foodweb, h = 1)\n\n # define parameters with extras\n params_comp = default_model(foodweb, BodyMass(; Z = z))\n\n # set bodymass\n B0 = rand(S)\n\n # simulate\n # note verbose = false ; remove this to see extinction detail for each sim\n out_comp = simulate(params_comp, B0, verbose = false)\n\n # generate stats and add to collector\n # collect data \n fin_rich = richness(out_comp)\n fin_bio = biomass(out_comp).total\n stab = community_cv(out_comp)\n\n push!(df_collect_comp, [alpha_ij, fin_rich, fin_bio, stab])\nend\n\ndf_collect_comp\n```\n:::\n\n\nLet's review the assumptions above. We've set the `Predator Prey Mass Ratio` to 100. We've set carrying capacity `K` to 10. We've set the functional response `h` value to 1, so it's a Type II functional response. Finally, we've set a range of interspecific competition to be 0.8 to 1.2 around the fixed intraspecific effect of 1.\n\n::: {#7d288b7a .cell execution_count=15}\n``` {.julia .cell-code}\np1 = @df df_collect_comp plot(:InterComp, [:FinalRichness],\n ylabel = \"Richness\",\n xlabel = \"alpha_ij\")\np2 = @df df_collect_comp plot(:InterComp, [:FinalBiomass],\n ylabel = \"Biomass\",\n xlabel = \"alpha_ij\")\np3 = @df df_collect_comp plot(:InterComp, [:FinalStability],\n ylabel = \"Stability\",\n xlabel = \"alpha_ij\")\n\nplot(p1, p2, p3, layout = (3,1), legend = false)\n```\n:::\n\n\n#### Challenge - Competition\n\nPerhaps consider expanding the code above to assess one of these?\n\nIs this pattern sensitive to specie richness?\nIs this pattern sensitive to the functional response?\nIs this pattern sensitive to the PPMR?\nIs this pattern sensitive to values of K?\n\n## Experiment 5: Multiple networks (replicates)\n\nTo Do: run S (3 values), C (3 values) and h (3 values) where there are 5 replicate networks per combination. Note we need 45 networks...\n\n", + "engine": "julia", + "markdown": "---\ntitle: \"Tutorial 10: Complex Experiments with the END\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nengine: julia\n---\n\n\n\n\n::: {.callout-caution}\n## Warning\n\nStability was replaced by Shannon diversity - need to review context as well as if we want that or rather re-integrate stability\n:::\n\nThe previous tutorial focused on experiments where we manipulated the number of networks and various network parameters. This is one set of things we can change/vary in an _in silico_ experiment. The other set of things we can change are features of the model, such as the shape of the functional response (see Tutorial 7), features of the environment such as the carrying capacity, or even empirical relationships that drive trophic structure and interaction strengths, such as the predator-prey mass ratio.\n\nIn this tutorial, we are going to implement three experiments. The first two will be 'simple' in that they vary only two things. The final example will implement a large experiment changing five features of the model.\n\nYou may want to start a new script in the project. We'll need the following packages (they are already installed... so we just need `using`).\n\n\n\n\n::: {#2 .cell execution_count=1}\n``` {.julia .cell-code}\nusing Random, Plots, Distributions, DataFrames, StatsPlots\nusing EcologicalNetworksDynamics\n```\n:::\n\n\n\n\n\n\n### Experiment 1: Carrying Capacity and the Predator Prey Mass Ratio\n\nNow we are set for our first experiment. Lets first establish the parameters we need to make the food web and do the experiment. We fix `S` at 20 and `C` at 0.15. We then create vectors of Z and K. \n\nZ is the predator - prey mass ratio, and defines how much bigger or smaller the predators are from their prey. The data suggest it is between predators are between 10 and 100 times bigger than their prey [see Brose et al 2006](https://doi.org/10.1890/0012-9658(2006)87[2411:CBRINF]2.0.CO;2). This value interacts with setting trophic levels in the model. \n\nThe default setting for the models is 1 - i.e. all species are within the same order of magnitude, predators are not bigger than their prey. Here, we create a vector of values to explore, from predators being smaller, to them being 10 or 100 x larger as the data suggests.\n\n\n\n\n\n::: {#4 .cell execution_count=1}\n``` {.julia .cell-code}\n#Fixed Parameters\nS = 20\nC = 0.15\n\n# Variable Parameters\nZ_levels = [0.1, 1, 10, 100]\nK_levels = [0.1, 1, 10, 100]\n\n# run this to get same results as in the document\nRandom.seed!(123)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\nTaskLocalRNG()\n```\n:::\n:::\n\n\n\n\n\n\nNow, lets set up the collecting data frame.\n\n\n\n\n::: {#6 .cell execution_count=1}\n``` {.julia .cell-code}\ndf_collect = DataFrame(Z = [], K = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
0×5 DataFrame
RowZKFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAnyAny
\n```\n:::\n:::\n\n\n\n\n\n\nNow, set up the loop to use these variables and generate outputs. Notice that we use `for z in Z_levels` - this is a clever trick of the looping method, where `z` simply iterates over the values of `Z_levels` without having to specify the index value (e.g. no use of `Z_levels[i]` etc).\n\nThe significant BIG thing here is the LogisticGrowth function which allows us to set things like the carrying capacity (K) of the resources. Here we use it to define custom values of the K paramter for carrying capacity, drawing on the values in the `K_levels` above. Here, `pg` stands for Producer Growth function, and the paramter set in the food web is K.\n\nNote too our use of `println` and the values of `Z` and `K` to produce an informative _break_ between each combination.\n\n::: {.callout-note icon=false}\n\nCan you guess what increasing K will do to the biomass and richness of the community at equilibrium? How about Z? Will higher Z make things more or less stable?\n:::\n\n\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\nfor z in Z_levels\n for k in K_levels\n\n println(\" ***> This is iteration with Z = $z and K = $k\\n\")\n\n # Define the food web\n fw = Foodweb(:niche; S = S, C = C)\n # specify the K value of the producer growth function\n\n B0 = rand(S)\n # specify model to simulate logistic growth as well as BM ratio\n params = default_model(fw, BodyMass(; Z = z), LogisticGrowth(; K = k))\n \n # number of timestamps\n t = 300\n\n out = simulate(params, B0, t)\n\n # calculate metrics\n fin_rich = richness(out)\n fin_biomass = total_biomass(out)\n s_div = shannon_diversity(out)\n\n push!(df_collect, [z, k, fin_rich, fin_biomass, s_div])\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n ***> This is iteration with Z = 0.1 and K = 0.1\n\n ***> This is iteration with Z = 0.1 and K = 1.0\n\n ***> This is iteration with Z = 0.1 and K = 10.0\n\n ***> This is iteration with Z = 0.1 and K = 100.0\n\n ***> This is iteration with Z = 1.0 and K = 0.1\n\n ***> This is iteration with Z = 1.0 and K = 1.0\n\n ***> This is iteration with Z = 1.0 and K = 10.0\n\n ***> This is iteration with Z = 1.0 and K = 100.0\n\n ***> This is iteration with Z = 10.0 and K = 0.1\n\n ***> This is iteration with Z = 10.0 and K = 1.0\n\n ***> This is iteration with Z = 10.0 and K = 10.0\n\n ***> This is iteration with Z = 10.0 and K = 100.0\n\n ***> This is iteration with Z = 100.0 and K = 0.1\n\n ***> This is iteration with Z = 100.0 and K = 1.0\n\n ***> This is iteration with Z = 100.0 and K = 10.0\n\n ***> This is iteration with Z = 100.0 and K = 100.0\n\n```\n:::\n:::\n\n\n\n\n\n\nWonderful. Now we are in a position to learn about two new plotting methods. First, let's look at the data frame we've created.\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\ndf_collect\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
16×5 DataFrame
RowZKFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAnyAny
10.10.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 5, 5, 5, 5, 5, 5, 5, 5, 5, 5][8.15104, 7.35599, 6.86766, 6.20173, 5.62064, 4.93607, 4.31825, 3.63121, 3.00669, 2.39632 … 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.3][16.6229, 16.7342, 16.5646, 16.1151, 15.6393, 15.1269, 14.7861, 14.5788, 14.548, 14.6324 … 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00005]
20.11.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 11, 11, 11, 11, 11, 11, 11, 11, 11, 11][12.4772, 11.4754, 10.7631, 9.95902, 9.14621, 8.41858, 7.61812, 6.84285, 6.08118, 5.33149 … 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616][17.742, 17.8484, 17.6835, 17.2513, 16.4331, 15.4516, 14.5648, 14.1409, 13.9903, 13.8445 … 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.38235]
30.110.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 13, 13, 13, 13, 13, 13, 13, 13, 13, 13][9.25026, 8.51092, 8.00559, 7.44123, 6.91671, 6.27631, 5.65377, 4.94222, 4.26539, 3.54824 … 2.25548, 2.2559, 2.25643, 2.25698, 2.25747, 2.25783, 2.25806, 2.25819, 2.25825, 2.25825][14.6862, 14.6468, 14.2896, 13.6899, 12.9845, 12.0663, 11.3051, 10.7473, 10.5693, 10.7805 … 9.57129, 9.59447, 9.62346, 9.6528, 9.67659, 9.69307, 9.70369, 9.71014, 9.71404, 9.71427]
40.1100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][11.7083, 11.0424, 10.5769, 9.93713, 9.4234, 8.80592, 8.23005, 7.54626, 6.97782, 6.26384 … 3.48233, 3.48295, 3.48399, 3.48495, 3.48596, 3.48667, 3.48716, 3.48743, 3.48757, 3.48759][18.2061, 17.7393, 17.1158, 15.8476, 14.5755, 13.1387, 12.2288, 11.7098, 11.6218, 11.8449 … 14.6644, 14.6766, 14.6955, 14.7124, 14.7303, 14.7429, 14.7523, 14.7579, 14.7612, 14.762]
51.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 14, 11, 11, 7, 7, 7, 7, 6, 6, 6][9.94865, 9.31694, 8.91556, 8.37917, 7.98085, 7.48504, 7.05457, 6.53892, 6.03007, 5.45877 … 0.599995, 0.599995, 0.600001, 0.600001, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6][16.9057, 16.7928, 16.5411, 15.9674, 15.4178, 14.6761, 13.9969, 13.1036, 12.1136, 10.9472 … 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0]
61.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 16, 16, 16, 16, 15, 15, 14, 14][8.18822, 7.87201, 7.51513, 7.09849, 6.67715, 6.24736, 5.77386, 5.30732, 4.78624, 4.26858 … 2.1041, 2.1036, 2.1036, 2.10339, 2.10338, 2.10338, 2.10338, 2.1034, 2.1034, 2.10341][17.8751, 17.9835, 17.9691, 17.7811, 17.4596, 17.0672, 16.6213, 16.2204, 15.8747, 15.676 … 9.70326, 9.70168, 9.70168, 9.70046, 9.7004, 9.7004, 9.7004, 9.70055, 9.70055, 9.70071]
71.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 18, 18, 18, 18, 17, 17, 17, 17, 17, 17][11.9214, 11.5912, 11.2096, 10.7345, 10.2291, 9.65051, 9.08087, 8.50293, 7.95285, 7.4397 … 12.5097, 12.5097, 12.5097, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098][17.7631, 17.8918, 17.8487, 17.5309, 16.9389, 15.9573, 14.662, 13.1789, 11.9185, 11.0675 … 4.62639, 4.61727, 4.60955, 4.60285, 4.60285, 4.59699, 4.59175, 4.58698, 4.58255, 4.57863]
81.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][9.81854, 9.78941, 9.7508, 9.70287, 9.63915, 9.53889, 9.36204, 9.09799, 8.78533, 8.50462 … 7.83776, 7.83881, 7.83874, 7.83824, 7.83785, 7.8378, 7.83791, 7.83792, 7.83791, 7.83792][15.8542, 15.9962, 16.1459, 16.2131, 16.1391, 15.9368, 15.6428, 15.2171, 14.6976, 14.3231 … 14.8658, 14.8748, 14.8756, 14.873, 14.8704, 14.8698, 14.8703, 14.8705, 14.8704, 14.8705]
910.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 13, 13, 12, 12, 10, 10, 10, 9, 9, 8][12.3589, 11.1366, 10.528, 9.73548, 9.28095, 8.70753, 8.38507, 7.92468, 7.6241, 7.16456 … 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7][17.9611, 18.047, 17.9192, 17.5077, 17.121, 16.4637, 16.0159, 15.3056, 14.8254, 14.13 … 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0]
1010.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 19, 19, 19, 19, 19, 19, 19, 19][8.42215, 8.20465, 7.99326, 7.76301, 7.53365, 7.30894, 7.04805, 6.82182, 6.50908, 6.21272 … 2.86069, 2.86431, 2.86431, 2.86744, 2.87126, 2.87422, 2.87704, 2.87913, 2.88089, 2.88177][15.0882, 15.2155, 15.2234, 15.0786, 14.8185, 14.5613, 14.3405, 14.2066, 14.0631, 13.9396 … 13.2383, 13.2133, 13.2133, 13.1887, 13.1531, 13.1189, 13.0773, 13.0366, 12.9906, 12.9603]
1110.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 17, 17, 17, 17, 16, 16, 16, 16][8.76005, 8.6219, 8.45014, 8.27291, 8.03749, 7.83254, 7.54527, 7.26893, 6.89872, 6.5367 … 4.352, 4.37513, 4.3948, 4.41157, 4.4259, 4.43803, 4.43803, 4.44812, 4.45638, 4.45893][16.3521, 16.3257, 16.2454, 16.1206, 15.8993, 15.6612, 15.275, 14.8714, 14.3179, 13.7872 … 5.58795, 5.46404, 5.36072, 5.2744, 5.20203, 5.14192, 5.14192, 5.09276, 5.0532, 5.04108]
1210.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.25211, 8.29101, 8.4592, 8.87757, 9.76632, 11.7568, 16.001, 25.5672, 46.8751, 88.1647 … 243.87, 243.868, 243.863, 243.857, 243.852, 243.848, 243.845, 243.843, 243.841, 243.84][15.4288, 15.4367, 15.3683, 14.9952, 14.0388, 12.1209, 9.40314, 6.56688, 4.55697, 3.55452 … 6.58682, 6.58612, 6.58472, 6.58295, 6.58118, 6.57958, 6.57821, 6.57708, 6.57618, 6.57556]
13100.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 19, 19, 18, 18, 18, 18, 18, 18, 18, 18][11.5095, 10.9511, 10.7168, 10.3916, 10.2152, 9.9237, 9.78424, 9.46529, 9.30356, 8.92472 … 0.472889, 0.463688, 0.463688, 0.455691, 0.448684, 0.442486, 0.436958, 0.431991, 0.427513, 0.425609][17.231, 17.3743, 17.335, 17.1761, 17.0496, 16.8121, 16.6962, 16.4432, 16.324, 16.0738 … 5.95521, 5.74108, 5.74108, 5.5499, 5.37858, 5.22417, 5.08415, 4.95644, 4.83969, 4.78959]
14100.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.94845, 8.84267, 8.70565, 8.58269, 8.46112, 8.33459, 8.2076, 8.07545, 7.93311, 7.80568 … 8.84776, 8.83373, 8.82279, 8.81646, 8.81702, 8.82562, 8.83778, 8.84947, 8.8573, 8.85948][16.8594, 16.831, 16.7339, 16.6093, 16.4917, 16.4208, 16.4238, 16.5015, 16.6608, 16.8785 … 11.6325, 11.5115, 11.4211, 11.3514, 11.3021, 11.2653, 11.2375, 11.2081, 11.1754, 11.1534]
15100.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][9.0416, 9.1737, 9.5697, 10.2502, 11.3574, 13.2685, 16.0394, 20.0685, 25.3442, 31.3042 … 79.4917, 79.5051, 79.498, 79.4849, 79.4774, 79.4781, 79.4801, 79.4797, 79.4785, 79.4782][15.9684, 16.1206, 16.4693, 16.7484, 16.6086, 15.5647, 13.7709, 11.8335, 10.3515, 9.58567 … 11.1015, 11.0926, 11.0865, 11.0856, 11.0869, 11.0872, 11.0863, 11.0855, 11.0854, 11.0854]
16100.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][11.5292, 11.6221, 11.8303, 12.2001, 12.9034, 14.2178, 16.6995, 21.3803, 29.102, 40.6004 … 466.619, 464.416, 463.06, 460.625, 457.236, 453.504, 450.831, 452.672, 465.621, 471.999][18.3089, 18.2607, 18.15, 17.9446, 17.542, 16.8141, 15.6206, 13.9258, 12.0175, 9.86971 … 7.06769, 7.20399, 7.09213, 6.94422, 6.80881, 6.70295, 6.69553, 6.94315, 7.66919, 7.96389]
\n```\n:::\n:::\n\n\n\n\n\n\n#### Visualising the experiment\n\nOne option here is to plot one of our `Final` Objects as the response variable against the valuse of Z and K. In R, we'd use ggplot2. Here we'll use `StatsPlots` as we learned about in Tutorial 5. Can you make this work in the regular `Plots` syntax?\n\nLet's first look at a single plot of stability\n\n\n\n::: {#12 .cell execution_count=0}\n``` {.julia .cell-code}\n@df df_collect plot(:K, [:FinalStability], group = :Z, \n ylabel = \"Stabilty\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line],\n legend = false)\n```\n:::\n\n\n\n\n\n\nNow some new ploting tricks... 3 plots in a layout.\n\n\n\n\n::: {#14 .cell execution_count=0}\n``` {.julia .cell-code}\np1 = @df df_collect plot(:K, [:FinalStability], group = :Z, \n legend = :bottomright,\n ylabel = \"Stabilty\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n\np2 = @df df_collect plot(:K, [:FinalBiomass], group = :Z, \n legend = :bottomright,\n ylabel = \"Biomass\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n \np3 = @df df_collect plot(:K, [:FinalRichness], group = :Z, \n legend = :bottomright,\n ylabel = \"Richness\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n\n# create a layout of 3 graphs stacked on top of each other.\nplot(p1, p2, p3, layout=(3,1), legend = false)\n```\n:::\n\n\n\n\n\n\n### Interpretation!\n\n#### Challenge - can you get the number of extinctions into the data frame?\n\n### Experiment 2: The Functional Response\n\nThe functional response is the relationship between how much a consumer eats and the 'density' of the prey items. If you can recall from your ecology courses/classes/modules, there are three classic shapes: The Type I, Type II and Type III.\n\nA predator feeding with a Type I delivers to the prey a 'constant mortality rate' (the slope of the Type I line). This means that the effect of predation is density _independent_ because prey mortality rate does not vary by prey density. Remember, density dependence (negative feedback that stabilises communities) is defined by survival decreasing with increasing density, or in this case, mortality rates _increasing_ with increasing density.\n\nA predator feeding with the Type II delivers an _inverse density dependent_ mortality rate. The slope of the Type II line actually goes down as density of the prey goes up meaning that mortality rates for the prey, caused by the predator, are going down with prey density. This means that the effect of predation is _inverse density dependent_ in the Type II. This is **destabilising**.\n\nFinally, a predator feeding via a Type III can deliver a _density dependent_ mortality rate to the prey, but only at low prey densities. This is an S shaped curve. Below the inflection point, the slope is actually getting steeper. This means that as prey density increases up to the inflection, their mortality rate from predation increases (survival goes down with density going up). This is the hallmark of density dependence and can **stabilise** consumer-resource interactions.\n\n::: {.callout-tip icon=false}\n\nRemember that the logistic growth equation, with a carying capacity specified, is also a source of _density dependent negative feedback_\n:::\n\n::: {.callout-tip icon=false}\n\nThe Type II is the MOST common. Type I is rare and even non-existent because it suggests there are no limits to how much a consumer can eat. Type III is also rare, but it is at least plausible and interesting.\n:::\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\n\nf_t1(n) = 0.5*n\nf_t2(n) = 0.5*n/(0.2+0.01*n)\nf_t3(n) = 0.5*n^2/(10 + 0.01*n^2)\n\nplot(f_t1, 0, 100, label = \"Type I\")\nplot!(f_t2, 0, 100, label = \"Type II\")\nplot!(f_t3, 0, 100, label = \"Type III\")\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\n#### How does the BEFW make a functional response?\n\nThere are two formulations of the functional response. One of them is called the _Bioenergetic_ response and the other is called the _Classic_. In both cases, we ignore the Type I.\n\nThe Bioenergetic functional response is deeply phenomenological in that the parameters that make the shapes move between Type II and III have no deliberate biological interpretation. They function is defined by a 1/2 saturation point, an asymptote (which is nominally a maxiumum feeding rate) and an exponent, which is called the _hill exponent_. The value of the exponent moves the model from Type II (h = 1) to Type III (h = 2). The other variables define the overall shape.\n\nThe Classic functional less phenomenological in that the response is defined more by 'traits': the attack rate of a consumer on a prey and the handling time of that prey. But it also moves between the Type II and Type III shape based on an exponent.\n\n#### Creating Type II vs. Type III with the Bioenergetic response\n\nLet's look at using the Bioenergetic functional response, and see here how we can vary the shape between Type II and Type III. We can do this by modifying the *hill_exponent* after we have specified the model (*i.e.,* after the `default_model` call). We will look at how Richness, Biomass and Shannon Diversity are affected by the hill exponent.\n\n\n\n\n::: {#18 .cell execution_count=1}\n``` {.julia .cell-code}\n\nRandom.seed!(12352)\n\n# fixed parameters\nS = 20\nC = 0.15\n\n# set the hill exponent to move from Type II to Type III)\nh_levels = [1.0, 1.1, 1.25, 2.0]\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_h = DataFrame(h = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\n# create look across values of h\nfor h in h_levels \n println(\"***> This is iteration with h = $h\\n\")\n \n # make the network\n # Note that we specify the Environment, but there is no K or T set (using defaults)\n # Note the new BioenergeticResponse function\n fw_h = Foodweb(:niche; S = S, C = C)\n \n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_h)\n\n # here we now update the exponent of the hill function\n params.hill_exponent = h\n\n # specify number of time steps\n t = 300\n\n # simulate\n sim_niche = simulate(params, B0, t)\n\n # collect data \n fin_rich = richness(sim_niche)\n fin_bio = total_biomass(sim_niche)\n s_div = shannon_diversity(sim_niche)\n\n push!(df_collect_h, [h, fin_rich, fin_bio, s_div])\nend\n\ndf_collect_h\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n***> This is iteration with h = 1.0\n\n***> This is iteration with h = 1.1\n\n***> This is iteration with h = 1.25\n\n***> This is iteration with h = 2.0\n\n```\n:::\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
4×4 DataFrame
RowhFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAny
11.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 16, 16, 15, 15, 15, 15, 15, 15, 15, 15][14.0154, 13.7814, 13.4658, 13.1783, 12.8834, 12.6007, 12.3015, 11.9503, 11.7107, 11.4361 … 6.42979, 6.44208, 6.44208, 6.44436, 6.43148, 6.44421, 6.44068, 6.43311, 6.44545, 6.44344][18.7295, 18.6847, 18.5806, 18.4524, 18.2893, 18.0832, 17.7706, 17.2078, 16.6571, 15.8173 … 7.82943, 7.8319, 7.8319, 7.84614, 7.82841, 7.83428, 7.84109, 7.82605, 7.83731, 7.84078]
21.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 17, 17, 17, 17, 16, 16, 16, 16][11.3827, 11.1345, 10.7624, 10.3913, 9.99559, 9.59857, 9.16844, 8.74251, 8.37833, 8.02815 … 5.77289, 5.7729, 5.77293, 5.77292, 5.7729, 5.77291, 5.77291, 5.77291, 5.77291, 5.77291][17.2879, 17.2245, 17.0354, 16.7364, 16.3009, 15.7385, 14.957, 13.9498, 12.8428, 11.4674 … 8.05783, 8.05797, 8.05789, 8.05783, 8.0578, 8.05778, 8.05778, 8.05775, 8.05773, 8.05772]
31.25[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][7.95051, 7.71008, 7.36973, 7.05915, 6.81253, 6.60547, 6.33242, 6.20856, 5.90247, 5.79213 … 5.73092, 5.7267, 5.72288, 5.71981, 5.71723, 5.71558, 5.71443, 5.71385, 5.71357, 5.71354][14.8364, 15.0814, 15.2094, 15.0455, 14.7772, 14.5307, 14.2246, 14.1041, 13.874, 13.816 … 12.4849, 12.445, 12.4101, 12.3868, 12.3692, 12.3593, 12.3531, 12.3504, 12.3493, 12.3492]
42.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.38822, 8.15315, 7.90496, 7.74148, 7.54947, 7.42629, 7.21904, 7.06338, 6.82622, 6.62508 … 5.63687, 5.63973, 5.64247, 5.64441, 5.64568, 5.64631, 5.64656, 5.64657, 5.64648, 5.64641][13.7108, 13.8974, 13.9356, 13.9101, 13.8971, 13.9043, 13.9225, 13.9274, 13.9095, 13.8705 … 13.7105, 13.7429, 13.7652, 13.7748, 13.7762, 13.7723, 13.7654, 13.7572, 13.7488, 13.7434]
\n```\n:::\n:::\n\n\n\n\n\n\nNow, we can visualise these data\n\n\n\n\n::: {#20 .cell execution_count=0}\n``` {.julia .cell-code}\n# Visualize the results\np1_h = @df df_collect_h plot(:h, [:FinalStability],\n legend = :bottomright,\n ylabel = \"Stability\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\np2_h = @df df_collect_h plot(:h, [:FinalBiomass],\n legend = :bottomright,\n ylabel = \"Biomass\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\np3_h = @df df_collect_h plot(:h, [:FinalRichness],\n legend = :bottomright,\n ylabel = \"Richness\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\nplot(p1_h, p2_h, p3_h, layout=(3,1), legend = false, size = (1000, 1000))\n```\n:::\n\n\n\n\n\n\n#### INTERPRETATION?\n\nWhat can you see happening as we move away from the destabilising Type II functional response?\n\nCan you modify this code to explore what happens at different values of K? You'll need to modify this section, and the collection data frame.\n\n\n\n\n::: {#22 .cell execution_count=0}\n``` {.julia .cell-code}\n # make the network\n fw_h = Foodweb(:niche; S = S, C = C)\n\n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_h, LogisticGrowth(; K = k))\n\n # update the exponent of the hill function\n params.hill_exponent = h\n```\n:::\n\n\n\n\n\n\n### Experiment 3: What is Z\n\nOne of the central features of the link between the Bioenergetic Food Web model and the structure of a foodweb created by models like the Niche Model is the organisation of trophic levels. At the heart of this is a _data driven_ assumption about the ratio of predator size to prey size. This is called the _Predator Prey Mass Ratio_, or `PPMR` for short. \n\nIn 2006, Uli Brose and team collated hundreds of data [to reveal that](https://esajournals.onlinelibrary.wiley.com/doi/10.1890/0012-9658%282006%2987%5B2411%3ACBRINF%5D2.0.CO%3B2), on average, predators were between 10 and 100x bigger than their prey.\n\nIn our modelling framework, we use this ratio to help organise species into trophic levels. This is done by organising the bodymass vector, and via a parameter called `Z`. The body mass of consumers is a function of their mean trophic level (T), and it increases with trophic level when Z ≥ 1 and decreases when Z ≤ 1 via this relationship (see Delmas et al 2017 and Williams et al 2007):\n\n$M_C = Z^(T-1)$\n\n[Brose et al 2006](https://onlinelibrary.wiley.com/doi/10.1111/j.1461-0248.2006.00978.x) explored the impact of the _PPMR_ on stability and dynamics as part of their wider exploration of scaling and allometry in the bioenergetic model. Here we show you how to manipulate `Z` and it's effect on stability. `Z` is specified in the call to FoodWeb as the allocation of species with specific sizes is central to the trophic structure of the model. This argument is interfaced with the bodysize vector in `model_parameters()`\n\n\n\n\n::: {#24 .cell execution_count=1}\n``` {.julia .cell-code}\nRandom.seed!(12352)\n\n# fixed parameters\nS = 20\nC = 0.15\n\n# set the PPRM\nz_levels= [0.1, 1, 10, 100]\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_z = DataFrame(z = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\n# create look across values of h\nfor z in z_levels \n println(\"***> This is iteration with z = $z\\n\")\n \n # make the network\n # Note that we specify the Environment, but there is no K or T set (using defaults)\n # Note Z is specified when building the FoodWeb() network\n fw_z = Foodweb(:niche; S = S, C = C)\n \n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_z, BodyMass(; Z = z))\n\n # specify number of time steps\n t = 300\n\n # simulate\n out_z = simulate(params, B0, t)\n\n # collect data \n fin_rich = richness(out_z)\n fin_bio = total_biomass(out_z)\n s_div = shannon_diversity(out_z)\n\n push!(df_collect_z, [z, fin_rich, fin_bio, s_div])\nend\n\ndf_collect_z\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n***> This is iteration with z = 0.1\n\n***> This is iteration with z = 1.0\n\n***> This is iteration with z = 10.0\n\n***> This is iteration with z = 100.0\n\n```\n:::\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
4×4 DataFrame
RowzFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAny
10.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 14, 14, 14, 14, 14, 13, 13, 12, 12, 12][14.0154, 13.1242, 12.5054, 11.7867, 11.1144, 10.4411, 9.65219, 8.81407, 7.85734, 6.85837 … 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144][18.7295, 18.6017, 18.0408, 17.0915, 16.2886, 15.7357, 15.3028, 14.9264, 14.5273, 14.1848 … 9.01235, 9.01233, 9.01232, 9.01231, 9.01231, 9.01231, 9.01231, 9.01231, 9.0123, 9.0123]
21.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 19, 19, 17, 17, 16, 16, 16, 16, 16, 16][11.3827, 11.0237, 10.6428, 10.1558, 9.68492, 9.08034, 8.44996, 7.73821, 7.12812, 6.50964 … 4.04905, 4.04904, 4.04904, 4.04904, 4.04904, 4.04903, 4.04903, 4.04902, 4.04902, 4.04902][17.2879, 17.2885, 17.2049, 16.9595, 16.5593, 15.7827, 14.6068, 12.8519, 11.257, 9.97863 … 12.411, 12.411, 12.411, 12.411, 12.411, 12.4109, 12.4109, 12.4108, 12.4108, 12.4108]
310.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][7.95051, 7.71606, 7.43686, 7.21154, 7.03513, 6.86424, 6.73195, 6.58726, 6.478, 6.39076 … 6.19265, 6.19575, 6.19649, 6.19564, 6.19442, 6.19361, 6.19319, 6.19306, 6.19304, 6.19304][14.8364, 15.1738, 15.4241, 15.5023, 15.5318, 15.5827, 15.6634, 15.816, 15.987, 16.1622 … 17.1402, 17.1371, 17.1269, 17.1157, 17.1054, 17.0988, 17.0953, 17.0943, 17.0942, 17.0942]
4100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.38822, 8.25788, 8.10381, 7.99055, 7.9029, 7.81458, 7.76517, 7.70146, 7.67839, 7.69968 … 10.4944, 10.5011, 10.5112, 10.5238, 10.5387, 10.553, 10.5648, 10.5725, 10.5769, 10.5779][13.7108, 13.8452, 13.9135, 13.9026, 13.8919, 13.9322, 13.9969, 14.1639, 14.3154, 14.5913 … 12.0742, 12.1247, 12.1854, 12.2463, 12.3038, 12.3476, 12.3764, 12.3919, 12.3991, 12.4006]
\n```\n:::\n:::\n\n\n\n\n\n\nAs with the variation in `h`, we can create a set of figures too! Perhaps it's worth your time to consult [Brose et al 2006](https://onlinelibrary.wiley.com/doi/10.1111/j.1461-0248.2006.00978.x) and [Reger et al 2017](https://besjournals.onlinelibrary.wiley.com/doi/10.1111/2041-210X.12713) to make sure you understand how Z works and particularly how stability is expected to vary with Z! One of the most important things to understanding is why the stability metric is negative and what values of stability close, or far away, from zero mean.\n\n\n\n\n::: {#26 .cell execution_count=0}\n``` {.julia .cell-code}\n# Visualize the results\np1_z = @df df_collect_z plot(:z, [:FinalStability],\n legend = :bottomright,\n ylabel = \"Stability\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\np2_z = @df df_collect_z plot(:z, [:FinalBiomass],\n legend = :bottomright,\n ylabel = \"Biomass\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\np3_z = @df df_collect_z plot(:z, [:FinalRichness],\n legend = :bottomright,\n ylabel = \"Richness\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\nplot(p1_z, p2_z, p3_z, layout=(3,1), legend = false, size = (1000, 1000))\n```\n:::\n\n\n\n\n\n\n#### Challenge\n\nCould you modify this to ask about the interaction between Z and K? This would be asking the question of whether the effect of PPMR on stability varies by system productivity. Or you could ask about the interaction between the functional response, which we know also has a direct effect on stability by the assumption we make of a Type II or Type III shape, and the value of Z, which we also know impacts stability from Brose et al's work.\n\n### Experiment 4: Manipulating Competition among producers\n\nOur final experiment for this section involves manipulating how the basal producers compete with each other. The default paramterisation of the model has each producer growing via the logistic equation and competing with itself via density dependence. There is only intraspecific competition, no interspecific competition.\n\nWe can modify this assumption by invoking another function called `ProducerCompetition`. This function acts like `Environment` that we use to set `K` and `BioenergeticResponse` that we used to modify the functional response between Type II and Type III.\n\nThe theory to recall is that coexistence among species is mediated by the balance between intraspecific and interspecific competition. When intraspecific competition is greater than interspecific competition, there is coexistence. However, when interspecific competition is greater than intraspecific competition, there will be compeitive exclusion and no coexistence. \n\nWe call the competition parameters $\\alpha$. $\\alpha~ii$ defines intraspecific competition and $\\alpha~ij$ defines interspecific competition. The $\\alpha~ij$ defines how the species $j$ reduces the carrying capacity (equilibrium) of species $i$. \n\nWhat we can do is set $\\alpha~ii = 1$ and then vary $\\alpha~ij$ from $<1$ to $>1$. We can expect that there will a dramatic change in biomass and species richness as we move from $alpha~ii > alpha~ij$ to $alpha~ii < alpha~ij$.\n\n\n\n\n\n::: {#28 .cell execution_count=0}\n``` {.julia .cell-code}\nS = 20 # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\nZ = 100 # Predator Prey Mass Ratio\n\n# here we set the \ninterspecific_vals = 0.8:0.05:1.2 # a set of (9) values between 0.8 and 1.2 in steps of 0.05\n# collect(0.8:0.05:1.2) # see them if you want to\n\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_comp = DataFrame(InterComp = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\nfor alpha_ij in interspecific_vals\n println(\"***> This is iteration with alpha_ij = $alpha_ij\\n\")\n \n # this will make always the same network and body mass\n Random.seed!(123)\n foodweb = Foodweb(:niche; S = S, C = C, Z = Z)\n\n # enhance detail in the network\n # specify K\n LogisticGrowth(foodweb; K = 10)\n # we fix intraspecific = 1 and vary interspecific\n ProducerCompetiton(foodweb; αii = 1.0, αij = 1)\n # set the hill exponent to 1 (type II Functional Response)\n BioenergeticResponse(foodweb, h = 1)\n\n # define parameters with extras\n params_comp = default_model(foodweb, BodyMass(; Z = z))\n\n # set bodymass\n B0 = rand(S)\n\n # simulate\n # note verbose = false ; remove this to see extinction detail for each sim\n out_comp = simulate(params_comp, B0, verbose = false)\n\n # generate stats and add to collector\n # collect data \n fin_rich = richness(out_comp)\n fin_bio = biomass(out_comp).total\n stab = community_cv(out_comp)\n\n push!(df_collect_comp, [alpha_ij, fin_rich, fin_bio, stab])\nend\n\ndf_collect_comp\n```\n:::\n\n\n\n\n\n\nLet's review the assumptions above. We've set the `Predator Prey Mass Ratio` to 100. We've set carrying capacity `K` to 10. We've set the functional response `h` value to 1, so it's a Type II functional response. Finally, we've set a range of interspecific competition to be 0.8 to 1.2 around the fixed intraspecific effect of 1.\n\n\n\n\n\n::: {#30 .cell execution_count=0}\n``` {.julia .cell-code}\np1 = @df df_collect_comp plot(:InterComp, [:FinalRichness],\n ylabel = \"Richness\",\n xlabel = \"alpha_ij\")\np2 = @df df_collect_comp plot(:InterComp, [:FinalBiomass],\n ylabel = \"Biomass\",\n xlabel = \"alpha_ij\")\np3 = @df df_collect_comp plot(:InterComp, [:FinalStability],\n ylabel = \"Stability\",\n xlabel = \"alpha_ij\")\n\nplot(p1, p2, p3, layout = (3,1), legend = false)\n```\n:::\n\n\n\n\n\n\n#### Challenge - Competition\n\nPerhaps consider expanding the code above to assess one of these?\n\nIs this pattern sensitive to specie richness?\nIs this pattern sensitive to the functional response?\nIs this pattern sensitive to the PPMR?\nIs this pattern sensitive to values of K?\n\n## Experiment 5: Multiple networks (replicates)\n\nTo Do: run S (3 values), C (3 values) and h (3 values) where there are 5 replicate networks per combination. Note we need 45 networks...\n\n", "supporting": [ "10_complex_experiments_end_files" ], diff --git a/_freeze/1_download_setup/execute-results/html.json b/_freeze/1_download_setup/execute-results/html.json index a26ba20..80c356f 100644 --- a/_freeze/1_download_setup/execute-results/html.json +++ b/_freeze/1_download_setup/execute-results/html.json @@ -2,7 +2,7 @@ "hash": "1c99d2294462e383472fc843d253e1f3", "result": { "engine": "julia", - "markdown": "---\ntitle: \"Tutorial 1: Downloads, Setups and Your First Project\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nengine: julia\n---\n\n\n\n\n\n\n## Downloading and Installing Julia and VSCode\n\n**Julia**\n\nNavigate to [this page](https://julialang.org/downloads/) and follow the platform-specific instructions to download and install Julia (we recommend installing the current stable release).\n\nDuring the installation process, you may be prompted to add Julia to the PATH, this box should be ticked.\n\n::: {.callout-tip collapse=\"true\"}\n## Using Juliaup\n\n[Juliaup](https://github.com/JuliaLang/juliaup) is an alternative platform to install and manage multiple versions of Julia you run on your computer. This is useful if you need to run different versions of Julia for different projects but probably not essential for a casual Julia user, although there is also something to be said about setting yourself up with the best toys on the market...\n::: \n\n**VSCode**\n\nNavigate to [this page](https://visualstudio.microsoft.com/) to download and install your platform specific Visual Studio Code (not Visual Studio or Visual Studio for Mac).\n\n## Setting Up VSCode to use Julia\n\nVS Code is a free source-code editor, allowing you to code in multiple coding languages all from a platform that is completely customisable to the user - think of it as a more language agnostic version of RStudio. This flexibility is great but it does mean that you need to spend time telling VS Code what it is you want to do and how. This is where extensions come in; extensions are higher level packages that permit the use of a given coding language like Julia, edit your themes and icons, provide helpful applications like spell checker or Bracket Pair Colorizer, and for adding your own [VS Code pets](https://tonybaloney.github.io/vscode-pets/usage) (a very important part of the VSCode experience).\n\nTo install Julia in VS Code do the following (you only need to do this once):\n\n1. open VS Code (you'll see the welcome page)\n2. navigate to the 'Marketplace' (5th symbol down in the activity bar - vertical panel on the lefthand side of the screen)\n\n![The Marketplace Button](Figs/VSCode_FirstView.png)\n\n3. search for Julia in the 'Search Extensions in Marketplace' search bar\n4. install `Julia`, this extension provides support for the Julia programming language and install `Julia Formatter`, this extension will help you write clean code that is easier to read\n\n![Selecting the Julia Language Support and Formatter](Figs/JuliaLangAndFormatter.png)\n\n## Making your first Julia project\n\nAs with working in R and RStudio, we advocate working in a contained project environment when using Julia. Each unique project may require a different setup (e.g. packages, package versions, working directories, data locations, etc.).\n\nTo set up a project in VS Code:\n\n1. Creating a folder at a location of your choosing (e.g. within your Documents folder). This can be on GoogleDrive, Dropbox or OneDrive. This is OK.\n\n2. Name the folder with relevant works. Here we will use `Julia - VS code - how to`.\n\n3. Navigate to VSCode and open your new project by clicking on the 'Explorer' symbol (top left symbol on the activity bar) and click Open Folder and navigate your finder or explorer to the `Julia - VS code - how to` folder.\n\n - this folder becomes the working directory (same as when using an `.RProject` in R)\n\n![Opening Your Project](Figs/OpenProject.png)\n\n4. Create a new file (a script) in your directory: do this by using cmd-N (mac) or ctrl-N (windows) or File -\\> New File or by left clicking -\\> New File within the directory pane\n\n5. Name your script as your see fit but please remember to include the .jl file extension (e.g. JuliaTuto.jl). the .jl file extension tells VS Code you want to use the Julia programming language. To save your script at any time use cmd-S (MAC) OR ctrl-S (windows) or File \\> Save.\n\n - Note, you can also open a project in VS Code by right-clicking on your folder (in Finder, Windows file explorer or Linux nautilus) and selecting Open with -\\> Other -\\> VS Code.\n\n### Activating the REPL and running some code.\n\nThis sequence of figures aligns with the instructions below.\n\n![Initiating and using the REPL](Figs/UsingREPL.png)\n\nNow that you have an active project and a new script file you can open the Julia REPL. REPL stands for *read, execute, print and loop*. The REPL is like the console in R and is where the magic happens. In Eva's words, it's VS Code's way of using Julia for a brain.\n\nTo do this you type F1 or cmd/ctrl - shift-p or View -\\> Command Palette and choose Julia REPL. The command palette will appear as a drop down menu with a search function at the top of the page.\n\nNow that you have an interface with Julia as a brain, you can actually do something! Try this: type `print(\"Hello world\")` in the REPL and press Enter/Return. If you've done all of the above correctly, Hello world should print in the REPL.\n\nNow, you can also make a 'script'. Type ctrl-n or cmd-n and a document will open at the top. There will be a prompt/link to select your language. Click the link and, yes, search for and choose Julia.\n\nNext, type `print(\"Hello world\")` in the script. Just like RStudio, you can send the information in the script to the REPL. There are two ways to do this. First, and probably what you'll want, is shift-enter(return). This will send the line of code you are on, and move to the next line. ctrl-enter(return) submits the line but does not move the cursor. Try it!\n\n## Activating your project, the Project.toml and Manifest.toml\n\nWe mentioned above that it is good practice to work within an environment specific to each project. The Julia package manager (`Pkg`) allows you to do that easily: Unlike traditional package managers, which install and manage a single global set of packages, `Pkg` is designed around environments: independent sets of packages that can be local to an individual project or shared and selected by name (text taken directly from the documentation).\n\n### Getting started: activating your project.\n\nActivating your project is something that only needs doing once per computer. It allows you to add packages and dependencies to the project.\n\nIf you move the project to a new computer, or share the project, activation will be needed again.\n\nThere are two ways to activate your project.\n\n1. type `Pkg.activate(\".\")` in the REPL.\n2. type `]` in the REPL and then `activate .`\n\nThe `]` is a shorthand for using the `Pkg` package and opens the package manager. To get out of this, you press the `backspace/delete` button on your keyboard.\n\nThere are two ways to double check that you are actually working within your project:\n\n- check/click the 'Julia env:...' on the bottom of your screen (blue bar), it should match your project name\n\n- enter the package manager by typing `]` in the Julia REPL, you should see (your-project-name) pkg\\> instead of julia\\>. Again, exit the package manager using `backspace/delete` button.\n\n### Working with the package manager and growing the project and manifest files\n\nOnce your project is activated, there are two ways to use the package manager (Pkg):\n\n1. directly from the REPL:\n\n- navigate to the REPL\n- type `]`\n- you will see that instead of seeing julia\\> you now see (your-project-name) pkg\\>, indicating that all the packages that you now install (or update) will be installed (or updated) within this specific project\n- to add a package, use the function `add`: `] add Plots`\n\n2. using `Pkg` (this is useful when you want to install packages or manage them from within your script):\n\n- first type `import Pkg` and execute this line using shift-Enter\n- on subsequent lines, add, remove and update packages from your script using `Pkg` functions such as `Pkg.add()`, `Pkg.remove()` or `Pkg.update()`.\n- To add a packages, the name of the package need to be written with quotes (`Pkg.add(\"Plots\")`).\n\n#### An example using the Plots package\n\nNow that we are all set up, we are going to install a package, check the project's status and remove a package. As this might be your first time installing a package (e.g., Plots), don't be concerned if it takes a couple of minutes to run.\n\n- type `] add Plots` in the REPL (or `Pkg.add(\"Plots\")`) in your script and execute using Ctrl-Enter.\n - you just installed the Plots package and a whole bunch of dependencies that Plots needs to work. This is equivalent to Base plots in R.\n\n![Package Installing](Figs/Pkg.adding.png)\n\n- type `] st` in the REPL. This will check the status of your project and print the content of your Project.toml file, which is the list of main packages, in this case, just Plots.\n\nyou should see something like:\n\n![Package Status Check](Figs/StatusCheck.png)\n\n::: {.callout-tip}\n## Tip\n\nPackages can removed in the same way i.e. `] rm Plots` (or `Pkg.rm(\"Plots\")`) will remove the Plots package from your project environment (and its record in the Project.toml and Manifest.toml files)\n::: \n\n## Gearing up to Do More Stuff (what packages do I need).\n\nThere are a core set of packages we use for all of our work. These 10 packages are almost always installed when we make a project.\n\nGo ahead and use either the `]` or `Pkg.add(\"package.name\")` method to add all of these to your project.\n\n#### For working with data\n\n`CSV` `DataFrames` `DelimitedFiles`\n\n#### For plotting\n\n`Plots`\n\n#### For statistical things\n\n`Distributions` `Random` `Statistics` `StatsBase` `StatsPlots`\n\n#### For Modelling\n\n`DifferentialEquations`\n\n## Your first script setup.\n\nAt this stage, you should have a good understanding about how to create a project folder, activate a project, start the REPL, open a script and add packages to the project.\n\nNow you are ready to 'setup' your first script.\n\n1. create a new script file (ctrl-n or cmd-n).\n2. choose Julia as the language\n3. Type some informative information at the top of the script\n a. just like in R and other programming languages, the `#` is a commenter.\n4. The first section of your script is where you declare the packages you'll be using.\n a. the function to do this is `using`.\n b. make Plots, Random and DataFrames available.\n\nNow you are ready to do something really simple. Let's make some variables, data frames and a few simple plots.\n\nFirst, lets get the setup sorted and packages available\n\n\n\n\n::: {#4 .cell execution_count=1}\n``` {.julia .cell-code}\n# This is my first example script\n# 25 Jan 2023\n\n# packages I need\nusing DataFrames, Plots, Random, StatsPlots\n```\n:::\n\n\n\n\n\n\nSecond, let's make some variables and see how Julia prints them to the screen\n\n\n\n\n::: {#6 .cell execution_count=1}\n``` {.julia .cell-code}\n# make two variables using the rand function\n# because we are using random numbers, we'll set the seed here for reproducibility\n\nRandom.seed!(12345)\n\nx = rand(10)\ny = rand(10)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n10-element Vector{Float64}:\n 0.3302627700323072\n 0.4219866389257305\n 0.6853069230253171\n 0.29579983859112813\n 0.9736588395655787\n 0.24458973555203245\n 0.46875054050900267\n 0.27705458732580956\n 0.6299157011197652\n 0.12180466275080659\n```\n:::\n:::\n\n\n\n\n\n\nCool. Now, lets create two data frames, one made of the x and y variables, and another with three variables made directly in a call to `DataFrame`.\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\n# combine into a data frame using the DataFrame function\ndf = DataFrame(x = x, y = y)\ndf\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
10×2 DataFrame
Rowxy
Float64Float64
10.7918050.330263
20.1595790.421987
30.3341910.685307
40.8113920.2958
50.7966290.973659
60.9178140.24459
70.3113270.468751
80.7529060.277055
90.6338480.629916
100.8999510.121805
\n```\n:::\n:::\n\n\n\n\n\n\n...and the second\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\n# make a second data frame with three variables\n# using DataFrame directly to create variables\ndf2 = DataFrame(a=1:10, b=10*rand(10), c=10*rand(10))\ndf2\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
10×3 DataFrame
Rowabc
Int64Float64Float64
110.5634039.77384
227.226793.58869
330.4666423.76688
444.594899.03599
550.4911088.73964
666.991921.36299
771.581220.815793
884.707453.75399
994.975720.599761
10104.586752.14792
\n```\n:::\n:::\n\n\n\n\n\n\nGreat. Now, lets see how to plot the 'solo' variables. Note how we specify the `seriestype`. Try getting rid of this....\n\n\n\n\n::: {#12 .cell execution_count=1}\n``` {.julia .cell-code}\n# plot the data using x and y, as a scatterplot\nplot(x, y, seriestype=:scatter)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nSuperb. So, `StatsPlots` provides a special macro to use a dataframe with plots. It's a three step process:\n\n1. declare the `@df` macro\n2. define the data frame\n3. declare the columns, using the `:`\n\n\n\n\n::: {#14 .cell execution_count=1}\n``` {.julia .cell-code}\n# plot the data using the data frame macro\n# declare the df macro, declare the data frame, use : to signify columns\n@df df plot(:x, :y)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nAnd here, we use the df2, and plot variable b and c vs. a.\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\n# the same, and plotting two y variables\n@df df2 plot(:a, [:b, :c])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\n#### A quick briefing about data frames in Julia versus R and dplyr is here\n\n[DataFrames Comparison R dplyr](https://dataframes.juliadata.org/stable/man/comparisons/#Comparison-with-the-R-package-dplyr)\n\n", + "markdown": "---\ntitle: \"Tutorial 1: Downloads, Setups and Your First Project\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nengine: julia\n---\n\n\n\n\n\n\n## Downloading and Installing Julia and VSCode\n\n**Julia**\n\nNavigate to [this page](https://julialang.org/downloads/) and follow the platform-specific instructions to download and install Julia (we recommend installing the current stable release).\n\nDuring the installation process, you may be prompted to add Julia to the PATH, this box should be ticked.\n\n::: {.callout-tip collapse=\"true\"}\n## Using Juliaup\n\n[Juliaup](https://github.com/JuliaLang/juliaup) is an alternative platform to install and manage multiple versions of Julia you run on your computer. This is useful if you need to run different versions of Julia for different projects but probably not essential for a casual Julia user, although there is also something to be said about setting yourself up with the best toys on the market...\n::: \n\n**VSCode**\n\nNavigate to [this page](https://visualstudio.microsoft.com/) to download and install your platform specific Visual Studio Code (not Visual Studio or Visual Studio for Mac).\n\n## Setting Up VSCode to use Julia\n\nVS Code is a free source-code editor, allowing you to code in multiple coding languages all from a platform that is completely customisable to the user - think of it as a more language agnostic version of RStudio. This flexibility is great but it does mean that you need to spend time telling VS Code what it is you want to do and how. This is where extensions come in; extensions are higher level packages that permit the use of a given coding language like Julia, edit your themes and icons, provide helpful applications like spell checker or Bracket Pair Colorizer, and for adding your own [VS Code pets](https://tonybaloney.github.io/vscode-pets/usage) (a very important part of the VSCode experience).\n\nTo install Julia in VS Code do the following (you only need to do this once):\n\n1. open VS Code (you'll see the welcome page)\n2. navigate to the 'Marketplace' (5th symbol down in the activity bar - vertical panel on the lefthand side of the screen)\n\n![The Marketplace Button](Figs/VSCode_FirstView.png)\n\n3. search for Julia in the 'Search Extensions in Marketplace' search bar\n4. install `Julia`, this extension provides support for the Julia programming language and install `Julia Formatter`, this extension will help you write clean code that is easier to read\n\n![Selecting the Julia Language Support and Formatter](Figs/JuliaLangAndFormatter.png)\n\n## Making your first Julia project\n\nAs with working in R and RStudio, we advocate working in a contained project environment when using Julia. Each unique project may require a different setup (e.g. packages, package versions, working directories, data locations, etc.).\n\nTo set up a project in VS Code:\n\n1. Creating a folder at a location of your choosing (e.g. within your Documents folder). This can be on GoogleDrive, Dropbox or OneDrive. This is OK.\n\n2. Name the folder with relevant works. Here we will use `Julia - VS code - how to`.\n\n3. Navigate to VSCode and open your new project by clicking on the 'Explorer' symbol (top left symbol on the activity bar) and click Open Folder and navigate your finder or explorer to the `Julia - VS code - how to` folder.\n\n - this folder becomes the working directory (same as when using an `.RProject` in R)\n\n![Opening Your Project](Figs/OpenProject.png)\n\n4. Create a new file (a script) in your directory: do this by using cmd-N (mac) or ctrl-N (windows) or File -\\> New File or by left clicking -\\> New File within the directory pane\n\n5. Name your script as your see fit but please remember to include the .jl file extension (e.g. JuliaTuto.jl). the .jl file extension tells VS Code you want to use the Julia programming language. To save your script at any time use cmd-S (MAC) OR ctrl-S (windows) or File \\> Save.\n\n - Note, you can also open a project in VS Code by right-clicking on your folder (in Finder, Windows file explorer or Linux nautilus) and selecting Open with -\\> Other -\\> VS Code.\n\n### Activating the REPL and running some code.\n\nThis sequence of figures aligns with the instructions below.\n\n![Initiating and using the REPL](Figs/UsingREPL.png)\n\nNow that you have an active project and a new script file you can open the Julia REPL. REPL stands for *read, execute, print and loop*. The REPL is like the console in R and is where the magic happens. In Eva's words, it's VS Code's way of using Julia for a brain.\n\nTo do this you type F1 or cmd/ctrl - shift-p or View -\\> Command Palette and choose Julia REPL. The command palette will appear as a drop down menu with a search function at the top of the page.\n\nNow that you have an interface with Julia as a brain, you can actually do something! Try this: type `print(\"Hello world\")` in the REPL and press Enter/Return. If you've done all of the above correctly, Hello world should print in the REPL.\n\nNow, you can also make a 'script'. Type ctrl-n or cmd-n and a document will open at the top. There will be a prompt/link to select your language. Click the link and, yes, search for and choose Julia.\n\nNext, type `print(\"Hello world\")` in the script. Just like RStudio, you can send the information in the script to the REPL. There are two ways to do this. First, and probably what you'll want, is shift-enter(return). This will send the line of code you are on, and move to the next line. ctrl-enter(return) submits the line but does not move the cursor. Try it!\n\n## Activating your project, the Project.toml and Manifest.toml\n\nWe mentioned above that it is good practice to work within an environment specific to each project. The Julia package manager (`Pkg`) allows you to do that easily: Unlike traditional package managers, which install and manage a single global set of packages, `Pkg` is designed around environments: independent sets of packages that can be local to an individual project or shared and selected by name (text taken directly from the documentation).\n\n### Getting started: activating your project.\n\nActivating your project is something that only needs doing once per computer. It allows you to add packages and dependencies to the project.\n\nIf you move the project to a new computer, or share the project, activation will be needed again.\n\nThere are two ways to activate your project.\n\n1. type `Pkg.activate(\".\")` in the REPL.\n2. type `]` in the REPL and then `activate .`\n\nThe `]` is a shorthand for using the `Pkg` package and opens the package manager. To get out of this, you press the `backspace/delete` button on your keyboard.\n\nThere are two ways to double check that you are actually working within your project:\n\n- check/click the 'Julia env:...' on the bottom of your screen (blue bar), it should match your project name\n\n- enter the package manager by typing `]` in the Julia REPL, you should see (your-project-name) pkg\\> instead of julia\\>. Again, exit the package manager using `backspace/delete` button.\n\n### Working with the package manager and growing the project and manifest files\n\nOnce your project is activated, there are two ways to use the package manager (Pkg):\n\n1. directly from the REPL:\n\n- navigate to the REPL\n- type `]`\n- you will see that instead of seeing julia\\> you now see (your-project-name) pkg\\>, indicating that all the packages that you now install (or update) will be installed (or updated) within this specific project\n- to add a package, use the function `add`: `] add Plots`\n\n2. using `Pkg` (this is useful when you want to install packages or manage them from within your script):\n\n- first type `import Pkg` and execute this line using shift-Enter\n- on subsequent lines, add, remove and update packages from your script using `Pkg` functions such as `Pkg.add()`, `Pkg.remove()` or `Pkg.update()`.\n- To add a packages, the name of the package need to be written with quotes (`Pkg.add(\"Plots\")`).\n\n#### An example using the Plots package\n\nNow that we are all set up, we are going to install a package, check the project's status and remove a package. As this might be your first time installing a package (e.g., Plots), don't be concerned if it takes a couple of minutes to run.\n\n- type `] add Plots` in the REPL (or `Pkg.add(\"Plots\")`) in your script and execute using Ctrl-Enter.\n - you just installed the Plots package and a whole bunch of dependencies that Plots needs to work. This is equivalent to Base plots in R.\n\n![Package Installing](Figs/Pkg.adding.png)\n\n- type `] st` in the REPL. This will check the status of your project and print the content of your Project.toml file, which is the list of main packages, in this case, just Plots.\n\nyou should see something like:\n\n![Package Status Check](Figs/StatusCheck.png)\n\n::: {.callout-tip}\n## Tip\n\nPackages can removed in the same way i.e. `] rm Plots` (or `Pkg.rm(\"Plots\")`) will remove the Plots package from your project environment (and its record in the Project.toml and Manifest.toml files)\n::: \n\n## Gearing up to Do More Stuff (what packages do I need).\n\nThere are a core set of packages we use for all of our work. These 10 packages are almost always installed when we make a project.\n\nGo ahead and use either the `]` or `Pkg.add(\"package.name\")` method to add all of these to your project.\n\n#### For working with data\n\n`CSV` `DataFrames` `DelimitedFiles`\n\n#### For plotting\n\n`Plots`\n\n#### For statistical things\n\n`Distributions` `Random` `Statistics` `StatsBase` `StatsPlots`\n\n#### For Modelling\n\n`DifferentialEquations`\n\n## Your first script setup.\n\nAt this stage, you should have a good understanding about how to create a project folder, activate a project, start the REPL, open a script and add packages to the project.\n\nNow you are ready to 'setup' your first script.\n\n1. create a new script file (ctrl-n or cmd-n).\n2. choose Julia as the language\n3. Type some informative information at the top of the script\n a. just like in R and other programming languages, the `#` is a commenter.\n4. The first section of your script is where you declare the packages you'll be using.\n a. the function to do this is `using`.\n b. make Plots, Random and DataFrames available.\n\nNow you are ready to do something really simple. Let's make some variables, data frames and a few simple plots.\n\nFirst, lets get the setup sorted and packages available\n\n\n\n\n::: {#4 .cell execution_count=1}\n``` {.julia .cell-code}\n# This is my first example script\n# 25 Jan 2023\n\n# packages I need\nusing DataFrames, Plots, Random, StatsPlots\n```\n:::\n\n\n\n\n\n\nSecond, let's make some variables and see how Julia prints them to the screen\n\n\n\n\n::: {#6 .cell execution_count=1}\n``` {.julia .cell-code}\n# make two variables using the rand function\n# because we are using random numbers, we'll set the seed here for reproducibility\n\nRandom.seed!(12345)\n\nx = rand(10)\ny = rand(10)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n10-element Vector{Float64}:\n 0.3302627700323072\n 0.4219866389257305\n 0.6853069230253171\n 0.29579983859112813\n 0.9736588395655787\n 0.24458973555203245\n 0.46875054050900267\n 0.27705458732580956\n 0.6299157011197652\n 0.12180466275080659\n```\n:::\n:::\n\n\n\n\n\n\nCool. Now, lets create two data frames, one made of the x and y variables, and another with three variables made directly in a call to `DataFrame`.\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\n# combine into a data frame using the DataFrame function\ndf = DataFrame(x = x, y = y)\ndf\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
10×2 DataFrame
Rowxy
Float64Float64
10.7918050.330263
20.1595790.421987
30.3341910.685307
40.8113920.2958
50.7966290.973659
60.9178140.24459
70.3113270.468751
80.7529060.277055
90.6338480.629916
100.8999510.121805
\n```\n:::\n:::\n\n\n\n\n\n\n...and the second\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\n# make a second data frame with three variables\n# using DataFrame directly to create variables\ndf2 = DataFrame(a=1:10, b=10*rand(10), c=10*rand(10))\ndf2\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
10×3 DataFrame
Rowabc
Int64Float64Float64
110.5634039.77384
227.226793.58869
330.4666423.76688
444.594899.03599
550.4911088.73964
666.991921.36299
771.581220.815793
884.707453.75399
994.975720.599761
10104.586752.14792
\n```\n:::\n:::\n\n\n\n\n\n\nGreat. Now, lets see how to plot the 'solo' variables. Note how we specify the `seriestype`. Try getting rid of this....\n\n\n\n\n::: {#12 .cell execution_count=1}\n``` {.julia .cell-code}\n# plot the data using x and y, as a scatterplot\nplot(x, y, seriestype=:scatter)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nSuperb. So, `StatsPlots` provides a special macro to use a dataframe with plots. It's a three step process:\n\n1. declare the `@df` macro\n2. define the data frame\n3. declare the columns, using the `:`\n\n\n\n\n::: {#14 .cell execution_count=1}\n``` {.julia .cell-code}\n# plot the data using the data frame macro\n# declare the df macro, declare the data frame, use : to signify columns\n@df df plot(:x, :y)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nAnd here, we use the df2, and plot variable b and c vs. a.\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\n# the same, and plotting two y variables\n@df df2 plot(:a, [:b, :c])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\n#### A quick briefing about data frames in Julia versus R and dplyr is here\n\n[DataFrames Comparison R dplyr](https://dataframes.juliadata.org/stable/man/comparisons/#Comparison-with-the-R-package-dplyr)\n\n", "supporting": [ "1_download_setup_files/figure-html" ], diff --git a/_freeze/3_dataframes/execute-results/html.json b/_freeze/3_dataframes/execute-results/html.json index 82f43cf..4deb34a 100644 --- a/_freeze/3_dataframes/execute-results/html.json +++ b/_freeze/3_dataframes/execute-results/html.json @@ -1,8 +1,8 @@ { "hash": "b49fbf90a318b4daf526cbfb8677669a", "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 3: Building and Working with DataFrames\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\nWorking with vectors, arrays and matrices is important. But quite often, we want to collect high-dimension data (multiple variables) from our simulations and store them in a spreadsheet type format.\n\nAs you've seen in Tutorial 1, there are plotting macros (`@df`) within the `StatsPlots` package that allow us to work with data frame objects from the `DataFrames` package. A second benefit of the data frame object is that we can export it as a `csv` file and import this into **R** where we may prefer working on plotting and statistics.\n\nTo this end, here we will also introduce the `CSV` package, which is very handy for exporting DataFrame objects to csv files, and importing them as well, if you'd like.\n\n## The Data Frame\n\nTo initialise a dataframe you use the `DataFrame` function from the **DataFrames** package:\n\n::: {#011d701f .cell execution_count=2}\n``` {.julia .cell-code}\ndat = DataFrame(col1=[], col2=[], col3=[]) # we use [] to specify an empty column of any type and size.\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```{=html}\n
0×3 DataFrame
Rowcol1col2col3
AnyAnyAny
\n```\n:::\n:::\n\n\nAlternately, you can specify the data type for each column.\n\n::: {#3bf7ab60 .cell execution_count=3}\n``` {.julia .cell-code}\ndat1 = DataFrame(col1=Float64[], col2=Int64[], col3=Float64[])\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```{=html}\n
0×3 DataFrame
Rowcol1col2col3
Float64Int64Float64
\n```\n:::\n:::\n\n\nOf course, `col1` is not the only label you provide: variable names are super important and the conventions we use in **R** are also important here in **Julia**, e.g. `a_b` or `AaBa` but not `a b` (no spaces allowed) or `a.b` (because the (dot) `.` functions as an operator).\n\n::: {#094ed121 .cell execution_count=4}\n``` {.julia .cell-code}\n# provide informative column titles using:\ndat2 = DataFrame(species=[], size=[], rate=[])\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```{=html}\n
0×3 DataFrame
Rowspeciessizerate
AnyAnyAny
\n```\n:::\n:::\n\n\n### Allocating or adding data to a data frame.\n\nTo add data to a dataframe, we use the `push!` (read as push bang) command.\n\n::: {#06bed4d2 .cell execution_count=5}\n``` {.julia .cell-code}\nspecies = \"D.magna\"\nsize = 2.2\nrate = 4.2\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n4.2\n```\n:::\n:::\n\n\n::: {#cd389d2c .cell execution_count=6}\n``` {.julia .cell-code}\n# push!() arguments: data frame, data\npush!(dat2, [species, size, rate])\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n
1×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
\n```\n:::\n:::\n\n\nOf course, the `push!()` function can append data to the existing data frame. It is worth noting that `push!` can only append one row at a time. But since Julia is so good with loops (compared to R), this will make adding data to a dataframe really easy, and we'll learn how to do this in the next tutorial. What makes the `!` (bang) function very useful is that you can append (or remove, with `pop!()`) items to an object without having to assign it.\n\n::: {#94a38dec .cell execution_count=7}\n``` {.julia .cell-code}\nspecies2 = \"D.pulex\"\nsize2 = 1.8\nrate2 = 3.1\n\n# push!() arguments: data frame, data\npush!(dat2, [species2, size2, rate2])\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\n### Helper Functions for Data Frames\n\nYou can print data frames using `println`\n\n::: {#1c74f7cc .cell execution_count=8}\n``` {.julia .cell-code}\nprintln(dat2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n2×3 DataFrame\n Row │ species size rate \n │ Any Any Any \n─────┼─────────────────────\n 1 │ D.magna 2.2 4.2\n 2 │ D.pulex 1.8 3.1\n```\n:::\n:::\n\n\nThere are `first` and `last` function that are like `head` and `tail` in R and elsewhere, with a first argument the data frame and the second argument the number of rows.\n\n::: {#a4509d62 .cell execution_count=9}\n``` {.julia .cell-code}\nfirst(dat2, 2)\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\n::: {#87cce997 .cell execution_count=10}\n``` {.julia .cell-code}\nlast(dat2,2)\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\nAnd as we learned with matrices and arrays, the `[row, column]` method also works for data frames:\n\n::: {#f57213cf .cell execution_count=11}\n``` {.julia .cell-code}\ndat2[1,2]\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```\n2.2\n```\n:::\n:::\n\n\n::: {#65b22b88 .cell execution_count=12}\n``` {.julia .cell-code}\ndat2[1,:]\n```\n\n::: {.cell-output .cell-output-display execution_count=13}\n```{=html}\n
DataFrameRow (3 columns)
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
\n```\n:::\n:::\n\n\n::: {#65203455 .cell execution_count=13}\n``` {.julia .cell-code}\ndat2[:,3]\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```\n2-element Vector{Any}:\n 4.2\n 3.1\n```\n:::\n:::\n\n\n## The CSV\n\nAs with *R*, there are functions to read and write `.csv` files to and from dataframes. This makes interoperability with tools in R and standard data storage file formats easy.\n\nTo write our daphnia data to a csv file, we use a familiar syntax, but a function from the `CSV` package.\n\n::: {#1d08b765 .cell execution_count=14}\n``` {.julia .cell-code}\nCSV.write(\"daphniadata.csv\", dat2)\n```\n:::\n\n\nOf course, you can read files in using.... yes, `CSV.read`. Note the second argument declares the data to go into a data frame.\n\n::: {#08f50a8a .cell execution_count=15}\n``` {.julia .cell-code}\ndaph_in = CSV.read(\"betterDaphniaData.csv\", DataFrame)\n```\n:::\n\n\n", + "engine": "julia", + "markdown": "---\ntitle: \"Tutorial 3: Building and Working with DataFrames\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nengine: julia\n---\n\n\n\n\n\n\n\nWorking with vectors, arrays and matrices is important. But quite often, we want to collect high-dimension data (multiple variables) from our simulations and store them in a spreadsheet type format.\n\nAs you've seen in Tutorial 1, there are plotting macros (`@df`) within the `StatsPlots` package that allow us to work with data frame objects from the `DataFrames` package. A second benefit of the data frame object is that we can export it as a `csv` file and import this into **R** where we may prefer working on plotting and statistics.\n\nTo this end, here we will also introduce the `CSV` package, which is very handy for exporting DataFrame objects to csv files, and importing them as well, if you'd like.\n\n## The Data Frame\n\nTo initialise a dataframe you use the `DataFrame` function from the **DataFrames** package:\n\n\n\n\n::: {#4 .cell execution_count=1}\n``` {.julia .cell-code}\ndat = DataFrame(col1=[], col2=[], col3=[]) # we use [] to specify an empty column of any type and size.\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
0×3 DataFrame
Rowcol1col2col3
AnyAnyAny
\n```\n:::\n:::\n\n\n\n\n\n\nAlternately, you can specify the data type for each column.\n\n\n\n\n::: {#6 .cell execution_count=1}\n``` {.julia .cell-code}\ndat1 = DataFrame(col1=Float64[], col2=Int64[], col3=Float64[])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
0×3 DataFrame
Rowcol1col2col3
Float64Int64Float64
\n```\n:::\n:::\n\n\n\n\n\n\nOf course, `col1` is not the only label you provide: variable names are super important and the conventions we use in **R** are also important here in **Julia**, e.g. `a_b` or `AaBa` but not `a b` (no spaces allowed) or `a.b` (because the (dot) `.` functions as an operator).\n\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\n# provide informative column titles using:\ndat2 = DataFrame(species=[], size=[], rate=[])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
0×3 DataFrame
Rowspeciessizerate
AnyAnyAny
\n```\n:::\n:::\n\n\n\n\n\n\n### Allocating or adding data to a data frame.\n\nTo add data to a dataframe, we use the `push!` (read as push bang) command.\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\nspecies = \"D.magna\"\nsize = 2.2\nrate = 4.2\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n4.2\n```\n:::\n:::\n\n\n\n::: {#12 .cell execution_count=1}\n``` {.julia .cell-code}\n# push!() arguments: data frame, data\npush!(dat2, [species, size, rate])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
1×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
\n```\n:::\n:::\n\n\n\n\n\n\nOf course, the `push!()` function can append data to the existing data frame. It is worth noting that `push!` can only append one row at a time. But since Julia is so good with loops (compared to R), this will make adding data to a dataframe really easy, and we'll learn how to do this in the next tutorial. What makes the `!` (bang) function very useful is that you can append (or remove, with `pop!()`) items to an object without having to assign it.\n\n\n\n\n::: {#14 .cell execution_count=1}\n``` {.julia .cell-code}\nspecies2 = \"D.pulex\"\nsize2 = 1.8\nrate2 = 3.1\n\n# push!() arguments: data frame, data\npush!(dat2, [species2, size2, rate2])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\n\n\n\n\n### Helper Functions for Data Frames\n\nYou can print data frames using `println`\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\nprintln(dat2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n2×3 DataFrame\n Row │ species size rate \n │ Any Any Any \n─────┼─────────────────────\n 1 │ D.magna 2.2 4.2\n 2 │ D.pulex 1.8 3.1\n```\n:::\n:::\n\n\n\n\n\n\nThere are `first` and `last` function that are like `head` and `tail` in R and elsewhere, with a first argument the data frame and the second argument the number of rows.\n\n\n\n\n::: {#18 .cell execution_count=1}\n``` {.julia .cell-code}\nfirst(dat2, 2)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\n\n::: {#20 .cell execution_count=1}\n``` {.julia .cell-code}\nlast(dat2,2)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\n\n\n\n\nAnd as we learned with matrices and arrays, the `[row, column]` method also works for data frames:\n\n\n\n\n::: {#22 .cell execution_count=1}\n``` {.julia .cell-code}\ndat2[1,2]\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n2.2\n```\n:::\n:::\n\n\n\n::: {#24 .cell execution_count=1}\n``` {.julia .cell-code}\ndat2[1,:]\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
DataFrameRow (3 columns)
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
\n```\n:::\n:::\n\n\n\n::: {#26 .cell execution_count=1}\n``` {.julia .cell-code}\ndat2[:,3]\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n2-element Vector{Any}:\n 4.2\n 3.1\n```\n:::\n:::\n\n\n\n\n\n\n## The CSV\n\nAs with *R*, there are functions to read and write `.csv` files to and from dataframes. This makes interoperability with tools in R and standard data storage file formats easy.\n\nTo write our daphnia data to a csv file, we use a familiar syntax, but a function from the `CSV` package.\n\n\n\n\n::: {#28 .cell execution_count=0}\n``` {.julia .cell-code}\nCSV.write(\"daphniadata.csv\", dat2)\n```\n:::\n\n\n\n\n\n\nOf course, you can read files in using.... yes, `CSV.read`. Note the second argument declares the data to go into a data frame.\n\n\n\n\n::: {#30 .cell execution_count=0}\n``` {.julia .cell-code}\ndaph_in = CSV.read(\"betterDaphniaData.csv\", DataFrame)\n```\n:::\n\n\n", "supporting": [ "3_dataframes_files" ], diff --git a/_freeze/4_programming_basics/execute-results/html.json b/_freeze/4_programming_basics/execute-results/html.json index 7977122..ea23daf 100644 --- a/_freeze/4_programming_basics/execute-results/html.json +++ b/_freeze/4_programming_basics/execute-results/html.json @@ -1,8 +1,8 @@ { "hash": "29dc80507167ac398fe5a080edd87cd1", "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 4: The Basics of Programming\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\nThis section of the tutorials introduces programming basics, including the art of simple functions, positional arguments, keyword arguments, loops, if-else-break usage and continue-while usage.\n\nIt is important to note that if you have experience programming R, there is a major difference in Julia - the use of loops is very much advocated in Julia where as *vectorising* loops is advocated in R.\n\nBasically, we write loops in Julia. We try to avoid them in R, if we want speed.\n\n## Functions\n\nFunctions work exactly like they do in R, however, there are three fundamental differences:\n\n- there is no need for {} brackets (thank god)\n- indenting (Julia requires seperate parts of a function to be indented - don't worry, VS Code should do this for you)\n- scoping (we'll attempt to explain this later)\n- functions always start with the word `function` and end with the word `end`. \n-to store something that is calculated in a function, you use the `return` command.\n\nLet's begin with a simple function - adding 2 to any number\n\n::: {#a5cdedb0 .cell execution_count=2}\n``` {.julia .cell-code}\nfunction plus_two(x)\n return x+2\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\nplus_two (generic function with 1 method)\n```\n:::\n:::\n\n\nLet's use it now by providing an defining and x value, and asking for the function to return the new value.\n\n::: {#906252b4 .cell execution_count=3}\n``` {.julia .cell-code}\nx_in = 33\nx_out = plus_two(x_in)\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n35\n```\n:::\n:::\n\n\nBecause we've defined `x_out`, we can request it...\n\n::: {#9d0b4c78 .cell execution_count=4}\n``` {.julia .cell-code}\nx_out\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n35\n```\n:::\n:::\n\n\n### Positional Arguments\n\nAs in **R**, input variables for functions have a specified and fixed order unless they have a default value which is explicitly specified. For instance, we can build a function that measures body weight on different planets, but defaults to estimating weight on earth with a gravitational force of 9.81:\n\n::: {#a50bde03 .cell execution_count=5}\n``` {.julia .cell-code}\nfunction bodyweight(BW_earth, g = 9.81)\n # bw should be in kg.\n return BW_earth*g/9.81\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\nbodyweight (generic function with 2 methods)\n```\n:::\n:::\n\n\nNote that the function is called bodyweight, it requires in the first position a weight in kg on earth and then defaults to estimating weight on earth by using g = 9.81\n\n::: {#ecd04a3f .cell execution_count=6}\n``` {.julia .cell-code}\nbodyweight(75)\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```\n75.0\n```\n:::\n:::\n\n\nNow, if we want to estimate they same bodyweight on Mars, where gravity is 3.72, you can specify the g-value.\n\n::: {#14c0f2af .cell execution_count=7}\n``` {.julia .cell-code}\nbodyweight(75, 3.72)\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\n28.44036697247706\n```\n:::\n:::\n\n\n### Keyword Arguments\n\n::: {#8766f6a0 .cell execution_count=8}\n``` {.julia .cell-code}\n# function with keyword arguments:\n# here, b and d are fixed = 2\n# a is positional\n# c is a keyword argument\n# the addition of ; before c means that c is an keyword argument and can be specified in any order, but must be named\nfunction key_word(a, b=2; c, d=2) \n return a + b + c + d\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```\nkey_word (generic function with 2 methods)\n```\n:::\n:::\n\n\nHere we specify _position_ 1 (a) and that c = 3\n\n::: {#7abace53 .cell execution_count=9}\n``` {.julia .cell-code}\nkey_word(1, c = 3)\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n8\n```\n:::\n:::\n\n\nHere we specify c = 3, and then position 1\n\n::: {#b24ea224 .cell execution_count=10}\n``` {.julia .cell-code}\nkey_word(c=3, 1)\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```\n8\n```\n:::\n:::\n\n\nHere we specify position 1 (a), redefine position 2 (b = 6) and declare c = 7.\n\n::: {#8364ff96 .cell execution_count=11}\n``` {.julia .cell-code}\nkey_word(1, 6, c=7)\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```\n16\n```\n:::\n:::\n\n\nNote that this DOES NOT work, because we've failed to define c. (and or b)\n\n::: {#01261519 .cell execution_count=12}\n``` {.julia .cell-code}\nkey_word(1, 8, d=4)\n```\n\n::: {.cell-output .cell-output-error}\n```\nLoadError: UndefKeywordError: keyword argument `c` not assigned\nUndefKeywordError: keyword argument `c` not assigned\n\nStacktrace:\n [1] top-level scope\n @ In[13]:1\n```\n:::\n:::\n\n\nTo redefine d, you'd need to define c and d.\n\n::: {#9fa30e35 .cell execution_count=13}\n``` {.julia .cell-code}\nkey_word(1, c = 8, d = 4)\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```\n15\n```\n:::\n:::\n\n\n## Loops\n\n### For loops\nFor loops work by iterating over a specified range (e.g. 1-10) at specified intervals (e.g. 1,2,3...). For instance, we might use a for loop to fill an array:\n\n#### Filling an array\nTo fill an array, we first define an object as an array using `[]`. \n\n::: {#95566ac9 .cell execution_count=14}\n``` {.julia .cell-code}\nI_array = []\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```\nAny[]\n```\n:::\n:::\n\n\nLike with function, all loops start with `for` and end with `end`. Here we iteratively fill `I_array` with 1000 random selections of 1 or 2.\n\n::: {#77e67baf .cell execution_count=15}\n``` {.julia .cell-code}\n# for loop to fill an array:\nfor i in 1:1000\n # pick from the number 1 or 2 at random \n # for each i'th step\n for_test = rand((1,2)) \n # push! and store for_test in I_array2\n # Julia is smart enough to do this iteratively\n # you don't necessarily have to index by `[i]` like you might do in R\n push!(I_array, for_test) \nend\n```\n:::\n\n\nLet's look at I_array now\n\n::: {#8fa11196 .cell execution_count=16}\n``` {.julia .cell-code}\nI_array\n```\n\n::: {.cell-output .cell-output-display execution_count=17}\n```\n1000-element Vector{Any}:\n 2\n 1\n 2\n 2\n 1\n 1\n 2\n 2\n 2\n 2\n 2\n 1\n 1\n ⋮\n 1\n 1\n 1\n 1\n 1\n 1\n 2\n 2\n 2\n 1\n 1\n 2\n```\n:::\n:::\n\n\nLet's try something more complex, iterating over multiple indices\n\nA new storage container:\n\n::: {#78b373ff .cell execution_count=17}\n``` {.julia .cell-code}\ntab = []\n```\n\n::: {.cell-output .cell-output-display execution_count=18}\n```\nAny[]\n```\n:::\n:::\n\n\nNow, we fill the storage container with values of i, j and k. Can you tell which in which order this will happen? The first entry will be `[1,1,1]`. The second will be `[2,1,1]`. Do you understand why? Mess around to check.\n\n::: {#66b745cc .cell execution_count=18}\n``` {.julia .cell-code}\n# nested for loop to fill an array:\nfor k in 1:4\n for j in 1:3\n for i in 1:2\n append!(tab,[[i,j,k]]) # here we've use append! to allocate iteratively to the array as opposed to using push! - both work. \n end\n end\nend\n```\n:::\n\n\nLet's look...\n\n::: {#a15bceab .cell execution_count=19}\n``` {.julia .cell-code}\ntab\n```\n\n::: {.cell-output .cell-output-display execution_count=20}\n```\n24-element Vector{Any}:\n [1, 1, 1]\n [2, 1, 1]\n [1, 2, 1]\n [2, 2, 1]\n [1, 3, 1]\n [2, 3, 1]\n [1, 1, 2]\n [2, 1, 2]\n [1, 2, 2]\n [2, 2, 2]\n [1, 3, 2]\n [2, 3, 2]\n [1, 1, 3]\n [2, 1, 3]\n [1, 2, 3]\n [2, 2, 3]\n [1, 3, 3]\n [2, 3, 3]\n [1, 1, 4]\n [2, 1, 4]\n [1, 2, 4]\n [2, 2, 4]\n [1, 3, 4]\n [2, 3, 4]\n```\n:::\n:::\n\n\nWe can also allocate to a multiple dimensional matrix. When working with matrices, we can build them out of zeros and the replace the values.\n\nHere we start with a three dimensional array with 4 two x three matrices.\n\n::: {#a2794b31 .cell execution_count=20}\n``` {.julia .cell-code}\nthreeDmatrix = zeros(2,3,4)\n```\n\n::: {.cell-output .cell-output-display execution_count=21}\n```\n2×3×4 Array{Float64, 3}:\n[:, :, 1] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 2] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 3] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 4] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n```\n:::\n:::\n\n\nNow, let's do a nested loop again, but this time into the matrices. The element we are adding each iteration is the sum of i+j+k.\n\nCan you guess how this works?\n\n::: {#29a3be11 .cell execution_count=21}\n``` {.julia .cell-code}\nfor k in 1:4\n for j in 1:3\n for i in 1:2\n # note default is by column....\n # first element allocated is 1+1+1, then 2+1+1 and this is first col\n # then 1+2+1 and 2+2+1 into the second col\n # then 1+3+1 and 2+3+1 into the third col\n threeDmatrix[i,j,k] = i+j+k\n end\n end\nend\n```\n:::\n\n\n::: {#c65ebde3 .cell execution_count=22}\n``` {.julia .cell-code}\nthreeDmatrix\n```\n\n::: {.cell-output .cell-output-display execution_count=23}\n```\n2×3×4 Array{Float64, 3}:\n[:, :, 1] =\n 3.0 4.0 5.0\n 4.0 5.0 6.0\n\n[:, :, 2] =\n 4.0 5.0 6.0\n 5.0 6.0 7.0\n\n[:, :, 3] =\n 5.0 6.0 7.0\n 6.0 7.0 8.0\n\n[:, :, 4] =\n 6.0 7.0 8.0\n 7.0 8.0 9.0\n```\n:::\n:::\n\n\nFinally, note that we can use `println` to provide a basic marker what what is happening: we show two ways to do this in the code.\n\n::: {#7edbb0b5 .cell execution_count=23}\n``` {.julia .cell-code}\nfor k in 1:4\n for j in 1:3\n for i in 1:2\n #println(i,\"-\",j,\"-\",k) # multiple quotes\n println(\"$i-$j-$k\") # one quote, $ to grab variables\n \n # note default is by column....\n # first element allocated is 1+1+1, then 2+1+1 and this is first col\n # then 1+2+1 and 2+2+1 into the second col\n # then 1+3+1 and 2+3+1 into the third col\n threeDmatrix[i,j,k] = i+j+k\n end\n end\nend\n```\n:::\n\n\nAnd just for fun... this `println` trick can be handy for verbose tracking. Note how `person in unique(persons)` iterates and how you can embed a variable's value in a text string.\n\n::: {#d5efcf8c .cell execution_count=24}\n``` {.julia .cell-code}\npersons = [\"Alice\", \"Alice\", \"Bob\", \"Bob2\", \"Carl\", \"Dan\"]\n\nfor person in unique(persons)\n println(\"Hello $person\")\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nHello Alice\nHello Bob\nHello Bob2\nHello Carl\nHello Dan\n```\n:::\n:::\n\n\nThere are tons of different functions that can be helpful when building loops. Take a few minutes to look into the help files for `eachindex`, `eachcol`, `eachrow` and `enumerate`. They all provide slightly different ways of telling Julia how you want to loop over a problem. Also, remember that loops aren't just for allocation, they can also be very useful when doing calculations.\n\n### if, else, breaks\nWhen building a loop, it is often meaningful to stop or modify the looping process when a certain condition is met. For example, we can use the `break`, `if` and `else` statements to stop a for loop when i exceeds a given value (e.g. 10):\n\n::: {#022fdd69 .cell execution_count=25}\n``` {.julia .cell-code}\n# if and break:\nfor i in 1:100\n println(i) # print i\n if i >10\n break # stop the loop with i >10\n end \nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n```\n:::\n:::\n\n\n::: {#d18bb32a .cell execution_count=26}\n``` {.julia .cell-code}\n# this loop can be modified using an if-else statement:\n# even though we are iterating to 100, it stops at 10.\nfor j in 1:100\n if j >10\n break # stop the loop with i >10\n else\n crj = j^3\n println(\"J is = $j\") # print i\n println(\"The Cube of $j is $crj\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nJ is = 1\nThe Cube of 1 is 1\nJ is = 2\nThe Cube of 2 is 8\nJ is = 3\nThe Cube of 3 is 27\nJ is = 4\nThe Cube of 4 is 64\nJ is = 5\nThe Cube of 5 is 125\nJ is = 6\nThe Cube of 6 is 216\nJ is = 7\nThe Cube of 7 is 343\nJ is = 8\nThe Cube of 8 is 512\nJ is = 9\nThe Cube of 9 is 729\nJ is = 10\nThe Cube of 10 is 1000\n```\n:::\n:::\n\n\nYou'll notice that every statement requires it's own set of `for` and `end` points, and is indented as per Julia's requirements. `if` and `else` statements can be very useful when building experiments: for example we might want to stop simulating a network's dynamics if more than 50% of the species have gone extinct.\n\n### continue and while\n\n#### continue\nThe `continue` command is the opposite to `break` and can be useful when you want to skip an iteration but not stop the loop:\n\n::: {#246fc469 .cell execution_count=27}\n``` {.julia .cell-code}\nfor i in 1:30\n # this reads: is it false that i is a multiple of 3?\n if i % 3 == false\n continue # makes the loop skip iterations that are a multiple of 3\n else println(\"$i is not a multiple of 3\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n1 is not a multiple of 3\n2 is not a multiple of 3\n4 is not a multiple of 3\n5 is not a multiple of 3\n7 is not a multiple of 3\n8 is not a multiple of 3\n10 is not a multiple of 3\n11 is not a multiple of 3\n13 is not a multiple of 3\n14 is not a multiple of 3\n16 is not a multiple of 3\n17 is not a multiple of 3\n19 is not a multiple of 3\n20 is not a multiple of 3\n22 is not a multiple of 3\n23 is not a multiple of 3\n25 is not a multiple of 3\n26 is not a multiple of 3\n28 is not a multiple of 3\n29 is not a multiple of 3\n```\n:::\n:::\n\n\nCan you figure out what the code would be for keeping even numbers only? Note the change of logic from false above to true here.\n\n::: {#6069047a .cell execution_count=28}\n``` {.julia .cell-code}\nfor i in 1:10\n # where is it true that i is a multiple of 2?\n if i % 2 == true\n continue # makes the loop skip iterations that are odd\n else println(\"$i is even\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n2 is even\n4 is even\n6 is even\n8 is even\n10 is even\n```\n:::\n:::\n\n\n#### while\n\n`while` loops provide an alternative to `for` loops and allow you to iterate until a certain condition is met:\n\n::: {#81d29bdb .cell execution_count=29}\n``` {.julia .cell-code}\n# counter that is globally scoped (see next section)\n# testval -- try changing this to see how this global variable can be used in \n# the local process below\nglobal j=0\nglobal testval = 17\n\n# note that we started with j = 0!!!\n# justify a condition\nwhile(j10\n break # stop the loop with i >10\n end \nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n```\n:::\n:::\n\n\n\n::: {#52 .cell execution_count=1}\n``` {.julia .cell-code}\n# this loop can be modified using an if-else statement:\n# even though we are iterating to 100, it stops at 10.\nfor j in 1:100\n if j >10\n break # stop the loop with i >10\n else\n crj = j^3\n println(\"J is = $j\") # print i\n println(\"The Cube of $j is $crj\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nJ is = 1\nThe Cube of 1 is 1\nJ is = 2\nThe Cube of 2 is 8\nJ is = 3\nThe Cube of 3 is 27\nJ is = 4\nThe Cube of 4 is 64\nJ is = 5\nThe Cube of 5 is 125\nJ is = 6\nThe Cube of 6 is 216\nJ is = 7\nThe Cube of 7 is 343\nJ is = 8\nThe Cube of 8 is 512\nJ is = 9\nThe Cube of 9 is 729\nJ is = 10\nThe Cube of 10 is 1000\n```\n:::\n:::\n\n\n\n\n\n\nYou'll notice that every statement requires it's own set of `for` and `end` points, and is indented as per Julia's requirements. `if` and `else` statements can be very useful when building experiments: for example we might want to stop simulating a network's dynamics if more than 50% of the species have gone extinct.\n\n### continue and while\n\n#### continue\nThe `continue` command is the opposite to `break` and can be useful when you want to skip an iteration but not stop the loop:\n\n\n\n\n::: {#54 .cell execution_count=1}\n``` {.julia .cell-code}\nfor i in 1:30\n # this reads: is it false that i is a multiple of 3?\n if i % 3 == false\n continue # makes the loop skip iterations that are a multiple of 3\n else println(\"$i is not a multiple of 3\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n1 is not a multiple of 3\n2 is not a multiple of 3\n4 is not a multiple of 3\n5 is not a multiple of 3\n7 is not a multiple of 3\n8 is not a multiple of 3\n10 is not a multiple of 3\n11 is not a multiple of 3\n13 is not a multiple of 3\n14 is not a multiple of 3\n16 is not a multiple of 3\n17 is not a multiple of 3\n19 is not a multiple of 3\n20 is not a multiple of 3\n22 is not a multiple of 3\n23 is not a multiple of 3\n25 is not a multiple of 3\n26 is not a multiple of 3\n28 is not a multiple of 3\n29 is not a multiple of 3\n```\n:::\n:::\n\n\n\n\n\n\nCan you figure out what the code would be for keeping even numbers only? Note the change of logic from false above to true here.\n\n\n\n\n::: {#56 .cell execution_count=1}\n``` {.julia .cell-code}\nfor i in 1:10\n # where is it true that i is a multiple of 2?\n if i % 2 == true\n continue # makes the loop skip iterations that are odd\n else println(\"$i is even\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n2 is even\n4 is even\n6 is even\n8 is even\n10 is even\n```\n:::\n:::\n\n\n\n\n\n\n#### while\n\n`while` loops provide an alternative to `for` loops and allow you to iterate until a certain condition is met:\n\n\n\n\n::: {#58 .cell execution_count=1}\n``` {.julia .cell-code}\n# counter that is globally scoped (see next section)\n# testval -- try changing this to see how this global variable can be used in \n# the local process below\nglobal j=0\nglobal testval = 17\n\n# note that we started with j = 0!!!\n# justify a condition\nwhile(j\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nIf you want to add more data to a plot, the `plot!()` function is super valuable, and complemented by the `xlabel!()` and `ylabel!()` function to update the x-axis\n\n::: {#bdbaf98e .cell execution_count=3}\n``` {.julia .cell-code}\ny2 = rand(100) # another 100 randoms\nplot!(x, y2, label = \"less amazing\")\nxlabel!(\"time is not your friend\")\nylabel!(\"ooh la la la\")\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nRecall too that there is a `seriestype` argument to shift between the default line and, perhaps a scatterplot. Note that we can deliver both y and y2.\n\n::: {#981969a9 .cell execution_count=4}\n``` {.julia .cell-code}\nplot(x, y, seriestype = [:line,:scatter], markershape = :diamond, lc = :orange, mc = :black, msc = :orange, label = \"Y\")\nplot!(x, y2, seriestype = [:line,:scatter], markershape = :diamond, lc = :blue, mc = :black, msc = :blue, label = \"Y2\")\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n`mc` is for marker colour, `msc` is the colour of the line around the marker/shape and `lc` is for line colour.\n\nOf course, there is a `scatter()` plot function\n\n::: {#289a3555 .cell execution_count=5}\n``` {.julia .cell-code}\nscatter(x, y)\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n### Grouping Variables in Plots\n\nJulia's Plots.jl library does some basic work with grouping variables too, linking to key ideas about tidy data. Let's look at some sample data where we have 12 data points.\n\n::: {#4dbc53b3 .cell execution_count=6}\n``` {.julia .cell-code}\nsample_data = DataFrame([rand(12), repeat([\"Network_1\",\"Network_2\",\"Network_3\"],4)], [\"stability\", \"network\"])\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n
12×2 DataFrame
Rowstabilitynetwork
Float64String
10.0491108Network_1
20.699192Network_2
30.158122Network_3
40.470745Network_1
50.625568Network_2
60.997392Network_3
70.572846Network_1
80.580858Network_2
90.141685Network_3
100.764872Network_1
110.690545Network_2
120.137958Network_3
\n```\n:::\n:::\n\n\nPlotting the data, by group, is accomplished like this (note the use of the `.` to connect the dataframe to the variable name)\n\n::: {#0ccc33bc .cell execution_count=7}\n``` {.julia .cell-code}\nplot(sample_data.stability, group = sample_data.network)\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nThis is a pretty silly plot because the x-axis makes no sense. We might have wanted a bar-chart instead.\n\n::: {#f8705241 .cell execution_count=8}\n``` {.julia .cell-code}\ngroupedbar(sample_data.stability, group = sample_data.network)\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nWe'll see below how the package `StatsPlots` makes this easier and more flexible (a bit more like `{ggplot2}`).\n\n### Saving Plots\n\nPlots can be saved and outputted using savefig or by using an output marco (e.g. png or pdf). savefig saves the most recent plot (.png is default format) or you can name figures e.g., p1, and use that reference name to save the plot object at any time:\n\n::: {#d22bb1ca .cell execution_count=9}\n``` {.julia .cell-code}\n#not run\nsavefig(p1, \"path/to/file/p1.png\")\npng(p1, \"path/to/file/p1\")\npdf(p1, \"path/to/file/p1\")\n```\n:::\n\n\nOnce you've created a plot it can be viewed or reopened in VS Code by navigating to the Julia explorer: Julia workspace symbol in the activity bar (three circles) and clicking on the plot object (e.g., p1). We advise that you always name and assign your plots (e.g. p1, p2, etc). The Plots package also has it's own [tutorial](https://docs.juliaplots.org/latest/tutorial/) for plotting in Julia.\n\n\n## StatsPlots\n\nAs you saw in the Setup introduction, we can also use the StatsPlots package for plotting. This approach invokes a background macro that allows you to use the DataFrames structure to deliver nice plots.\n\n::: {#022a66e8 .cell execution_count=10}\n``` {.julia .cell-code}\n# make a second data frame with three variables\n# using DataFrame directly to create variables\ndf2 = DataFrame(a=1:10, b=10*rand(10), c=10*rand(10))\ndf2\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```{=html}\n
10×3 DataFrame
Rowabc
Int64Float64Float64
110.8157936.88707
223.753992.40944
339.760621.53078
449.964353.45292
554.19571.77534
668.545171.37223
777.833734.74956
888.69492.89649
995.101120.930789
10107.899568.68376
\n```\n:::\n:::\n\n\nThe use of the `@df` macro from StatsPlots is a three step process:\n\n1. declare the `@df` macro\n2. define the data frame\n3. declare the columns, using the `:` symbol.\n\n::: {#df26265a .cell execution_count=11}\n``` {.julia .cell-code}\n# plot the data using the data frame macro\n# declare the df macro, declare the data frame, use : to signify columns\n# note that the default is `x then y`.\n@df df2 plot(:a, :b)\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nOne of the handy things about the `@df` macro and `StatsPlots` is the ability to add two or more variables at once:\n\n::: {#dbf6e943 .cell execution_count=12}\n``` {.julia .cell-code}\n# the same, and plotting two y variables (b and c)\n@df df2 plot(:a, [:b, :c])\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nThere are several helper functions too. For example, instead of the `[[:b, :c]` approach to multiple columns, there is a `cols` argument.\n\n::: {#dc08a784 .cell execution_count=13}\n``` {.julia .cell-code}\n@df df2 plot(:a, cols(2:3), colour = [:red :blue])\n```\n\n::: {.cell-output .cell-output-display execution_count=13}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nFinally, coming back to the example above for plots using the `sample_data` dataframe with a grouping variable, we can see how `StatsPlots` mimics some of the faceting options and group options from `ggplot2`.\n\nFirst, the three groups in the same figure with an informative legend.\n\n::: {#5fa3bf3c .cell execution_count=14}\n``` {.julia .cell-code}\n@df sample_data plot(:stability, group = :network, legend = :topleft)\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nSecond, the same data but in three panels.\n\n::: {#0448074d .cell execution_count=15}\n``` {.julia .cell-code}\n@df sample_data plot(:stability, group = :network, layout = 3)\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nAnd following the standard `Plots.jl` example for grouped bars....\n\n::: {#6b03447f .cell execution_count=16}\n``` {.julia .cell-code}\n@df sample_data groupedbar(:stability, group = :network)\n```\n\n::: {.cell-output .cell-output-display execution_count=16}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n## Gadfly\n\nThere is a actively developed package called `Gadfly` which implements an interpretation of the `[ggplot2]` grammar of graphics. It has been finicky and unstable for us in the past, but you are welcome to try it. To use it, you need to install the package with the `] add Gadfly` first step, and then `using Gadfly` in the top of your script.\n\nA tutorial and set of examples can be found [here](http://gadflyjl.org/v0.5/tutorial.html)\n\n## Makie\n\nFinally Makie is another alternative to consider. It allows you to make very complex figure layout as well as 2D or 3D plots. Same as above to use this you'll need to first install the package - `] add Makie` and then call in you script with `using Makie`\n\nThe documentation can be found [here](https://docs.makie.org/stable/)\n\n", + "engine": "julia", + "markdown": "---\ntitle: \"Tutorial 5: Plotting in Julia\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nengine: julia\n---\n\n\n\n\n\n\n\nIn R, the plotting of data is either done in base R or via the `{ggplot2}` package. If you're a base R person, you'll probably feel more comfortable with the Plots package. Alternatively, if you prefer `{ggplot2}`, the StatsPlots and Gadfly package is the closest thing you'll find in Julia. We'll introduce both in the following sections.\n\nIt is worth noting that Julia is based on a 'Just in Time' compiler (or JIT) so the first time you call a function it needs to compile, and can take longer than expected. This is especially true when rendering a plot. Consequently, the first plot you make might take some time but it gets significantly faster after that.\n\n## Plots\n\nAs you saw in Tutorial 2, we can make plots out of variables very easily with the `plot` function.\n\n\n\n\n::: {#4 .cell execution_count=1}\n``` {.julia .cell-code}\nRandom.seed!(12345)\nx = 1:100\ny = rand(100)\n\n# label is for the legend/key\n# lw = linewidth\nplot(x, y, label = \"amazing\", title = \"not amazing\", lw = 3)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nIf you want to add more data to a plot, the `plot!()` function is super valuable, and complemented by the `xlabel!()` and `ylabel!()` function to update the x-axis\n\n\n\n\n::: {#6 .cell execution_count=1}\n``` {.julia .cell-code}\ny2 = rand(100) # another 100 randoms\nplot!(x, y2, label = \"less amazing\")\nxlabel!(\"time is not your friend\")\nylabel!(\"ooh la la la\")\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nRecall too that there is a `seriestype` argument to shift between the default line and, perhaps a scatterplot. Note that we can deliver both y and y2.\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\nplot(x, y, seriestype = [:line,:scatter], markershape = :diamond, lc = :orange, mc = :black, msc = :orange, label = \"Y\")\nplot!(x, y2, seriestype = [:line,:scatter], markershape = :diamond, lc = :blue, mc = :black, msc = :blue, label = \"Y2\")\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\n`mc` is for marker colour, `msc` is the colour of the line around the marker/shape and `lc` is for line colour.\n\nOf course, there is a `scatter()` plot function\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\nscatter(x, y)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\n### Grouping Variables in Plots\n\nJulia's Plots.jl library does some basic work with grouping variables too, linking to key ideas about tidy data. Let's look at some sample data where we have 12 data points.\n\n\n\n\n::: {#12 .cell execution_count=1}\n``` {.julia .cell-code}\nsample_data = DataFrame([rand(12), repeat([\"Network_1\",\"Network_2\",\"Network_3\"],4)], [\"stability\", \"network\"])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
12×2 DataFrame
Rowstabilitynetwork
Float64String
10.0491108Network_1
20.699192Network_2
30.158122Network_3
40.470745Network_1
50.625568Network_2
60.997392Network_3
70.572846Network_1
80.580858Network_2
90.141685Network_3
100.764872Network_1
110.690545Network_2
120.137958Network_3
\n```\n:::\n:::\n\n\n\n\n\n\nPlotting the data, by group, is accomplished like this (note the use of the `.` to connect the dataframe to the variable name)\n\n\n\n\n::: {#14 .cell execution_count=1}\n``` {.julia .cell-code}\nplot(sample_data.stability, group = sample_data.network)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nThis is a pretty silly plot because the x-axis makes no sense. We might have wanted a bar-chart instead.\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\ngroupedbar(sample_data.stability, group = sample_data.network)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nWe'll see below how the package `StatsPlots` makes this easier and more flexible (a bit more like `{ggplot2}`).\n\n### Saving Plots\n\nPlots can be saved and outputted using savefig or by using an output marco (e.g. png or pdf). savefig saves the most recent plot (.png is default format) or you can name figures e.g., p1, and use that reference name to save the plot object at any time:\n\n\n\n\n::: {#18 .cell execution_count=0}\n``` {.julia .cell-code}\n#not run\nsavefig(p1, \"path/to/file/p1.png\")\npng(p1, \"path/to/file/p1\")\npdf(p1, \"path/to/file/p1\")\n```\n:::\n\n\n\n\n\n\nOnce you've created a plot it can be viewed or reopened in VS Code by navigating to the Julia explorer: Julia workspace symbol in the activity bar (three circles) and clicking on the plot object (e.g., p1). We advise that you always name and assign your plots (e.g. p1, p2, etc). The Plots package also has it's own [tutorial](https://docs.juliaplots.org/latest/tutorial/) for plotting in Julia.\n\n\n## StatsPlots\n\nAs you saw in the Setup introduction, we can also use the StatsPlots package for plotting. This approach invokes a background macro that allows you to use the DataFrames structure to deliver nice plots.\n\n\n\n\n\n::: {#20 .cell execution_count=1}\n``` {.julia .cell-code}\n# make a second data frame with three variables\n# using DataFrame directly to create variables\ndf2 = DataFrame(a=1:10, b=10*rand(10), c=10*rand(10))\ndf2\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n
10×3 DataFrame
Rowabc
Int64Float64Float64
110.8157936.88707
223.753992.40944
339.760621.53078
449.964353.45292
554.19571.77534
668.545171.37223
777.833734.74956
888.69492.89649
995.101120.930789
10107.899568.68376
\n```\n:::\n:::\n\n\n\n\n\n\nThe use of the `@df` macro from StatsPlots is a three step process:\n\n1. declare the `@df` macro\n2. define the data frame\n3. declare the columns, using the `:` symbol.\n\n\n\n\n::: {#22 .cell execution_count=1}\n``` {.julia .cell-code}\n# plot the data using the data frame macro\n# declare the df macro, declare the data frame, use : to signify columns\n# note that the default is `x then y`.\n@df df2 plot(:a, :b)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nOne of the handy things about the `@df` macro and `StatsPlots` is the ability to add two or more variables at once:\n\n\n\n\n::: {#24 .cell execution_count=1}\n``` {.julia .cell-code}\n# the same, and plotting two y variables (b and c)\n@df df2 plot(:a, [:b, :c])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nThere are several helper functions too. For example, instead of the `[[:b, :c]` approach to multiple columns, there is a `cols` argument.\n\n\n\n\n::: {#26 .cell execution_count=1}\n``` {.julia .cell-code}\n@df df2 plot(:a, cols(2:3), colour = [:red :blue])\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nFinally, coming back to the example above for plots using the `sample_data` dataframe with a grouping variable, we can see how `StatsPlots` mimics some of the faceting options and group options from `ggplot2`.\n\nFirst, the three groups in the same figure with an informative legend.\n\n\n\n\n::: {#28 .cell execution_count=1}\n``` {.julia .cell-code}\n@df sample_data plot(:stability, group = :network, legend = :topleft)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nSecond, the same data but in three panels.\n\n\n\n\n::: {#30 .cell execution_count=1}\n``` {.julia .cell-code}\n@df sample_data plot(:stability, group = :network, layout = 3)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nAnd following the standard `Plots.jl` example for grouped bars....\n\n\n\n\n::: {#32 .cell execution_count=1}\n``` {.julia .cell-code}\n@df sample_data groupedbar(:stability, group = :network)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\n## Gadfly\n\nThere is a actively developed package called `Gadfly` which implements an interpretation of the `[ggplot2]` grammar of graphics. It has been finicky and unstable for us in the past, but you are welcome to try it. To use it, you need to install the package with the `] add Gadfly` first step, and then `using Gadfly` in the top of your script.\n\nA tutorial and set of examples can be found [here](http://gadflyjl.org/v0.5/tutorial.html)\n\n## Makie\n\nFinally Makie is another alternative to consider. It allows you to make very complex figure layout as well as 2D or 3D plots. Same as above to use this you'll need to first install the package - `] add Makie` and then call in you script with `using Makie`\n\nThe documentation can be found [here](https://docs.makie.org/stable/)\n\n", "supporting": [ "5_plotting_files" ], diff --git a/_freeze/6_tips_tricks/execute-results/html.json b/_freeze/6_tips_tricks/execute-results/html.json index c8ceb39..291240a 100644 --- a/_freeze/6_tips_tricks/execute-results/html.json +++ b/_freeze/6_tips_tricks/execute-results/html.json @@ -1,10 +1,10 @@ { "hash": "cbcfdfefbce0bf3adef7f5d448b9ca0d", "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 6: Extra Tips and Tricks\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\n\n\nSome quick tips that we've learnt the hard way...\n\n1. In the REPL, you can use the up arrow to scroll through past code\n2. You can even filter through your past code by typing the first letter of a line previously executed in the REPL. For example, try typing p in the REPL and using the up arrow to scroll through your code history, you should quickly find the last plot command you executed.\n3. Toggle word wrap via `View>Toggle Word Wrap` or `alt-Z`\n4. To interrupt Julia while it is running through code use `⌘`/`Ctrl` + `C`\n5. Red wavy line under code in your script = *error in code*\n6. Blue wavy line under code in your script = *possible error in code*\n7. Errors and possible errors can be viewed in the PROBLEMS section of the REPL\n8. You can view your current variables (similar to the top right hand panel in RStudio) by clicking on the Julia explorer: Julia workspace symbol in the activity bar (three circles). You can then look at them in more detail by clicking the sideways arrow (when allowed).\n9. The `copy` function in Julia does not behave as one intuitively expects and if you want to make changes to a copied item without altering the original use `deepcopy` instead\n\n::: {.callout-tip collapse=\"true\"}\n## COPYING versus DEEP COPYING\n\nJulia has a strange copying behaviour where if `a` = `b`, any change in `b` will automatically cause the same change in `a`. For example, let's make an array of three numbers:\n\n::: {#a9cf2886 .cell execution_count=1}\n``` {.julia .cell-code}\naa = [1,2,3]\n```\n\n::: {.cell-output .cell-output-display execution_count=2}\n```\n3-element Vector{Int64}:\n 1\n 2\n 3\n```\n:::\n:::\n\n\nHere we make a copy of `aa` and call it `bb`.\n\n::: {#1e19b4cb .cell execution_count=2}\n``` {.julia .cell-code}\nbb = aa\nprint(bb)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1, 2, 3]\n```\n:::\n:::\n\n\nNow, we replace the second element of `bb` with the value 41.\n\n::: {#f87b61e8 .cell execution_count=3}\n``` {.julia .cell-code}\nbb[2] = 41\nbb\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\nThe default behaviour of `=` in Julia is to *UPDATE* any copy of the array, so we see the same change in `aa`:\n\n::: {#43298253 .cell execution_count=4}\n``` {.julia .cell-code}\naa\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\nWhoa... that's not what we expect, though it's pretty cool. This approach is advantageous because it lets Julia save memory, however, it is not ideal.\n\nTo remedy this, and create copies that don't update their parent or other offspring, we can force c to be an independent copy of a using the `deepcopy` function:\n\n::: {#2747ad48 .cell execution_count=5}\n``` {.julia .cell-code}\ncc = deepcopy(aa)\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\n::: {#d21bedae .cell execution_count=6}\n``` {.julia .cell-code}\ncc[3] = 101\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```\n101\n```\n:::\n:::\n\n\nSee how only the third element of `cc` s changed but not `aa`?\n\n::: {#3dd3c4d1 .cell execution_count=7}\n``` {.julia .cell-code}\naa,cc\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\n([1, 41, 3], [1, 41, 101])\n```\n:::\n:::\n\n\n:::\n\n9. You can view a `.csv` or `.txt` file by clicking on a file name in the project directory (left panel) - this opens a viewing window. CSV's also have a built in 'Preview' mode - try using right click\\>Open Preview on a `.csv` file and check it out.\n\n10. Docstrings are a supplement to `#`-based comments for documenting your workflow. Basically, any string that appears just before an object will be interpreted as documenting it. When you use a docstring it is possible to call that description using help (`?` in the REPL) or hovering over the object in VSCode. This can be very useful when you start declaring variables or building your own functions.\n\n::: {.callout-tip collapse=\"true\"}\n## Docstrings\n\nBelow is an examle of a docstring for a global variable as well as how it would look for a function\n\n::: {#c88b9109 .cell execution_count=8}\n``` {.julia .cell-code}\n\"a wonderfully documented and described variable\"\nvar = 101\n```\n:::\n\n\nyou can (should) also do this with functions\n\n::: {#3fab715d .cell execution_count=9}\n``` {.julia .cell-code}\n\"\"\"\n _rategradient(∂X, ∂Y)\n\nReturns the rate of change in units of the values stored in the grid, and the\nangle of the change in wind direction, *i.e.* an angle of 180 means that the\nvalue is increasing *from* the south. When both ∂X and ∂Y are equal to 0, the\nangle is assumed to be 0.\n\"\"\"\nfunction _rategradient(∂X::T, ∂Y::T) where {T <: Number}\n if ∂X == ∂Y == 0.0\n return (0.0, 0.0)\n end\n m = sqrt(∂X^2 + ∂Y^2)\n Δ = ∂X >= 0.0 ? 0.0 : 180.0\n θ = rad2deg(atan(∂X, ∂Y)) + Δ\n θ = ∂X > 0.0 ? θ + 180.0 : θ\n return (m, θ)\nend\n```\n:::\n\n\n:::\n\n", + "engine": "julia", + "markdown": "---\ntitle: \"Tutorial 6: Extra Tips and Tricks\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nengine: julia\n---\n\n\n\n\nSome quick tips that we've learnt the hard way...\n\n1. In the REPL, you can use the up arrow to scroll through past code\n2. You can even filter through your past code by typing the first letter of a line previously executed in the REPL. For example, try typing p in the REPL and using the up arrow to scroll through your code history, you should quickly find the last plot command you executed.\n3. Toggle word wrap via `View>Toggle Word Wrap` or `alt-Z`\n4. To interrupt Julia while it is running through code use `⌘`/`Ctrl` + `C`\n5. Red wavy line under code in your script = *error in code*\n6. Blue wavy line under code in your script = *possible error in code*\n7. Errors and possible errors can be viewed in the PROBLEMS section of the REPL\n8. You can view your current variables (similar to the top right hand panel in RStudio) by clicking on the Julia explorer: Julia workspace symbol in the activity bar (three circles). You can then look at them in more detail by clicking the sideways arrow (when allowed).\n9. The `copy` function in Julia does not behave as one intuitively expects and if you want to make changes to a copied item without altering the original use `deepcopy` instead\n\n::: {.callout-tip collapse=\"true\"}\n## COPYING versus DEEP COPYING\n\nJulia has a strange copying behaviour where if `a` = `b`, any change in `b` will automatically cause the same change in `a`. For example, let's make an array of three numbers:\n\n\n\n\n::: {#2 .cell execution_count=1}\n``` {.julia .cell-code}\naa = [1,2,3]\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n3-element Vector{Int64}:\n 1\n 2\n 3\n```\n:::\n:::\n\n\n\n\n\n\nHere we make a copy of `aa` and call it `bb`.\n\n\n\n\n::: {#4 .cell execution_count=1}\n``` {.julia .cell-code}\nbb = aa\nprint(bb)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1, 2, 3]\n```\n:::\n:::\n\n\n\n\n\n\nNow, we replace the second element of `bb` with the value 41.\n\n\n\n\n::: {#6 .cell execution_count=1}\n``` {.julia .cell-code}\nbb[2] = 41\nbb\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\n\n\n\n\nThe default behaviour of `=` in Julia is to *UPDATE* any copy of the array, so we see the same change in `aa`:\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\naa\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\n\n\n\n\nWhoa... that's not what we expect, though it's pretty cool. This approach is advantageous because it lets Julia save memory, however, it is not ideal.\n\nTo remedy this, and create copies that don't update their parent or other offspring, we can force c to be an independent copy of a using the `deepcopy` function:\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\ncc = deepcopy(aa)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\n\n::: {#12 .cell execution_count=1}\n``` {.julia .cell-code}\ncc[3] = 101\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n101\n```\n:::\n:::\n\n\n\n\n\n\nSee how only the third element of `cc` s changed but not `aa`?\n\n\n\n\n::: {#14 .cell execution_count=1}\n``` {.julia .cell-code}\naa,cc\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n([1, 41, 3], [1, 41, 101])\n```\n:::\n:::\n\n\n\n\n\n:::\n\n9. You can view a `.csv` or `.txt` file by clicking on a file name in the project directory (left panel) - this opens a viewing window. CSV's also have a built in 'Preview' mode - try using right click\\>Open Preview on a `.csv` file and check it out.\n\n10. Docstrings are a supplement to `#`-based comments for documenting your workflow. Basically, any string that appears just before an object will be interpreted as documenting it. When you use a docstring it is possible to call that description using help (`?` in the REPL) or hovering over the object in VSCode. This can be very useful when you start declaring variables or building your own functions.\n\n::: {.callout-tip collapse=\"true\"}\n## Docstrings\n\nBelow is an examle of a docstring for a global variable as well as how it would look for a function\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\n\"a wonderfully documented and described variable\"\nvar = 101\n```\n:::\n\n\n\n\n\n\nyou can (should) also do this with functions\n\n\n\n\n::: {#18 .cell execution_count=1}\n``` {.julia .cell-code}\n\"\"\"\n _rategradient(∂X, ∂Y)\n\nReturns the rate of change in units of the values stored in the grid, and the\nangle of the change in wind direction, *i.e.* an angle of 180 means that the\nvalue is increasing *from* the south. When both ∂X and ∂Y are equal to 0, the\nangle is assumed to be 0.\n\"\"\"\nfunction _rategradient(∂X::T, ∂Y::T) where {T <: Number}\n if ∂X == ∂Y == 0.0\n return (0.0, 0.0)\n end\n m = sqrt(∂X^2 + ∂Y^2)\n Δ = ∂X >= 0.0 ? 0.0 : 180.0\n θ = rad2deg(atan(∂X, ∂Y)) + Δ\n θ = ∂X > 0.0 ? θ + 180.0 : θ\n return (m, θ)\nend\n```\n:::\n\n\n\n\n\n:::\n\n", "supporting": [ - "6_tips_tricks_files" + "6_tips_tricks_files/figure-html" ], "filters": [], "includes": {} diff --git a/_freeze/7_differential_equations/execute-results/html.json b/_freeze/7_differential_equations/execute-results/html.json index beccd88..917da3c 100644 --- a/_freeze/7_differential_equations/execute-results/html.json +++ b/_freeze/7_differential_equations/execute-results/html.json @@ -1,8 +1,8 @@ { "hash": "fbc16c92fd721206e3c6b6f1f68582be", "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 7: Introducing Differential Equations\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nbibliography: references.bib\n---\n\n::: {#bdb9f7bf .cell execution_count=1}\n\n::: {.cell-output .cell-output-stderr}\n```\n[ Info: Precompiling PlotsExt [ee28d484-87b8-5b84-8c5c-a74b800bbc50] (cache misses: wrong dep version loaded (2))\n```\n:::\n:::\n\n\nThis document illustrates how to construct and solve differential equations in Julia using the `DifferentialEquations.jl` package.\n\nIn particular, we are interested in modelling a two species Lotka-Volterra like (predator-prey/consumer-resource) system. Such systems are fundamental in ecology and form the building blocks of complex networks and the models that represent them.\n\nFor this tutorial you'll need the following two packages:\n\n- `DifferentialEquations.jl` to solve the differential equations (same 'engine' as the one used by the `BioEnergeticFoodWebs.jl` model)\n- `Plots.jl` to visualise the results\n\nWhile we already have `Plots.jl` in this project, we just need to `] add DifferentialEquations`.\n\nThe `DifferentialEquations.jl` can be a tad clunky so the below code might take a while to compile. If you hit errors, we recommend removing (`] rm DifferentialEquations`) and reinstalling (`] add DifferentialEquations`) the package.\n\nYou probably want to start a new script for this exercise. File -\\> New File -\\> julia\n\n### An introduction to Differential Equations.\n\nDifferential equations are frequently used to model the change in variables of interest through time. These changes are often referred to as derivatives (or `du/dt`). In this case, we are interested in modelling changes in the abundance of a consumer and its resource as a function of the system's key processes (growth, ingestion of food/foraging and mortality) and its parameters.\n\nThis type of model can be formalised as a simple Lotka-Volterra predator prey model, consisting of a set of differential equations:\n\n- Resource dynamics: $\\frac{dR}{dt} = r R (1-\\frac{R}{K}) - \\alpha R C$\n- Consumer dynamics: $\\frac{dC}{dt} = e \\alpha R C - m C$\n\nwhere $R$ and $C$ are the abundances of the resource and consumer respectively, $r$ is the resource's growth rate, $K$ is the producer's carrying capacity, $\\alpha$ is the consumer's ingestion rate, $e$ is the assimilation efficiency and $m$ is the consumer's mortality rate.\n\nTo recall from your ecology modules, this is a system of equations with logistic growth for the producers (plants) and a Type I [functional response](https://en.wikipedia.org/wiki/Functional_response) describing how consumer foraging (the loss of prey caused by predators eating them) varies with prey density, a simple conversion efficiency that translates the functional response (eating the prey) into babies of the consumer (predator reproduction) and then a mortality rate for the consumer/predator.\n\nA few details to note.\n\n- there is only one source of density dependence in this model/system - logistic growth of the producer. Density dependence is required to generate coexistence and stability.\n- the Type I functional response means that the consumer foraging rate increases with prey density and does not saturate. It means that the mortality rate that consumers impose on the prey is constant and independent of the prey density. It is thus density independent and does not contribute to stability. There are two other functional responses. The Type II, which has saturating consumption rate and generates *inverse* density dependence, and the Type III, which has accelerating consumption rate with prey density, and thus generates increasing mortality in the prey with increasing prey density, and thus density dependence. It is only Type III functional responses that are linked to consumers/predators *stabilising* their prey populations. It is also a pretty rare functional response!\n- the consumer mortality rate is also constant and thus density independent.\n\n### How does this relate to the Bioenergetic Food Web Model?\n\nThe complex model of consumer - resource interactions that is represented by the `BEFW` model has at it's heart two equations: one for producers and one for consumers. So at it's heart, it is not too different in structure to the model above! However, the differences, spelled out in @delmas2017, are\n\n- the parameters are functions of body size\n- because of this, we can expand the number of resource and consumer equations for multiple values of body size\n- this creates a potentially big system of equations, instead of just 2.\n\nHowever, and this is important, the process of solving these equations, whether it is two of them, or 100 of them, is essentially what we are introducing below. If you were to look inside of the `BEFW` model, you would see the same functions and structure as we introduce here.\n\n#### The Three Steps For Simulating Food Web Dynamics\n\nThere are 3 major steps involved in constructing and solving this model in Julia (these happen to be the same three steps in all programming languages, including R where the `deSolve` package accomplishes much of this same functionality):\n\n1. Define a function for your model (i.e. transform the above differential equations into a function that can be read by the solver). This function tells the solver how the variables of interest (here $R$ and $C$) change over time.\n2. Define the problem. Here, the problem is defined by the function, the parameters ($r$, $\\alpha$, $e$ and $m$), the initial conditions and the timespan of the simulation. In this step you provide the solver with all the details it needs to find the solution.\n3. Solve!\n\n#### Step 1. Define the function\n\nHere we construct a function for our model. The function needs to accept the following:\n\n- `du` (derivatives) - a vector of changes in abundance for each species\n- `u` (values) - a vector of abundance for each species\n- `p` (parameters) - a list of parameter values\n- `t` (time) - timespan\n\n::: {#d2293387 .cell execution_count=2}\n``` {.julia .cell-code}\nfunction LV_model(du,u,p,t)\n # growth rate of the resource (modelled as a logistic growth function)\n GrowthR = p.growthrate * u[1] * (1 - u[1]/p.K) \n # rate of resource ingestion by consumer (modelled as a type I functional response)\n IngestC = p.ingestrate * u[1] * u[2]\n # mortality of consumer (modelled as density independent)\n MortC = p.mortrate * u[2]\n # calculate and store changes in abundance (du/dt):\n # change in resource abundance\n du[1] = GrowthR - IngestC\n # change in consumer abundance\n du[2] = p.assimeff * IngestC - MortC\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\nLV_model (generic function with 1 method)\n```\n:::\n:::\n\n\nYou'll notice that in the above function (`LV_model`), we've specified specific parameters using the `p.name` notation. This is because we've opted to store our parameters in a named tuple called `p`. `p` is created below but it's worth noting that when this notation is used e.g., `p.growthrate`, we are telling Julia that we want to use the value of `growthrate` that is stored as a named part of our tuple (a fancy name for an object in Julia) `p`.\n\n#### Step 2. Define the problem\n\nTo define the problem we first have to fix the system's parameters, the initial values and the timespan of the simulation:\n\n::: {#05dac6c8 .cell execution_count=3}\n``` {.julia .cell-code}\np = (\n growthrate = 1.0, # growth rate of resource (per day)\n ingestrate = 0.2, # rate of ingestion (per day)\n mortrate = 0.2, # mortality rate of consumer (per day)\n assimeff = 0.5, # assimilation efficiency\n K = 10 # carrying capacity of the system (mmol/m3)\n )\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n(growthrate = 1.0, ingestrate = 0.2, mortrate = 0.2, assimeff = 0.5, K = 10)\n```\n:::\n:::\n\n\nHere, we have chosen to define `p` as a named tuple (similar to a list in R). A vector or dictionary would also work, however, named tuples are advantageous because they allow us to use explicit names and are unmutable meaning that once it's created you can't change it.\n\n- **Initial values:** For simplicity, we start with $R = C = 1$:\n\n::: {#b716018f .cell execution_count=4}\n``` {.julia .cell-code}\nu0 = [1.0; 1.0]\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n2-element Vector{Float64}:\n 1.0\n 1.0\n```\n:::\n:::\n\n\n- **Timespan:**\n\n::: {#f60f66fe .cell execution_count=5}\n``` {.julia .cell-code}\ntspan = (0.0,100.0) # you have to use a Pair (tuple with 2 values) of floating point numbers.\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n(0.0, 100.0)\n```\n:::\n:::\n\n\nWe then formally define the problem by passing the function (`LV_model`), the parameters (listed in our named tuple `p`), the initial values (`u0`) and the timespan (`tspan`) to `ODEProblem()`:\n\n::: {#53b05f20 .cell execution_count=6}\n``` {.julia .cell-code}\nprob = ODEProblem(LV_model, u0, tspan, p)\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n\n::: {.ansi-escaped-output}\n```{=html}\n
ODEProblem with uType Vector{Float64} and tType Float64. In-place: true\ntimespan: (0.0, 100.0)\nu0: 2-element Vector{Float64}:\n 1.0\n 1.0
\n```\n:::\n\n:::\n:::\n\n\n#### Step 3. Solve\n\nTo solve the problem, we pass the `ODEProblem` object to the solver.\n\nHere we have chosen to use the default algorithm because it's a simple problem, however there are several available - see [here](https://diffeq.sciml.ai/dev/solvers/ode_solve/) for more information. These two final steps (define and solve the problem) are analogous to using the `deSolve` package in R.\"\n\n::: {#8652dce0 .cell execution_count=7}\n``` {.julia .cell-code}\nsol = solve(prob)\n```\n:::\n\n\nThe solver produces 2 objects: `sol.t` and `sol.u` that respectively store the time steps and the variables of interest through time. Let's have a look.\n\n#### Step 4. Visualise the outputs\"\n\nOnce the problem has been solved, the results can be explored and plotted. In fact, the `DifferentialEquations.jl` package has its own built in plotting recipe that provides a very fast and convenient way of visualising the abundance of the two species through time:\n\n::: {#460020eb .cell execution_count=8}\n``` {.julia .cell-code}\nplot(sol, \n\tylabel = \"Abundance\", \n\txlabel = \"Time\", \n\ttitle = \"Lotka-Volterra\", \n\tlabel = [\"prey\" \"predator\"], \n\tlinestyle = [:dash :dot], \n\tlw = 2) \n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nOne thing to note here, when plotting in Julia you don't need to separate label names (`label = [prey predator]`) or linestyles (`linestyle = [:dash :dot]`) with a comma as you would in R. This will also be case for most plotting options in Julia.\n\n#### Step 5. Play some games\n\nNow that you see how this works, perhaps you can do a bit of an experiment by varying things in the `p =` (parameters) part of the code?\n\n- Can you increase the number of time steps?\n- What happens when you increase `K`?\n- What happens when you increase or decrease `growthrate`?\n- What happens when you change the `ingestrate`\n\n#### EXTRA CREDIT\n\nIf you are really keen.... how about trying to run the model in a loop over 3 values of `growthrate`, collect the final population size of the consumer and resource in a data frame with three columns (`growthrate`, finalCons, finalRes), and plot these values?\n\n## References\n\n::: {#refs}\n:::\n\n", + "engine": "julia", + "markdown": "---\ntitle: \"Tutorial 7: Introducing Differential Equations\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nbibliography: references.bib\nengine: julia\n---\n\n\n\n\n\n\n\nThis document illustrates how to construct and solve differential equations in Julia using the `DifferentialEquations.jl` package.\n\nIn particular, we are interested in modelling a two species Lotka-Volterra like (predator-prey/consumer-resource) system. Such systems are fundamental in ecology and form the building blocks of complex networks and the models that represent them.\n\nFor this tutorial you'll need the following two packages:\n\n- `DifferentialEquations.jl` to solve the differential equations (same 'engine' as the one used by the `BioEnergeticFoodWebs.jl` model)\n- `Plots.jl` to visualise the results\n\nWhile we already have `Plots.jl` in this project, we just need to `] add DifferentialEquations`.\n\nThe `DifferentialEquations.jl` can be a tad clunky so the below code might take a while to compile. If you hit errors, we recommend removing (`] rm DifferentialEquations`) and reinstalling (`] add DifferentialEquations`) the package.\n\nYou probably want to start a new script for this exercise. File -\\> New File -\\> julia\n\n### An introduction to Differential Equations.\n\nDifferential equations are frequently used to model the change in variables of interest through time. These changes are often referred to as derivatives (or `du/dt`). In this case, we are interested in modelling changes in the abundance of a consumer and its resource as a function of the system's key processes (growth, ingestion of food/foraging and mortality) and its parameters.\n\nThis type of model can be formalised as a simple Lotka-Volterra predator prey model, consisting of a set of differential equations:\n\n- Resource dynamics: $\\frac{dR}{dt} = r R (1-\\frac{R}{K}) - \\alpha R C$\n- Consumer dynamics: $\\frac{dC}{dt} = e \\alpha R C - m C$\n\nwhere $R$ and $C$ are the abundances of the resource and consumer respectively, $r$ is the resource's growth rate, $K$ is the producer's carrying capacity, $\\alpha$ is the consumer's ingestion rate, $e$ is the assimilation efficiency and $m$ is the consumer's mortality rate.\n\nTo recall from your ecology modules, this is a system of equations with logistic growth for the producers (plants) and a Type I [functional response](https://en.wikipedia.org/wiki/Functional_response) describing how consumer foraging (the loss of prey caused by predators eating them) varies with prey density, a simple conversion efficiency that translates the functional response (eating the prey) into babies of the consumer (predator reproduction) and then a mortality rate for the consumer/predator.\n\nA few details to note.\n\n- there is only one source of density dependence in this model/system - logistic growth of the producer. Density dependence is required to generate coexistence and stability.\n- the Type I functional response means that the consumer foraging rate increases with prey density and does not saturate. It means that the mortality rate that consumers impose on the prey is constant and independent of the prey density. It is thus density independent and does not contribute to stability. There are two other functional responses. The Type II, which has saturating consumption rate and generates *inverse* density dependence, and the Type III, which has accelerating consumption rate with prey density, and thus generates increasing mortality in the prey with increasing prey density, and thus density dependence. It is only Type III functional responses that are linked to consumers/predators *stabilising* their prey populations. It is also a pretty rare functional response!\n- the consumer mortality rate is also constant and thus density independent.\n\n### How does this relate to the Bioenergetic Food Web Model?\n\nThe complex model of consumer - resource interactions that is represented by the `BEFW` model has at it's heart two equations: one for producers and one for consumers. So at it's heart, it is not too different in structure to the model above! However, the differences, spelled out in @delmas2017, are\n\n- the parameters are functions of body size\n- because of this, we can expand the number of resource and consumer equations for multiple values of body size\n- this creates a potentially big system of equations, instead of just 2.\n\nHowever, and this is important, the process of solving these equations, whether it is two of them, or 100 of them, is essentially what we are introducing below. If you were to look inside of the `BEFW` model, you would see the same functions and structure as we introduce here.\n\n#### The Three Steps For Simulating Food Web Dynamics\n\nThere are 3 major steps involved in constructing and solving this model in Julia (these happen to be the same three steps in all programming languages, including R where the `deSolve` package accomplishes much of this same functionality):\n\n1. Define a function for your model (i.e. transform the above differential equations into a function that can be read by the solver). This function tells the solver how the variables of interest (here $R$ and $C$) change over time.\n2. Define the problem. Here, the problem is defined by the function, the parameters ($r$, $\\alpha$, $e$ and $m$), the initial conditions and the timespan of the simulation. In this step you provide the solver with all the details it needs to find the solution.\n3. Solve!\n\n#### Step 1. Define the function\n\nHere we construct a function for our model. The function needs to accept the following:\n\n- `du` (derivatives) - a vector of changes in abundance for each species\n- `u` (values) - a vector of abundance for each species\n- `p` (parameters) - a list of parameter values\n- `t` (time) - timespan\n\n\n\n\n::: {#4 .cell execution_count=1}\n``` {.julia .cell-code}\nfunction LV_model(du,u,p,t)\n # growth rate of the resource (modelled as a logistic growth function)\n GrowthR = p.growthrate * u[1] * (1 - u[1]/p.K) \n # rate of resource ingestion by consumer (modelled as a type I functional response)\n IngestC = p.ingestrate * u[1] * u[2]\n # mortality of consumer (modelled as density independent)\n MortC = p.mortrate * u[2]\n # calculate and store changes in abundance (du/dt):\n # change in resource abundance\n du[1] = GrowthR - IngestC\n # change in consumer abundance\n du[2] = p.assimeff * IngestC - MortC\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\nLV_model (generic function with 1 method)\n```\n:::\n:::\n\n\n\n\n\n\nYou'll notice that in the above function (`LV_model`), we've specified specific parameters using the `p.name` notation. This is because we've opted to store our parameters in a named tuple called `p`. `p` is created below but it's worth noting that when this notation is used e.g., `p.growthrate`, we are telling Julia that we want to use the value of `growthrate` that is stored as a named part of our tuple (a fancy name for an object in Julia) `p`.\n\n#### Step 2. Define the problem\n\nTo define the problem we first have to fix the system's parameters, the initial values and the timespan of the simulation:\n\n\n\n\n::: {#6 .cell execution_count=1}\n``` {.julia .cell-code}\np = (\n growthrate = 1.0, # growth rate of resource (per day)\n ingestrate = 0.2, # rate of ingestion (per day)\n mortrate = 0.2, # mortality rate of consumer (per day)\n assimeff = 0.5, # assimilation efficiency\n K = 10 # carrying capacity of the system (mmol/m3)\n )\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n(growthrate = 1.0, ingestrate = 0.2, mortrate = 0.2, assimeff = 0.5, K = 10)\n```\n:::\n:::\n\n\n\n\n\n\nHere, we have chosen to define `p` as a named tuple (similar to a list in R). A vector or dictionary would also work, however, named tuples are advantageous because they allow us to use explicit names and are unmutable meaning that once it's created you can't change it.\n\n- **Initial values:** For simplicity, we start with $R = C = 1$:\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\nu0 = [1.0; 1.0]\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n2-element Vector{Float64}:\n 1.0\n 1.0\n```\n:::\n:::\n\n\n\n\n\n\n- **Timespan:**\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\ntspan = (0.0,100.0) # you have to use a Pair (tuple with 2 values) of floating point numbers.\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n(0.0, 100.0)\n```\n:::\n:::\n\n\n\n\n\n\nWe then formally define the problem by passing the function (`LV_model`), the parameters (listed in our named tuple `p`), the initial values (`u0`) and the timespan (`tspan`) to `ODEProblem()`:\n\n\n\n\n::: {#12 .cell execution_count=1}\n``` {.julia .cell-code}\nprob = ODEProblem(LV_model, u0, tspan, p)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\nODEProblem with uType Vector{Float64} and tType Float64. In-place: true\ntimespan: (0.0, 100.0)\nu0: 2-element Vector{Float64}:\n 1.0\n 1.0\n```\n:::\n:::\n\n\n\n\n\n\n#### Step 3. Solve\n\nTo solve the problem, we pass the `ODEProblem` object to the solver.\n\nHere we have chosen to use the default algorithm because it's a simple problem, however there are several available - see [here](https://diffeq.sciml.ai/dev/solvers/ode_solve/) for more information. These two final steps (define and solve the problem) are analogous to using the `deSolve` package in R.\"\n\n\n\n\n::: {#14 .cell execution_count=1}\n``` {.julia .cell-code}\nsol = solve(prob)\n```\n:::\n\n\n\n\n\n\nThe solver produces 2 objects: `sol.t` and `sol.u` that respectively store the time steps and the variables of interest through time. Let's have a look.\n\n#### Step 4. Visualise the outputs\"\n\nOnce the problem has been solved, the results can be explored and plotted. In fact, the `DifferentialEquations.jl` package has its own built in plotting recipe that provides a very fast and convenient way of visualising the abundance of the two species through time:\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\nplot(sol, \n\tylabel = \"Abundance\", \n\txlabel = \"Time\", \n\ttitle = \"Lotka-Volterra\", \n\tlabel = [\"prey\" \"predator\"], \n\tlinestyle = [:dash :dot], \n\tlw = 2)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nOne thing to note here, when plotting in Julia you don't need to separate label names (`label = [prey predator]`) or linestyles (`linestyle = [:dash :dot]`) with a comma as you would in R. This will also be case for most plotting options in Julia.\n\n#### Step 5. Play some games\n\nNow that you see how this works, perhaps you can do a bit of an experiment by varying things in the `p =` (parameters) part of the code?\n\n- Can you increase the number of time steps?\n- What happens when you increase `K`?\n- What happens when you increase or decrease `growthrate`?\n- What happens when you change the `ingestrate`\n\n#### EXTRA CREDIT\n\nIf you are really keen.... how about trying to run the model in a loop over 3 values of `growthrate`, collect the final population size of the consumer and resource in a data frame with three columns (`growthrate`, finalCons, finalRes), and plot these values?\n\n## References\n\n::: {#refs}\n:::\n\n", "supporting": [ "7_differential_equations_files" ], diff --git a/_freeze/8_intro_end/execute-results/html.json b/_freeze/8_intro_end/execute-results/html.json index 7ed69df..8fd53c3 100644 --- a/_freeze/8_intro_end/execute-results/html.json +++ b/_freeze/8_intro_end/execute-results/html.json @@ -1,8 +1,8 @@ { "hash": "42d7f56d16d534013c31185eed56dcfd", "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 8: Introducing Ecological Networks Dynamics (END)\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nabstract: |\n This section of the tutorials initiates you into using the Bioenergetic Food Web Model.\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nbibliography: references.bib\n---\n\n\n\n## Using the Bioenergetic Food Web\n\n### Preamble: The Bioenergetic Food Web.\n\nIt is very worth pausing for a moment and looking at @delmas2017. It describes the BioEnergetic Food Web Model, provides some history of the model, and also showcases how the original `Julia` version of the model worked. This section of the tutorials is designed to introduce a newer, faster and more flexible version of the `Julia` package.\n\nA very basic interpretation of the model is as follows:\n\n1. The model is a model of biomass dynamics, not numbers of individuals.\n2. The model is comprised of an equation for plants (producers) an equation for consumers (herbivores, predators).\n3. Plants have traits that make their biomass grow and sets their carrying capacity; they are eaten by consumers via an equation describing a functional response. To link to ecology courses you have, this can be logistic growth for the plant and a type II functional response.\n4. Consumer have three sets of traits. One is metabolism, which is a rate that describes losses of biomass due to, well, metabolism! The second set of traits correspond to the functional response - for example describing attack rates and handling times of prey items. The third corresponds to the numerical response, or the conversion of biomass they eat into new biomass (e.g. babies)\n5. We can make complex networks and systems of these equations by letting many of these parameters *scale with body size* via the rules of allometry and the Metabolic Theory of Ecology. This *trick* expands the two equations to n = number of species when we provide the toolbox with a list of species biomasses.\n6. Embedded in this process are rules about how to distribute species of different sizes across trophic levels, so that we end up with predators, omnivores, herbivores and plants. We can also designate the body size relationships for different groups of organisms, like producers, invertebrates, endothermic vertebrates and ectothermic vertebrates.\n7. Once we've done this, we can simulate the biomass dynamics of complex communities. And we can summarise things like changes in biodiversity (number of species), stability (coefficient of variation of the time series) and anything about the biomass of species, trophic levels or the community!\n\n### Preamble: Setup\n\nOne of main advantages of running food web models in Julia is that simulations are fast and can be readily stored in your active project. With this in mind, make a new folder in your project called `out_objects` (right click \\> New Folder).\n\nWe will be using the `EcologicalNetworksDynamics.jl` package [@lajaaiti2024] to implement the BEFW. Although we will go through and explain the functionality it may be useful to have both the preprint as well as the complete [documentation](https://beckslab.github.io/EcologicalNetworksDynamics.jl/) on hand for more detailed explanations. You can install `EcologicalNetworksDynamics` as you would any other normal `Julia` package.\n\n::: {#dddeac7c .cell execution_count=2}\n``` {.julia .cell-code}\nPkg.add EcologicalNetworksDynamics\n```\n:::\n\n\n### A first run using Ecological Networks Dynamics (END)\n\nThere are four major steps when running the BioEnergetic Food Web model in Julia. These should be familiar from our introduction to the `DifferentialEquations` package:\n\n1. Generate an initial food web network\n2. Set the parameters for each species in the network to generate the equations\n3. Simulate the network and equations\n4. Explore output and plot\n\nWhile in the previous example with `Differential Equations` we assumed a simple 2-species network, one of the new activities here is to take advantage of a rich history of theory and tools to construct species rich networks with appropriate structural properties, such as *connectance/complexity* and levels of *generalism/specialism* and things the number of trophic levels and a body size distribution of the species across trophic levels.\n\n#### Step 1: generate an initial network {#sec-step1}\n\n::: {#70bdd634 .cell execution_count=3}\n``` {.julia .cell-code}\n## My first BEFW Modelling\n\n## Packages I need\nusing DataFrames, Plots, Random, Distributions\nusing EcologicalNetworksDynamics\n\n## Time to do some Experiments!\n```\n:::\n\n\nHere we make a foodweb, actually, a food chain, from an *adjacency matrix* using `Foodweb`.\n\n::: {#4db18fc8 .cell execution_count=4}\n``` {.julia .cell-code}\nA = [0 0 0; 1 0 0; 0 1 0] # 1 basal producer ⋅ Species 2 eats 1 ⋅ Species 3 eats 2\nfoodweb = Foodweb(A)\n```\n:::\n\n\n#### Step 2: Generate the model parameters\n\nOnce the foodweb is created, the next step is to attribute values to the model parameters. This can be simply done by calling `default_model` with foodweb as an argument.\n\n::: {#f3dd39d1 .cell execution_count=5}\n``` {.julia .cell-code}\n# construct the equations and fixed parameters\n# see below for body size dependent parameters etc\nparams = default_model(foodweb)\n```\n:::\n\n\nIf we look at our `params` object we can see that it has all the required parameters for the **BEFW**. Later in this tutorial you will see how we can access and modify these parameters.\n\n#### Step 3: Simulate biomass dynamics\n\nEverything is ready to run the simulation, which can be simply done by calling simulate with the model parameters (params) and a vector species' initial biomass (B0).\n\n::: {#c38d92ad .cell execution_count=6}\n``` {.julia .cell-code}\n# create body sizes for each species\nB0 = [0.5, 0.5, 0.5]\n# specify number of time steps\nt = 300\n\n# use simulate function\n# builds equations and uses DiffEq to run them!\nsim = simulate(params, B0, t)\n```\n:::\n\n\n#### Step 4: Seeing the outputs!\n\nTo plot the time series, we can use the actual `simulate` object directly.\n\n::: {#89767d2d .cell execution_count=7}\n``` {.julia .cell-code}\n plot(sim, label = [\"Producer\" \"Consumer\" \"Top consumer\";])\n```\n:::\n\n\nEventually you may want to plot the biomass dynamics - the trajectory - of your community to see what is happening. For our minimal example, it can be done as follows:\n\n::: {#09ea07af .cell execution_count=8}\n``` {.julia .cell-code}\n# create multiple objects: time = t pulled from the sim.t component\n# and Bx = biomass for each species pulled from the larger sim object\n# note how julia allows multiple things on left of the =\nt, B1, B2, B3 = sim.t, sim[1,:], sim[2,:], sim[3,:] # unpack variables\n\n# Plot the basal species\nplot(t, B1, lw = 3, label=\"Producer\", xlabel = \"Time\", ylabel = \"Biomass\")\n# add the herbivore\nplot!(t, B2, lw = 3, label=\"Consumer\")\n# add the top predator\nplot!(t, B3, lw = 3, label=\"Top consumer\")\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n## A More Complex Example\n\n#### Step 1: Generate the initial network\n\nIn order to run the BEFW model with a more complex network, we have to construct an initial food web network (an adjacency matrix) using the niche model [@williams2000]. The network is characterised by the number of species in the network and its [connectance/complexity](https://en.wikipedia.org/wiki/Ecological_network) value.\n\nNote that we are now using functionality provided by the `EcologicalNetworks` package.\n\n::: {#2dc32135 .cell execution_count=9}\n``` {.julia .cell-code}\nS = 20 # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\n\n# construct the food web\nRandom.seed!(12325) # ensures your network and this one are the same\nfoodweb_niche = Foodweb(:niche; S = S, C = C)\n```\n:::\n\n\n#### Step 2. Setting up the parameters, body masses (species) and running the model!\n\nAs above, our next step is to define a vector of bodymasses and then pass this, and the network to the `simulate` function. Here we combine the `Uniform` function from the *Distributions* package with the `rand` function from the *Random* package.\n\n::: {#dcaec127 .cell execution_count=10}\n``` {.julia .cell-code}\n# construct the equations and fixed parameters\n# see below for body size dependent parameters etc\nparams_niche = default_model(foodweb_niche)\n\n# define bodymasses between 0 and 1 and get S = 20 of them.\n# this will ensure your plot looks like the one in the document\nRandom.seed!(123)\nB0 = rand(S)\nt = 300\n\n# simulate using params and bodymasses\n# note additional argument tmax for max time steps\n# default is 300\nsim_niche = simulate(params_niche, B0, t)\n```\n:::\n\n\n#### Step 3. Visualising the dynamics\n\nNow we can move to plotting again. Note how we now ask for the time directly from the simulate object and all of the biomasses from that object as well.\n\nNote too how we can suppress the legend (which covers some of the time series).\n\n::: {#f7c2e5ea .cell execution_count=11}\n``` {.julia .cell-code}\nplot(sim_niche, legend = false)\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nOne game to play now is to alter the bodymass distribution. `rand` selects a random uniform number between 0 and 1. Can you figure out how to make the distribution uniform between 0 and 10? See what that does.\n\n#### A bit more about the process: dissecting the ModelParameters\n\nLet's dissect the `default_model` object a bit, to understand just a bit more about what is going on.\n\n::: {#3c84813b .cell execution_count=12}\n``` {.julia .cell-code}\nparams_niche\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n\n::: {.ansi-escaped-output}\n```{=html}\n
Model (alias for EcologicalNetworksDynamics.Framework.System{<inner parms>}) with 17 components:\n  - Species: 20 (:s1, :s2, :s3, :s4, ..., :s20)\n  - Foodweb: 82 links\n  - Body masses: [396.6757314506745, 1000.0, 138.23722273578997, 150.62580571223663, ..., 1.0]\n  - Metabolic classes: [:invertebrate, :invertebrate, :invertebrate, :invertebrate, ..., :producer]\n  - GrowthRate: [·, ·, ·, ·, ..., 1.0]\n  - Carrying capacity: [·, ·, ·, ·, ..., 1.0]\n  - ProducersCompetition: 1.0\n  - LogisticGrowth\n  - Efficiency: 0.45 to 0.85.\n  - MaximumConsumption: [8.0, 8.0, 8.0, 8.0, ..., ·]\n  - Hill exponent: 2.0\n  - Consumers preferences: 0.07692307692307693 to 1.0.\n  - Intra-specific interference: [·, ·, ·, ·, ..., ·]\n  - Half-saturation density: [0.5, 0.5, 0.5, 0.5, ..., ·]\n  - BioenergeticResponse\n  - Metabolism: [0.0703591752903408, 0.05583797347522218, 0.09157425582526797, 0.08963029015067063, ..., 0.0]\n  - Mortality: [0.0, 0.0, 0.0, 0.0, ..., 0.0]
\n```\n:::\n\n:::\n:::\n\n\nWalking through this\n\n::: callout-caution\n## Warning\n\nThis section still reflects the old version of END structure and naming conventions\n:::\n\n1. The `network` component defines the food web and reports the number of species and the links\n2. the `environment` component reports on values of the carrying capacity (K) and the baseline temperature (`T`). Note that K is specified only for the basal species via `[1, 1, ... nothing, nothing]`. All the producers have the same K at this point (1,1,1...). The presence of the `T` suggests that we can ultimately work with climate change by running the model at different temperatures. There is a way to make some of the biorates and components of the functional response (see 3, 4) dependent not only on body mass, but also on temperature.\n3. the `biorates` component contains detail on parameters central to making the model reflect a bit of reality: `d` is ...; `r` is the intrinsic rate of increase (population growth rate) for the producers (plants); `x` and `y` are parameters associated with metabolic rates and consumption rates of the consumers (non-plant species). Finally, `e` is an efficiency/assimilation rate for the consumers eating either plants or other animals.\n4. the `functional_response` component defines the type of *consumption function* being used (e.g. Type I, II, or III sensu classic ecology and Holling). The functional response defines the *interaction strength* between species and how consumers change how much they eat dependent on the amount (density) of resource available.There are two options. The default `Bioenergetic Response` corresponds to a *phenomenological* formulation where there are just two variables that describe how consumer consumption varies with resource density: a *half-saturation* parameter and an *asymptote*. The alternative called `Classic Response` is more *trait based* and includes the parameters *attack rate* and *handling time*. There are several other features of the functional response that can be manipulated, and these are introduced in later tutorials.\n5. the `producer_growth` details the default that all plants are growing logistically.\n6. the `temperature response`componewnt defines the absence or presence of temperature dependence, and when present, the shape of the relationship between biorates and functional response parameters and temperature.\n\n### Helper Functions: What can we do with the outputs?\n\n::: callout-caution\n## Warning\n\nThis section should be reviewed and revised by an END user who knows what we want to do with outputs.\n:::\n\nAs noted in the pre-amble, we are most often interested in additional information about the scenarios we build with the models. These include, for example, total biomass, biodiversity and stability. Let's see how we can calculate some of these.\n\n#### How long till steady state?\n\nWe can find out how long the simulations ran to reach steady state - remember that this is a deterministic model that typically reaches equilibrium for all species that survive.\n\n::: {#e6a09d70 .cell execution_count=13}\n``` {.julia .cell-code}\nsize(sim_niche.t)\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```\n(51,)\n```\n:::\n:::\n\n\n#### Who went extinct and when?\n\n::: callout-caution\n## Warning\n\nNot a functionality in END.\n:::\n\nWe can also find out who went extinct, and when. You saw some of that detail, I hope, in the output of `simulate`.\n\n::: {#e28cdcc1 .cell execution_count=14}\n``` {.julia .cell-code}\nget_extinct_species(sim_niche)\n```\n:::\n\n\n#### Biomass, Diversity and Stability\n\nFirst, we can get a measure of total biomass in the community, at equilibrium, and that of each species. Note how you can get the components too.\n\n::: {#e88897f6 .cell execution_count=15}\n``` {.julia .cell-code}\nsim_niche.u\n```\n\n::: {.cell-output .cell-output-display execution_count=13}\n```\n51-element Vector{Vector{Float64}}:\n [0.906299638797481, 0.44349373245960455, 0.7456733811393941, 0.5120830400366143, 0.2538490889415096, 0.33415153638191886, 0.4273278808735992, 0.867547200255958, 0.09913361484360417, 0.12528740769155033, 0.6922086620547391, 0.13655147513745736, 0.03209667335274724, 0.3505458214588266, 0.9303323763821093, 0.9594335994071538, 0.5819123423876457, 0.3114475007050529, 0.12114752051812694, 0.20452981732035946]\n [0.9169483131714715, 0.444402194534041, 0.7667640455857161, 0.5179071161683636, 0.25596644376248334, 0.3439614083570855, 0.42881389580038637, 0.8404857181508336, 0.10207349613818459, 0.12980979255930417, 0.7045585608788062, 0.14142469702894178, 0.033700254458592344, 0.35322775442579823, 0.9254383246584946, 0.8428424981719224, 0.5353929049386887, 0.2716712297929136, 0.11790964375471776, 0.20588623005171253]\n [0.9372189186622565, 0.446138581295766, 0.8030805319662981, 0.5280429096670912, 0.25960285298532004, 0.36088969827160805, 0.43143000229873113, 0.7941678141517742, 0.107334065965393, 0.13803877097876832, 0.7224846396419364, 0.150274714852675, 0.03655779055568964, 0.35202356186576755, 0.8867871855452475, 0.6561325211685619, 0.45370991951901846, 0.21879863147029777, 0.1144327890249893, 0.21137607850479412]\n [0.963419944890434, 0.4478457678502066, 0.8407656301021255, 0.5394619505769526, 0.26358620538619504, 0.3785307293750754, 0.43443524658702654, 0.7426580903726461, 0.11338938338304744, 0.1475698891121404, 0.7345099631141349, 0.16048747662896795, 0.03959434344670769, 0.3379755377009729, 0.7958692645000881, 0.48283669535781387, 0.36706195693003885, 0.17548000193294144, 0.1136592394878268, 0.22309854306314952]\n [0.995616193064571, 0.44805738727466143, 0.8700643195894429, 0.5512240918443782, 0.2674989824178032, 0.3924051349926597, 0.4375425793363201, 0.6886449125246876, 0.11960335804730916, 0.15695502649258633, 0.7327878032629778, 0.17047486846995694, 0.0420936774665965, 0.3062032871443506, 0.6610340292426684, 0.34855000462048347, 0.2881369319293169, 0.14175624955652485, 0.11666389844136492, 0.24243967254676815]\n [1.0331366869886944, 0.44448629343725343, 0.8788288901686566, 0.5620901047900512, 0.2708572048035862, 0.39695429480179645, 0.44018298027640984, 0.6333401253753693, 0.1252037789780579, 0.1640984843116221, 0.7114983769875807, 0.17795514254857084, 0.04354809380952039, 0.26092610308891634, 0.5154058541922188, 0.25624511921879434, 0.22330145420147088, 0.11586948470233616, 0.12436895504970236, 0.26962910331924905]\n [1.0773089982155897, 0.43396923698721435, 0.8556572961992899, 0.5707904139404543, 0.2731983214483226, 0.38705755776238965, 0.4413794083264426, 0.57197930814629, 0.12978003467017415, 0.16724868374246712, 0.6675169557355778, 0.18101017312972054, 0.04388752925907648, 0.20909394578211202, 0.3805309865842198, 0.19230727005942244, 0.16943175281775166, 0.09443672996682428, 0.13906102138589269, 0.30741066949967055]\n [1.1213743703927337, 0.4149870885160012, 0.7975741540831984, 0.5733620864984142, 0.2733077885606147, 0.36141676843558873, 0.4391552288251882, 0.5071960218562799, 0.13225598133704913, 0.1649144766546638, 0.6093837906327526, 0.17807037605762552, 0.04315159765633695, 0.1631734536430942, 0.2790930366914647, 0.15237925689592774, 0.12890880773111002, 0.0777317468581009, 0.16225155189984958, 0.35425475261372863]\n [1.1573410183305781, 0.3875799067335869, 0.7122633234623346, 0.5656661531044221, 0.2699342224158771, 0.32362037390928877, 0.43151833519945715, 0.43980122366299085, 0.1320832740044849, 0.15754833392958092, 0.5485937790090555, 0.16967851768901068, 0.04155688582593655, 0.12670961646818607, 0.20790093579654878, 0.12919220653556573, 0.09920527144448085, 0.06511083602693121, 0.1957265685332169, 0.40863184877785175]\n [1.1744909386178761, 0.35353525150930704, 0.6130415990319116, 0.5442924204781258, 0.2619765432579562, 0.2797239154423789, 0.41725964546931765, 0.3734718885747243, 0.12906194711831975, 0.14648620822639452, 0.49617455885534983, 0.15734180901650238, 0.039351964038387546, 0.0993990767009241, 0.15977668195469585, 0.1193453433823383, 0.07853078787521317, 0.05684848395648957, 0.23880211323157663, 0.46473430625333423]\n [1.1636651009007108, 0.3155425241026375, 0.5129043599973696, 0.5086210124289895, 0.24908969960788688, 0.23553191470443982, 0.3966456636545259, 0.3124900352369809, 0.12355869405172261, 0.13330212010711523, 0.45885425946835634, 0.14280589051662543, 0.036833828434965285, 0.07940681588029759, 0.1280065867800307, 0.12159259236413968, 0.06534238144397321, 0.053601952458352684, 0.28528412637082984, 0.5126103913127859]\n [1.1215900120487023, 0.2768216752264026, 0.42206636648520485, 0.46189135063482056, 0.23215126320140814, 0.19551978933588599, 0.37144587200796514, 0.26042387609908113, 0.11647562742120145, 0.11955373899209087, 0.4381554894529827, 0.1277697315605396, 0.034397853577932694, 0.06512710102028911, 0.10768752758342186, 0.13551750917697, 0.058102384679568894, 0.055907692857973916, 0.3220846544335181, 0.5412432565515389]\n [1.051674472438156, 0.2396400556460993, 0.34499392466732914, 0.408962875223587, 0.21264909765819076, 0.16158429863184295, 0.3435589630316772, 0.2180232510648064, 0.10878792457246415, 0.10632571872188118, 0.43013574616355804, 0.11339063974249527, 0.03248700163555598, 0.055268908325187105, 0.0946316891444375, 0.1595784203240174, 0.05459709129704919, 0.0631635952778267, 0.33753068620574334, 0.5455404467088186]\n ⋮\n [0.00032755644980272486, 0.00042642730013303957, 0.00024189593390109746, 3.1111688980955344e-5, 0.002186365444974394, 0.0001284836050334962, 0.009392611128074742, 0.2289263661082618, 0.027817843518977224, 0.00011632790937708126, 0.4448717546882417, 0.0001223774188672115, 0.198564855194196, 0.09669339044487263, 0.041438780171243736, 0.21624377256231636, 0.010260398961170272, 0.1106446052574405, 0.30895191650548376, 0.48344362584850714]\n [0.0001996798247022266, 0.0003009378761392906, 0.00015346749983007282, 1.8190449427202614e-5, 0.0017884347223449826, 8.151473534424173e-5, 0.0077101296606787864, 0.23181199431785626, 0.025313811373776522, 7.379449257908107e-5, 0.44476144744230767, 7.763164111187508e-5, 0.19771575290544488, 0.0981753484444294, 0.0415237986113816, 0.21618611797874981, 0.010096001729578499, 0.1107711243020971, 0.3089588621965838, 0.4835526097023227]\n [0.00011328126257715799, 0.0002025145740727682, 9.102676275323986e-5, 9.86615934389697e-6, 0.0014273867429624918, 4.834918126253599e-5, 0.006152674701416408, 0.2345821350465174, 0.022777702555973164, 4.3766536607882777e-5, 0.44485825775398713, 4.604210489119089e-5, 0.19677603845677671, 0.0996135511824476, 0.04163063947534051, 0.21611456663905765, 0.00992313898370846, 0.1108762739174712, 0.30896257460215903, 0.4836121681503955]\n [6.07969185813491e-5, 0.00013150891522278353, 5.122984902532575e-5, 5.0559263528295375e-6, 0.0011197509119850043, 2.721092248119792e-5, 0.004805123705498752, 0.2371493862104039, 0.02034698607033935, 2.4630532478594332e-5, 0.44507776580317365, 2.591108561516969e-5, 0.19582059389086015, 0.10090484291104647, 0.04175110898630074, 0.21605866945798072, 0.009748297718843965, 0.1109547748500005, 0.308965762906422, 0.48361873148098766]\n [2.9540113221979872e-5, 8.00347447973086e-5, 2.6268553079549285e-5, 2.3358462951272875e-6, 0.0008502538978690424, 1.3952641028662382e-5, 0.0036125895986525765, 0.23963412412998863, 0.017924696653654346, 1.2629101514971793e-5, 0.4453417610345992, 1.3285671319358326e-5, 0.19486664345382582, 0.10209874101875081, 0.041891604062307145, 0.2160237975426658, 0.00956208380761516, 0.11101835580249045, 0.3089707135225891, 0.48359145640506035]\n [1.3166616427449579e-5, 4.60961582614326e-5, 1.241859399595492e-5, 9.875013357564836e-7, 0.0006289434801525733, 6.596183545884943e-6, 0.0026293723865516917, 0.24190491545204867, 0.015626334170708748, 5.970359692556319e-6, 0.44560575498650923, 6.280744324641365e-6, 0.19400924653479448, 0.10314206416955765, 0.04204857588531362, 0.2160007866180423, 0.009371522869382096, 0.11107366457263641, 0.3089769794039354, 0.48355133078668755]\n [5.288582093742206e-6, 2.4853056623534485e-5, 5.32431964558186e-6, 3.7495755123700837e-7, 0.0004510237192764804, 2.8280327624688987e-6, 0.0018418173438047715, 0.24395924306889033, 0.013458321791607284, 2.559692577943294e-6, 0.44587256631997335, 2.692763414898462e-6, 0.19326957086896235, 0.10403490013949204, 0.04222157762263886, 0.21597907364688387, 0.009176377022194124, 0.11112583015368675, 0.30898347361961076, 0.4835073952384332]\n [1.960571333984018e-6, 1.2748386630159753e-5, 2.115911956181734e-6, 1.3122771778296083e-7, 0.00031649230625780636, 1.1238747466059242e-6, 0.0012535673852407435, 0.2457433105385709, 0.011504652249667801, 1.0172301703560636e-6, 0.44612733302168156, 1.0701126911743665e-6, 0.19267165202271308, 0.1047507539103007, 0.04240100704365944, 0.21595925499391128, 0.008984468602875842, 0.11117426849212075, 0.30898978378818076, 0.48346305093339226]\n [6.595296475377276e-7, 6.157495485353746e-6, 7.673573735587585e-7, 4.1573174269355544e-8, 0.0002163095240186386, 4.0758481170993133e-7, 0.0008246351715236552, 0.24730063052972948, 0.009744807150823888, 3.6890828571649465e-7, 0.4463589658982419, 3.880865976484553e-7, 0.19219749029253488, 0.10531819548561512, 0.042584771757986466, 0.21594251593637606, 0.008795235529894242, 0.11122083597743129, 0.3089962400343031, 0.48342085434013]\n [2.0108052810226762e-7, 2.8004575219465937e-6, 2.5369560293790977e-7, 1.190656631256341e-8, 0.00014408987057401768, 1.3475139250220505e-7, 0.0005246117248146955, 0.24864251960077316, 0.008183727277329841, 1.2196446538994685e-7, 0.4465625705694917, 1.2830498581813105e-7, 0.19183327165148306, 0.10575941597710509, 0.04276848561656389, 0.21592768854223388, 0.008611086962690943, 0.11126649455166937, 0.30900276016604544, 0.4833835692529364]\n [5.35850498787597e-8, 1.174593201709331e-6, 7.398752912499898e-8, 2.965192061208363e-9, 9.266705935747393e-5, 3.929875986723788e-8, 0.00031929137827090367, 0.24981133030734196, 0.006788855740405869, 3.556958190340493e-8, 0.4467437607797747, 3.7418723667047955e-8, 0.19155285868338037, 0.10610455981258715, 0.04295191471606665, 0.21591384077514106, 0.008430160333184566, 0.1113122756892104, 0.30900934087551246, 0.48335082223348647]\n [3.2821854904203205e-8, 8.406671643638472e-7, 4.6640508998017896e-8, 1.7793663607263053e-9, 7.799523091116062e-5, 2.4773285240091262e-8, 0.0002627973314424048, 0.2502039748903548, 0.00631276636245039, 2.2422472598477954e-8, 0.4468055436036614, 2.358814075481337e-8, 0.19146688286657296, 0.10621159455428622, 0.04301932407939025, 0.21590899888568155, 0.008364030293673712, 0.11132929056683419, 0.3090117977250657, 0.4833397504740079]\n```\n:::\n:::\n\n\n::: {#ee024792 .cell execution_count=16}\n``` {.julia .cell-code}\n# components\ntotal_biomass(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```\n51-element Vector{Float64}:\n 9.035052310145453\n 8.879184522388458\n 8.608521978391984\n 8.302235859798492\n 7.977752408265428\n 7.6479265310498565\n 7.293056293658903\n 6.933942335839723\n 6.569662630859385\n 6.203645482991124\n 5.835689949822736\n 5.4639327723474995\n 5.082524806480722\n ⋮\n 2.180830466139856\n 2.179270649906686\n 2.177861954789722\n 2.1766481390536\n 2.1755648676013255\n 2.174661007473904\n 2.1739250919601236\n 2.1733597626038192\n 2.1729302781639843\n 2.1726139439247745\n 2.172383095801758\n 2.172315739557126\n```\n:::\n:::\n\n\nSecond, we can an estimate of species persistence - how many have gone extinct! Remember that we started with 20, so a value of 0.45 means that there are 12 species left.\n\n::: {#9257433c .cell execution_count=17}\n``` {.julia .cell-code}\n# the percentage that persist\npersistence(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```\n51-element Vector{Float64}:\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n ⋮\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n```\n:::\n:::\n\n\n::: {#9382737c .cell execution_count=18}\n``` {.julia .cell-code}\n# quick calculation of number left (but see richness below!)\n20*persistence(sim_niche) # the number left\n```\n\n::: {.cell-output .cell-output-display execution_count=16}\n```\n51-element Vector{Float64}:\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n ⋮\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n```\n:::\n:::\n\n\nThird, we can look at measures of diversity. First, we can get species richness and a measure of diversity, using the Shannon index. This confirms that our persistence estimate (45%) is in line!\n\n::: {#d23b4942 .cell execution_count=19}\n``` {.julia .cell-code}\nrichness(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=17}\n```\n51-element Vector{Int64}:\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n ⋮\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n```\n:::\n:::\n\n\n::: {#06511816 .cell execution_count=20}\n``` {.julia .cell-code}\nshannon_diversity(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=18}\n```\n51-element Vector{Float64}:\n 15.838289686150633\n 15.938034479922063\n 16.062630873979742\n 16.120434078447378\n 16.08114076965578\n 15.938487296717936\n 15.697940272210305\n 15.410182133499104\n 15.107012611506958\n 14.810310060152338\n 14.548540861111752\n 14.364162310889597\n 14.284610563485106\n ⋮\n 8.172811865080977\n 8.1142305814134\n 8.05780958633494\n 8.006127953781233\n 7.956790341905648\n 7.911831829238024\n 7.87087151813162\n 7.835016456582986\n 7.803489117438748\n 7.776056823831216\n 7.751865699167424\n 7.743665633968\n```\n:::\n:::\n\n\n::: callout-caution\n## Warning\n\nSection is no longer a built-in functionality in END. Alain should be able to address\n:::\n\nFinally, we can look at stability - all built in metrics of stability are based on the coefficient of variation of species biomass. The CV is a measure of standardised variation - the standard [deviation / mean](https://en.wikipedia.org/wiki/Coefficient_of_variation) It is not 'stability' in the strict mathematical sense, but an estimation of how variable the dynamics are.\n\ndefined as the average coefficient of variation estimated across all of the coefficients of variation for each species.\n\nThe master function is `coefficient_of_variation` and delivers four results - Coefficient of Variation (CV) of community biomass and its partition into average species CV (`community_cv` above), species mean CV and synchrony, along with the variation of each species; following Thibault & Connolly (2013):\n\n::: {#341a25bd .cell execution_count=21}\n``` {.julia .cell-code}\ncoefficient_of_variation(sim_niche)\n```\n:::\n\n\nNote the warning.... do you understand what it's talking about? Think about the extinctions detail above. You can follow the instructions, right?\n\n::: {#6617b8c0 .cell execution_count=22}\n``` {.julia .cell-code}\ncoefficient_of_variation(sim_niche, last = 4)\n```\n:::\n\n\nYou can get parts of this with specific helper functions, such as:\n\n::: {#d86da1ed .cell execution_count=23}\n``` {.julia .cell-code}\ncommunity_cv(sim_niche, last = 4)\n```\n:::\n\n\n### What's next\n\nThe next section will introduce how to create simulations where we work with multiple networks and collect data across these. We do this using loops, and collect information in a data frame. We then work on how to embed additional changes to parameters in the loops as well.\n\n## References\n\n::: {#refs}\n:::\n\n", + "engine": "julia", + "markdown": "---\ntitle: \"Tutorial 8: Introducing Ecological Networks Dynamics (END)\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nabstract: |\n This section of the tutorials initiates you into using the Bioenergetic Food Web Model.\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nbibliography: references.bib\nengine: julia\n---\n\n\n\n\n\n\n\n## Using the Bioenergetic Food Web\n\n### Preamble: The Bioenergetic Food Web.\n\nIt is very worth pausing for a moment and looking at @delmas2017. It describes the BioEnergetic Food Web Model, provides some history of the model, and also showcases how the original `Julia` version of the model worked. This section of the tutorials is designed to introduce a newer, faster and more flexible version of the `Julia` package.\n\nA very basic interpretation of the model is as follows:\n\n1. The model is a model of biomass dynamics, not numbers of individuals.\n2. The model is comprised of an equation for plants (producers) an equation for consumers (herbivores, predators).\n3. Plants have traits that make their biomass grow and sets their carrying capacity; they are eaten by consumers via an equation describing a functional response. To link to ecology courses you have, this can be logistic growth for the plant and a type II functional response.\n4. Consumer have three sets of traits. One is metabolism, which is a rate that describes losses of biomass due to, well, metabolism! The second set of traits correspond to the functional response - for example describing attack rates and handling times of prey items. The third corresponds to the numerical response, or the conversion of biomass they eat into new biomass (e.g. babies)\n5. We can make complex networks and systems of these equations by letting many of these parameters *scale with body size* via the rules of allometry and the Metabolic Theory of Ecology. This *trick* expands the two equations to n = number of species when we provide the toolbox with a list of species biomasses.\n6. Embedded in this process are rules about how to distribute species of different sizes across trophic levels, so that we end up with predators, omnivores, herbivores and plants. We can also designate the body size relationships for different groups of organisms, like producers, invertebrates, endothermic vertebrates and ectothermic vertebrates.\n7. Once we've done this, we can simulate the biomass dynamics of complex communities. And we can summarise things like changes in biodiversity (number of species), stability (coefficient of variation of the time series) and anything about the biomass of species, trophic levels or the community!\n\n### Preamble: Setup\n\nOne of main advantages of running food web models in Julia is that simulations are fast and can be readily stored in your active project. With this in mind, make a new folder in your project called `out_objects` (right click \\> New Folder).\n\nWe will be using the `EcologicalNetworksDynamics.jl` package [@lajaaiti2024] to implement the BEFW. Although we will go through and explain the functionality it may be useful to have both the preprint as well as the complete [documentation](https://beckslab.github.io/EcologicalNetworksDynamics.jl/) on hand for more detailed explanations. You can install `EcologicalNetworksDynamics` as you would any other normal `Julia` package.\n\n\n\n\n::: {#4 .cell execution_count=0}\n``` {.julia .cell-code}\nPkg.add EcologicalNetworksDynamics\n\n```\n:::\n\n\n\n\n\n\n### A first run using Ecological Networks Dynamics (END)\n\nThere are four major steps when running the BioEnergetic Food Web model in Julia. These should be familiar from our introduction to the `DifferentialEquations` package:\n\n1. Generate an initial food web network\n2. Set the parameters for each species in the network to generate the equations\n3. Simulate the network and equations\n4. Explore output and plot\n\nWhile in the previous example with `Differential Equations` we assumed a simple 2-species network, one of the new activities here is to take advantage of a rich history of theory and tools to construct species rich networks with appropriate structural properties, such as *connectance/complexity* and levels of *generalism/specialism* and things the number of trophic levels and a body size distribution of the species across trophic levels.\n\n#### Step 1: generate an initial network {#sec-step1}\n\n\n\n\n::: {#6 .cell execution_count=0}\n``` {.julia .cell-code}\n## My first BEFW Modelling\n\n## Packages I need\nusing DataFrames, Plots, Random, Distributions\nusing EcologicalNetworksDynamics\n\n## Time to do some Experiments!\n```\n:::\n\n\n\n\n\n\nHere we make a foodweb, actually, a food chain, from an *adjacency matrix* using `Foodweb`.\n\n\n\n\n::: {#8 .cell execution_count=1}\n``` {.julia .cell-code}\nA = [0 0 0; 1 0 0; 0 1 0] # 1 basal producer ⋅ Species 2 eats 1 ⋅ Species 3 eats 2\nfoodweb = Foodweb(A)\n```\n:::\n\n\n\n\n\n\n#### Step 2: Generate the model parameters\n\nOnce the foodweb is created, the next step is to attribute values to the model parameters. This can be simply done by calling `default_model` with foodweb as an argument.\n\n\n\n\n::: {#10 .cell execution_count=1}\n``` {.julia .cell-code}\n# construct the equations and fixed parameters\n# see below for body size dependent parameters etc\nparams = default_model(foodweb)\n```\n:::\n\n\n\n\n\n\nIf we look at our `params` object we can see that it has all the required parameters for the **BEFW**. Later in this tutorial you will see how we can access and modify these parameters.\n\n#### Step 3: Simulate biomass dynamics\n\nEverything is ready to run the simulation, which can be simply done by calling simulate with the model parameters (params) and a vector species' initial biomass (B0).\n\n\n\n\n::: {#12 .cell execution_count=1}\n``` {.julia .cell-code}\n# create body sizes for each species\nB0 = [0.5, 0.5, 0.5]\n# specify number of time steps\nt = 300\n\n# use simulate function\n# builds equations and uses DiffEq to run them!\nsim = simulate(params, B0, t)\n```\n:::\n\n\n\n\n\n\n#### Step 4: Seeing the outputs!\n\nTo plot the time series, we can use the actual `simulate` object directly.\n\n\n\n\n::: {#14 .cell execution_count=1}\n``` {.julia .cell-code}\n plot(sim, label = [\"Producer\" \"Consumer\" \"Top consumer\";])\n```\n:::\n\n\n\n\n\n\nEventually you may want to plot the biomass dynamics - the trajectory - of your community to see what is happening. For our minimal example, it can be done as follows:\n\n\n\n\n::: {#16 .cell execution_count=1}\n``` {.julia .cell-code}\n\n# create multiple objects: time = t pulled from the sim.t component\n# and Bx = biomass for each species pulled from the larger sim object\n# note how julia allows multiple things on left of the =\nt, B1, B2, B3 = sim.t, sim[1,:], sim[2,:], sim[3,:] # unpack variables\n\n# Plot the basal species\nplot(t, B1, lw = 3, label=\"Producer\", xlabel = \"Time\", ylabel = \"Biomass\")\n# add the herbivore\nplot!(t, B2, lw = 3, label=\"Consumer\")\n# add the top predator\nplot!(t, B3, lw = 3, label=\"Top consumer\")\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\n## A More Complex Example\n\n#### Step 1: Generate the initial network\n\nIn order to run the BEFW model with a more complex network, we have to construct an initial food web network (an adjacency matrix) using the niche model [@williams2000]. The network is characterised by the number of species in the network and its [connectance/complexity](https://en.wikipedia.org/wiki/Ecological_network) value.\n\nNote that we are now using functionality provided by the `EcologicalNetworks` package.\n\n\n\n\n::: {#18 .cell execution_count=1}\n``` {.julia .cell-code}\nS = 20 # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\n\n# construct the food web\nRandom.seed!(12325) # ensures your network and this one are the same\nfoodweb_niche = Foodweb(:niche; S = S, C = C)\n\n```\n:::\n\n\n\n\n\n\n#### Step 2. Setting up the parameters, body masses (species) and running the model!\n\nAs above, our next step is to define a vector of bodymasses and then pass this, and the network to the `simulate` function. Here we combine the `Uniform` function from the *Distributions* package with the `rand` function from the *Random* package.\n\n\n\n\n::: {#20 .cell execution_count=1}\n``` {.julia .cell-code}\n# construct the equations and fixed parameters\n# see below for body size dependent parameters etc\nparams_niche = default_model(foodweb_niche)\n\n# define bodymasses between 0 and 1 and get S = 20 of them.\n# this will ensure your plot looks like the one in the document\nRandom.seed!(123)\nB0 = rand(S)\nt = 300\n\n# simulate using params and bodymasses\n# note additional argument tmax for max time steps\n# default is 300\nsim_niche = simulate(params_niche, B0, t)\n```\n:::\n\n\n\n\n\n\n#### Step 3. Visualising the dynamics\n\nNow we can move to plotting again. Note how we now ask for the time directly from the simulate object and all of the biomasses from that object as well.\n\nNote too how we can suppress the legend (which covers some of the time series).\n\n\n\n\n::: {#22 .cell execution_count=1}\n``` {.julia .cell-code}\nplot(sim_niche, legend = false)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n\n\n\n\nOne game to play now is to alter the bodymass distribution. `rand` selects a random uniform number between 0 and 1. Can you figure out how to make the distribution uniform between 0 and 10? See what that does.\n\n#### A bit more about the process: dissecting the ModelParameters\n\nLet's dissect the `default_model` object a bit, to understand just a bit more about what is going on.\n\n\n\n\n::: {#24 .cell execution_count=1}\n``` {.julia .cell-code}\nparams_niche\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n\n::: {.ansi-escaped-output}\n```{=html}\n
Model (alias for EcologicalNetworksDynamics.Framework.System{<inner parms>}) with 17 components:\n  - Species: 20 (:s1, :s2, :s3, :s4, ..., :s20)\n  - Foodweb: 82 links\n  - Body masses: [396.6757314506745, 1000.0, 138.23722273578997, 150.62580571223663, ..., 1.0]\n  - Metabolic classes: [:invertebrate, :invertebrate, :invertebrate, :invertebrate, ..., :producer]\n  - GrowthRate: [·, ·, ·, ·, ..., 1.0]\n  - Carrying capacity: [·, ·, ·, ·, ..., 1.0]\n  - ProducersCompetition: 1.0\n  - EcologicalNetworksDynamics.LogisticGrowth\n  - Efficiency: 0.45 to 0.85.\n  - MaximumConsumption: [8.0, 8.0, 8.0, 8.0, ..., ·]\n  - Hill exponent: 2.0\n  - Consumers preferences: 0.07692307692307693 to 1.0.\n  - Intra-specific interference: [·, ·, ·, ·, ..., ·]\n  - Half-saturation density: [0.5, 0.5, 0.5, 0.5, ..., ·]\n  - EcologicalNetworksDynamics.BioenergeticResponse\n  - Metabolism: [0.0703591752903408, 0.05583797347522218, 0.09157425582526797, 0.08963029015067063, ..., 0.0]\n  - Mortality: [0.0, 0.0, 0.0, 0.0, ..., 0.0]
\n```\n:::\n\n:::\n:::\n\n\n\n\n\n\nWalking through this\n\n::: callout-caution\n## Warning\n\nThis section still reflects the old version of END structure and naming conventions\n:::\n\n1. The `network` component defines the food web and reports the number of species and the links\n2. the `environment` component reports on values of the carrying capacity (K) and the baseline temperature (`T`). Note that K is specified only for the basal species via `[1, 1, ... nothing, nothing]`. All the producers have the same K at this point (1,1,1...). The presence of the `T` suggests that we can ultimately work with climate change by running the model at different temperatures. There is a way to make some of the biorates and components of the functional response (see 3, 4) dependent not only on body mass, but also on temperature.\n3. the `biorates` component contains detail on parameters central to making the model reflect a bit of reality: `d` is ...; `r` is the intrinsic rate of increase (population growth rate) for the producers (plants); `x` and `y` are parameters associated with metabolic rates and consumption rates of the consumers (non-plant species). Finally, `e` is an efficiency/assimilation rate for the consumers eating either plants or other animals.\n4. the `functional_response` component defines the type of *consumption function* being used (e.g. Type I, II, or III sensu classic ecology and Holling). The functional response defines the *interaction strength* between species and how consumers change how much they eat dependent on the amount (density) of resource available.There are two options. The default `Bioenergetic Response` corresponds to a *phenomenological* formulation where there are just two variables that describe how consumer consumption varies with resource density: a *half-saturation* parameter and an *asymptote*. The alternative called `Classic Response` is more *trait based* and includes the parameters *attack rate* and *handling time*. There are several other features of the functional response that can be manipulated, and these are introduced in later tutorials.\n5. the `producer_growth` details the default that all plants are growing logistically.\n6. the `temperature response`componewnt defines the absence or presence of temperature dependence, and when present, the shape of the relationship between biorates and functional response parameters and temperature.\n\n### Helper Functions: What can we do with the outputs?\n\n::: callout-caution\n## Warning\n\nThis section should be reviewed and revised by an END user who knows what we want to do with outputs.\n:::\n\nAs noted in the pre-amble, we are most often interested in additional information about the scenarios we build with the models. These include, for example, total biomass, biodiversity and stability. Let's see how we can calculate some of these.\n\n#### How long till steady state?\n\nWe can find out how long the simulations ran to reach steady state - remember that this is a deterministic model that typically reaches equilibrium for all species that survive.\n\n\n\n\n::: {#26 .cell execution_count=1}\n``` {.julia .cell-code}\nsize(sim_niche.t)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n(51,)\n```\n:::\n:::\n\n\n\n\n\n\n#### Who went extinct and when?\n\n::: callout-caution\n## Warning\n\nNot a functionality in END.\n:::\n\nWe can also find out who went extinct, and when. You saw some of that detail, I hope, in the output of `simulate`.\n\n\n\n\n::: {#28 .cell execution_count=0}\n``` {.julia .cell-code}\nget_extinct_species(sim_niche)\n```\n:::\n\n\n\n\n\n\n#### Biomass, Diversity and Stability\n\nFirst, we can get a measure of total biomass in the community, at equilibrium, and that of each species. Note how you can get the components too.\n\n\n\n\n::: {#30 .cell execution_count=1}\n``` {.julia .cell-code}\nsim_niche.u\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n51-element Vector{Vector{Float64}}:\n [0.906299638797481, 0.44349373245960455, 0.7456733811393941, 0.5120830400366143, 0.2538490889415096, 0.33415153638191886, 0.4273278808735992, 0.867547200255958, 0.09913361484360417, 0.12528740769155033, 0.6922086620547391, 0.13655147513745736, 0.03209667335274724, 0.3505458214588266, 0.9303323763821093, 0.9594335994071538, 0.5819123423876457, 0.3114475007050529, 0.12114752051812694, 0.20452981732035946]\n [0.9169483131714715, 0.444402194534041, 0.7667640455857161, 0.5179071161683636, 0.25596644376248334, 0.3439614083570855, 0.42881389580038637, 0.8404857181508336, 0.10207349613818459, 0.12980979255930417, 0.7045585608788062, 0.14142469702894178, 0.033700254458592344, 0.35322775442579823, 0.9254383246584946, 0.8428424981719224, 0.5353929049386887, 0.2716712297929136, 0.11790964375471776, 0.20588623005171253]\n [0.9372189186622565, 0.446138581295766, 0.8030805319662981, 0.5280429096670912, 0.25960285298532004, 0.36088969827160805, 0.43143000229873113, 0.7941678141517742, 0.107334065965393, 0.13803877097876832, 0.7224846396419364, 0.150274714852675, 0.03655779055568964, 0.35202356186576755, 0.8867871855452475, 0.6561325211685619, 0.45370991951901846, 0.21879863147029777, 0.1144327890249893, 0.21137607850479412]\n [0.963419944890434, 0.4478457678502066, 0.8407656301021255, 0.5394619505769526, 0.26358620538619504, 0.3785307293750754, 0.43443524658702654, 0.7426580903726461, 0.11338938338304744, 0.1475698891121404, 0.7345099631141349, 0.16048747662896795, 0.03959434344670769, 0.3379755377009729, 0.7958692645000881, 0.48283669535781387, 0.36706195693003885, 0.17548000193294144, 0.1136592394878268, 0.22309854306314952]\n [0.995616193064571, 0.44805738727466143, 0.8700643195894429, 0.5512240918443782, 0.2674989824178032, 0.3924051349926597, 0.4375425793363201, 0.6886449125246876, 0.11960335804730916, 0.15695502649258633, 0.7327878032629778, 0.17047486846995694, 0.0420936774665965, 0.3062032871443506, 0.6610340292426684, 0.34855000462048347, 0.2881369319293169, 0.14175624955652485, 0.11666389844136492, 0.24243967254676815]\n [1.0331366869886944, 0.44448629343725343, 0.8788288901686566, 0.5620901047900512, 0.2708572048035862, 0.39695429480179645, 0.44018298027640984, 0.6333401253753693, 0.1252037789780579, 0.1640984843116221, 0.7114983769875807, 0.17795514254857084, 0.04354809380952039, 0.26092610308891634, 0.5154058541922188, 0.25624511921879434, 0.22330145420147088, 0.11586948470233616, 0.12436895504970236, 0.26962910331924905]\n [1.0773089982155897, 0.43396923698721435, 0.8556572961992899, 0.5707904139404543, 0.2731983214483226, 0.38705755776238965, 0.4413794083264426, 0.57197930814629, 0.12978003467017415, 0.16724868374246712, 0.6675169557355778, 0.18101017312972054, 0.04388752925907648, 0.20909394578211202, 0.3805309865842198, 0.19230727005942244, 0.16943175281775166, 0.09443672996682428, 0.13906102138589269, 0.30741066949967055]\n [1.1213743703927337, 0.4149870885160012, 0.7975741540831984, 0.5733620864984142, 0.2733077885606147, 0.36141676843558873, 0.4391552288251882, 0.5071960218562799, 0.13225598133704913, 0.1649144766546638, 0.6093837906327526, 0.17807037605762552, 0.04315159765633695, 0.1631734536430942, 0.2790930366914647, 0.15237925689592774, 0.12890880773111002, 0.0777317468581009, 0.16225155189984958, 0.35425475261372863]\n [1.1573410183305781, 0.3875799067335869, 0.7122633234623346, 0.5656661531044221, 0.2699342224158771, 0.32362037390928877, 0.43151833519945715, 0.43980122366299085, 0.1320832740044849, 0.15754833392958092, 0.5485937790090555, 0.16967851768901068, 0.04155688582593655, 0.12670961646818607, 0.20790093579654878, 0.12919220653556573, 0.09920527144448085, 0.06511083602693121, 0.1957265685332169, 0.40863184877785175]\n [1.1744909386178761, 0.35353525150930704, 0.6130415990319116, 0.5442924204781258, 0.2619765432579562, 0.2797239154423789, 0.41725964546931765, 0.3734718885747243, 0.12906194711831975, 0.14648620822639452, 0.49617455885534983, 0.15734180901650238, 0.039351964038387546, 0.0993990767009241, 0.15977668195469585, 0.1193453433823383, 0.07853078787521317, 0.05684848395648957, 0.23880211323157663, 0.46473430625333423]\n ⋮\n [6.07969185813491e-5, 0.00013150891522278353, 5.122984902532575e-5, 5.0559263528295375e-6, 0.0011197509119850043, 2.721092248119792e-5, 0.004805123705498752, 0.2371493862104039, 0.02034698607033935, 2.4630532478594332e-5, 0.44507776580317365, 2.591108561516969e-5, 0.19582059389086015, 0.10090484291104647, 0.04175110898630074, 0.21605866945798072, 0.009748297718843965, 0.1109547748500005, 0.308965762906422, 0.48361873148098766]\n [2.9540113221979872e-5, 8.00347447973086e-5, 2.6268553079549285e-5, 2.3358462951272875e-6, 0.0008502538978690424, 1.3952641028662382e-5, 0.0036125895986525765, 0.23963412412998863, 0.017924696653654346, 1.2629101514971793e-5, 0.4453417610345992, 1.3285671319358326e-5, 0.19486664345382582, 0.10209874101875081, 0.041891604062307145, 0.2160237975426658, 0.00956208380761516, 0.11101835580249045, 0.3089707135225891, 0.48359145640506035]\n [1.3166616427449579e-5, 4.60961582614326e-5, 1.241859399595492e-5, 9.875013357564836e-7, 0.0006289434801525733, 6.596183545884943e-6, 0.0026293723865516917, 0.24190491545204867, 0.015626334170708748, 5.970359692556319e-6, 0.44560575498650923, 6.280744324641365e-6, 0.19400924653479448, 0.10314206416955765, 0.04204857588531362, 0.2160007866180423, 0.009371522869382096, 0.11107366457263641, 0.3089769794039354, 0.48355133078668755]\n [5.288582093742206e-6, 2.4853056623534485e-5, 5.32431964558186e-6, 3.7495755123700837e-7, 0.0004510237192764804, 2.8280327624688987e-6, 0.0018418173438047715, 0.24395924306889033, 0.013458321791607284, 2.559692577943294e-6, 0.44587256631997335, 2.692763414898462e-6, 0.19326957086896235, 0.10403490013949204, 0.04222157762263886, 0.21597907364688387, 0.009176377022194124, 0.11112583015368675, 0.30898347361961076, 0.4835073952384332]\n [1.960571333984018e-6, 1.2748386630159753e-5, 2.115911956181734e-6, 1.3122771778296083e-7, 0.00031649230625780636, 1.1238747466059242e-6, 0.0012535673852407435, 0.2457433105385709, 0.011504652249667801, 1.0172301703560636e-6, 0.44612733302168156, 1.0701126911743665e-6, 0.19267165202271308, 0.1047507539103007, 0.04240100704365944, 0.21595925499391128, 0.008984468602875842, 0.11117426849212075, 0.30898978378818076, 0.48346305093339226]\n [6.595296475377276e-7, 6.157495485353746e-6, 7.673573735587585e-7, 4.1573174269355544e-8, 0.0002163095240186386, 4.0758481170993133e-7, 0.0008246351715236552, 0.24730063052972948, 0.009744807150823888, 3.6890828571649465e-7, 0.4463589658982419, 3.880865976484553e-7, 0.19219749029253488, 0.10531819548561512, 0.042584771757986466, 0.21594251593637606, 0.008795235529894242, 0.11122083597743129, 0.3089962400343031, 0.48342085434013]\n [2.0108052810226762e-7, 2.8004575219465937e-6, 2.5369560293790977e-7, 1.190656631256341e-8, 0.00014408987057401768, 1.3475139250220505e-7, 0.0005246117248146955, 0.24864251960077316, 0.008183727277329841, 1.2196446538994685e-7, 0.4465625705694917, 1.2830498581813105e-7, 0.19183327165148306, 0.10575941597710509, 0.04276848561656389, 0.21592768854223388, 0.008611086962690943, 0.11126649455166937, 0.30900276016604544, 0.4833835692529364]\n [5.35850498787597e-8, 1.174593201709331e-6, 7.398752912499898e-8, 2.965192061208363e-9, 9.266705935747393e-5, 3.929875986723788e-8, 0.00031929137827090367, 0.24981133030734196, 0.006788855740405869, 3.556958190340493e-8, 0.4467437607797747, 3.7418723667047955e-8, 0.19155285868338037, 0.10610455981258715, 0.04295191471606665, 0.21591384077514106, 0.008430160333184566, 0.1113122756892104, 0.30900934087551246, 0.48335082223348647]\n [3.2821854904203205e-8, 8.406671643638472e-7, 4.6640508998017896e-8, 1.7793663607263053e-9, 7.799523091116062e-5, 2.4773285240091262e-8, 0.0002627973314424048, 0.2502039748903548, 0.00631276636245039, 2.2422472598477954e-8, 0.4468055436036614, 2.358814075481337e-8, 0.19146688286657296, 0.10621159455428622, 0.04301932407939025, 0.21590899888568155, 0.008364030293673712, 0.11132929056683419, 0.3090117977250657, 0.4833397504740079]\n```\n:::\n:::\n\n\n\n::: {#32 .cell execution_count=1}\n``` {.julia .cell-code}\n# components\ntotal_biomass(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n51-element Vector{Float64}:\n 9.035052310145453\n 8.879184522388458\n 8.608521978391984\n 8.302235859798492\n 7.977752408265428\n 7.6479265310498565\n 7.293056293658903\n 6.933942335839723\n 6.569662630859385\n 6.203645482991124\n ⋮\n 2.1766481390536\n 2.1755648676013255\n 2.174661007473904\n 2.1739250919601236\n 2.1733597626038192\n 2.1729302781639843\n 2.1726139439247745\n 2.172383095801758\n 2.172315739557126\n```\n:::\n:::\n\n\n\n\n\n\nSecond, we can an estimate of species persistence - how many have gone extinct! Remember that we started with 20, so a value of 0.45 means that there are 12 species left.\n\n\n\n\n::: {#34 .cell execution_count=1}\n``` {.julia .cell-code}\n# the percentage that persist\npersistence(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n51-element Vector{Float64}:\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n ⋮\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n```\n:::\n:::\n\n\n\n::: {#36 .cell execution_count=1}\n``` {.julia .cell-code}\n# quick calculation of number left (but see richness below!)\n20*persistence(sim_niche) # the number left\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n51-element Vector{Float64}:\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n ⋮\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n```\n:::\n:::\n\n\n\n\n\n\nThird, we can look at measures of diversity. First, we can get species richness and a measure of diversity, using the Shannon index. This confirms that our persistence estimate (45%) is in line!\n\n\n\n\n::: {#38 .cell execution_count=1}\n``` {.julia .cell-code}\nrichness(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n51-element Vector{Int64}:\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n ⋮\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n```\n:::\n:::\n\n\n\n::: {#40 .cell execution_count=1}\n``` {.julia .cell-code}\nshannon_diversity(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=1}\n```\n51-element Vector{Float64}:\n 15.838289686150633\n 15.938034479922063\n 16.062630873979742\n 16.120434078447378\n 16.08114076965578\n 15.938487296717936\n 15.697940272210305\n 15.410182133499104\n 15.107012611506958\n 14.810310060152338\n ⋮\n 8.006127953781233\n 7.956790341905648\n 7.911831829238024\n 7.87087151813162\n 7.835016456582986\n 7.803489117438748\n 7.776056823831216\n 7.751865699167424\n 7.743665633968\n```\n:::\n:::\n\n\n\n\n\n\n::: callout-caution\n## Warning\n\nSection is no longer a built-in functionality in END. Alain should be able to address\n:::\n\nFinally, we can look at stability - all built in metrics of stability are based on the coefficient of variation of species biomass. The CV is a measure of standardised variation - the standard [deviation / mean](https://en.wikipedia.org/wiki/Coefficient_of_variation) It is not 'stability' in the strict mathematical sense, but an estimation of how variable the dynamics are.\n\ndefined as the average coefficient of variation estimated across all of the coefficients of variation for each species.\n\nThe master function is `coefficient_of_variation` and delivers four results - Coefficient of Variation (CV) of community biomass and its partition into average species CV (`community_cv` above), species mean CV and synchrony, along with the variation of each species; following Thibault & Connolly (2013):\n\n\n\n\n::: {#42 .cell execution_count=0}\n``` {.julia .cell-code}\ncoefficient_of_variation(sim_niche)\n```\n:::\n\n\n\n\n\n\nNote the warning.... do you understand what it's talking about? Think about the extinctions detail above. You can follow the instructions, right?\n\n\n\n\n::: {#44 .cell execution_count=0}\n``` {.julia .cell-code}\ncoefficient_of_variation(sim_niche, last = 4)\n```\n:::\n\n\n\n\n\n\nYou can get parts of this with specific helper functions, such as:\n\n\n\n\n::: {#46 .cell execution_count=0}\n``` {.julia .cell-code}\ncommunity_cv(sim_niche, last = 4)\n```\n:::\n\n\n\n\n\n\n### What's next\n\nThe next section will introduce how to create simulations where we work with multiple networks and collect data across these. We do this using loops, and collect information in a data frame. We then work on how to embed additional changes to parameters in the loops as well.\n\n## References\n\n::: {#refs}\n:::\n\n", "supporting": [ "8_intro_end_files" ], diff --git a/_freeze/9_experiments_end/execute-results/html.json b/_freeze/9_experiments_end/execute-results/html.json index 7ab4658..4aeaa45 100644 --- a/_freeze/9_experiments_end/execute-results/html.json +++ b/_freeze/9_experiments_end/execute-results/html.json @@ -1,8 +1,8 @@ { - "hash": "d39fe2665bdcff9e52bb9bbdc2c04c94", + "hash": "0a39070013fb8cfee78c4da8a996a262", "result": { "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 9: Experiments with the END\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\n\nIn the previous chapter, we learned how to make networks and run a simulation. We did this for a simple tri-trophic chain where we specified the network with a matrix of ones and zeros, and for a more complex network defined by the niche model where we specified species richness and connectance. We also learned how to visualise the simulations and to collect several metrics about the simulations, including detail on biomass, diversity and stability.\n\nIn this tutorial, we are going to learn how to do experiments. We'll learn first how to generate multiple networks and collect information on how network structure impacts our metrics. Then we'll learn how to manipulate parameters in the model, again collecting information on how variation in these parameters impacts our metrics.\n\nFor example, we might be interested in how species richness or connectance impacts biomass and stability. Or how the carrying capacity of the producers impacts biomass and stability of the community (e.g. bottom up processes). We'll look at both of these.\n\n### Getting Setup\n\nAs with our previous exercises, we need to have a few packages that allow making networks, simulating them and collecting the data\n\n::: {#5970f701 .cell execution_count=1}\n``` {.julia .cell-code}\nusing DataFrames, Plots, Random, Distributions\nusing EcologicalNetworksDynamics\n```\n:::\n\n\n### Your (re)introduction to loops: making multiple networks example\n\nOne of the tricks to doing experiments is learning how to run a loop. Julia is super-fast with running loops. This is a bit different to R, which has a bad rep for loops. It's not terrible. But Julia is built to do loops fast.\n\nWhat we will do here is build a simple loop that makes 3 networks, each with a different species richness, but the same connectance.\n\nNote here that we introduce the use of the argument `tol_C`. Because the `niche model` produces networks based on probability theory (it uses the beta-distribution), the connectance we ask for is not always the connectance we get. The `tol_C` argument ensure that connectance is within a _tolerance_ range - in this case, having asked for `C = 0.2` and a `tol_C = 0.01` we will get `0.19 < C < 2.01`. This is like embedding a while loop within the `FoodWeb` function! We note too that the function `nichemodel` can take a value of `L` instead of `C`, and there is an associated `tol_L` argument for this choice too.\n\n::: {#93f93e19 .cell execution_count=2}\n``` {.julia .cell-code}\nRandom.seed!(12325) # ensures your network and this one are the same\n\nS = [10,20,30] # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\n\n# collection zone for the networks\nnets = []\n\n# construct the food webs\n# we loop over the 3 values of S\n# we use push!() to add the food webs to nets\n# always start with a for and end with an end.\nfor i in 1:3\n push!(nets, Foodweb(:niche; S = S[i], C = C))\nend\n```\n:::\n\n\nGreat. Let's see if we got what we expected in nets.\n\n::: {#5558af13 .cell execution_count=3}\n``` {.julia .cell-code}\nnets\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n3-element Vector{Any}:\n blueprint for Foodweb with 22 trophic links\n blueprint for Foodweb with 81 trophic links\n blueprint for Foodweb with 182 trophic links\n```\n:::\n:::\n\n\nMagnificent, we have three networs and that's a win. We also see that they are each for a different and appropriate S. Win no. 2. We can actually now check to see what the connectances actually are. Again, we'll use a loop, `println` and introduce you to the details of the `FoodWeb` object.\n\nFirst, let's look at one of the networks.\n\n::: {#437965d3 .cell execution_count=4}\n``` {.julia .cell-code}\nnets[1]\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\nblueprint for Foodweb with 22 trophic links:\n A: 10×10 SparseArrays.SparseMatrixCSC{Bool, Int64} with 22 stored entries:\n ⋅ 1 1 1 1 1 1 1 1 1\n ⋅ 1 1 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ 1 1 1 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 1\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ 1 1 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n```\n:::\n:::\n\n\nWe can see that the `A` element is the matrix and you can guess that the `M` is the body `M`asses. We also find tha there are 3 producers and 7 invertebrates and it is derived from the niche model\n\n::: {.callout-tip}\n\nA side note on the metabolic classes. The default parametrisation, and nearly all of the published work with the BEFW, uses invertebrates for all the non-producer species. It is possible to include others. But the data, currently, are not helpful (low volume) in supporting robust inference with these types of species.\n:::\n\nNow, recall that we can look specifically at the matrix by using `nets[1].A` which grabs the `A` part. We introduce here the function `sum`. As in **R**, `sum()` does what it says on the tin: for a vector, it addes up all the numbers and for a matrix, it does the same! In our case here, when `sum()` is applied to a matrix of ones and zeros, it counts all the 1's.... thus is the estimate of the number of links in the community. \n\nFinally, we note (again?) that `size` applied to the network returns two numbers - the number of rows and the number of columns. For our networks, the matrix is square. So grabbing one of these (rows = [1]) and squaring it delivers our 'potential number of links' (e.g. $species^2$). \n\nWe can put that all together here to define connectance as $Con = links/S^2$. Do be careful to watch where you put the various `[]`'s. One of them is about the _index_ (i.e. `[i]`) and the other is about the dimension (`[1]`) of the matrix.\n\n::: {#47d43053 .cell execution_count=5}\n``` {.julia .cell-code}\nfor i in 1:3\n println(sum(nets[i].A)/size(nets[i].A)[1]^2)\n end\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n0.22\n0.2025\n0.20222222222222222\n```\n:::\n:::\n\n\n#### Different ways to run loops.\n\nThere is another way to make this set of networks. Here we use a `while` loop to create 3 networks with the same species richness and connectance. We might need to do this to generate _replicates_. This is a good exercise with the **niche model** as it reminds you that it is a probabilistic tool... you can get several networks with the same S and C, but the links will be in slightly different places.\n\n`while` loops work on conditions... for example, if we want three networks, we could ask that the loop keep working to make the networks until we have three. To do this, we need a _monitoring_ variable that lets us assess where we are against our target.\n\nLets see how to do that.\n\n::: {#38a5c44c .cell execution_count=6}\n``` {.julia .cell-code}\n# how many replicates do we want?\nreps = 3\n\nbegin\n\t# list to store networks\n\tglobal networks = []\n\t# monitoring variable l (the letter l)\n\tglobal l = length(networks)\n\n # while loop\n\twhile l < reps # reps is 3 here...\n\t # generate a network\n\t A = Foodweb(:niche; S = 20, C = 0.15)\n\t # add the network to the set\n push!(networks, A)\n # update the monitor\n\t global l = length(networks)\n\tend\nend\n```\n:::\n\n\nThe term `global` means that the obects are made available in our global environment and should be there for us to see. If you look closely at the mini-matrices, you'll see they are all different in micro-structure, despite having the same number of links and the same connectance.\n\n::: {.callout-note}\n\nThe presentation of the matrix is very specific here... the rows correspond to the predators and the columns the resources. Obstensibly, the ranking is by body size, so small things are at the upper left. This view shows that big things tend to eat small and big things, while small things eat small. Historically, the reflection (pivot around the diagnol) has also been used, where the predators are the columns and the resources the rows. This lead to a 'feature' of real and theoretical networks aligning, call `upper triangularity`. In this latter presentation, most of the links would be in the upper triangle. In the current presentation, the links are in the lower triangle. So we can just call the feature `triangularity`. The niche model reproduces this triangularity.\n:::\n\n::: {#6c334610 .cell execution_count=7}\n``` {.julia .cell-code}\nnetworks\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\n3-element Vector{Any}:\n blueprint for Foodweb with 55 trophic links\n blueprint for Foodweb with 63 trophic links\n blueprint for Foodweb with 62 trophic links\n```\n:::\n:::\n\n\n::: {#85ba739e .cell execution_count=8}\n``` {.julia .cell-code}\nnetworks[1].A\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 55 stored entries:\n⎡⠉⠉⠉⣉⡡⠐⠒⠒⠒⠂⎤\n⎢⠀⠀⠀⠀⠀⠔⠒⠒⠒⠂⎥\n⎢⠀⠀⠀⠀⠨⠕⠒⠒⠒⠂⎥\n⎢⠀⠀⠀⠀⠀⠀⠐⠒⠿⡅⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦\n```\n:::\n:::\n\n\n::: {#cf0160c2 .cell execution_count=9}\n``` {.julia .cell-code}\nnetworks[2].A\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 63 stored entries:\n⎡⠉⠩⠭⠉⠉⠁⠀⠀⠀⠒⎤\n⎢⠀⠀⠈⠒⣒⠒⠒⠶⠤⠀⎥\n⎢⠀⠀⠀⠀⠒⠀⠨⣭⣭⡤⎥\n⎢⠀⠀⠀⠀⠀⠀⠀⠤⠤⠉⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠐⠛⎦\n```\n:::\n:::\n\n\n::: {#51cf9243 .cell execution_count=10}\n``` {.julia .cell-code}\nnetworks[3].A\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 62 stored entries:\n⎡⣀⣭⣭⣍⣉⣉⡉⠉⠁⠀⎤\n⎢⠀⠀⠀⠉⠉⠁⢠⠤⠤⠤⎥\n⎢⠀⠀⠀⠀⠀⠉⢰⣶⠀⠀⎥\n⎢⠀⠀⠀⠀⠀⠀⠈⠉⡀⠀⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦\n```\n:::\n:::\n\n\n### Linking the networks to the Ecological Networks Dynamics\n\nFantastic. Now you are ready for the next steps. We want to run the `EcologicalNetworksDynamics` model on each of these networks. Furthermore, we want to collect the biomass and stability information for all three into a data frame. Let's see how we do that.\n\n#### Step 1: Create the collecting data frame\n\nFirst, we create the holding pen for our information. We'll construct a data frame to collect five pieces of information: the network id (1,2 or 3), species richness at the start (our initial S), species richness at the end, total biomass at the end and stability at the end.\n\n::: {#1c405ecb .cell execution_count=11}\n``` {.julia .cell-code}\noutputs = DataFrame(Network = [], Init_Rich = [], Fin_Rich = [], Tot_biomass = [], Shannon_dic = [])\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```{=html}\n
0×5 DataFrame
RowNetworkInit_RichFin_RichTot_biomassShannon_dic
AnyAnyAnyAnyAny
\n```\n:::\n:::\n\n\n#### Step 2: use the pre-defined networks\n\nWe can use our `nets` object from above now. Each of these networks has a different species richness.\n\n::: {#bf2bdd00 .cell execution_count=12}\n``` {.julia .cell-code}\nfor i in 1:3\n\n # prep: define size of network\n S = size(nets[i].A)[1]\n\n # deliver some progress reporting\n println(\"\\nThis is network: \", i, \"with species richness = \", S,\"\\n\")\n\n # step A: define model paramters\n params = default_model(nets[i])\n\n # step B: define body mass\n B0 = rand(S)\n\n # step C: set number of timestamps\n t = 300\n\n # step D: simulate\n out = simulate(params, B0, t)\n\n # steps D: calculate metrics\n fin_rich = richness(out)\n fin_biomass = total_biomass(out)\n s_div = shannon_diversity(out)\n\n # step E: add things to the data frame\n # note the first arg is the data frame and then\n # the values we want allocated to the five slots\n # are in []\n push!(outputs, [i, S, fin_rich, fin_biomass, s_div])\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nThis is network: 1with species richness = 10\n\n\nThis is network: 2with species richness = 20\n\n\nThis is network: 3with species richness = 30\n\n```\n:::\n:::\n\n\nAmazing. Let's see if what we wanted collected has ended up in our data frame. Wonderful! Splendiferous. Fantabulous.\n\n::: {#0ee2b078 .cell execution_count=13}\n``` {.julia .cell-code}\nprintln(outputs)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n3×5 DataFrame\n Row │ Network Init_Rich Fin_Rich Tot_biomass Shannon_dic \n │ Any Any Any Any Any \n─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n 1 │ 1 10 [10, 10, 10, 10, 10, 10, 10, 10,… [4.70537, 4.63199, 4.53209, 4.42… [8.375, 8.40912, 8.44306, 8.4699…\n 2 │ 2 20 [20, 20, 20, 20, 20, 20, 20, 20,… [8.52201, 8.4081, 8.26162, 8.102… [15.0407, 15.0769, 15.1077, 15.1…\n 3 │ 3 30 [30, 30, 30, 30, 30, 30, 30, 30,… [14.7649, 14.5082, 14.2062, 13.8… [24.3797, 24.4948, 24.5777, 24.6…\n```\n:::\n:::\n\n\n#### Dissecting more from simulate\n\nNote the details on extinctions that comes from a model run. For example, let's revisit our `sim_niche` object (you won't necessarily have to re-run this if you are working in one big script)\n\n::: {#f90a5d58 .cell execution_count=14}\n``` {.julia .cell-code}\nS = 20; # define the number of species\nC = 0.2; # define the connectance (complexity) of the network\n\n# construct the food web\nRandom.seed!(12325) # ensures your network and this one are the same\nfoodweb_niche = Foodweb(:niche; S = S, C = C)\n\n# construct the equations and fixed parameters\nparams_niche = default_model(foodweb_niche)\n\n# define bodymasses between 0 and 1 and get S = 20 of them.\nRandom.seed!(123)\nB0 = rand(S)\n\n# simulate using params and bodymasses\n# specify number of time steps\nt = 300\nsim_niche = simulate(params_niche, B0, t)\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```\nretcode: Success\nInterpolation: 3rd order Hermite\nt: 51-element Vector{Float64}:\n 0.0\n 0.0983252574499891\n 0.28544083243480267\n 0.5267982237043161\n 0.8245753364604138\n 1.181896742988936\n 1.6418353914084878\n 2.203829100924959\n 2.893464061893281\n 3.729699102007749\n 4.728753111889612\n 5.890702747756841\n 7.2218772360496395\n ⋮\n 136.70283821576533\n 145.48441982502288\n 155.57070934467725\n 166.67876410920994\n 179.5612866567586\n 193.9800038364207\n 210.21105297520486\n 227.83156289127072\n 247.0838336915681\n 267.94281052881126\n 290.8959793077713\n 300.0\nu: 51-element Vector{Vector{Float64}}:\n [0.906299638797481, 0.44349373245960455, 0.7456733811393941, 0.5120830400366143, 0.2538490889415096, 0.33415153638191886, 0.4273278808735992, 0.867547200255958, 0.09913361484360417, 0.12528740769155033, 0.6922086620547391, 0.13655147513745736, 0.03209667335274724, 0.3505458214588266, 0.9303323763821093, 0.9594335994071538, 0.5819123423876457, 0.3114475007050529, 0.12114752051812694, 0.20452981732035946]\n [0.9169483131714715, 0.444402194534041, 0.7667640455857161, 0.5179071161683636, 0.25596644376248334, 0.3439614083570855, 0.42881389580038637, 0.8404857181508336, 0.10207349613818459, 0.12980979255930417, 0.7045585608788062, 0.14142469702894178, 0.033700254458592344, 0.35322775442579823, 0.9254383246584946, 0.8428424981719224, 0.5353929049386887, 0.2716712297929136, 0.11790964375471776, 0.20588623005171253]\n [0.9372189186622565, 0.446138581295766, 0.8030805319662981, 0.5280429096670912, 0.25960285298532004, 0.36088969827160805, 0.43143000229873113, 0.7941678141517742, 0.107334065965393, 0.13803877097876832, 0.7224846396419364, 0.150274714852675, 0.03655779055568964, 0.35202356186576755, 0.8867871855452475, 0.6561325211685619, 0.45370991951901846, 0.21879863147029777, 0.1144327890249893, 0.21137607850479412]\n [0.963419944890434, 0.4478457678502066, 0.8407656301021255, 0.5394619505769526, 0.26358620538619504, 0.3785307293750754, 0.43443524658702654, 0.7426580903726461, 0.11338938338304744, 0.1475698891121404, 0.7345099631141349, 0.16048747662896795, 0.03959434344670769, 0.3379755377009729, 0.7958692645000881, 0.48283669535781387, 0.36706195693003885, 0.17548000193294144, 0.1136592394878268, 0.22309854306314952]\n [0.995616193064571, 0.44805738727466143, 0.8700643195894429, 0.5512240918443782, 0.2674989824178032, 0.3924051349926597, 0.4375425793363201, 0.6886449125246876, 0.11960335804730916, 0.15695502649258633, 0.7327878032629778, 0.17047486846995694, 0.0420936774665965, 0.3062032871443506, 0.6610340292426684, 0.34855000462048347, 0.2881369319293169, 0.14175624955652485, 0.11666389844136492, 0.24243967254676815]\n [1.0331366869886944, 0.44448629343725343, 0.8788288901686566, 0.5620901047900512, 0.2708572048035862, 0.39695429480179645, 0.44018298027640984, 0.6333401253753693, 0.1252037789780579, 0.1640984843116221, 0.7114983769875807, 0.17795514254857084, 0.04354809380952039, 0.26092610308891634, 0.5154058541922188, 0.25624511921879434, 0.22330145420147088, 0.11586948470233616, 0.12436895504970236, 0.26962910331924905]\n [1.0773089982155897, 0.43396923698721435, 0.8556572961992899, 0.5707904139404543, 0.2731983214483226, 0.38705755776238965, 0.4413794083264426, 0.57197930814629, 0.12978003467017415, 0.16724868374246712, 0.6675169557355778, 0.18101017312972054, 0.04388752925907648, 0.20909394578211202, 0.3805309865842198, 0.19230727005942244, 0.16943175281775166, 0.09443672996682428, 0.13906102138589269, 0.30741066949967055]\n [1.1213743703927337, 0.4149870885160012, 0.7975741540831984, 0.5733620864984142, 0.2733077885606147, 0.36141676843558873, 0.4391552288251882, 0.5071960218562799, 0.13225598133704913, 0.1649144766546638, 0.6093837906327526, 0.17807037605762552, 0.04315159765633695, 0.1631734536430942, 0.2790930366914647, 0.15237925689592774, 0.12890880773111002, 0.0777317468581009, 0.16225155189984958, 0.35425475261372863]\n [1.1573410183305781, 0.3875799067335869, 0.7122633234623346, 0.5656661531044221, 0.2699342224158771, 0.32362037390928877, 0.43151833519945715, 0.43980122366299085, 0.1320832740044849, 0.15754833392958092, 0.5485937790090555, 0.16967851768901068, 0.04155688582593655, 0.12670961646818607, 0.20790093579654878, 0.12919220653556573, 0.09920527144448085, 0.06511083602693121, 0.1957265685332169, 0.40863184877785175]\n [1.1744909386178761, 0.35353525150930704, 0.6130415990319116, 0.5442924204781258, 0.2619765432579562, 0.2797239154423789, 0.41725964546931765, 0.3734718885747243, 0.12906194711831975, 0.14648620822639452, 0.49617455885534983, 0.15734180901650238, 0.039351964038387546, 0.0993990767009241, 0.15977668195469585, 0.1193453433823383, 0.07853078787521317, 0.05684848395648957, 0.23880211323157663, 0.46473430625333423]\n [1.1636651009007108, 0.3155425241026375, 0.5129043599973696, 0.5086210124289895, 0.24908969960788688, 0.23553191470443982, 0.3966456636545259, 0.3124900352369809, 0.12355869405172261, 0.13330212010711523, 0.45885425946835634, 0.14280589051662543, 0.036833828434965285, 0.07940681588029759, 0.1280065867800307, 0.12159259236413968, 0.06534238144397321, 0.053601952458352684, 0.28528412637082984, 0.5126103913127859]\n [1.1215900120487023, 0.2768216752264026, 0.42206636648520485, 0.46189135063482056, 0.23215126320140814, 0.19551978933588599, 0.37144587200796514, 0.26042387609908113, 0.11647562742120145, 0.11955373899209087, 0.4381554894529827, 0.1277697315605396, 0.034397853577932694, 0.06512710102028911, 0.10768752758342186, 0.13551750917697, 0.058102384679568894, 0.055907692857973916, 0.3220846544335181, 0.5412432565515389]\n [1.051674472438156, 0.2396400556460993, 0.34499392466732914, 0.408962875223587, 0.21264909765819076, 0.16158429863184295, 0.3435589630316772, 0.2180232510648064, 0.10878792457246415, 0.10632571872188118, 0.43013574616355804, 0.11339063974249527, 0.03248700163555598, 0.055268908325187105, 0.0946316891444375, 0.1595784203240174, 0.05459709129704919, 0.0631635952778267, 0.33753068620574334, 0.5455404467088186]\n ⋮\n [0.00032755644980272486, 0.00042642730013303957, 0.00024189593390109746, 3.1111688980955344e-5, 0.002186365444974394, 0.0001284836050334962, 0.009392611128074742, 0.2289263661082618, 0.027817843518977224, 0.00011632790937708126, 0.4448717546882417, 0.0001223774188672115, 0.198564855194196, 0.09669339044487263, 0.041438780171243736, 0.21624377256231636, 0.010260398961170272, 0.1106446052574405, 0.30895191650548376, 0.48344362584850714]\n [0.0001996798247022266, 0.0003009378761392906, 0.00015346749983007282, 1.8190449427202614e-5, 0.0017884347223449826, 8.151473534424173e-5, 0.0077101296606787864, 0.23181199431785626, 0.025313811373776522, 7.379449257908107e-5, 0.44476144744230767, 7.763164111187508e-5, 0.19771575290544488, 0.0981753484444294, 0.0415237986113816, 0.21618611797874981, 0.010096001729578499, 0.1107711243020971, 0.3089588621965838, 0.4835526097023227]\n [0.00011328126257715799, 0.0002025145740727682, 9.102676275323986e-5, 9.86615934389697e-6, 0.0014273867429624918, 4.834918126253599e-5, 0.006152674701416408, 0.2345821350465174, 0.022777702555973164, 4.3766536607882777e-5, 0.44485825775398713, 4.604210489119089e-5, 0.19677603845677671, 0.0996135511824476, 0.04163063947534051, 0.21611456663905765, 0.00992313898370846, 0.1108762739174712, 0.30896257460215903, 0.4836121681503955]\n [6.07969185813491e-5, 0.00013150891522278353, 5.122984902532575e-5, 5.0559263528295375e-6, 0.0011197509119850043, 2.721092248119792e-5, 0.004805123705498752, 0.2371493862104039, 0.02034698607033935, 2.4630532478594332e-5, 0.44507776580317365, 2.591108561516969e-5, 0.19582059389086015, 0.10090484291104647, 0.04175110898630074, 0.21605866945798072, 0.009748297718843965, 0.1109547748500005, 0.308965762906422, 0.48361873148098766]\n [2.9540113221979872e-5, 8.00347447973086e-5, 2.6268553079549285e-5, 2.3358462951272875e-6, 0.0008502538978690424, 1.3952641028662382e-5, 0.0036125895986525765, 0.23963412412998863, 0.017924696653654346, 1.2629101514971793e-5, 0.4453417610345992, 1.3285671319358326e-5, 0.19486664345382582, 0.10209874101875081, 0.041891604062307145, 0.2160237975426658, 0.00956208380761516, 0.11101835580249045, 0.3089707135225891, 0.48359145640506035]\n [1.3166616427449579e-5, 4.60961582614326e-5, 1.241859399595492e-5, 9.875013357564836e-7, 0.0006289434801525733, 6.596183545884943e-6, 0.0026293723865516917, 0.24190491545204867, 0.015626334170708748, 5.970359692556319e-6, 0.44560575498650923, 6.280744324641365e-6, 0.19400924653479448, 0.10314206416955765, 0.04204857588531362, 0.2160007866180423, 0.009371522869382096, 0.11107366457263641, 0.3089769794039354, 0.48355133078668755]\n [5.288582093742206e-6, 2.4853056623534485e-5, 5.32431964558186e-6, 3.7495755123700837e-7, 0.0004510237192764804, 2.8280327624688987e-6, 0.0018418173438047715, 0.24395924306889033, 0.013458321791607284, 2.559692577943294e-6, 0.44587256631997335, 2.692763414898462e-6, 0.19326957086896235, 0.10403490013949204, 0.04222157762263886, 0.21597907364688387, 0.009176377022194124, 0.11112583015368675, 0.30898347361961076, 0.4835073952384332]\n [1.960571333984018e-6, 1.2748386630159753e-5, 2.115911956181734e-6, 1.3122771778296083e-7, 0.00031649230625780636, 1.1238747466059242e-6, 0.0012535673852407435, 0.2457433105385709, 0.011504652249667801, 1.0172301703560636e-6, 0.44612733302168156, 1.0701126911743665e-6, 0.19267165202271308, 0.1047507539103007, 0.04240100704365944, 0.21595925499391128, 0.008984468602875842, 0.11117426849212075, 0.30898978378818076, 0.48346305093339226]\n [6.595296475377276e-7, 6.157495485353746e-6, 7.673573735587585e-7, 4.1573174269355544e-8, 0.0002163095240186386, 4.0758481170993133e-7, 0.0008246351715236552, 0.24730063052972948, 0.009744807150823888, 3.6890828571649465e-7, 0.4463589658982419, 3.880865976484553e-7, 0.19219749029253488, 0.10531819548561512, 0.042584771757986466, 0.21594251593637606, 0.008795235529894242, 0.11122083597743129, 0.3089962400343031, 0.48342085434013]\n [2.0108052810226762e-7, 2.8004575219465937e-6, 2.5369560293790977e-7, 1.190656631256341e-8, 0.00014408987057401768, 1.3475139250220505e-7, 0.0005246117248146955, 0.24864251960077316, 0.008183727277329841, 1.2196446538994685e-7, 0.4465625705694917, 1.2830498581813105e-7, 0.19183327165148306, 0.10575941597710509, 0.04276848561656389, 0.21592768854223388, 0.008611086962690943, 0.11126649455166937, 0.30900276016604544, 0.4833835692529364]\n [5.35850498787597e-8, 1.174593201709331e-6, 7.398752912499898e-8, 2.965192061208363e-9, 9.266705935747393e-5, 3.929875986723788e-8, 0.00031929137827090367, 0.24981133030734196, 0.006788855740405869, 3.556958190340493e-8, 0.4467437607797747, 3.7418723667047955e-8, 0.19155285868338037, 0.10610455981258715, 0.04295191471606665, 0.21591384077514106, 0.008430160333184566, 0.1113122756892104, 0.30900934087551246, 0.48335082223348647]\n [3.2821854904203205e-8, 8.406671643638472e-7, 4.6640508998017896e-8, 1.7793663607263053e-9, 7.799523091116062e-5, 2.4773285240091262e-8, 0.0002627973314424048, 0.2502039748903548, 0.00631276636245039, 2.2422472598477954e-8, 0.4468055436036614, 2.358814075481337e-8, 0.19146688286657296, 0.10621159455428622, 0.04301932407939025, 0.21590899888568155, 0.008364030293673712, 0.11132929056683419, 0.3090117977250657, 0.4833397504740079]\n```\n:::\n:::\n\n\nWe've constructed a helper function to get information on which species go extinct and when they do.\n\n::: {.callout-caution}\n## Warning\n\nSection is no longer a built-in functionality in END. Alain should be able to address\n:::\n\n::: {#0f2558c7 .cell execution_count=15}\n``` {.julia .cell-code}\n# collect and organise extinctions\nextinctions = get_extinct_species(sim_niche)\n```\n:::\n\n\nThis is a `Dict` object. The numbers on the left of the `=>` are known as the `keys` and the numbers on the right are `values`. We can create a mini- data frame out of this with the following code. `key` and `values` are actually _extractor_ functions and `collect` is translating the extracted information into a vector.\n\n::: {#45e6f9e7 .cell execution_count=16}\n``` {.julia .cell-code}\n# create a data frame of extinctions\nee1 = DataFrame(who = collect(keys(extinctions)), when = collect(values(extinctions)))\n```\n:::\n\n\nNow we can try and add this information to the plot. For the time being, we'll focus on adding the times that each of these species goes extinct to our figure. To do this we need to access the extinction time column (`when`), add a bit of noise/jitter so that times that are really close together can be seen on our x-axis, and then plot these as points with coordinates `x = when` and `y = 0`.\n\n::: {#4d9b34b2 .cell execution_count=17}\n``` {.julia .cell-code}\n# add some jitter for close together events\nexts = ee1[:,2] .+rand.()\n\n# plot\nplot(sim_niche)\n# add jittered extinction events.\nplot!(exts, zeros(size(ee1[:,1])), seriestype = :scatter, legend = false)\n```\n:::\n\n\nPretty cool!\n\n### What's next\n\nIn the next chapter, you'll be creating larger experiments with loops over actual parameters in the model, including the predator-prey size ratio, values of carry capacity and the predator-prey size ratio.\n\n", + "markdown": "---\ntitle: \"Tutorial 9: Experiments with the END\"\ndate: last-modified\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\nIn the previous chapter, we learned how to make networks and run a simulation. We did this for a simple tri-trophic chain where we specified the network with a matrix of ones and zeros, and for a more complex network defined by the niche model where we specified species richness and connectance. We also learned how to visualise the simulations and to collect several metrics about the simulations, including detail on biomass, diversity and stability.\n\nIn this tutorial, we are going to learn how to do experiments. We'll learn first how to generate multiple networks and collect information on how network structure impacts our metrics. Then we'll learn how to manipulate parameters in the model, again collecting information on how variation in these parameters impacts our metrics.\n\nFor example, we might be interested in how species richness or connectance impacts biomass and stability. Or how the carrying capacity of the producers impacts biomass and stability of the community (e.g. bottom up processes). We'll look at both of these.\n\n### Getting Setup\n\nAs with our previous exercises, we need to have a few packages that allow making networks, simulating them and collecting the data\n\n::: {#2a0d1045 .cell execution_count=2}\n``` {.julia .cell-code}\nusing DataFrames, Plots, Random, Distributions\nusing EcologicalNetworksDynamics\n```\n:::\n\n\n### Your (re)introduction to loops: making multiple networks example\n\nOne of the tricks to doing experiments is learning how to run a loop. Julia is super-fast with running loops. This is a bit different to R, which has a bad rep for loops. It's not terrible. But Julia is built to do loops fast.\n\nWhat we will do here is build a simple loop that makes 3 networks, each with a different species richness, but the same connectance.\n\nNote here that we introduce the use of the argument `tol_C`. Because the `niche model` produces networks based on probability theory (it uses the beta-distribution), the connectance we ask for is not always the connectance we get. The `tol_C` argument ensure that connectance is within a _tolerance_ range - in this case, having asked for `C = 0.2` and a `tol_C = 0.01` we will get `0.19 < C < 2.01`. This is like embedding a while loop within the `FoodWeb` function! We note too that the function `nichemodel` can take a value of `L` instead of `C`, and there is an associated `tol_L` argument for this choice too.\n\n::: {#a93ded18 .cell execution_count=3}\n``` {.julia .cell-code}\nRandom.seed!(12325) # ensures your network and this one are the same\n\nS = [10,20,30] # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\n\n# collection zone for the networks\nnets = []\n\n# construct the food webs\n# we loop over the 3 values of S\n# we use push!() to add the food webs to nets\n# always start with a for and end with an end.\nfor i in 1:3\n push!(nets, Foodweb(:niche; S = S[i], C = C))\nend\n```\n:::\n\n\nGreat. Let's see if we got what we expected in nets.\n\n::: {#fd958129 .cell execution_count=4}\n``` {.julia .cell-code}\nnets\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n3-element Vector{Any}:\n blueprint for Foodweb with 22 trophic links\n blueprint for Foodweb with 81 trophic links\n blueprint for Foodweb with 182 trophic links\n```\n:::\n:::\n\n\nMagnificent, we have three networs and that's a win. We also see that they are each for a different and appropriate S. Win no. 2. We can actually now check to see what the connectances actually are. Again, we'll use a loop, `println` and introduce you to the details of the `FoodWeb` object.\n\nFirst, let's look at one of the networks.\n\n::: {#7f4cf2b8 .cell execution_count=5}\n``` {.julia .cell-code}\nnets[1]\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\nblueprint for Foodweb with 22 trophic links:\n A: 10×10 SparseArrays.SparseMatrixCSC{Bool, Int64} with 22 stored entries:\n ⋅ 1 1 1 1 1 1 1 1 1\n ⋅ 1 1 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ 1 1 1 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 1\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ 1 1 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n```\n:::\n:::\n\n\nWe can see that the `A` element is the matrix and you can guess that the `M` is the body `M`asses. We also find tha there are 3 producers and 7 invertebrates and it is derived from the niche model\n\n::: {.callout-tip}\n\nA side note on the metabolic classes. The default parametrisation, and nearly all of the published work with the BEFW, uses invertebrates for all the non-producer species. It is possible to include others. But the data, currently, are not helpful (low volume) in supporting robust inference with these types of species.\n:::\n\nNow, recall that we can look specifically at the matrix by using `nets[1].A` which grabs the `A` part. We introduce here the function `sum`. As in **R**, `sum()` does what it says on the tin: for a vector, it addes up all the numbers and for a matrix, it does the same! In our case here, when `sum()` is applied to a matrix of ones and zeros, it counts all the 1's.... thus is the estimate of the number of links in the community. \n\nFinally, we note (again?) that `size` applied to the network returns two numbers - the number of rows and the number of columns. For our networks, the matrix is square. So grabbing one of these (rows = [1]) and squaring it delivers our 'potential number of links' (e.g. $species^2$). \n\nWe can put that all together here to define connectance as $Con = links/S^2$. Do be careful to watch where you put the various `[]`'s. One of them is about the _index_ (i.e. `[i]`) and the other is about the dimension (`[1]`) of the matrix.\n\n::: {#2d3c399b .cell execution_count=6}\n``` {.julia .cell-code}\nfor i in 1:3\n println(sum(nets[i].A)/size(nets[i].A)[1]^2)\n end\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n0.22\n0.2025\n0.20222222222222222\n```\n:::\n:::\n\n\n#### Different ways to run loops.\n\nThere is another way to make this set of networks. Here we use a `while` loop to create 3 networks with the same species richness and connectance. We might need to do this to generate _replicates_. This is a good exercise with the **niche model** as it reminds you that it is a probabilistic tool... you can get several networks with the same S and C, but the links will be in slightly different places.\n\n`while` loops work on conditions... for example, if we want three networks, we could ask that the loop keep working to make the networks until we have three. To do this, we need a _monitoring_ variable that lets us assess where we are against our target.\n\nLets see how to do that.\n\n::: {#065e7c73 .cell execution_count=7}\n``` {.julia .cell-code}\n# how many replicates do we want?\nreps = 3\n\nbegin\n\t# list to store networks\n\tglobal networks = []\n\t# monitoring variable l (the letter l)\n\tglobal l = length(networks)\n\n # while loop\n\twhile l < reps # reps is 3 here...\n\t # generate a network\n\t A = Foodweb(:niche; S = 20, C = 0.15)\n\t # add the network to the set\n push!(networks, A)\n # update the monitor\n\t global l = length(networks)\n\tend\nend\n```\n:::\n\n\nThe term `global` means that the obects are made available in our global environment and should be there for us to see. If you look closely at the mini-matrices, you'll see they are all different in micro-structure, despite having the same number of links and the same connectance.\n\n::: {.callout-note}\n\nThe presentation of the matrix is very specific here... the rows correspond to the predators and the columns the resources. Obstensibly, the ranking is by body size, so small things are at the upper left. This view shows that big things tend to eat small and big things, while small things eat small. Historically, the reflection (pivot around the diagnol) has also been used, where the predators are the columns and the resources the rows. This lead to a 'feature' of real and theoretical networks aligning, call `upper triangularity`. In this latter presentation, most of the links would be in the upper triangle. In the current presentation, the links are in the lower triangle. So we can just call the feature `triangularity`. The niche model reproduces this triangularity.\n:::\n\n::: {#3106f32b .cell execution_count=8}\n``` {.julia .cell-code}\nnetworks\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```\n3-element Vector{Any}:\n blueprint for Foodweb with 55 trophic links\n blueprint for Foodweb with 63 trophic links\n blueprint for Foodweb with 62 trophic links\n```\n:::\n:::\n\n\n::: {#dc22875b .cell execution_count=9}\n``` {.julia .cell-code}\nnetworks[1].A\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 55 stored entries:\n⎡⠉⠉⠉⣉⡡⠐⠒⠒⠒⠂⎤\n⎢⠀⠀⠀⠀⠀⠔⠒⠒⠒⠂⎥\n⎢⠀⠀⠀⠀⠨⠕⠒⠒⠒⠂⎥\n⎢⠀⠀⠀⠀⠀⠀⠐⠒⠿⡅⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦\n```\n:::\n:::\n\n\n::: {#295a25dc .cell execution_count=10}\n``` {.julia .cell-code}\nnetworks[2].A\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 63 stored entries:\n⎡⠉⠩⠭⠉⠉⠁⠀⠀⠀⠒⎤\n⎢⠀⠀⠈⠒⣒⠒⠒⠶⠤⠀⎥\n⎢⠀⠀⠀⠀⠒⠀⠨⣭⣭⡤⎥\n⎢⠀⠀⠀⠀⠀⠀⠀⠤⠤⠉⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠐⠛⎦\n```\n:::\n:::\n\n\n::: {#8f315f28 .cell execution_count=11}\n``` {.julia .cell-code}\nnetworks[3].A\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 62 stored entries:\n⎡⣀⣭⣭⣍⣉⣉⡉⠉⠁⠀⎤\n⎢⠀⠀⠀⠉⠉⠁⢠⠤⠤⠤⎥\n⎢⠀⠀⠀⠀⠀⠉⢰⣶⠀⠀⎥\n⎢⠀⠀⠀⠀⠀⠀⠈⠉⡀⠀⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦\n```\n:::\n:::\n\n\n### Linking the networks to the Ecological Networks Dynamics\n\nFantastic. Now you are ready for the next steps. We want to run the `EcologicalNetworksDynamics` model on each of these networks. Furthermore, we want to collect the biomass and stability information for all three into a data frame. Let's see how we do that.\n\n#### Step 1: Create the collecting data frame\n\nFirst, we create the holding pen for our information. We'll construct a data frame to collect five pieces of information: the network id (1,2 or 3), species richness at the start (our initial S), species richness at the end, total biomass at the end and stability at the end.\n\n::: {#882b602d .cell execution_count=12}\n``` {.julia .cell-code}\noutputs = DataFrame(Network = [], Init_Rich = [], Fin_Rich = [], Tot_biomass = [], Shannon_dic = [])\n```\n\n::: {.cell-output .cell-output-display execution_count=13}\n```{=html}\n
0×5 DataFrame
RowNetworkInit_RichFin_RichTot_biomassShannon_dic
AnyAnyAnyAnyAny
\n```\n:::\n:::\n\n\n#### Step 2: use the pre-defined networks\n\nWe can use our `nets` object from above now. Each of these networks has a different species richness.\n\n::: {#f2b9e1e4 .cell execution_count=13}\n``` {.julia .cell-code}\nfor i in 1:3\n\n # prep: define size of network\n S = size(nets[i].A)[1]\n\n # deliver some progress reporting\n println(\"\\nThis is network: \", i, \"with species richness = \", S,\"\\n\")\n\n # step A: define model paramters\n params = default_model(nets[i])\n\n # step B: define body mass\n B0 = rand(S)\n\n # step C: set number of timestamps\n t = 300\n\n # step D: simulate\n out = simulate(params, B0, t)\n\n # steps D: calculate metrics\n fin_rich = richness(out)\n fin_biomass = total_biomass(out)\n s_div = shannon_diversity(out)\n\n # step E: add things to the data frame\n # note the first arg is the data frame and then\n # the values we want allocated to the five slots\n # are in []\n push!(outputs, [i, S, fin_rich, fin_biomass, s_div])\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nThis is network: 1with species richness = 10\n\n\nThis is network: 2with species richness = 20\n\n\nThis is network: 3with species richness = 30\n\n```\n:::\n:::\n\n\nAmazing. Let's see if what we wanted collected has ended up in our data frame. Wonderful! Splendiferous. Fantabulous.\n\n::: {#5cfde7c1 .cell execution_count=14}\n``` {.julia .cell-code}\nprintln(outputs)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n3×5 DataFrame\n Row │ Network Init_Rich Fin_Rich Tot_biomass Shannon_dic \n │ Any Any Any Any Any \n─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n 1 │ 1 10 [10, 10, 10, 10, 10, 10, 10, 10,… [4.70537, 4.63199, 4.53209, 4.42… [8.375, 8.40912, 8.44306, 8.4699…\n 2 │ 2 20 [20, 20, 20, 20, 20, 20, 20, 20,… [8.52201, 8.4081, 8.26162, 8.102… [15.0407, 15.0769, 15.1077, 15.1…\n 3 │ 3 30 [30, 30, 30, 30, 30, 30, 30, 30,… [14.7649, 14.5082, 14.2062, 13.8… [24.3797, 24.4948, 24.5777, 24.6…\n```\n:::\n:::\n\n\n#### Dissecting more from simulate\n\nNote the details on extinctions that comes from a model run. For example, let's revisit our `sim_niche` object (you won't necessarily have to re-run this if you are working in one big script)\n\n::: {#d7b9116d .cell execution_count=15}\n``` {.julia .cell-code}\nS = 20; # define the number of species\nC = 0.2; # define the connectance (complexity) of the network\n\n# construct the food web\nRandom.seed!(12325) # ensures your network and this one are the same\nfoodweb_niche = Foodweb(:niche; S = S, C = C)\n\n# construct the equations and fixed parameters\nparams_niche = default_model(foodweb_niche)\n\n# define bodymasses between 0 and 1 and get S = 20 of them.\nRandom.seed!(123)\nB0 = rand(S)\n\n# simulate using params and bodymasses\n# specify number of time steps\nt = 300\nsim_niche = simulate(params_niche, B0, t)\n```\n\n::: {.cell-output .cell-output-display execution_count=16}\n```\nretcode: Success\nInterpolation: 3rd order Hermite\nt: 51-element Vector{Float64}:\n 0.0\n 0.0983252574499891\n 0.28544083243480267\n 0.5267982237043161\n 0.8245753364604138\n 1.181896742988936\n 1.6418353914084878\n 2.203829100924959\n 2.893464061893281\n 3.729699102007749\n 4.728753111889612\n 5.890702747756841\n 7.2218772360496395\n ⋮\n 136.70283821576533\n 145.48441982502288\n 155.57070934467725\n 166.67876410920994\n 179.5612866567586\n 193.9800038364207\n 210.21105297520486\n 227.83156289127072\n 247.0838336915681\n 267.94281052881126\n 290.8959793077713\n 300.0\nu: 51-element Vector{Vector{Float64}}:\n [0.906299638797481, 0.44349373245960455, 0.7456733811393941, 0.5120830400366143, 0.2538490889415096, 0.33415153638191886, 0.4273278808735992, 0.867547200255958, 0.09913361484360417, 0.12528740769155033, 0.6922086620547391, 0.13655147513745736, 0.03209667335274724, 0.3505458214588266, 0.9303323763821093, 0.9594335994071538, 0.5819123423876457, 0.3114475007050529, 0.12114752051812694, 0.20452981732035946]\n [0.9169483131714715, 0.444402194534041, 0.7667640455857161, 0.5179071161683636, 0.25596644376248334, 0.3439614083570855, 0.42881389580038637, 0.8404857181508336, 0.10207349613818459, 0.12980979255930417, 0.7045585608788062, 0.14142469702894178, 0.033700254458592344, 0.35322775442579823, 0.9254383246584946, 0.8428424981719224, 0.5353929049386887, 0.2716712297929136, 0.11790964375471776, 0.20588623005171253]\n [0.9372189186622565, 0.446138581295766, 0.8030805319662981, 0.5280429096670912, 0.25960285298532004, 0.36088969827160805, 0.43143000229873113, 0.7941678141517742, 0.107334065965393, 0.13803877097876832, 0.7224846396419364, 0.150274714852675, 0.03655779055568964, 0.35202356186576755, 0.8867871855452475, 0.6561325211685619, 0.45370991951901846, 0.21879863147029777, 0.1144327890249893, 0.21137607850479412]\n [0.963419944890434, 0.4478457678502066, 0.8407656301021255, 0.5394619505769526, 0.26358620538619504, 0.3785307293750754, 0.43443524658702654, 0.7426580903726461, 0.11338938338304744, 0.1475698891121404, 0.7345099631141349, 0.16048747662896795, 0.03959434344670769, 0.3379755377009729, 0.7958692645000881, 0.48283669535781387, 0.36706195693003885, 0.17548000193294144, 0.1136592394878268, 0.22309854306314952]\n [0.995616193064571, 0.44805738727466143, 0.8700643195894429, 0.5512240918443782, 0.2674989824178032, 0.3924051349926597, 0.4375425793363201, 0.6886449125246876, 0.11960335804730916, 0.15695502649258633, 0.7327878032629778, 0.17047486846995694, 0.0420936774665965, 0.3062032871443506, 0.6610340292426684, 0.34855000462048347, 0.2881369319293169, 0.14175624955652485, 0.11666389844136492, 0.24243967254676815]\n [1.0331366869886944, 0.44448629343725343, 0.8788288901686566, 0.5620901047900512, 0.2708572048035862, 0.39695429480179645, 0.44018298027640984, 0.6333401253753693, 0.1252037789780579, 0.1640984843116221, 0.7114983769875807, 0.17795514254857084, 0.04354809380952039, 0.26092610308891634, 0.5154058541922188, 0.25624511921879434, 0.22330145420147088, 0.11586948470233616, 0.12436895504970236, 0.26962910331924905]\n [1.0773089982155897, 0.43396923698721435, 0.8556572961992899, 0.5707904139404543, 0.2731983214483226, 0.38705755776238965, 0.4413794083264426, 0.57197930814629, 0.12978003467017415, 0.16724868374246712, 0.6675169557355778, 0.18101017312972054, 0.04388752925907648, 0.20909394578211202, 0.3805309865842198, 0.19230727005942244, 0.16943175281775166, 0.09443672996682428, 0.13906102138589269, 0.30741066949967055]\n [1.1213743703927337, 0.4149870885160012, 0.7975741540831984, 0.5733620864984142, 0.2733077885606147, 0.36141676843558873, 0.4391552288251882, 0.5071960218562799, 0.13225598133704913, 0.1649144766546638, 0.6093837906327526, 0.17807037605762552, 0.04315159765633695, 0.1631734536430942, 0.2790930366914647, 0.15237925689592774, 0.12890880773111002, 0.0777317468581009, 0.16225155189984958, 0.35425475261372863]\n [1.1573410183305781, 0.3875799067335869, 0.7122633234623346, 0.5656661531044221, 0.2699342224158771, 0.32362037390928877, 0.43151833519945715, 0.43980122366299085, 0.1320832740044849, 0.15754833392958092, 0.5485937790090555, 0.16967851768901068, 0.04155688582593655, 0.12670961646818607, 0.20790093579654878, 0.12919220653556573, 0.09920527144448085, 0.06511083602693121, 0.1957265685332169, 0.40863184877785175]\n [1.1744909386178761, 0.35353525150930704, 0.6130415990319116, 0.5442924204781258, 0.2619765432579562, 0.2797239154423789, 0.41725964546931765, 0.3734718885747243, 0.12906194711831975, 0.14648620822639452, 0.49617455885534983, 0.15734180901650238, 0.039351964038387546, 0.0993990767009241, 0.15977668195469585, 0.1193453433823383, 0.07853078787521317, 0.05684848395648957, 0.23880211323157663, 0.46473430625333423]\n [1.1636651009007108, 0.3155425241026375, 0.5129043599973696, 0.5086210124289895, 0.24908969960788688, 0.23553191470443982, 0.3966456636545259, 0.3124900352369809, 0.12355869405172261, 0.13330212010711523, 0.45885425946835634, 0.14280589051662543, 0.036833828434965285, 0.07940681588029759, 0.1280065867800307, 0.12159259236413968, 0.06534238144397321, 0.053601952458352684, 0.28528412637082984, 0.5126103913127859]\n [1.1215900120487023, 0.2768216752264026, 0.42206636648520485, 0.46189135063482056, 0.23215126320140814, 0.19551978933588599, 0.37144587200796514, 0.26042387609908113, 0.11647562742120145, 0.11955373899209087, 0.4381554894529827, 0.1277697315605396, 0.034397853577932694, 0.06512710102028911, 0.10768752758342186, 0.13551750917697, 0.058102384679568894, 0.055907692857973916, 0.3220846544335181, 0.5412432565515389]\n [1.051674472438156, 0.2396400556460993, 0.34499392466732914, 0.408962875223587, 0.21264909765819076, 0.16158429863184295, 0.3435589630316772, 0.2180232510648064, 0.10878792457246415, 0.10632571872188118, 0.43013574616355804, 0.11339063974249527, 0.03248700163555598, 0.055268908325187105, 0.0946316891444375, 0.1595784203240174, 0.05459709129704919, 0.0631635952778267, 0.33753068620574334, 0.5455404467088186]\n ⋮\n [0.00032755644980272486, 0.00042642730013303957, 0.00024189593390109746, 3.1111688980955344e-5, 0.002186365444974394, 0.0001284836050334962, 0.009392611128074742, 0.2289263661082618, 0.027817843518977224, 0.00011632790937708126, 0.4448717546882417, 0.0001223774188672115, 0.198564855194196, 0.09669339044487263, 0.041438780171243736, 0.21624377256231636, 0.010260398961170272, 0.1106446052574405, 0.30895191650548376, 0.48344362584850714]\n [0.0001996798247022266, 0.0003009378761392906, 0.00015346749983007282, 1.8190449427202614e-5, 0.0017884347223449826, 8.151473534424173e-5, 0.0077101296606787864, 0.23181199431785626, 0.025313811373776522, 7.379449257908107e-5, 0.44476144744230767, 7.763164111187508e-5, 0.19771575290544488, 0.0981753484444294, 0.0415237986113816, 0.21618611797874981, 0.010096001729578499, 0.1107711243020971, 0.3089588621965838, 0.4835526097023227]\n [0.00011328126257715799, 0.0002025145740727682, 9.102676275323986e-5, 9.86615934389697e-6, 0.0014273867429624918, 4.834918126253599e-5, 0.006152674701416408, 0.2345821350465174, 0.022777702555973164, 4.3766536607882777e-5, 0.44485825775398713, 4.604210489119089e-5, 0.19677603845677671, 0.0996135511824476, 0.04163063947534051, 0.21611456663905765, 0.00992313898370846, 0.1108762739174712, 0.30896257460215903, 0.4836121681503955]\n [6.07969185813491e-5, 0.00013150891522278353, 5.122984902532575e-5, 5.0559263528295375e-6, 0.0011197509119850043, 2.721092248119792e-5, 0.004805123705498752, 0.2371493862104039, 0.02034698607033935, 2.4630532478594332e-5, 0.44507776580317365, 2.591108561516969e-5, 0.19582059389086015, 0.10090484291104647, 0.04175110898630074, 0.21605866945798072, 0.009748297718843965, 0.1109547748500005, 0.308965762906422, 0.48361873148098766]\n [2.9540113221979872e-5, 8.00347447973086e-5, 2.6268553079549285e-5, 2.3358462951272875e-6, 0.0008502538978690424, 1.3952641028662382e-5, 0.0036125895986525765, 0.23963412412998863, 0.017924696653654346, 1.2629101514971793e-5, 0.4453417610345992, 1.3285671319358326e-5, 0.19486664345382582, 0.10209874101875081, 0.041891604062307145, 0.2160237975426658, 0.00956208380761516, 0.11101835580249045, 0.3089707135225891, 0.48359145640506035]\n [1.3166616427449579e-5, 4.60961582614326e-5, 1.241859399595492e-5, 9.875013357564836e-7, 0.0006289434801525733, 6.596183545884943e-6, 0.0026293723865516917, 0.24190491545204867, 0.015626334170708748, 5.970359692556319e-6, 0.44560575498650923, 6.280744324641365e-6, 0.19400924653479448, 0.10314206416955765, 0.04204857588531362, 0.2160007866180423, 0.009371522869382096, 0.11107366457263641, 0.3089769794039354, 0.48355133078668755]\n [5.288582093742206e-6, 2.4853056623534485e-5, 5.32431964558186e-6, 3.7495755123700837e-7, 0.0004510237192764804, 2.8280327624688987e-6, 0.0018418173438047715, 0.24395924306889033, 0.013458321791607284, 2.559692577943294e-6, 0.44587256631997335, 2.692763414898462e-6, 0.19326957086896235, 0.10403490013949204, 0.04222157762263886, 0.21597907364688387, 0.009176377022194124, 0.11112583015368675, 0.30898347361961076, 0.4835073952384332]\n [1.960571333984018e-6, 1.2748386630159753e-5, 2.115911956181734e-6, 1.3122771778296083e-7, 0.00031649230625780636, 1.1238747466059242e-6, 0.0012535673852407435, 0.2457433105385709, 0.011504652249667801, 1.0172301703560636e-6, 0.44612733302168156, 1.0701126911743665e-6, 0.19267165202271308, 0.1047507539103007, 0.04240100704365944, 0.21595925499391128, 0.008984468602875842, 0.11117426849212075, 0.30898978378818076, 0.48346305093339226]\n [6.595296475377276e-7, 6.157495485353746e-6, 7.673573735587585e-7, 4.1573174269355544e-8, 0.0002163095240186386, 4.0758481170993133e-7, 0.0008246351715236552, 0.24730063052972948, 0.009744807150823888, 3.6890828571649465e-7, 0.4463589658982419, 3.880865976484553e-7, 0.19219749029253488, 0.10531819548561512, 0.042584771757986466, 0.21594251593637606, 0.008795235529894242, 0.11122083597743129, 0.3089962400343031, 0.48342085434013]\n [2.0108052810226762e-7, 2.8004575219465937e-6, 2.5369560293790977e-7, 1.190656631256341e-8, 0.00014408987057401768, 1.3475139250220505e-7, 0.0005246117248146955, 0.24864251960077316, 0.008183727277329841, 1.2196446538994685e-7, 0.4465625705694917, 1.2830498581813105e-7, 0.19183327165148306, 0.10575941597710509, 0.04276848561656389, 0.21592768854223388, 0.008611086962690943, 0.11126649455166937, 0.30900276016604544, 0.4833835692529364]\n [5.35850498787597e-8, 1.174593201709331e-6, 7.398752912499898e-8, 2.965192061208363e-9, 9.266705935747393e-5, 3.929875986723788e-8, 0.00031929137827090367, 0.24981133030734196, 0.006788855740405869, 3.556958190340493e-8, 0.4467437607797747, 3.7418723667047955e-8, 0.19155285868338037, 0.10610455981258715, 0.04295191471606665, 0.21591384077514106, 0.008430160333184566, 0.1113122756892104, 0.30900934087551246, 0.48335082223348647]\n [3.2821854904203205e-8, 8.406671643638472e-7, 4.6640508998017896e-8, 1.7793663607263053e-9, 7.799523091116062e-5, 2.4773285240091262e-8, 0.0002627973314424048, 0.2502039748903548, 0.00631276636245039, 2.2422472598477954e-8, 0.4468055436036614, 2.358814075481337e-8, 0.19146688286657296, 0.10621159455428622, 0.04301932407939025, 0.21590899888568155, 0.008364030293673712, 0.11132929056683419, 0.3090117977250657, 0.4833397504740079]\n```\n:::\n:::\n\n\nWe've constructed a helper function to get information on which species go extinct and when they do.\n\n::: {.callout-caution}\n## Warning\n\nSection is no longer a built-in functionality in END. Alain should be able to address\n:::\n\n::: {#78af4773 .cell execution_count=16}\n``` {.julia .cell-code}\n# collect and organise extinctions\nextinctions = get_extinct_species(sim_niche)\n```\n:::\n\n\nThis is a `Dict` object. The numbers on the left of the `=>` are known as the `keys` and the numbers on the right are `values`. We can create a mini- data frame out of this with the following code. `key` and `values` are actually _extractor_ functions and `collect` is translating the extracted information into a vector.\n\n::: {#ff14f336 .cell execution_count=17}\n``` {.julia .cell-code}\n# create a data frame of extinctions\nee1 = DataFrame(who = collect(keys(extinctions)), when = collect(values(extinctions)))\n```\n:::\n\n\nNow we can try and add this information to the plot. For the time being, we'll focus on adding the times that each of these species goes extinct to our figure. To do this we need to access the extinction time column (`when`), add a bit of noise/jitter so that times that are really close together can be seen on our x-axis, and then plot these as points with coordinates `x = when` and `y = 0`.\n\n::: {#ed3e6c59 .cell execution_count=18}\n``` {.julia .cell-code}\n# add some jitter for close together events\nexts = ee1[:,2] .+rand.()\n\n# plot\nplot(sim_niche)\n# add jittered extinction events.\nplot!(exts, zeros(size(ee1[:,1])), seriestype = :scatter, legend = false)\n```\n:::\n\n\nPretty cool!\n\n### What's next\n\nIn the next chapter, you'll be creating larger experiments with loops over actual parameters in the model, including the predator-prey size ratio, values of carry capacity and the predator-prey size ratio.\n\n", "supporting": [ "9_experiments_end_files" ], diff --git a/_freeze/Tutorial-10_Complex Experiments with the BEFWM2/execute-results/html.json b/_freeze/Tutorial-10_Complex Experiments with the BEFWM2/execute-results/html.json deleted file mode 100644 index 225fa38..0000000 --- a/_freeze/Tutorial-10_Complex Experiments with the BEFWM2/execute-results/html.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "hash": "fb672266adb58b5069bfc94959329944", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 10: Complex Experiments with the BEFWM2\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\nThe previous tutorial focused on experiments where we manipulated the number of networks and various network parameters. This is one set of things we can change/vary in an _in silico_ experiment. The other set of things we can change are features of the model, such as the shape of the functional response (see Tutorial 7), features of the environment such as the carrying capacity, or even empirical relationships that drive trophic structure and interaction strengths, such as the predator-prey mass ratio.\n\nIn this tutorial, we are going to implement three experiments. The first two will be 'simple' in that they vary only two things. The final example will implement a large experiment changing five features of the model.\n\nYou may want to start a new script in the project. We'll need the following packages (they are already installed... so we just need `using`).\n\n::: {#b39d7b14 .cell execution_count=1}\n``` {.julia .cell-code}\nusing Random, Plots, Distributions, DataFrames, StatsPlots\nusing EcologicalNetworksDynamics\n```\n:::\n\n\n### Experiment 1: Carrying Capacity and the Predator Prey Mass Ratio\n\nNow we are set for our first experiment. Lets first establish the parameters we need to make the food web and do the experiment. We fix `S` at 20 and `C` at 0.15. We then create vectors of Z and K. \n\nZ is the predator - prey mass ratio, and defines how much bigger or smaller the predators are from their prey. The data suggest it is between predators are between 10 and 100 times bigger than their prey [see Brose et al 2006](https://doi.org/10.1890/0012-9658(2006)87[2411:CBRINF]2.0.CO;2). This value interacts with setting trophic levels in the model. \n\nThe default setting for the models is 1 - i.e. all species are within the same order of magnitude, predators are not bigger than their prey. Here, we create a vector of values to explore, from predators being smaller, to them being 10 or 100 x larger as the data suggests.\n\n::: {#b0744bb9 .cell execution_count=2}\n``` {.julia .cell-code}\n#Fixed Parameters\nS = 20\nC = 0.15\n\n# Variable Parameters\nZ_levels = [0.1, 1, 10, 100]\nK_levels = [0.1, 1, 10, 100]\n\n# run this to get same results as in the document\nRandom.seed!(123)\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\nTaskLocalRNG()\n```\n:::\n:::\n\n\nNow, lets set up the collecting data frame.\n\n::: {#d987c5f1 .cell execution_count=3}\n``` {.julia .cell-code}\ndf_collect = DataFrame(Z = [], K = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```{=html}\n
0×5 DataFrame
RowZKFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAnyAny
\n```\n:::\n:::\n\n\nNow, set up the loop to use these variables and generate outputs. Notice that we use `for z in Z_levels` - this is a clever trick of the looping method, where `z` simply iterates over the values of `Z_levels` without having to specify the index value (e.g. no use of `Z_levels[i]` etc).\n\nThe significant BIG thing here is the LogisticGrowth function which allows us to set things like the carrying capacity (K) of the resources. Here we use it to define custom values of the K paramter for carrying capacity, drawing on the values in the `K_levels` above. Here, `pg` stands for Producer Growth function, and the paramter set in the food web is K.\n\nNote too our use of `println` and the values of `Z` and `K` to produce an informative _break_ between each combination.\n\n> Can you guess what increasing K will do to the biomass and richness of the community at equilibrium? How about Z? Will higher Z make things more or less stable?\n\n::: {#0dd0f521 .cell execution_count=4}\n``` {.julia .cell-code}\nfor z in Z_levels\n for k in K_levels\n\n println(\" ***> This is iteration with Z = $z and K = $k\\n\")\n\n # Define the food web\n fw = Foodweb(:niche; S = S, C = C)\n # specify the K value of the producer growth function\n\n B0 = rand(S)\n # specify model to simulate logistic growth as well as BM ratio\n params = default_model(fw, BodyMass(; Z = z), LogisticGrowth(; K = k))\n \n # number of timestamps\n t = 300\n\n out = simulate(params, B0, t)\n\n # calculate metrics\n fin_rich = richness(out)\n fin_biomass = total_biomass(out)\n s_div = shannon_diversity(out)\n\n push!(df_collect, [z, k, fin_rich, fin_biomass, s_div])\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n ***> This is iteration with Z = 0.1 and K = 0.1\n\n ***> This is iteration with Z = 0.1 and K = 1.0\n\n ***> This is iteration with Z = 0.1 and K = 10.0\n\n ***> This is iteration with Z = 0.1 and K = 100.0\n\n ***> This is iteration with Z = 1.0 and K = 0.1\n\n ***> This is iteration with Z = 1.0 and K = 1.0\n\n ***> This is iteration with Z = 1.0 and K = 10.0\n\n ***> This is iteration with Z = 1.0 and K = 100.0\n\n ***> This is iteration with Z = 10.0 and K = 0.1\n\n ***> This is iteration with Z = 10.0 and K = 1.0\n\n ***> This is iteration with Z = 10.0 and K = 10.0\n\n ***> This is iteration with Z = 10.0 and K = 100.0\n\n ***> This is iteration with Z = 100.0 and K = 0.1\n\n ***> This is iteration with Z = 100.0 and K = 1.0\n\n ***> This is iteration with Z = 100.0 and K = 10.0\n\n ***> This is iteration with Z = 100.0 and K = 100.0\n\n```\n:::\n:::\n\n\nWonderful. Now we are in a position to learn about two new plotting methods. First, let's look at the data frame we've created.\n\n::: {#0c11a693 .cell execution_count=5}\n``` {.julia .cell-code}\ndf_collect\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```{=html}\n
16×5 DataFrame
RowZKFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAnyAny
10.10.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 5, 5, 5, 5, 5, 5, 5, 5, 5, 5][8.15104, 7.35599, 6.86766, 6.20173, 5.62064, 4.93607, 4.31825, 3.63121, 3.00669, 2.39632 … 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.300001, 0.3][16.6229, 16.7342, 16.5646, 16.1151, 15.6393, 15.1269, 14.7861, 14.5788, 14.548, 14.6324 … 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00016, 3.00005]
20.11.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 11, 11, 11, 11, 11, 11, 11, 11, 11, 11][12.4772, 11.4754, 10.7631, 9.95902, 9.14621, 8.41858, 7.61812, 6.84285, 6.08118, 5.33149 … 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616, 1.76616][17.742, 17.8484, 17.6835, 17.2513, 16.4331, 15.4516, 14.5648, 14.1409, 13.9903, 13.8445 … 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.3824, 7.38235]
30.110.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 13, 13, 13, 13, 13, 13, 13, 13, 13, 13][9.25026, 8.51092, 8.00559, 7.44123, 6.91671, 6.27631, 5.65377, 4.94222, 4.26539, 3.54824 … 2.25548, 2.2559, 2.25643, 2.25698, 2.25747, 2.25783, 2.25806, 2.25819, 2.25825, 2.25825][14.6862, 14.6468, 14.2896, 13.6899, 12.9845, 12.0663, 11.3051, 10.7473, 10.5693, 10.7805 … 9.57129, 9.59447, 9.62346, 9.6528, 9.67659, 9.69307, 9.70369, 9.71014, 9.71404, 9.71427]
40.1100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][11.7083, 11.0424, 10.5769, 9.93713, 9.4234, 8.80592, 8.23005, 7.54626, 6.97782, 6.26384 … 3.48233, 3.48295, 3.48399, 3.48495, 3.48596, 3.48667, 3.48716, 3.48743, 3.48757, 3.48759][18.2061, 17.7393, 17.1158, 15.8476, 14.5755, 13.1387, 12.2288, 11.7098, 11.6218, 11.8449 … 14.6644, 14.6766, 14.6955, 14.7124, 14.7303, 14.7429, 14.7523, 14.7579, 14.7612, 14.762]
51.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 14, 11, 11, 7, 7, 7, 7, 6, 6, 6][9.94865, 9.31694, 8.91556, 8.37917, 7.98085, 7.48504, 7.05457, 6.53892, 6.03007, 5.45877 … 0.599995, 0.599995, 0.600001, 0.600001, 0.6, 0.6, 0.6, 0.6, 0.6, 0.6][16.9057, 16.7928, 16.5411, 15.9674, 15.4178, 14.6761, 13.9969, 13.1036, 12.1136, 10.9472 … 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0, 6.0]
61.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 16, 16, 16, 16, 15, 15, 14, 14][8.18822, 7.87201, 7.51513, 7.09849, 6.67715, 6.24736, 5.77386, 5.30732, 4.78624, 4.26858 … 2.1041, 2.1036, 2.1036, 2.10339, 2.10338, 2.10338, 2.10338, 2.1034, 2.1034, 2.10341][17.8751, 17.9835, 17.9691, 17.7811, 17.4596, 17.0672, 16.6213, 16.2204, 15.8747, 15.676 … 9.70326, 9.70168, 9.70168, 9.70046, 9.7004, 9.7004, 9.7004, 9.70055, 9.70055, 9.70071]
71.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 18, 18, 18, 18, 17, 17, 17, 17, 17, 17][11.9214, 11.5912, 11.2096, 10.7345, 10.2291, 9.65051, 9.08087, 8.50293, 7.95285, 7.4397 … 12.5097, 12.5097, 12.5097, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098, 12.5098][17.7631, 17.8918, 17.8487, 17.5309, 16.9389, 15.9573, 14.662, 13.1789, 11.9185, 11.0675 … 4.62639, 4.61727, 4.60955, 4.60285, 4.60285, 4.59699, 4.59175, 4.58698, 4.58255, 4.57863]
81.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][9.81854, 9.78941, 9.7508, 9.70287, 9.63915, 9.53889, 9.36204, 9.09799, 8.78533, 8.50462 … 7.83776, 7.83881, 7.83874, 7.83824, 7.83785, 7.8378, 7.83791, 7.83792, 7.83791, 7.83792][15.8542, 15.9962, 16.1459, 16.2131, 16.1391, 15.9368, 15.6428, 15.2171, 14.6976, 14.3231 … 14.8658, 14.8748, 14.8756, 14.873, 14.8704, 14.8698, 14.8703, 14.8705, 14.8704, 14.8705]
910.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 13, 13, 12, 12, 10, 10, 10, 9, 9, 8][12.3589, 11.1366, 10.528, 9.73548, 9.28095, 8.70753, 8.38507, 7.92468, 7.6241, 7.16456 … 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7, 0.7][17.9611, 18.047, 17.9192, 17.5077, 17.121, 16.4637, 16.0159, 15.3056, 14.8254, 14.13 … 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0, 7.0]
1010.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 19, 19, 19, 19, 19, 19, 19, 19][8.42215, 8.20465, 7.99326, 7.76301, 7.53365, 7.30894, 7.04805, 6.82182, 6.50908, 6.21272 … 2.86069, 2.86431, 2.86431, 2.86744, 2.87126, 2.87422, 2.87704, 2.87913, 2.88089, 2.88177][15.0882, 15.2155, 15.2234, 15.0786, 14.8185, 14.5613, 14.3405, 14.2066, 14.0631, 13.9396 … 13.2383, 13.2133, 13.2133, 13.1887, 13.1531, 13.1189, 13.0773, 13.0366, 12.9906, 12.9603]
1110.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 17, 17, 17, 17, 16, 16, 16, 16][8.76005, 8.6219, 8.45014, 8.27291, 8.03749, 7.83254, 7.54527, 7.26893, 6.89872, 6.5367 … 4.352, 4.37513, 4.3948, 4.41157, 4.4259, 4.43803, 4.43803, 4.44812, 4.45638, 4.45893][16.3521, 16.3257, 16.2454, 16.1206, 15.8993, 15.6612, 15.275, 14.8714, 14.3179, 13.7872 … 5.58795, 5.46404, 5.36072, 5.2744, 5.20203, 5.14192, 5.14192, 5.09276, 5.0532, 5.04108]
1210.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.25211, 8.29101, 8.4592, 8.87757, 9.76632, 11.7568, 16.001, 25.5672, 46.8751, 88.1647 … 243.87, 243.868, 243.863, 243.857, 243.852, 243.848, 243.845, 243.843, 243.841, 243.84][15.4288, 15.4367, 15.3683, 14.9952, 14.0388, 12.1209, 9.40314, 6.56688, 4.55697, 3.55452 … 6.58682, 6.58612, 6.58472, 6.58295, 6.58118, 6.57958, 6.57821, 6.57708, 6.57618, 6.57556]
13100.00.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 19, 19, 18, 18, 18, 18, 18, 18, 18, 18][11.5095, 10.9511, 10.7168, 10.3916, 10.2152, 9.9237, 9.78424, 9.46529, 9.30356, 8.92472 … 0.472889, 0.463688, 0.463688, 0.455691, 0.448684, 0.442486, 0.436958, 0.431991, 0.427513, 0.425609][17.231, 17.3743, 17.335, 17.1761, 17.0496, 16.8121, 16.6962, 16.4432, 16.324, 16.0738 … 5.95521, 5.74108, 5.74108, 5.5499, 5.37858, 5.22417, 5.08415, 4.95644, 4.83969, 4.78959]
14100.01.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.94845, 8.84267, 8.70565, 8.58269, 8.46112, 8.33459, 8.2076, 8.07545, 7.93311, 7.80568 … 8.84776, 8.83373, 8.82279, 8.81646, 8.81702, 8.82562, 8.83778, 8.84947, 8.8573, 8.85948][16.8594, 16.831, 16.7339, 16.6093, 16.4917, 16.4208, 16.4238, 16.5015, 16.6608, 16.8785 … 11.6325, 11.5115, 11.4211, 11.3514, 11.3021, 11.2653, 11.2375, 11.2081, 11.1754, 11.1534]
15100.010.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][9.0416, 9.1737, 9.5697, 10.2502, 11.3574, 13.2685, 16.0394, 20.0685, 25.3442, 31.3042 … 79.4917, 79.5051, 79.498, 79.4849, 79.4774, 79.4781, 79.4801, 79.4797, 79.4785, 79.4782][15.9684, 16.1206, 16.4693, 16.7484, 16.6086, 15.5647, 13.7709, 11.8335, 10.3515, 9.58567 … 11.1015, 11.0926, 11.0865, 11.0856, 11.0869, 11.0872, 11.0863, 11.0855, 11.0854, 11.0854]
16100.0100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][11.5292, 11.6221, 11.8303, 12.2001, 12.9034, 14.2178, 16.6995, 21.3803, 29.102, 40.6004 … 466.619, 464.416, 463.06, 460.625, 457.236, 453.504, 450.831, 452.672, 465.621, 471.999][18.3089, 18.2607, 18.15, 17.9446, 17.542, 16.8141, 15.6206, 13.9258, 12.0175, 9.86971 … 7.06769, 7.20399, 7.09213, 6.94422, 6.80881, 6.70295, 6.69553, 6.94315, 7.66919, 7.96389]
\n```\n:::\n:::\n\n\n#### Visualising the experiment\n\nOne option here is to plot one of our `Final` Objects as the response variable against the valuse of Z and K. In R, we'd use ggplot2. Here we'll use `StatsPlots` as we learned about in Tutorial 5. Can you make this work in the regular `Plots` syntax?\n\nLet's first look at a single plot of stability\n\n::: {#7aef45a3 .cell execution_count=6}\n``` {.julia .cell-code}\n@df df_collect plot(:K, [:FinalStability], group = :Z, \n ylabel = \"Stabilty\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line],\n legend = false)\n```\n:::\n\n\nNow some new ploting tricks... 3 plots in a layout.\n\n::: {#5755beff .cell execution_count=7}\n``` {.julia .cell-code}\np1 = @df df_collect plot(:K, [:FinalStability], group = :Z, \n legend = :bottomright,\n ylabel = \"Stabilty\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n\np2 = @df df_collect plot(:K, [:FinalBiomass], group = :Z, \n legend = :bottomright,\n ylabel = \"Biomass\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n \np3 = @df df_collect plot(:K, [:FinalRichness], group = :Z, \n legend = :bottomright,\n ylabel = \"Richness\", \n\txlabel = \"Karrying Kapacity\",\n seriestype = [:scatter, :line])\n\n# create a layout of 3 graphs stacked on top of each other.\nplot(p1, p2, p3, layout=(3,1), legend = false)\n```\n:::\n\n\n### Interpretation!\n\n#### Challenge - can you get the number of extinctions into the data frame?\n\n### Experiment 2: The Functional Response\n\nThe functional response is the relationship between how much a consumer eats and the 'density' of the prey items. If you can recall from your ecology courses/classes/modules, there are three classic shapes: The Type I, Type II and Type III.\n\nA predator feeding with a Type I delivers to the prey a 'constant mortality rate' (the slope of the Type I line). This means that the effect of predation is density _independent_ because prey mortality rate does not vary by prey density. Remember, density dependence (negative feedback that stabilises communities) is defined by survival decreasing with increasing density, or in this case, mortality rates _increasing_ with increasing density.\n\nA predator feeding with the Type II delivers an _inverse density dependent_ mortality rate. The slope of the Type II line actually goes down as density of the prey goes up meaning that mortality rates for the prey, caused by the predator, are going down with prey density. This means that the effect of predation is _inverse density dependent_ in the Type II. This is **destabilising**.\n\nFinally, a predator feeding via a Type III can deliver a _density dependent_ mortality rate to the prey, but only at low prey densities. This is an S shaped curve. Below the inflection point, the slope is actually getting steeper. This means that as prey density increases up to the inflection, their mortality rate from predation inceases (survival goes down with density going up). This is the hallmark of density dependence and can **stabilise** consumer-resource interactions.\n\n> Remember that the logistic growth equation, with a carying capacity specified, is also a source of _density dependent negative feedback_\n\n> Remember No. 2: The Type II is the MOST common. Type I is rare and even non-existent because it suggests there are no limits to how much a consumer can eat. Type III is also rare, but it is at least plausible and interesting.\n\n::: {#d656144a .cell execution_count=8}\n``` {.julia .cell-code}\nf_t1(n) = 0.5*n\nf_t2(n) = 0.5*n/(0.2+0.01*n)\nf_t3(n) = 0.5*n^2/(10 + 0.01*n^2)\n\nplot(f_t1, 0, 100, label = \"Type I\")\nplot!(f_t2, 0, 100, label = \"Type II\")\nplot!(f_t3, 0, 100, label = \"Type III\")\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n#### How does the BEFW make a functional response?\n\nThere are two formulations of the functional response. One of them is called the _Bioenergetic_ response and the other is called the _Classic_. In both cases, we ignore the Type I.\n\nThe Bioenergetic functional response is deeply phenomenological in that the parameters that make the shapes move between Type II and III have no deliberate biological interpretation. They function is defined by a 1/2 saturation point, an asymptote (which is nominally a maxiumum feeding rate) and an exponent, which is called the _hill exponent_. The value of the exponent moves the model from Type II (h = 1) to Type III (h = 2). The other variables define the overall shape.\n\nThe Classic functional less phenomenological in that the response is defined more by 'traits': the attack rate of a consumer on a prey and the handling time of that prey. But it also moves between the Type II and Type III shape based on an exponent.\n\n#### Creating Type II vs. Type III with the Bioenergetic response\n\nLet's look at using the Bioenergetic functional response, and see here how we can vary the shape between Type II and Type III. We can do this by modifying the *hill_exponent* after we have specified the model (*i.e.,* after the `default_model` call). We will look at how Richness, Biomass and Shannon Diversity are affected by the hill exponent.\n\n::: {#06d2cbc2 .cell execution_count=9}\n``` {.julia .cell-code}\nRandom.seed!(12352)\n\n# fixed parameters\nS = 20\nC = 0.15\n\n# set the hill exponent to move from Type II to Type III)\nh_levels = [1.0, 1.1, 1.25, 2.0]\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_h = DataFrame(h = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\n# create look across values of h\nfor h in h_levels \n println(\"***> This is iteration with h = $h\\n\")\n \n # make the network\n # Note that we specify the Environment, but there is no K or T set (using defaults)\n # Note the new BioenergeticResponse function\n fw_h = Foodweb(:niche; S = S, C = C)\n \n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_h)\n\n # here we now update the exponent of the hill function\n params.hill_exponent = h\n\n # specify number of time steps\n t = 300\n\n # simulate\n sim_niche = simulate(params, B0, t)\n\n # collect data \n fin_rich = richness(sim_niche)\n fin_bio = total_biomass(sim_niche)\n s_div = shannon_diversity(sim_niche)\n\n push!(df_collect_h, [h, fin_rich, fin_bio, s_div])\nend\n\ndf_collect_h\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n***> This is iteration with h = 1.0\n\n***> This is iteration with h = 1.1\n\n***> This is iteration with h = 1.25\n\n***> This is iteration with h = 2.0\n\n```\n:::\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n
4×4 DataFrame
RowhFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAny
11.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 16, 16, 15, 15, 15, 15, 15, 15, 15, 15][14.0154, 13.7814, 13.4658, 13.1783, 12.8834, 12.6007, 12.3015, 11.9503, 11.7107, 11.4361 … 6.42979, 6.44208, 6.44208, 6.44436, 6.43148, 6.44421, 6.44068, 6.43311, 6.44545, 6.44344][18.7295, 18.6847, 18.5806, 18.4524, 18.2893, 18.0832, 17.7706, 17.2078, 16.6571, 15.8173 … 7.82943, 7.8319, 7.8319, 7.84614, 7.82841, 7.83428, 7.84109, 7.82605, 7.83731, 7.84078]
21.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 17, 17, 17, 17, 17, 17, 16, 16, 16, 16][11.3827, 11.1345, 10.7624, 10.3913, 9.99559, 9.59857, 9.16844, 8.74251, 8.37833, 8.02815 … 5.77289, 5.7729, 5.77293, 5.77292, 5.7729, 5.77291, 5.77291, 5.77291, 5.77291, 5.77291][17.2879, 17.2245, 17.0354, 16.7364, 16.3009, 15.7385, 14.957, 13.9498, 12.8428, 11.4674 … 8.05783, 8.05797, 8.05789, 8.05783, 8.0578, 8.05778, 8.05778, 8.05775, 8.05773, 8.05772]
31.25[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][7.95051, 7.71008, 7.36973, 7.05915, 6.81253, 6.60547, 6.33242, 6.20856, 5.90247, 5.79213 … 5.73092, 5.7267, 5.72288, 5.71981, 5.71723, 5.71558, 5.71443, 5.71385, 5.71357, 5.71354][14.8364, 15.0814, 15.2094, 15.0455, 14.7772, 14.5307, 14.2246, 14.1041, 13.874, 13.816 … 12.4849, 12.445, 12.4101, 12.3868, 12.3692, 12.3593, 12.3531, 12.3504, 12.3493, 12.3492]
42.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.38822, 8.15315, 7.90496, 7.74148, 7.54947, 7.42629, 7.21904, 7.06338, 6.82622, 6.62508 … 5.63687, 5.63973, 5.64247, 5.64441, 5.64568, 5.64631, 5.64656, 5.64657, 5.64648, 5.64641][13.7108, 13.8974, 13.9356, 13.9101, 13.8971, 13.9043, 13.9225, 13.9274, 13.9095, 13.8705 … 13.7105, 13.7429, 13.7652, 13.7748, 13.7762, 13.7723, 13.7654, 13.7572, 13.7488, 13.7434]
\n```\n:::\n:::\n\n\nNow, we can visualise these data\n\n::: {#0f5bce25 .cell execution_count=10}\n``` {.julia .cell-code}\n# Visualize the results\np1_h = @df df_collect_h plot(:h, [:FinalStability],\n legend = :bottomright,\n ylabel = \"Stability\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\np2_h = @df df_collect_h plot(:h, [:FinalBiomass],\n legend = :bottomright,\n ylabel = \"Biomass\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\np3_h = @df df_collect_h plot(:h, [:FinalRichness],\n legend = :bottomright,\n ylabel = \"Richness\",\n xlabel = \"Functional response\",\n seriestype = [:scatter, :line])\n\nplot(p1_h, p2_h, p3_h, layout=(3,1), legend = false, size = (1000, 1000))\n```\n:::\n\n\n#### INTERPRETATION?\n\nWhat can you see happening as we move away from the destabilising Type II functional response?\n\nCan you modify this code to explore what happens at different values of K? You'll need to modify this section, and the collection data frame.\n\n::: {#6661fd10 .cell execution_count=11}\n``` {.julia .cell-code}\n # make the network\n fw_h = Foodweb(:niche; S = S, C = C)\n\n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_h, LogisticGrowth(; K = k))\n\n # update the exponent of the hill function\n params.hill_exponent = h\n```\n:::\n\n\n### Experiment 3: What is Z\n\nOne of the central features of the link between the Bioenergetic Food Web model and the structure of a foodweb created by models like the Niche Model is the organisation of trophic levels. At the heart of this is a _data driven_ assumption about the ratio of predator size to prey size. This is called the _Predator Prey Mass Ratio_, or `PPMR` for short. \n\nIn 2006, Uli Brose and team collated hundreds of data [to reveal that](https://esajournals.onlinelibrary.wiley.com/doi/10.1890/0012-9658%282006%2987%5B2411%3ACBRINF%5D2.0.CO%3B2), on average, predators were between 10 and 100x bigger than their prey.\n\nIn our modelling framework, we use this ratio to help organise species into trophic levels. This is done by organising the bodymass vector, and via a parameter called `Z`. The body mass of consumers is a function of their mean trophic level (T), and it increases with trophic level when Z ≥ 1 and decreases when Z ≤ 1 via this relationship (see Delmas et al 2017 and Williams et al 2007):\n\n$M_C = Z^(T-1)$\n\n[Brose et al 2006](https://onlinelibrary.wiley.com/doi/10.1111/j.1461-0248.2006.00978.x) explored the impact of the _PPMR_ on stability and dynamics as part of their wider exploration of scaling and allometry in the bioenergetic model. Here we show you how to manipulate `Z` and it's effect on stability. `Z` is specified in the call to FoodWeb as the allocation of species with specific sizes is central to the trophic structure of the model. This argument is interfaced with the bodysize vector in `model_parameters()`\n\n::: {#1d032240 .cell execution_count=12}\n``` {.julia .cell-code}\nRandom.seed!(12352)\n\n# fixed parameters\nS = 20\nC = 0.15\n\n# set the PPRM\nz_levels= [0.1, 1, 10, 100]\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_z = DataFrame(z = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\n# create look across values of h\nfor z in z_levels \n println(\"***> This is iteration with z = $z\\n\")\n \n # make the network\n # Note that we specify the Environment, but there is no K or T set (using defaults)\n # Note Z is specified when building the FoodWeb() network\n fw_z = Foodweb(:niche; S = S, C = C)\n \n # set body sizes and parameters \n B0 = rand(S)\n params = default_model(fw_z, BodyMass(; Z = z))\n\n # specify number of time steps\n t = 300\n\n # simulate\n out_z = simulate(params, B0, t)\n\n # collect data \n fin_rich = richness(out_z)\n fin_bio = total_biomass(out_z)\n s_div = shannon_diversity(out_z)\n\n push!(df_collect_z, [z, fin_rich, fin_bio, s_div])\nend\n\ndf_collect_z\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n***> This is iteration with z = 0.1\n\n***> This is iteration with z = 1.0\n\n***> This is iteration with z = 10.0\n\n***> This is iteration with z = 100.0\n\n```\n:::\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n
4×4 DataFrame
RowzFinalRichnessFinalBiomassShannonDiversity
AnyAnyAnyAny
10.1[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 14, 14, 14, 14, 14, 13, 13, 12, 12, 12][14.0154, 13.1242, 12.5054, 11.7867, 11.1144, 10.4411, 9.65219, 8.81407, 7.85734, 6.85837 … 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144, 2.54144][18.7295, 18.6017, 18.0408, 17.0915, 16.2886, 15.7357, 15.3028, 14.9264, 14.5273, 14.1848 … 9.01235, 9.01233, 9.01232, 9.01231, 9.01231, 9.01231, 9.01231, 9.01231, 9.0123, 9.0123]
21.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 19, 19, 17, 17, 16, 16, 16, 16, 16, 16][11.3827, 11.0237, 10.6428, 10.1558, 9.68492, 9.08034, 8.44996, 7.73821, 7.12812, 6.50964 … 4.04905, 4.04904, 4.04904, 4.04904, 4.04904, 4.04903, 4.04903, 4.04902, 4.04902, 4.04902][17.2879, 17.2885, 17.2049, 16.9595, 16.5593, 15.7827, 14.6068, 12.8519, 11.257, 9.97863 … 12.411, 12.411, 12.411, 12.411, 12.411, 12.4109, 12.4109, 12.4108, 12.4108, 12.4108]
310.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][7.95051, 7.71606, 7.43686, 7.21154, 7.03513, 6.86424, 6.73195, 6.58726, 6.478, 6.39076 … 6.19265, 6.19575, 6.19649, 6.19564, 6.19442, 6.19361, 6.19319, 6.19306, 6.19304, 6.19304][14.8364, 15.1738, 15.4241, 15.5023, 15.5318, 15.5827, 15.6634, 15.816, 15.987, 16.1622 … 17.1402, 17.1371, 17.1269, 17.1157, 17.1054, 17.0988, 17.0953, 17.0943, 17.0942, 17.0942]
4100.0[20, 20, 20, 20, 20, 20, 20, 20, 20, 20 … 20, 20, 20, 20, 20, 20, 20, 20, 20, 20][8.38822, 8.25788, 8.10381, 7.99055, 7.9029, 7.81458, 7.76517, 7.70146, 7.67839, 7.69968 … 10.4944, 10.5011, 10.5112, 10.5238, 10.5387, 10.553, 10.5648, 10.5725, 10.5769, 10.5779][13.7108, 13.8452, 13.9135, 13.9026, 13.8919, 13.9322, 13.9969, 14.1639, 14.3154, 14.5913 … 12.0742, 12.1247, 12.1854, 12.2463, 12.3038, 12.3476, 12.3764, 12.3919, 12.3991, 12.4006]
\n```\n:::\n:::\n\n\nAs with the variation in `h`, we can create a set of figures too! Perhaps it's worth your time to consult [Brose et al 2006](https://onlinelibrary.wiley.com/doi/10.1111/j.1461-0248.2006.00978.x) and [Reger et al 2017](https://besjournals.onlinelibrary.wiley.com/doi/10.1111/2041-210X.12713) to make sure you understand how Z works and particularly how stability is expected to vary with Z! One of the most important things to understanding is why the stability metric is negative and what values of stability close, or far away, from zero mean.\n\n::: {#d4f22cbb .cell execution_count=13}\n``` {.julia .cell-code}\n# Visualize the results\np1_z = @df df_collect_z plot(:z, [:FinalStability],\n legend = :bottomright,\n ylabel = \"Stability\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\np2_z = @df df_collect_z plot(:z, [:FinalBiomass],\n legend = :bottomright,\n ylabel = \"Biomass\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\np3_z = @df df_collect_z plot(:z, [:FinalRichness],\n legend = :bottomright,\n ylabel = \"Richness\",\n xlabel = \"Z value (PPMR)\",\n seriestype = [:scatter, :line])\n\nplot(p1_z, p2_z, p3_z, layout=(3,1), legend = false, size = (1000, 1000))\n```\n:::\n\n\n#### Challenge\n\nCould you modify this to ask about the interaction between Z and K? This would be asking the question of whether the effect of PPMR on stability varies by system productivity. Or you could ask about the interaction between the functional response, which we know also has a direct effect on stability by the assumption we make of a Type II or Type III shape, and the value of Z, which we also know impacts stability from Brose et al's work.\n\n### Experiment 4: Manipulating Competition among producers\n\nOur final experiment for this section involves manipulating how the basal producers compete with each other. The default paramterisation of the model has each producer growing via the logistic equation and competing with itself via density dependence. There is only intraspecific competition, no interspecific competition.\n\nWe can modify this assumption by invoking another function called `ProducerCompetition`. This function acts like `Environment` that we use to set `K` and `BioenergeticResponse` that we used to modify the functional response between Type II and Type III.\n\nThe theory to recall is that coexistence among species is mediated by the balance between intraspecific and interspecific competition. When intraspecific competition is greater than interspecific competition, there is coexistence. However, when interspecific competition is greater than intraspecific competition, there will be compeitive exclusion and no coexistence. \n\nWe call the competition parameters $\\alpha$. $\\alpha~ii$ defines intraspecific competition and $\\alpha~ij$ defines interspecific competition. The $\\alpha~ij$ defines how the species $j$ reduces the carrying capacity (equilibrium) of species $i$. \n\nWhat we can do is set $\\alpha~ii = 1$ and then vary $\\alpha~ij$ from $<1$ to $>1$. We can expect that there will a dramatic change in biomass and species richness as we move from $alpha~ii > alpha~ij$ to $alpha~ii < alpha~ij$.\n\n::: {#11722271 .cell execution_count=14}\n``` {.julia .cell-code}\nS = 20 # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\nZ = 100 # Predator Prey Mass Ratio\n\n# here we set the \ninterspecific_vals = 0.8:0.05:1.2 # a set of (9) values between 0.8 and 1.2 in steps of 0.05\n# collect(0.8:0.05:1.2) # see them if you want to\n\n\n# set collecting data frame \n# we will look at how Richness, Biomass and Stability are affected by the hill exponent\ndf_collect_comp = DataFrame(InterComp = [], FinalRichness = [], FinalBiomass = [], ShannonDiversity = [])\n\nfor alpha_ij in interspecific_vals\n println(\"***> This is iteration with alpha_ij = $alpha_ij\\n\")\n \n # this will make always the same network and body mass\n Random.seed!(123)\n foodweb = Foodweb(:niche; S = S, C = C, Z = Z)\n\n # enhance detail in the network\n # specify K\n LogisticGrowth(foodweb; K = 10)\n # we fix intraspecific = 1 and vary interspecific\n ProducerCompetiton(foodweb; αii = 1.0, αij = 1)\n # set the hill exponent to 1 (type II Functional Response)\n BioenergeticResponse(foodweb, h = 1)\n\n # define parameters with extras\n params_comp = default_model(foodweb, BodyMass(; Z = z))\n\n # set bodymass\n B0 = rand(S)\n\n # simulate\n # note verbose = false ; remove this to see extinction detail for each sim\n out_comp = simulate(params_comp, B0, verbose = false)\n\n # generate stats and add to collector\n # collect data \n fin_rich = richness(out_comp)\n fin_bio = biomass(out_comp).total\n stab = community_cv(out_comp)\n\n push!(df_collect_comp, [alpha_ij, fin_rich, fin_bio, stab])\nend\n\ndf_collect_comp\n```\n:::\n\n\nLet's review the assumptions above. We've set the `Predator Prey Mass Ratio` to 100. We've set carrying capacity `K` to 10. We've set the functional response `h` value to 1, so it's a Type II functional response. Finally, we've set a range of interspecific competition to be 0.8 to 1.2 around the fixed intraspecific effect of 1.\n\n::: {#07d0d076 .cell execution_count=15}\n``` {.julia .cell-code}\np1 = @df df_collect_comp plot(:InterComp, [:FinalRichness],\n ylabel = \"Richness\",\n xlabel = \"alpha_ij\")\np2 = @df df_collect_comp plot(:InterComp, [:FinalBiomass],\n ylabel = \"Biomass\",\n xlabel = \"alpha_ij\")\np3 = @df df_collect_comp plot(:InterComp, [:FinalStability],\n ylabel = \"Stability\",\n xlabel = \"alpha_ij\")\n\nplot(p1, p2, p3, layout = (3,1), legend = false)\n```\n:::\n\n\n#### Challenge - Competition\n\nPerhaps consider expanding the code above to assess one of these?\n\nIs this pattern sensitive to specie richness?\nIs this pattern sensitive to the functional response?\nIs this pattern sensitive to the PPMR?\nIs this pattern sensitive to values of K?\n\n## Experiment 5: Multiple networks (replicates)\n\nTo Do: run S (3 values), C (3 values) and h (3 values) where there are 5 replicate networks per combination. Note we need 45 networks...\n\n", - "supporting": [ - "Tutorial-10_Complex Experiments with the BEFWM2_files/figure-html" - ], - "filters": [], - "includes": { - "include-in-header": [ - "\n\n\n" - ] - } - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-1_Downloads Setups and Your First Project/execute-results/html.json b/_freeze/Tutorial-1_Downloads Setups and Your First Project/execute-results/html.json deleted file mode 100644 index b88a322..0000000 --- a/_freeze/Tutorial-1_Downloads Setups and Your First Project/execute-results/html.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "hash": "4479be47466b6252fc94c3a6b5736678", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 1: Downloads, Setups and Your First Project\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n## Downloading and Installing Julia and VSCode\n\n**Julia**\n\nNavigate to [this page](https://julialang.org/downloads/) and follow the platform-specific instructions to download and install Julia (we recommend installing the current stable release).\n\nDuring the installation process, you may be prompted to add Julia to the PATH, this box should be ticked.\n\n> Juliaup is also an option but it might be worth keeping it simple since I'm assuming most people aren't going to be at the space where they need to be able to tap into multiple versions of Julia, although there is also something to be said about setting yourself up with the best toys on the market...\n\n**VSCode**\n\nNavigate to [this page](https://visualstudio.microsoft.com/) to download and install your platform specific Visual Studio Code (not Visual Studio or Visual Studio for Mac).\n\n## Setting Up VSCode to use Julia\n\nVS Code is a free source-code editor, allowing you to code in multiple coding languages all from a platform that is completely customisable to the user - think of it as a more language agnostic version of RStudio. This flexibility is great but it does mean that you need to spend time telling VS Code what it is you want to do and how. This is where extensions come in; extensions are higher level packages that permit the use of a given coding language like Julia, edit your themes and icons, provide helpful applications like spell checker or Bracket Pair Colorizer, and for adding your own [VS Code pets](https://tonybaloney.github.io/vscode-pets/usage) (a very important part of the VSCode experience).\n\nTo install Julia in VS Code do the following (you only need to do this once):\n\n1. open VS Code (you'll see the welcome page)\n2. navigate to the 'Marketplace' (5th symbol down in the activity bar - vertical panel on the lefthand side of the screen)\n\n![The Marketplace Button](Figs/VSCode_FirstView.png)\n\n3. search for Julia in the 'Search Extensions in Marketplace' search bar\n4. install `Julia`, this extension provides support for the Julia programming language and install `Julia Formatter`, this extension will help you write clean code that is easier to read\n\n![Selecting the Julia Language Support and Formatter](Figs/JuliaLangAndFormatter.png)\n\n## Making your first Julia project\n\nAs with working in R and RStudio, we advocate working in a contained project environment when using Julia. Each unique project may require a different setup (e.g. packages, package versions, working directories, data locations, etc.).\n\nTo set up a project in VS Code:\n\n1. Creating a folder at a location of your choosing (e.g. within your Documents folder). This can be on GoogleDrive, Dropbox or OneDrive. This is OK.\n\n2. Name the folder with relevant works. Here we will use `Julia - VS code - how to`.\n\n3. Navigate to VSCode and open your new project by clicking on the 'Explorer' symbol (top left symbol on the activity bar) and click Open Folder and navigate your finder or explorer to the `Julia - VS code - how to` folder.\n\n - this folder becomes the working directory (same as when using an `.RProject` in R)\n\n![Opening Your Project](Figs/OpenProject.png)\n\n4. Create a new file (a script) in your directory: do this by using cmd-N (mac) or ctrl-N (windows) or File -\\> New File or by left clicking -\\> New File within the directory pane\n\n5. Name your script as your see fit but please remember to include the .jl file extension (e.g. JuliaTuto.jl). the .jl file extension tells VS Code you want to use the Julia programming language. To save your script at any time use cmd-S (MAC) OR ctrl-S (windows) or File \\> Save.\n\n - Note, you can also open a project in VS Code by right-clicking on your folder (in Finder, Windows file explorer or Linux nautilus) and selecting Open with -\\> Other -\\> VS Code.\n\n### Activating the REPL and running some code.\n\nThis sequence of figures aligns with the instructions below.\n\n![Initiating and using the REPL](Figs/UsingREPL.png)\n\nNow that you have an active project and a new script file you can open the Julia REPL. REPL stands for *read, execute, print and loop*. The REPL is like the console in R and is where the magic happens. In Eva's words, it's VS Code's way of using Julia for a brain.\n\nTo do this you type F1 or cmd/ctrl - shift-p or View -\\> Command Palette and choose Julia REPL. The command palette will appear as a drop down menu with a search function at the top of the page.\n\nNow that you have an interface with Julia as a brain, you can actually do something! Try this: type `print(\"Hello world\")` in the REPL and press Enter/Return. If you've done all of the above correctly, Hello world should print in the REPL.\n\nNow, you can also make a 'script'. Type ctrl-n or cmd-n and a document will open at the top. There will be a prompt/link to select your language. Click the link and, yes, search for and choose Julia.\n\nNext, type `print(\"Hello world\")` in the script. Just like RStudio, you can send the information in the script to the REPL. There are two ways to do this. First, and probably what you'll want, is shift-enter(return). This will send the line of code you are on, and move to the next line. ctrl-enter(return) submits the line but does not move the cursor. Try it!\n\n## Activating your project, the Project.toml and Manifest.toml\n\nWe mentioned above that it is good practice to work within an environment specific to each project. The Julia package manager (`Pkg`) allows you to do that easily: Unlike traditional package managers, which install and manage a single global set of packages, `Pkg` is designed around environments: independent sets of packages that can be local to an individual project or shared and selected by name (text taken directly from the documentation).\n\n### Getting started: activating your project.\n\nActivating your project is something that only needs doing once per computer. It allows you to add packages and dependencies to the project.\n\nIf you move the project to a new computer, or share the project, activation will be needed again.\n\nThere are two ways to activate your project.\n\n1. type `Pkg.activate(\".\")` in the REPL.\n2. type `]` in the REPL and then `activate .`\n\nThe `]` is a shorthand for using the `Pkg` package and opens the package manager. To get out of this, you press the `backspace/delete` button on your keyboard.\n\nThere are two ways to double check that you are actually working within your project:\n\n- check/click the 'Julia env:...' on the bottom of your screen (blue bar), it should match your project name\n\n- enter the package manager by typing `]` in the Julia REPL, you should see (your-project-name) pkg\\> instead of julia\\>. Again, exit the package manager using `backspace/delete` button.\n\n### Working with the package manager and growing the project and manifest files\n\nOnce your project is activated, there are two ways to use the package manager (Pkg):\n\n1. directly from the REPL:\n\n- navigate to the REPL\n- type `]`\n- you will see that instead of seeing julia\\> you now see (your-project-name) pkg\\>, indicating that all the packages that you now install (or update) will be installed (or updated) within this specific project\n- to add a package, use the function `add`: `] add Plots`\n\n2. using `Pkg` (this is useful when you want to install packages or manage them from within your script):\n\n- first type `import Pkg` and execute this line using shift-Enter\n- on subsequent lines, add, remove and update packages from your script using `Pkg` functions such as `Pkg.add()`, `Pkg.remove()` or `Pkg.update()`.\n- To add a packages, the name of the package need to be written with quotes (`Pkg.add(\"Plots\")`).\n\n#### An example using the Plots package\n\nNow that we are all set up, we are going to install a package, check the project's status and remove a package. As this might be your first time installing a package (e.g., Plots), don't be concerned if it takes a couple of minutes to run.\n\n- type `] add Plots` in the REPL (or `Pkg.add(\"Plots\")`) in your script and execute using Ctrl-Enter.\n - you just installed the Plots package and a whole bunch of dependencies that Plots needs to work. This is equivalent to Base plots in R.\n\n![Package Installing](Figs/Pkg.adding.png)\n\n- type `] st` in the REPL. This will check the status of your project and print the content of your Project.toml file, which is the list of main packages, in this case, just Plots.\n\nyou should see something like:\n\n![Package Status Check](Figs/StatusCheck.png)\n\n> packages can removed in the same way i.e. `] rm Plots` (or `Pkg.rm(\"Plots\")`) will remove the Plots package from your project environment (and its record in the Project.toml and Manifest.toml files)\n\n## Gearing up to Do More Stuff (what packages do I need).\n\nThere are a core set of packages we use for all of our work. These 10 packages are almost always installed when we make a project.\n\nGo ahead and use either the `]` or `Pkg.add(\"package.name\")` method to add all of these to your project.\n\n#### For working with data\n\nCSV DataFrames DelimitedFiles\n\n#### For plotting\n\nPlots\n\n#### For statistical things\n\nDistributions Random Statistics StatsBase StatsPlots\n\n#### For Modelling\n\nDifferentialEquations\n\n## Your first script setup.\n\nAt this stage, you should have a good understanding about how to create a project folder, activate a project, start the REPL, open a script and add packages to the project.\n\nNow you are ready to 'setup' your first script.\n\n1. create a new script file (ctrl-n or cmd-n).\n2. choose Julia as the language\n3. Type some informative information at the top of the script\n a. just like in R and other programming languages, the `#` is a commenter.\n4. The first section of your script is where you declare the packages you'll be using.\n a. the function to do this is `using`.\n b. make Plots, Random and DataFrames available.\n\nNow you are ready to do something really simple. Let's make some variables, data frames and a few simple plots.\n\nFirst, lets get the setup sorted and packages available\n\n::: {#2b0b408f .cell execution_count=2}\n``` {.julia .cell-code}\n# This is my first example script\n# 25 Jan 2023\n\n# packages I need\nusing DataFrames, Plots, Random, StatsPlots\n```\n:::\n\n\nSecond, let's make some variables and see how Julia print them to the screen\n\n::: {#87598216 .cell execution_count=3}\n``` {.julia .cell-code}\n# make two variables using the rand function\n# because we are using random numbers, we'll set the seed here for reproducibility\n\nRandom.seed!(12345)\n\nx = rand(10)\ny = rand(10)\n\nx\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n10-element Vector{Float64}:\n 0.7918054038647908\n 0.1595789996994108\n 0.33419142747606\n 0.8113922657011057\n 0.7966292033537833\n 0.9178138221831842\n 0.31132682723725014\n 0.7529056805990061\n 0.6338479453532103\n 0.8999510969166794\n```\n:::\n:::\n\n\nCool. Now, lets create two data frames, one made of the x and y variables, and another with three variables made directly in a call to `DataFrame`.\n\n::: {#eb88cf79 .cell execution_count=4}\n``` {.julia .cell-code}\n# combine into a data frame using the DataFrame function\ndf = DataFrame(x = x, y = y)\ndf\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```{=html}\n
10×2 DataFrame
Rowxy
Float64Float64
10.7918050.330263
20.1595790.421987
30.3341910.685307
40.8113920.2958
50.7966290.973659
60.9178140.24459
70.3113270.468751
80.7529060.277055
90.6338480.629916
100.8999510.121805
\n```\n:::\n:::\n\n\n...and the second\n\n::: {#2672e02a .cell execution_count=5}\n``` {.julia .cell-code}\n# make a second data frame with three variables\n# using DataFrame directly to create variables\ndf2 = DataFrame(a=1:10, b=10*rand(10), c=10*rand(10))\ndf2\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```{=html}\n
10×3 DataFrame
Rowabc
Int64Float64Float64
110.5634039.77384
227.226793.58869
330.4666423.76688
444.594899.03599
550.4911088.73964
666.991921.36299
771.581220.815793
884.707453.75399
994.975720.599761
10104.586752.14792
\n```\n:::\n:::\n\n\nGreat. Now, lets see how to plot the 'solo' variables. Note how we specify the seriestype. Try getting rid of this....\n\n::: {#d7354f82 .cell execution_count=6}\n``` {.julia .cell-code}\n# plot the data using x and y, as a scatterplot\nplot(x, y, seriestype=:scatter)\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nSuperb. So, `StatsPlots` provides a special macro to use a dataframe with plots. It's a three step process:\n\n1. declare the `@df` macro\n2. define the data frame\n3. declare the columns, using the `:`\n\n::: {#30b89551 .cell execution_count=7}\n``` {.julia .cell-code}\n# plot the data using the data frame macro\n# declare the df macro, declare the data frame, use : to signify columns\n@df df plot(:x, :y)\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nAnd here, we use the df2, and plot variable b and c vs. a.\n\n::: {#94bf85f2 .cell execution_count=8}\n``` {.julia .cell-code}\n# the same, and plotting two y variables\n@df df2 plot(:a, [:b, :c])\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n#### A quick briefing about data frames in Julia versus R and dplyr is here\n\n[DataFrames Comparison R dplyr)](https://dataframes.juliadata.org/stable/man/comparisons/#Comparison-with-the-R-package-dplyr)\n\n", - "supporting": [ - "Tutorial-1_Downloads Setups and Your First Project_files" - ], - "filters": [], - "includes": { - "include-in-header": [ - "\n\n\n" - ] - } - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-2_Using Julia for Maths and Vector Stuff/execute-results/html.json b/_freeze/Tutorial-2_Using Julia for Maths and Vector Stuff/execute-results/html.json deleted file mode 100644 index 0474a11..0000000 --- a/_freeze/Tutorial-2_Using Julia for Maths and Vector Stuff/execute-results/html.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "hash": "878bbfaf20ec9f06c4a2131022a79323", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 2: Using Julia for Maths and Vector Stuff\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\nThis second document follows on from Tutorial 1: \"Getting started\" and assumes that you're still working in your active project.\n\nThis document covers the following:\n\n- Basic maths\n- Arrays and Matrices\n- Dictionaries\n- DataFrames and CSVs\n- Functions\n- Loops\n- Plots\n- Scoping\n\nThere is also a section at the end with some \"Quick tips\".\n\n## Basic Maths {#sec-basic-maths}\n\nAs you probably can guess, the REPL is an interface onto a large calculator. Julia does all the things R does... and you can find the basic maths operations defined [The Julia Manual](https://docs.julialang.org/en/v1/manual/mathematical-operations/index.html)\n\n::: {#2b02f561 .cell execution_count=2}\n``` {.julia .cell-code}\n# sums\n1+1\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\n2\n```\n:::\n:::\n\n\n::: {#602a23d1 .cell execution_count=3}\n``` {.julia .cell-code}\n# power\n10^3\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n1000\n```\n:::\n:::\n\n\n::: {#b5000926 .cell execution_count=4}\n``` {.julia .cell-code}\n# sequences in a vector\n# From 0, by 1, to 10...\n\nx = collect(0:1:10)\n\n# see it\nx\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n11-element Vector{Int64}:\n 0\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n```\n:::\n:::\n\n\n::: {#dcd965aa .cell execution_count=5}\n``` {.julia .cell-code}\n# multply scaler x vector.\nx*10\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n11-element Vector{Int64}:\n 0\n 10\n 20\n 30\n 40\n 50\n 60\n 70\n 80\n 90\n 100\n```\n:::\n:::\n\n\n## Getting Help {#sec-getting-help}\n\nBefore we move on, lets talk about the help files and how to access them. As in R, the help files associated with a given package, function or command can be accessed using `?` followed by the function name (e.g. type `? pi` in the REPL).\n\nSimilar to when you entered Julia's package manager (using `]`) you'll notice that the `?` command causes a change in the REPL with `help?> `replacing `julia>` as the prompt. This informs you that you've entered the help mode. As an exercise, use the help mode to find the difference between `print` and `println`.\n\n## Preamble to Objects like scalars, vectors and arrays\n\nBefore we start creating arrays and matrices, we'd like to demonstrate how you allocate numbers and strings to objects in Julia and check an object's type. We'd also like to highlight some simple mathematical operations.\n\n### Allocating data to objects\n\nAllocating in Julia is useful as it means that variables can be stored and used elsewhere. You allocate numbers to objects using the following:\n\nFirst note that we use the `=` in `Julia`, not the `<-` as in R.\n\n::: {#7d70e321 .cell execution_count=6}\n``` {.julia .cell-code}\n# allocate an Integer number to a variable\nn = 5\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```\n5\n```\n:::\n:::\n\n\nJulia, like other languages, has some built in values, like `pi`. We can allocate these to variable names we will use. Notice that Julia converts pi into the unicode symbol!\n\n::: {#3ec2029e .cell execution_count=7}\n``` {.julia .cell-code}\n# allocate a pre-defined number of importance to a variable\n# note that pi is converted to π\n# note2 - you can use \\pi in a julia script to get the unicode π ...\n# this works for numerous greek letters etc. Like \\lambda for λ\npi_sum = pi\npi_sum\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\nπ = 3.1415926535897...\n```\n:::\n:::\n\n\nWe can use these unicode symbols (and emojis!), like λ, as objects\n\n::: {#386548df .cell execution_count=8}\n``` {.julia .cell-code}\nλ = 4\nλ\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```\n4\n```\n:::\n:::\n\n\nYou can also assign multiple values to separate variables in a concise manner. Julia can manage something like this:\n\n::: {#b559ebcb .cell execution_count=9}\n``` {.julia .cell-code}\nαi, βi, γi = 1.3, 2.1, exp(39)\n\n# confirm...\nαi, βi, γi\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n(1.3, 2.1, 8.659340042399374e16)\n```\n:::\n:::\n\n\n#### Allocating strings\n\nOf course you can also allocate strings of text to objects. You must use the `\"\"` and not `''` to define strings.\n\n::: {#7010b31b .cell execution_count=10}\n``` {.julia .cell-code}\nsob = \"School of Biosciences\"\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```\n\"School of Biosciences\"\n```\n:::\n:::\n\n\nYou can combine strings and numbers to print like this. Note how you use $object.name within the text string you are writing... and this works for objects that are text or numeric.\n\n::: {#fa287465 .cell execution_count=11}\n``` {.julia .cell-code}\nprintln(\"The favourite number in $sob is $n\")\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nThe favourite number in School of Biosciences is 5\n```\n:::\n:::\n\n\n### Identifying the Type of object you've made\n\nJulia is very specific about types of objects. Most programming languages are. One way to learn about them is to look at what is made when you make things in different ways.\n\n::: {#57720a9a .cell execution_count=12}\n``` {.julia .cell-code}\ntypeof(n), typeof(sob), typeof(pi)\n```\n\n::: {.cell-output .cell-output-display execution_count=13}\n```\n(Int64, String, Irrational{:π})\n```\n:::\n:::\n\n\nJulia is like R and Python in that it can infer the type of object (Integer, Float, etc) on the left hand side of the equals sign - you don't have to justify it like you do in C. However, you can declare the type if needed e.g.\n\n::: {#96440f84 .cell execution_count=13}\n``` {.julia .cell-code}\npi_custom = Float64(3.141592)\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```\n3.141592\n```\n:::\n:::\n\n\nFor those of you that are interested, a floating-point object (a Float) is a number that has a decimal place. An Int object is an integer, a number without a decimal place, whereas an Irrational object is a specific type of Float used only for representing some irrational numbers of special significance (e.g. π and γ). The 64 purely refers to 64-bit which is the type of processor your computer uses, most modern computers are 64-bit.\n\nOccasionally it will be valuable to convert an object from one type to another. For example, `n` is currently an Integer (Int64), and we might want it to be Float (Float64). To be clear, this is a distinction between `5` and `5.0`!\n\n::: {#fa6cd712 .cell execution_count=14}\n``` {.julia .cell-code}\ntypeof(n)\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```\nInt64\n```\n:::\n:::\n\n\n::: {#9319b3ed .cell execution_count=15}\n``` {.julia .cell-code}\nn2 = convert(Float64, n)\ntypeof(n2)\n```\n\n::: {.cell-output .cell-output-display execution_count=16}\n```\nFloat64\n```\n:::\n:::\n\n\n## Understanding Arrays, Vectors and Sequences.\n\nAs you saw above, we created a sequence of numbers using `collect(0:1:10)`. Let's look at what type of object this is:\n\n::: {#54de39e5 .cell execution_count=16}\n``` {.julia .cell-code}\ntypeof(x)\n```\n\n::: {.cell-output .cell-output-display execution_count=17}\n\n::: {.ansi-escaped-output}\n```{=html}\n
Vector{Int64} (alias for Array{Int64, 1})
\n```\n:::\n\n:::\n:::\n\n\nThis is a vector. Let's step back to see the difference between arrays and vectors. Arrays, for the R users, are best thought of as `lists` - they are storage boxes for any type of variables and can contain collections of various types. The general way to create an array, in this case and empty one, is the `[ ]`.\n\n::: {#b1a71040 .cell execution_count=17}\n``` {.julia .cell-code}\nempty_array = []\n```\n\n::: {.cell-output .cell-output-display execution_count=18}\n```\nAny[]\n```\n:::\n:::\n\n\n We will first create an array with the same values as x and then see how collect() is the function that converts this to a vector, and actually lets us see the numbers too!\n\nFirst, `range` can be used to make an array. This is very similar to `seq()` in `R` and has the two variations - `by` and `length` that the `R` function has. The difference is that `by` is replaced by the argument `step`. Note how a very concise summary of this array is presented using information in square brackets `[ ]`:\n\n::: {#e527e04c .cell execution_count=18}\n``` {.julia .cell-code}\nx_array1 = range(start = 1, step = 1, stop = 10)\nx_array2 = range(start = 1, stop = 10, length = 5)\n\nx_array1, x_array2\n```\n\n::: {.cell-output .cell-output-display execution_count=19}\n```\n(1:1:10, 1.0:2.25:10.0)\n```\n:::\n:::\n\n\nYou can also now see that creating arrays is possible with `[ ]` and the use of the `:` :\n\n::: {#3867ff09 .cell execution_count=19}\n``` {.julia .cell-code}\nx_array3 = [1:1:10]\n```\n\n::: {.cell-output .cell-output-display execution_count=20}\n```\n1-element Vector{StepRange{Int64, Int64}}:\n 1:1:10\n```\n:::\n:::\n\n\nQuite often, you want to either see the values, or specifically be using a vector. To do this, you can use the function `collect()`:\n\n::: {#c0562fe1 .cell execution_count=20}\n``` {.julia .cell-code}\ncollect(x_array1)\n```\n\n::: {.cell-output .cell-output-display execution_count=21}\n```\n10-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n```\n:::\n:::\n\n\n## Indices of Arrays.\n\nYou should recall from **R** that values in arrays and vectors and dataframes have _addresses_ that we call indices. Julia works with indexing very similarly.\n\nLet's make a simple array of 5 numbers and another simple array of five words. Note that the `[]` array function is a but like the `c()` function in **R**.\n\n::: {#b93a3bd9 .cell execution_count=21}\n``` {.julia .cell-code}\nar = [6,7,8,9,10]\nbr = [\"Pint\", \"of\", \"Moonshine\", \"please\"]\n```\n\n::: {.cell-output .cell-output-display execution_count=22}\n```\n4-element Vector{String}:\n \"Pint\"\n \"of\"\n \"Moonshine\"\n \"please\"\n```\n:::\n:::\n\n\nYou can get any address in these using... square brackets!\n\n::: {#4ab590ae .cell execution_count=22}\n``` {.julia .cell-code}\nar[2] # gets the number 7!\n```\n\n::: {.cell-output .cell-output-display execution_count=23}\n```\n7\n```\n:::\n:::\n\n\n::: {#fd938e1f .cell execution_count=23}\n``` {.julia .cell-code}\nbr[3] # gets the word Moonshine\n```\n\n::: {.cell-output .cell-output-display execution_count=24}\n```\n\"Moonshine\"\n```\n:::\n:::\n\n\nIf you want two addresses in a sequence, you can just provide the sequence:\n\n::: {#dba2afcb .cell execution_count=24}\n``` {.julia .cell-code}\nar[2:3]\n```\n\n::: {.cell-output .cell-output-display execution_count=25}\n```\n2-element Vector{Int64}:\n 7\n 8\n```\n:::\n:::\n\n\nBut if you want non-adjacent values, you need to provide the 'list of indices' as an array, which results in the use of `[[ ]]`.\n\n::: {#8c46227d .cell execution_count=25}\n``` {.julia .cell-code}\nar[[2,4]]\n```\n\n::: {.cell-output .cell-output-display execution_count=26}\n```\n2-element Vector{Int64}:\n 7\n 9\n```\n:::\n:::\n\n\nNote this would be like using in R `ar[c(2,4)]`.\n\n## Broadcasting: something VERY special\n\nBroadcasting allows you to apply a function, like a `log()` or `exp()`, in an element-wise manner to an array (in other words apply the function to every element of an array). \n\nWe saw above that we can create a vector using `collect()` and multiply this by a scalar\n\n::: {#4add369c .cell execution_count=26}\n``` {.julia .cell-code}\n# sequences in a vector\n# From 0, by 1, to 10...\n\nx = collect(0:1:10)\n\n# see it\nx\n```\n\n::: {.cell-output .cell-output-display execution_count=27}\n```\n11-element Vector{Int64}:\n 0\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n```\n:::\n:::\n\n\n::: {#355ad2d2 .cell execution_count=27}\n``` {.julia .cell-code}\n# multply scaler x vector.\nx*10\n```\n\n::: {.cell-output .cell-output-display execution_count=28}\n```\n11-element Vector{Int64}:\n 0\n 10\n 20\n 30\n 40\n 50\n 60\n 70\n 80\n 90\n 100\n```\n:::\n:::\n\n\nYou can work directly with arrays and pre-built functions to do things like this. To do-so, we combine the function with the (dot) `.` operator. Let's work with `x_array1` from above. Note how broadcasting the function across the array returns a vector.\n\n::: {#1442874a .cell execution_count=28}\n``` {.julia .cell-code}\n# Look at the help file for exp10\nexp_array1 = exp10.(x_array1)\n```\n\n::: {.cell-output .cell-output-display execution_count=29}\n```\n10-element Vector{Float64}:\n 10.0\n 100.0\n 1000.0\n 10000.0\n 100000.0\n 1.0e6\n 1.0e7\n 1.0e8\n 1.0e9\n 1.0e10\n```\n:::\n:::\n\n\nIf you try to do this without the (dot) `.` operator what happens?\n\n::: {#5fa689b9 .cell execution_count=29}\n``` {.julia .cell-code}\n# look at the help file for log - what is the default!?\nlog_array1 = log.(x_array1)\n```\n\n::: {.cell-output .cell-output-display execution_count=30}\n```\n10-element Vector{Float64}:\n 0.0\n 0.6931471805599453\n 1.0986122886681098\n 1.3862943611198906\n 1.6094379124341003\n 1.791759469228055\n 1.9459101490553132\n 2.0794415416798357\n 2.1972245773362196\n 2.302585092994046\n```\n:::\n:::\n\n\nDid you check the help file for `log`? Is it the same default as we find in **R**?\n\n## Matrices\n\nSometimes we'll be interested in a 2-dimensional or higher version of the array/vector, and this is a matrix. Making a matrix in Julia uses the `[ ]` again, an separates rows of numbers with the `;`\n\n::: {#9ee3d4b1 .cell execution_count=30}\n``` {.julia .cell-code}\nmat = [1 2 3; 4 5 6]\n```\n\n::: {.cell-output .cell-output-display execution_count=31}\n```\n2×3 Matrix{Int64}:\n 1 2 3\n 4 5 6\n```\n:::\n:::\n\n\nNote how there are NO commas between the numbers in each row! This is read as 'rows are separated by ; and columns by spaces'!\n\nYou can also 'pre-fill' a matrix with zeros. This is good practice in loops and programming as pre-filling and replacing variables in a matrix is more efficient than creating the matrix on the fly. Here we demonstrate how to pre-fil a vector, matrix and high dimension array! Matrices can have more than two dimensions!\n\n::: {#3f57f6a5 .cell execution_count=31}\n``` {.julia .cell-code}\nvec0 = zeros(2) # 2 zeros allocated in a vector\n```\n\n::: {.cell-output .cell-output-display execution_count=32}\n```\n2-element Vector{Float64}:\n 0.0\n 0.0\n```\n:::\n:::\n\n\n::: {#06be0aa0 .cell execution_count=32}\n``` {.julia .cell-code}\nmat0 = zeros(2,3) # zeros allocated to 2 rows and 3 columns!\n```\n\n::: {.cell-output .cell-output-display execution_count=33}\n```\n2×3 Matrix{Float64}:\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n```\n:::\n:::\n\n\n::: {#c2282dcf .cell execution_count=33}\n``` {.julia .cell-code}\narr0 = zeros(2,3,4) # 2 rows, 3 columns and 4 dimensions!\n```\n\n::: {.cell-output .cell-output-display execution_count=34}\n```\n2×3×4 Array{Float64, 3}:\n[:, :, 1] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 2] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 3] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 4] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n```\n:::\n:::\n\n\nAccessing values in a matrix follows the same convention as with the vector. The convention is `[row, column]`\n\n::: {#5d42e97b .cell execution_count=34}\n``` {.julia .cell-code}\nmat[1,2] # value in the first row and second column\n```\n\n::: {.cell-output .cell-output-display execution_count=35}\n```\n2\n```\n:::\n:::\n\n\n::: {#7a5316da .cell execution_count=35}\n``` {.julia .cell-code}\nmat[1:2, 3] # rows 1 AND 2 in the 3rd column\n```\n\n::: {.cell-output .cell-output-display execution_count=36}\n```\n2-element Vector{Int64}:\n 3\n 6\n```\n:::\n:::\n\n\nFinally, to get a row or column, you need to know that we need a placeholder for the _missing_ bit of what you are asking for. If we want the second row, we ask for row 2, and stick the `:` placeholder in the column spot:\n\n::: {#9b71fea9 .cell execution_count=36}\n``` {.julia .cell-code}\nmat[2,:]\n```\n\n::: {.cell-output .cell-output-display execution_count=37}\n```\n3-element Vector{Int64}:\n 4\n 5\n 6\n```\n:::\n:::\n\n\nFor a column, we reverse this.\n\n::: {#a0b6a6c0 .cell execution_count=37}\n``` {.julia .cell-code}\nmat[:,2]\n```\n\n::: {.cell-output .cell-output-display execution_count=38}\n```\n2-element Vector{Int64}:\n 2\n 5\n```\n:::\n:::\n\n\n### A quick interlude on types\n\nAs discussed earlier **Julia** is able to infer the type of an object based on the input. So the `mat` object we created earlier will be a matrix of integers i.e. `Matrix{Int64}`.\n\n::: {#a166fe19 .cell execution_count=38}\n``` {.julia .cell-code}\ntypeof(mat)\n```\n\n::: {.cell-output .cell-output-display execution_count=39}\n\n::: {.ansi-escaped-output}\n```{=html}\n
Matrix{Int64} (alias for Array{Int64, 2})
\n```\n:::\n\n:::\n:::\n\n\nSo what happens if we want to replace one of the elements with a Float?\n\n::: {#251cf8df .cell execution_count=39}\n``` {.julia .cell-code}\nmat[1,2] = 1.5\n```\n:::\n\n\nThis is because we are trying to add a Float to an object that is of the type Integer. What happens if we convert `mat` to be a matrix of floats and then try again?\n\n::: {#274f115b .cell execution_count=40}\n``` {.julia .cell-code}\nmat = convert(Matrix{Float64}, mat)\nmat[1,2] = 1.5\n```\n\n::: {.cell-output .cell-output-display execution_count=40}\n```\n1.5\n```\n:::\n:::\n\n\n## Dictionaries\n\nDictionaries are another way to collect information in **Julia**, these look-up tables allow you to organise information (the **key**) with corresponding data (**value**). When we create a dictionary we specify it as 'value' `=>` 'key'. Dictionaries are useful if you need to store a collection of parameters or outputs, especially because the values for each pair can be of a different type.\n\n::: {#99889347 .cell execution_count=41}\n``` {.julia .cell-code}\nparameters = Dict{Symbol,Any}(\n :growth_rate => 0.4,\n :response => :logistic,\n :carry_capacity => 0.28,\n )\n```\n\n::: {.cell-output .cell-output-display execution_count=41}\n```\nDict{Symbol, Any} with 3 entries:\n :growth_rate => 0.4\n :response => :logistic\n :carry_capacity => 0.28\n```\n:::\n:::\n\n\nWe can also add an 'entry' to our dictionary very easily (or change the value)\n\n::: {#2350f0c9 .cell execution_count=42}\n``` {.julia .cell-code}\nparameters[:abundance] = collect(1:10)\n```\n\n::: {.cell-output .cell-output-display execution_count=42}\n```\n10-element Vector{Int64}:\n 1\n 2\n 3\n 4\n 5\n 6\n 7\n 8\n 9\n 10\n```\n:::\n:::\n\n\n### Looking things up\n\nTo get a value, if you have the key:\n\n::: {#f712ac87 .cell execution_count=43}\n``` {.julia .cell-code}\nparameters[:growth_rate]\n```\n\n::: {.cell-output .cell-output-display execution_count=43}\n```\n0.4\n```\n:::\n:::\n\n\nYou can also get all values using `values()` (and the same for keys using `keys()`). Note that these functions are iterators and they have one job: to iterate through a dictionary value by value (or key by key) so if we want to turn these into an array we need to also call `collect()`\n\n::: {#44a9429e .cell execution_count=44}\n``` {.julia .cell-code}\nparam_vals = collect(values(parameters))\n\nparam_keys = collect(keys(parameters))\n```\n\n::: {.cell-output .cell-output-display execution_count=44}\n```\n4-element Vector{Symbol}:\n :growth_rate\n :response\n :carry_capacity\n :abundance\n```\n:::\n:::\n\n\n", - "supporting": [ - "Tutorial-2_Using Julia for Maths and Vector Stuff_files/figure-html" - ], - "filters": [], - "includes": {} - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-3_Building and Working with DataFrames/execute-results/html.json b/_freeze/Tutorial-3_Building and Working with DataFrames/execute-results/html.json deleted file mode 100644 index c02788b..0000000 --- a/_freeze/Tutorial-3_Building and Working with DataFrames/execute-results/html.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "hash": "07969745aa8a731f48f848fb7b9b3ab6", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 3: Building and Working with DataFrames\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\nWorking with vectors, arrays and matrices is important. But quite often, we want to collect high-dimension data (multiple variables) from our simulations and store them in a spreadsheet type format.\n\nAs you've seen in Tutorial 1, there are plotting macros (`@df`) within the `StatsPlots` package that allow us to work with data frame objects from the `DataFrames` package. A second benefit of the data frame object is that we can export it as a `csv` file and import this into **R** where we may prefer working on plotting and statistics.\n\nTo this end, here we will also introduce the `CSV` package, which is very handy for exporting DataFrame objects to csv files, and importing them as well, if you'd like.\n\n## The Data Frame\n\nTo initialise a dataframe you use the `DataFrame` function from the **DataFrames** package:\n\n::: {#e9e4f6ea .cell execution_count=2}\n``` {.julia .cell-code}\ndat = DataFrame(col1=[], col2=[], col3=[]) # we use [] to specify an empty column of any type and size.\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```{=html}\n
0×3 DataFrame
Rowcol1col2col3
AnyAnyAny
\n```\n:::\n:::\n\n\nAlternately, you can specify the data type for each column.\n\n::: {#92a4af58 .cell execution_count=3}\n``` {.julia .cell-code}\ndat1 = DataFrame(col1=Float64[], col2=Int64[], col3=Float64[])\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```{=html}\n
0×3 DataFrame
Rowcol1col2col3
Float64Int64Float64
\n```\n:::\n:::\n\n\nOf course, `col1` is not the only label you provide: variable names are super important and the conventions we use in **R** are also important here in **Julia**, e.g. `a_b` or `AaBa` but not `a b` (no spaces allowed) or `a.b` (because the (dot) `.` functions as an operator).\n\n::: {#2eec31bc .cell execution_count=4}\n``` {.julia .cell-code}\n# provide informative column titles using:\ndat2 = DataFrame(species=[], size=[], rate=[])\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```{=html}\n
0×3 DataFrame
Rowspeciessizerate
AnyAnyAny
\n```\n:::\n:::\n\n\n### Allocating or adding data to a data frame.\n\nTo add data to a dataframe, we use the `push!` (read as push bang) command.\n\n::: {#5b9f080b .cell execution_count=5}\n``` {.julia .cell-code}\nspecies = \"D.magna\"\nsize = 2.2\nrate = 4.2\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n4.2\n```\n:::\n:::\n\n\n::: {#7439277e .cell execution_count=6}\n``` {.julia .cell-code}\n# push!() arguments: data frame, data\npush!(dat2, [species, size, rate])\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n
1×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
\n```\n:::\n:::\n\n\nOf course, the `push!()` function can append data to the existing data frame. It is worth noting that `push!` can only append one row at a time. But since Julia is so good with loops (compared to R), this will make adding data to a dataframe really easy, and we'll learn how to do this in the next tutorial. What makes the `!` (bang) function very useful is that you can append (or remove, with `pop!()`) items to an object without having to assign it.\n\n::: {#136d8934 .cell execution_count=7}\n``` {.julia .cell-code}\nspecies2 = \"D.pulex\"\nsize2 = 1.8\nrate2 = 3.1\n\n# push!() arguments: data frame, data\npush!(dat2, [species2, size2, rate2])\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\n### Helper Functions for Data Frames\n\nYou can print data frames using `println`\n\n::: {#b98350a8 .cell execution_count=8}\n``` {.julia .cell-code}\nprintln(dat2)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n2×3 DataFrame\n Row │ species size rate \n │ Any Any Any \n─────┼─────────────────────\n 1 │ D.magna 2.2 4.2\n 2 │ D.pulex 1.8 3.1\n```\n:::\n:::\n\n\nThere are `first` and `last` function that are like `head` and `tail` in R and elsewhere, with a first argument the data frame and the second argument the number of rows.\n\n::: {#fa1728de .cell execution_count=9}\n``` {.julia .cell-code}\nfirst(dat2, 2)\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\n::: {#84780904 .cell execution_count=10}\n``` {.julia .cell-code}\nlast(dat2,2)\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```{=html}\n
2×3 DataFrame
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
2D.pulex1.83.1
\n```\n:::\n:::\n\n\nAnd as we learned with matrices and arrays, the `[row, column]` method also works for data frames:\n\n::: {#6a8645da .cell execution_count=11}\n``` {.julia .cell-code}\ndat2[1,2]\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```\n2.2\n```\n:::\n:::\n\n\n::: {#a86fc51e .cell execution_count=12}\n``` {.julia .cell-code}\ndat2[1,:]\n```\n\n::: {.cell-output .cell-output-display execution_count=13}\n```{=html}\n
DataFrameRow (3 columns)
Rowspeciessizerate
AnyAnyAny
1D.magna2.24.2
\n```\n:::\n:::\n\n\n::: {#88a7f878 .cell execution_count=13}\n``` {.julia .cell-code}\ndat2[:,3]\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```\n2-element Vector{Any}:\n 4.2\n 3.1\n```\n:::\n:::\n\n\n## The CSV\n\nAs with *R*, there are functions to read and write `.csv` files to and from dataframes. This makes interoperability with tools in R and standard data storage file formats easy.\n\nTo write our daphnia data to a csv file, we use a familiar syntax, but a function from the `CSV` package.\n\n::: {#5eac335b .cell execution_count=14}\n``` {.julia .cell-code}\nCSV.write(\"daphniadata.csv\", dat2)\n```\n:::\n\n\nOf course, you can read files in using.... yes, `CSV.read`. Note the second argument declares the data to go into a data frame.\n\n::: {#a82459c7 .cell execution_count=15}\n``` {.julia .cell-code}\ndaph_in = CSV.read(\"betterDaphniaData.csv\", DataFrame)\n```\n:::\n\n\n", - "supporting": [ - "Tutorial-3_Building and Working with DataFrames_files/figure-html" - ], - "filters": [], - "includes": { - "include-in-header": [ - "\n\n\n" - ] - } - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-4_Programming Basics/execute-results/html.json b/_freeze/Tutorial-4_Programming Basics/execute-results/html.json deleted file mode 100644 index 28ad334..0000000 --- a/_freeze/Tutorial-4_Programming Basics/execute-results/html.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "hash": "075a555ef3c47f30c85e815e57c38ebe", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 4: The Basics of Programming\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\n\n\nThis section of the tutorials introduces programming basics, including the art of simple functions, positional arguments, keyword arguments, loops, if-else-break usage and continue-while usage.\n\nIt is important to note that if you have experience programming R, there is a major difference in Julia - the use of loops is very much advocated in Julia where as *vectorising* loops is advocated in R.\n\nBasically, we write loops in Julia. We try to avoid them in R, if we want speed.\n\n## Functions\n\nFunctions work exactly like they do in R, however, there are three fundamental differences:\n\n- there is no need for {} brackets (thank god)\n- indenting (Julia requires seperate parts of a function to be indented - don't worry, VS Code should do this for you)\n- scoping (we'll attempt to explain this later)\n- functions always start with the word `function` and end with the word `end`. \n-to store something that is calculated in a function, you use the `return` command.\n\nLet's begin with a simple function - adding 2 to any number\n\n::: {#a35eb997 .cell execution_count=2}\n``` {.julia .cell-code}\nfunction plus_two(x)\n return x+2\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\nplus_two (generic function with 1 method)\n```\n:::\n:::\n\n\nLet's use it now by providing an defining and x value, and asking for the function to return the new value.\n\n::: {#36a049a8 .cell execution_count=3}\n``` {.julia .cell-code}\nx_in = 33\nx_out = plus_two(x_in)\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n35\n```\n:::\n:::\n\n\nBecause we've defined `x_out`, we can request it...\n\n::: {#9074b985 .cell execution_count=4}\n``` {.julia .cell-code}\nx_out\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n35\n```\n:::\n:::\n\n\n### Positional Arguments\n\nAs in **R**, input variables for functions have a specified and fixed order unless they have a default value which is explicitly specified. For instance, we can build a function that measures body weight on different planets, but defaults to estimating weight on earth with a gravitational force of 9.81:\n\n::: {#03226d8f .cell execution_count=5}\n``` {.julia .cell-code}\nfunction bodyweight(BW_earth, g = 9.81)\n # bw should be in kg.\n return BW_earth*g/9.81\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\nbodyweight (generic function with 2 methods)\n```\n:::\n:::\n\n\nNote that the function is called bodyweight, it requires in the first position a weight in kg on earth and then defaults to estimating weight on earth by using g = 9.81\n\n::: {#dad23e7d .cell execution_count=6}\n``` {.julia .cell-code}\nbodyweight(75)\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```\n75.0\n```\n:::\n:::\n\n\nNow, if we want to estimate they same bodyweight on Mars, where gravity is 3.72, you can specify the g-value.\n\n::: {#1d6ae56b .cell execution_count=7}\n``` {.julia .cell-code}\nbodyweight(75, 3.72)\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\n28.44036697247706\n```\n:::\n:::\n\n\n### Keyword Arguments\n\n::: {#466c1d38 .cell execution_count=8}\n``` {.julia .cell-code}\n# function with keyword arguments:\n# here, b and d are fixed = 2\n# a is positional\n# c is a keyword argument\n# the addition of ; before c means that c is an keyword argument and can be specified in any order, but must be named\nfunction key_word(a, b=2; c, d=2) \n return a + b + c + d\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```\nkey_word (generic function with 2 methods)\n```\n:::\n:::\n\n\nHere we specify _position_ 1 (a) and that c = 3\n\n::: {#27a02028 .cell execution_count=9}\n``` {.julia .cell-code}\nkey_word(1, c = 3)\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n8\n```\n:::\n:::\n\n\nHere we specify c = 3, and then position 1\n\n::: {#e2a20030 .cell execution_count=10}\n``` {.julia .cell-code}\nkey_word(c=3, 1)\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```\n8\n```\n:::\n:::\n\n\nHere we specify position 1 (a), redefine position 2 (b = 6) and declare c = 7.\n\n::: {#97eac289 .cell execution_count=11}\n``` {.julia .cell-code}\nkey_word(1, 6, c=7)\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```\n16\n```\n:::\n:::\n\n\nNote that this DOES NOT work, because we've failed to define c. (and or b)\n\n::: {#88e6922e .cell execution_count=12}\n``` {.julia .cell-code}\nkey_word(1, 8, d=4)\n```\n\n::: {.cell-output .cell-output-error}\n```\nLoadError: UndefKeywordError: keyword argument `c` not assigned\n```\n:::\n:::\n\n\nTo redefine d, you'd need to define c and d.\n\n::: {#9868853c .cell execution_count=13}\n``` {.julia .cell-code}\nkey_word(1, c = 8, d = 4)\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```\n15\n```\n:::\n:::\n\n\n## Loops\n\n### For loops\nFor loops work by iterating over a specified range (e.g. 1-10) at specified intervals (e.g. 1,2,3...). For instance, we might use a for loop to fill an array:\n\n#### Filling an array\nTo fill an array, we first define an object as an array using `[]`. \n\n::: {#56ae443d .cell execution_count=14}\n``` {.julia .cell-code}\nI_array = []\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```\nAny[]\n```\n:::\n:::\n\n\nLike with function, all loops start with `for` and end with `end`. Here we iteratively fill `I_array` with 1000 random selections of 1 or 2.\n\n::: {#54861a86 .cell execution_count=15}\n``` {.julia .cell-code}\n# for loop to fill an array:\nfor i in 1:1000\n # pick from the number 1 or 2 at random \n # for each i'th step\n for_test = rand((1,2)) \n # push! and store for_test in I_array2\n # Julia is smart enough to do this iteratively\n # you don't necessarily have to index by `[i]` like you might do in R\n push!(I_array, for_test) \nend\n```\n:::\n\n\nLet's look at I_array now\n\n::: {#8babd443 .cell execution_count=16}\n``` {.julia .cell-code}\nI_array\n```\n\n::: {.cell-output .cell-output-display execution_count=17}\n```\n1000-element Vector{Any}:\n 1\n 2\n 2\n 2\n 1\n 2\n 2\n 2\n 2\n 1\n 1\n 2\n 1\n ⋮\n 2\n 2\n 1\n 1\n 2\n 1\n 1\n 1\n 2\n 1\n 2\n 1\n```\n:::\n:::\n\n\nLet's try something more complex, iterating over multiple indices\n\nA new storage container:\n\n::: {#bf18d6b1 .cell execution_count=17}\n``` {.julia .cell-code}\ntab = []\n```\n\n::: {.cell-output .cell-output-display execution_count=18}\n```\nAny[]\n```\n:::\n:::\n\n\nNow, we fill the storage container with values of i, j and k. Can you tell which in which order this will happen? The first entry will be `[1,1,1]`. The second will be `[2,1,1]`. Do you understand why? Mess around to check.\n\n::: {#a607e3ff .cell execution_count=18}\n``` {.julia .cell-code}\n# nested for loop to fill an array:\nfor k in 1:4\n for j in 1:3\n for i in 1:2\n append!(tab,[[i,j,k]]) # here we've use append! to allocate iteratively to the array as opposed to using push! - both work. \n end\n end\nend\n```\n:::\n\n\nLet's look...\n\n::: {#bbfa4088 .cell execution_count=19}\n``` {.julia .cell-code}\ntab\n```\n\n::: {.cell-output .cell-output-display execution_count=20}\n```\n24-element Vector{Any}:\n [1, 1, 1]\n [2, 1, 1]\n [1, 2, 1]\n [2, 2, 1]\n [1, 3, 1]\n [2, 3, 1]\n [1, 1, 2]\n [2, 1, 2]\n [1, 2, 2]\n [2, 2, 2]\n [1, 3, 2]\n [2, 3, 2]\n [1, 1, 3]\n [2, 1, 3]\n [1, 2, 3]\n [2, 2, 3]\n [1, 3, 3]\n [2, 3, 3]\n [1, 1, 4]\n [2, 1, 4]\n [1, 2, 4]\n [2, 2, 4]\n [1, 3, 4]\n [2, 3, 4]\n```\n:::\n:::\n\n\nWe can also allocate to a multiple dimensional matrix. When working with matrices, we can build them out of zeros and the replace the values.\n\nHere we start with a three dimensional array with 4 two x three matrices.\n\n::: {#21cdd457 .cell execution_count=20}\n``` {.julia .cell-code}\nthreeDmatrix = zeros(2,3,4)\n```\n\n::: {.cell-output .cell-output-display execution_count=21}\n```\n2×3×4 Array{Float64, 3}:\n[:, :, 1] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 2] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 3] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n\n[:, :, 4] =\n 0.0 0.0 0.0\n 0.0 0.0 0.0\n```\n:::\n:::\n\n\nNow, let's do a nested loop again, but this time into the matrices. The element we are adding each iteration is the sum of i+j+k.\n\nCan you guess how this works?\n\n::: {#68804aae .cell execution_count=21}\n``` {.julia .cell-code}\nfor k in 1:4\n for j in 1:3\n for i in 1:2\n # note default is by column....\n # first element allocated is 1+1+1, then 2+1+1 and this is first col\n # then 1+2+1 and 2+2+1 into the second col\n # then 1+3+1 and 2+3+1 into the third col\n threeDmatrix[i,j,k] = i+j+k\n end\n end\nend\n```\n:::\n\n\n::: {#279f412e .cell execution_count=22}\n``` {.julia .cell-code}\nthreeDmatrix\n```\n\n::: {.cell-output .cell-output-display execution_count=23}\n```\n2×3×4 Array{Float64, 3}:\n[:, :, 1] =\n 3.0 4.0 5.0\n 4.0 5.0 6.0\n\n[:, :, 2] =\n 4.0 5.0 6.0\n 5.0 6.0 7.0\n\n[:, :, 3] =\n 5.0 6.0 7.0\n 6.0 7.0 8.0\n\n[:, :, 4] =\n 6.0 7.0 8.0\n 7.0 8.0 9.0\n```\n:::\n:::\n\n\nFinally, note that we can use `println` to provide a basic marker what what is happening: we show two ways to do this in the code.\n\n::: {#95d985c7 .cell execution_count=23}\n``` {.julia .cell-code}\nfor k in 1:4\n for j in 1:3\n for i in 1:2\n #println(i,\"-\",j,\"-\",k) # multiple quotes\n println(\"$i-$j-$k\") # one quote, $ to grab variables\n \n # note default is by column....\n # first element allocated is 1+1+1, then 2+1+1 and this is first col\n # then 1+2+1 and 2+2+1 into the second col\n # then 1+3+1 and 2+3+1 into the third col\n threeDmatrix[i,j,k] = i+j+k\n end\n end\nend\n```\n:::\n\n\nAnd just for fun... this `println` trick can be handy for verbose tracking. Note how `person in unique(persons)` iterates and how you can embed a variable's value in a text string.\n\n::: {#3c8605c6 .cell execution_count=24}\n``` {.julia .cell-code}\npersons = [\"Alice\", \"Alice\", \"Bob\", \"Bob2\", \"Carl\", \"Dan\"]\n\nfor person in unique(persons)\n println(\"Hello $person\")\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nHello Alice\nHello Bob\nHello Bob2\nHello Carl\nHello Dan\n```\n:::\n:::\n\n\nThere are tons of different functions that can be helpful when building loops. Take a few minutes to look into the help files for `eachindex`, `eachcol`, `eachrow` and `enumerate`. They all provide slightly different ways of telling Julia how you want to loop over a problem. Also, remember that loops aren't just for allocation, they can also be very useful when doing calculations.\n\n### if, else, breaks\nWhen building a loop, it is often meaningful to stop or modify the looping process when a certain condition is met. For example, we can use the `break`, `if` and `else` statements to stop a for loop when i exceeds a given value (e.g. 10):\n\n::: {#226bd80a .cell execution_count=25}\n``` {.julia .cell-code}\n# if and break:\nfor i in 1:100\n println(i) # print i\n if i >10\n break # stop the loop with i >10\n end \nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n```\n:::\n:::\n\n\n::: {#f71013e2 .cell execution_count=26}\n``` {.julia .cell-code}\n# this loop can be modified using an if-else statement:\n# even though we are iterating to 100, it stops at 10.\nfor j in 1:100\n if j >10\n break # stop the loop with i >10\n else\n crj = j^3\n println(\"J is = $j\") # print i\n println(\"The Cube of $j is $crj\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\nJ is = 1\nThe Cube of 1 is 1\nJ is = 2\nThe Cube of 2 is 8\nJ is = 3\nThe Cube of 3 is 27\nJ is = 4\nThe Cube of 4 is 64\nJ is = 5\nThe Cube of 5 is 125\nJ is = 6\nThe Cube of 6 is 216\nJ is = 7\nThe Cube of 7 is 343\nJ is = 8\nThe Cube of 8 is 512\nJ is = 9\nThe Cube of 9 is 729\nJ is = 10\nThe Cube of 10 is 1000\n```\n:::\n:::\n\n\nYou'll notice that every statement requires it's own set of `for` and `end` points, and is indented as per Julia's requirements. `if` and `else` statements can be very useful when building experiments: for example we might want to stop simulating a network's dynamics if more than 50% of the species have gone extinct.\n\n### continue and while\n\n#### continue\nThe `continue` command is the opposite to `break` and can be useful when you want to skip an iteration but not stop the loop:\n\n::: {#debc1055 .cell execution_count=27}\n``` {.julia .cell-code}\nfor i in 1:30\n # this reads: is it false that i is a multiple of 3?\n if i % 3 == false\n continue # makes the loop skip iterations that are a multiple of 3\n else println(\"$i is not a multiple of 3\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n1 is not a multiple of 3\n2 is not a multiple of 3\n4 is not a multiple of 3\n5 is not a multiple of 3\n7 is not a multiple of 3\n8 is not a multiple of 3\n10 is not a multiple of 3\n11 is not a multiple of 3\n13 is not a multiple of 3\n14 is not a multiple of 3\n16 is not a multiple of 3\n17 is not a multiple of 3\n19 is not a multiple of 3\n20 is not a multiple of 3\n22 is not a multiple of 3\n23 is not a multiple of 3\n25 is not a multiple of 3\n26 is not a multiple of 3\n28 is not a multiple of 3\n29 is not a multiple of 3\n```\n:::\n:::\n\n\nCan you figure out what the code would be for keeping even numbers only? Note the change of logic from false above to true here.\n\n::: {#0b7b7253 .cell execution_count=28}\n``` {.julia .cell-code}\nfor i in 1:10\n # where is it true that i is a multiple of 2?\n if i % 2 == true\n continue # makes the loop skip iterations that are odd\n else println(\"$i is even\")\n end\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n2 is even\n4 is even\n6 is even\n8 is even\n10 is even\n```\n:::\n:::\n\n\n#### while\n\n`while` loops provide an alternative to `for` loops and allow you to iterate until a certain condition is met:\n\n::: {#48619437 .cell execution_count=29}\n``` {.julia .cell-code}\n# counter that is globally scoped (see next section)\n# testval -- try changing this to see how this global variable can be used in \n# the local process below\nglobal j=0\nglobal testval = 17\n\n# note that we started with j = 0!!!\n# justify a condition\nwhile(j\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nIf you want to add more data to a plot, the `plot!()` function is super valuable, and complemented by the `xlabel!()` and `ylabel!()` function to update the x-axis\n\n::: {#3bc58b39 .cell execution_count=3}\n``` {.julia .cell-code}\ny2 = rand(100) # another 100 randoms\nplot!(x, y2, label = \"less amazing\")\nxlabel!(\"time is not your friend\")\nylabel!(\"ooh la la la\")\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nRecall too that there is a `seriestype` argument to shift between the default line and, perhaps a scatterplot. Note that we can deliver both y and y2.\n\n::: {#8c976460 .cell execution_count=4}\n``` {.julia .cell-code}\nplot(x, y, seriestype = [:line,:scatter], markershape = :diamond, lc = :orange, mc = :black, msc = :orange, label = \"Y\")\nplot!(x, y2, seriestype = [:line,:scatter], markershape = :diamond, lc = :blue, mc = :black, msc = :blue, label = \"Y2\")\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n`mc` is for marker colour, `msc` is the colour of the line around the marker/shape and `lc` is for line colour.\n\nOf course, there is a `scatter()` plot function\n\n::: {#39267d35 .cell execution_count=5}\n``` {.julia .cell-code}\nscatter(x, y)\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n### Grouping Variables in Plots\n\nJulia's Plots.jl library does some basic work with grouping variables too, linking to key ideas about tidy data. Let's look at some sample data where we have 12 data points.\n\n::: {#ab389b5a .cell execution_count=6}\n``` {.julia .cell-code}\nsample_data = DataFrame([rand(12), repeat([\"Network_1\",\"Network_2\",\"Network_3\"],4)], [\"stability\", \"network\"])\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```{=html}\n
12×2 DataFrame
Rowstabilitynetwork
Float64String
10.0491108Network_1
20.699192Network_2
30.158122Network_3
40.470745Network_1
50.625568Network_2
60.997392Network_3
70.572846Network_1
80.580858Network_2
90.141685Network_3
100.764872Network_1
110.690545Network_2
120.137958Network_3
\n```\n:::\n:::\n\n\nPlotting the data, by group, is accomplished like this (note the use of the `.` to connect the dataframe to the variable name)\n\n::: {#f4c73344 .cell execution_count=7}\n``` {.julia .cell-code}\nplot(sample_data.stability, group = sample_data.network)\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nThis is a pretty silly plot because the x-axis makes no sense. We might have wanted a bar-chart instead.\n\n::: {#f1a39930 .cell execution_count=8}\n``` {.julia .cell-code}\ngroupedbar(sample_data.stability, group = sample_data.network)\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nWe'll see below how the package `StatsPlots` makes this easier and more flexible (a bit more like `{ggplot2}`).\n\n### Saving Plots\n\nPlots can be saved and outputted using savefig or by using an output marco (e.g. png or pdf). savefig saves the most recent plot (.png is default format) or you can name figures e.g., p1, and use that reference name to save the plot object at any time:\n\n::: {#0fee5ab8 .cell execution_count=9}\n``` {.julia .cell-code}\n#not run\nsavefig(p1, \"path/to/file/p1.png\")\npng(p1, \"path/to/file/p1\")\npdf(p1, \"path/to/file/p1\")\n```\n:::\n\n\nOnce you've created a plot it can be viewed or reopened in VS Code by navigating to the Julia explorer: Julia workspace symbol in the activity bar (three circles) and clicking on the plot object (e.g., p1). We advise that you always name and assign your plots (e.g. p1, p2, etc). The Plots package also has it's own [tutorial](https://docs.juliaplots.org/latest/tutorial/) for plotting in Julia.\n\n\n## StatsPlots\n\nAs you saw in the Setup introduction, we can also use the StatsPlots package for plotting. This approach invokes a background macro that allows you to use the DataFrames structure to deliver nice plots.\n\n::: {#46a262a5 .cell execution_count=10}\n``` {.julia .cell-code}\n# make a second data frame with three variables\n# using DataFrame directly to create variables\ndf2 = DataFrame(a=1:10, b=10*rand(10), c=10*rand(10))\ndf2\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```{=html}\n
10×3 DataFrame
Rowabc
Int64Float64Float64
110.8157936.88707
223.753992.40944
339.760621.53078
449.964353.45292
554.19571.77534
668.545171.37223
777.833734.74956
888.69492.89649
995.101120.930789
10107.899568.68376
\n```\n:::\n:::\n\n\nThe use of the `@df` macro from StatsPlots is a three step process:\n\n1. declare the `@df` macro\n2. define the data frame\n3. declare the columns, using the `:` symbol.\n\n::: {#f585dd27 .cell execution_count=11}\n``` {.julia .cell-code}\n# plot the data using the data frame macro\n# declare the df macro, declare the data frame, use : to signify columns\n# note that the default is `x then y`.\n@df df2 plot(:a, :b)\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nOne of the handy things about the `@df` macro and `StatsPlots` is the ability to add two or more variables at once:\n\n::: {#48ea5d52 .cell execution_count=12}\n``` {.julia .cell-code}\n# the same, and plotting two y variables (b and c)\n@df df2 plot(:a, [:b, :c])\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nThere are several helper functions too. For example, instead of the `[[:b, :c]` approach to multiple columns, there is a `cols` argument.\n\n::: {#4e3f8066 .cell execution_count=13}\n``` {.julia .cell-code}\n@df df2 plot(:a, cols(2:3), colour = [:red :blue])\n```\n\n::: {.cell-output .cell-output-display execution_count=13}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nFinally, coming back to the example above for plots using the `sample_data` dataframe with a grouping variable, we can see how `StatsPlots` mimics some of the faceting options and group options from `ggplot2`.\n\nFirst, the three groups in the same figure with an informative legend.\n\n::: {#4cd3915c .cell execution_count=14}\n``` {.julia .cell-code}\n@df sample_data plot(:stability, group = :network, legend = :topleft)\n```\n\n::: {.cell-output .cell-output-display execution_count=14}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nSecond, the same data but in three panels.\n\n::: {#ef8cc233 .cell execution_count=15}\n``` {.julia .cell-code}\n@df sample_data plot(:stability, group = :network, layout = 3)\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nAnd following the standard `Plots.jl` example for grouped bars....\n\n::: {#70ffb95f .cell execution_count=16}\n``` {.julia .cell-code}\n@df sample_data groupedbar(:stability, group = :network)\n```\n\n::: {.cell-output .cell-output-display execution_count=16}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n## Gadfly\n\nThere is a actively developed package called `Gadfly` which implements an interpretation of the `[ggplot2]` grammar of graphics. It has been finicky and unstable for us in the past, but you are welcome to try it. To use it, you need to install the package with the `] add Gadfly` first step, and then `using Gadfly` in the top of your script.\n\nA tutorial and set of examples can be found [here](http://gadflyjl.org/v0.5/tutorial.html)\n\n## Makie\n\nFinally Makie is another alternative to consider. It allows you to make very complex figure layout as well as 2D or 3D plots. Same as above to use this you'll need to first install the package - `] add Makie` and then call in you script with `using Makie`\n\nThe documentation can be found [here](https://docs.makie.org/stable/)\n\n", - "supporting": [ - "Tutorial-5_Plotting in Julia_files" - ], - "filters": [], - "includes": { - "include-in-header": [ - "\n\n\n" - ] - } - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-6_Extra Tips and Tricks/execute-results/html.json b/_freeze/Tutorial-6_Extra Tips and Tricks/execute-results/html.json deleted file mode 100644 index 5fe54ce..0000000 --- a/_freeze/Tutorial-6_Extra Tips and Tricks/execute-results/html.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "hash": "a48114531637e0cef8a105d94591195b", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 6: Extra Tips and Tricks\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\nSome quick tips that we've learnt the hard way...\n\n1. In the REPL, you can use the up arrow to scroll through past code\n2. You can even filter through your past code by typing the first letter of a line previously executed in the REPL. For example, try typing p in the REPL and using the up arrow to scroll through your code history, you should quickly find the last plot command you executed.\n3. Toggle word wrap via `View>Toggle Word Wrap` or `alt-Z`\n4. Red wavy line under code in your script = _error in code_\n5. Blue wavy line under code in your script = _possible error in code_\n6. Errors and possible errors can be viewed in the PROBLEMS section of the REPL\n7. You can view your current variables (similar to the top right hand panel in RStudio) by clicking on the Julia explorer: Julia workspace symbol in the activity bar (three circles). You can then look at them in more detail by clicking the sideways arrow (when allowed).\n\n### COPYING versus DEEP COPYING :-)\n\n8. Julia has a strange copying behaviour where if `a` = `b`, any change in `b` will automatically cause the same change in `a`. For example, let's make an array of three numbers:\n\n::: {#8f3746aa .cell execution_count=1}\n``` {.julia .cell-code}\naa = [1,2,3]\n```\n\n::: {.cell-output .cell-output-display execution_count=2}\n```\n3-element Vector{Int64}:\n 1\n 2\n 3\n```\n:::\n:::\n\n\nHere we make a copy of `aa` and call it `bb`.\n\n::: {#d8e72229 .cell execution_count=2}\n``` {.julia .cell-code}\nbb = aa\nprint(bb)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n[1, 2, 3]\n```\n:::\n:::\n\n\nNow, we replace the second element of `bb` with the value 41.\n\n::: {#fa310c4e .cell execution_count=3}\n``` {.julia .cell-code}\nbb[2] = 41\nbb\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\nThe default behaviour of `=` in Julia is to *UPDATE* any copy of the array, so we see the same change in `aa`:\n\n::: {#60da8df2 .cell execution_count=4}\n``` {.julia .cell-code}\naa\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\nWhoa... that's not what we expect, though it's pretty cool. This approach is advantageous because it lets Julia save memory, however, it is not ideal.\n\nTo remedy this, and create copies that don't update their parent or other offspring, we can force c to be an independent copy of a using the `deepcopy` function:\n\n::: {#77e1ba86 .cell execution_count=5}\n``` {.julia .cell-code}\ncc = deepcopy(aa)\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n3-element Vector{Int64}:\n 1\n 41\n 3\n```\n:::\n:::\n\n\n::: {#912cab52 .cell execution_count=6}\n``` {.julia .cell-code}\ncc[3] = 101\naa,cc\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n```\n([1, 41, 3], [1, 41, 101])\n```\n:::\n:::\n\n\n9. You can view a `.csv` or `.txt` file by clicking on a file name in the project directory (left panel) - this opens a viewing window. CSV's also have a built in 'Preview' mode - try using right click>Open Preview on a `.csv` file and check it out.\n\n10. Docstrings are a supplement to `#`-based comments for documenting your workflow. Basically, any string that appears just before an object will be interpreted as documenting it. When you use a docstring it is possible to call that description using help (`?` in the REPL) or hovering over the object in VSCode. This can be very useful when you start declaring variables or building your own functions.\n\n::: {#3fc0be1b .cell execution_count=7}\n``` {.julia .cell-code}\n\"a wonderfully documented and described variable\"\nvar = 101\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\nvar\n```\n:::\n:::\n\n\nyou can (should) also do this with functions\n\n::: {#74ef1313 .cell execution_count=8}\n``` {.julia .cell-code}\n\"\"\"\n _rategradient(∂X, ∂Y)\n\nReturns the rate of change in units of the values stored in the grid, and the\nangle of the change in wind direction, *i.e.* an angle of 180 means that the\nvalue is increasing *from* the south. When both ∂X and ∂Y are equal to 0, the\nangle is assumed to be 0.\n\"\"\"\nfunction _rategradient(∂X::T, ∂Y::T) where {T <: Number}\n if ∂X == ∂Y == 0.0\n return (0.0, 0.0)\n end\n m = sqrt(∂X^2 + ∂Y^2)\n Δ = ∂X >= 0.0 ? 0.0 : 180.0\n θ = rad2deg(atan(∂X, ∂Y)) + Δ\n θ = ∂X > 0.0 ? θ + 180.0 : θ\n return (m, θ)\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```\n_rategradient\n```\n:::\n:::\n\n\n", - "supporting": [ - "Tutorial-6_Extra Tips and Tricks_files/figure-html" - ], - "filters": [], - "includes": {} - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-7_Intro To Differential Equations/execute-results/html.json b/_freeze/Tutorial-7_Intro To Differential Equations/execute-results/html.json deleted file mode 100644 index a77be58..0000000 --- a/_freeze/Tutorial-7_Intro To Differential Equations/execute-results/html.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "hash": "9e09352864d7934892370dd18a4ae509", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 7: Introducing Differential Equations\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nbibliography: references.bib\n---\n\n::: {#b2206270 .cell execution_count=1}\n\n::: {.cell-output .cell-output-stderr}\n```\n[ Info: Waiting for another process (pid: 98609) to finish precompiling DifferentialEquations [0c46a032-eb83-5123-abaf-570d42b7fbaa]. Pidfile: /Users/tanyastrydom/.julia/compiled/v1.11/DifferentialEquations/UQdwS_Fp437.ji.pidfile\n```\n:::\n:::\n\n\nThis document illustrates how to construct and solve differential equations in Julia using the `DifferentialEquations.jl` package.\n\nIn particular, we are interested in modelling a two species Lotka-Volterra like (predator-prey/consumer-resource) system. Such systems are fundamental in ecology and form the building blocks of complex networks and the models that represent them.\n\nFor this tutorial you'll need the following two packages:\n\n- `DifferentialEquations.jl` to solve the differential equations (same 'engine' as the one used by the `BioEnergeticFoodWebs.jl` model)\n- `Plots.jl` to visualise the results\n\nWhile we already have `Plots.jl` in this project, we just need to `] add DifferentialEquations`.\n\nThe `DifferentialEquations.jl` can be a tad clunky so the below code might take a while to compile. If you hit errors, we recommend removing (`] rm DifferentialEquations`) and reinstalling (`] add DifferentialEquations`) the package.\n\nYou probably want to start a new script for this exercise. File -\\> New File -\\> julia\n\n### An introduction to Differential Equations.\n\nDifferential equations are frequently used to model the change in variables of interest through time. These changes are often referred to as derivatives (or `du/dt`). In this case, we are interested in modelling changes in the abundance of a consumer and its resource as a function of the system's key processes (growth, ingestion of food/foraging and mortality) and its parameters.\n\nThis type of model can be formalised as a simple Lotka-Volterra predator prey model, consisting of a set of differential equations:\n\n- Resource dynamics: $\\frac{dR}{dt} = r R (1-\\frac{R}{K}) - \\alpha R C$\n- Consumer dynamics: $\\frac{dC}{dt} = e \\alpha R C - m C$\n\nwhere $R$ and $C$ are the abundances of the resource and consumer respectively, $r$ is the resource's growth rate, $K$ is the producer's carrying capacity, $\\alpha$ is the consumer's ingestion rate, $e$ is the assimilation efficiency and $m$ is the consumer's mortality rate.\n\nTo recall from your ecology modules, this is a system of equations with logistic growth for the producers (plants) and a Type I [functional response](https://en.wikipedia.org/wiki/Functional_response) describing how consumer foraging (the loss of prey caused by predators eating them) varies with prey density, a simple conversion efficiency that translates the functional response (eating the prey) into babies of the consumer (predator reproduction) and then a mortality rate for the consumer/predator.\n\nA few details to note.\n\n- there is only one source of density dependence in this model/system - logistic growth of the producer. Density dependence is required to generate coexistence and stability.\n- the Type I functional response means that the consumer foraging rate increases with prey density and does not saturate. It means that the mortality rate that consumers impose on the prey is constant and independent of the prey density. It is thus density independent and does not contribute to stability. There are two other functional responses. The Type II, which has saturating consumption rate and generates *inverse* density dependence, and the Type III, which has accelerating consumption rate with prey density, and thus generates increasing mortality in the prey with increasing prey density, and thus density dependence. It is only Type III functional responses that are linked to consumers/predators *stabilising* their prey populations. It is also a pretty rare functional response!\n- the consumer mortality rate is also constant and thus density independent.\n\n### How does this relate to the Bioenergetic Food Web Model?\n\nThe complex model of consumer - resource interactions that is represented by the `BEFW` model has at it's heart two equations: one for producers and one for consumers. So at it's heart, it is not too different in structure to the model above! However, the differences, spelled out in @delmas2017, are\n\n- the parameters are functions of body size\n- because of this, we can expand the number of resource and consumer equations for multiple values of body size\n- this creates a potentially big system of equations, instead of just 2.\n\nHowever, and this is important, the process of solving these equations, whether it is two of them, or 100 of them, is essentially what we are introducing below. If you were to look inside of the `BEFW` model, you would see the same functions and structure as we introduce here.\n\n#### The Three Steps For Simulating Food Web Dynamics\n\nThere are 3 major steps involved in constructing and solving this model in Julia (these happen to be the same three steps in all programming languages, including R where the `deSolve` package accomplishes much of this same functionality):\n\n1. Define a function for your model (i.e. transform the above differential equations into a function that can be read by the solver). This function tells the solver how the variables of interest (here $R$ and $C$) change over time.\n2. Define the problem. Here, the problem is defined by the function, the parameters ($r$, $\\alpha$, $e$ and $m$), the initial conditions and the timespan of the simulation. In this step you provide the solver with all the details it needs to find the solution.\n3. Solve!\n\n#### Step 1. Define the function\n\nHere we construct a function for our model. The function needs to accept the following:\n\n- `du` (derivatives) - a vector of changes in abundance for each species\n- `u` (values) - a vector of abundance for each species\n- `p` (parameters) - a list of parameter values\n- `t` (time) - timespan\n\n::: {#f648a6c1 .cell execution_count=2}\n``` {.julia .cell-code}\nfunction LV_model(du,u,p,t)\n # growth rate of the resource (modelled as a logistic growth function)\n GrowthR = p.growthrate * u[1] * (1 - u[1]/p.K) \n # rate of resource ingestion by consumer (modelled as a type I functional response)\n IngestC = p.ingestrate * u[1] * u[2]\n # mortality of consumer (modelled as density independent)\n MortC = p.mortrate * u[2]\n # calculate and store changes in abundance (du/dt):\n # change in resource abundance\n du[1] = GrowthR - IngestC\n # change in consumer abundance\n du[2] = p.assimeff * IngestC - MortC\nend\n```\n\n::: {.cell-output .cell-output-display execution_count=3}\n```\nLV_model (generic function with 1 method)\n```\n:::\n:::\n\n\nYou'll notice that in the above function (`LV_model`), we've specified specific parameters using the `p.name` notation. This is because we've opted to store our parameters in a named tuple called `p`. `p` is created below but it's worth noting that when this notation is used e.g., `p.growthrate`, we are telling Julia that we want to use the value of `growthrate` that is stored as a named part of our tuple (a fancy name for an object in Julia) `p`.\n\n#### Step 2. Define the problem\n\nTo define the problem we first have to fix the system's parameters, the initial values and the timespan of the simulation:\n\n::: {#c5dae01c .cell execution_count=3}\n``` {.julia .cell-code}\np = (\n growthrate = 1.0, # growth rate of resource (per day)\n ingestrate = 0.2, # rate of ingestion (per day)\n mortrate = 0.2, # mortality rate of consumer (per day)\n assimeff = 0.5, # assimilation efficiency\n K = 10 # carrying capacity of the system (mmol/m3)\n )\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n(growthrate = 1.0, ingestrate = 0.2, mortrate = 0.2, assimeff = 0.5, K = 10)\n```\n:::\n:::\n\n\nHere, we have chosen to define `p` as a named tuple (similar to a list in R). A vector or dictionary would also work, however, named tuples are advantageous because they allow us to use explicit names and are unmutable meaning that once it's created you can't change it.\n\n- **Initial values:** For simplicity, we start with $R = C = 1$:\n\n::: {#5fd760ed .cell execution_count=4}\n``` {.julia .cell-code}\nu0 = [1.0; 1.0]\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\n2-element Vector{Float64}:\n 1.0\n 1.0\n```\n:::\n:::\n\n\n- **Timespan:**\n\n::: {#2ede748f .cell execution_count=5}\n``` {.julia .cell-code}\ntspan = (0.0,100.0) # you have to use a Pair (tuple with 2 values) of floating point numbers.\n```\n\n::: {.cell-output .cell-output-display execution_count=6}\n```\n(0.0, 100.0)\n```\n:::\n:::\n\n\nWe then formally define the problem by passing the function (`LV_model`), the parameters (listed in our named tuple `p`), the initial values (`u0`) and the timespan (`tspan`) to `ODEProblem()`:\n\n::: {#2ae8e959 .cell execution_count=6}\n``` {.julia .cell-code}\nprob = ODEProblem(LV_model, u0, tspan, p)\n```\n\n::: {.cell-output .cell-output-display execution_count=7}\n\n::: {.ansi-escaped-output}\n```{=html}\n
ODEProblem with uType Vector{Float64} and tType Float64. In-place: true\ntimespan: (0.0, 100.0)\nu0: 2-element Vector{Float64}:\n 1.0\n 1.0
\n```\n:::\n\n:::\n:::\n\n\n#### Step 3. Solve\n\nTo solve the problem, we pass the `ODEProblem` object to the solver.\n\nHere we have chosen to use the default algorithm because it's a simple problem, however there are several available - see [here](https://diffeq.sciml.ai/dev/solvers/ode_solve/) for more information. These two final steps (define and solve the problem) are analogous to using the `deSolve` package in R.\"\n\n::: {#4062e42c .cell execution_count=7}\n``` {.julia .cell-code}\nsol = solve(prob)\n```\n:::\n\n\nThe solver produces 2 objects: `sol.t` and `sol.u` that respectively store the time steps and the variables of interest through time. Let's have a look.\n\n#### Step 4. Visualise the outputs\"\n\nOnce the problem has been solved, the results can be explored and plotted. In fact, the `DifferentialEquations.jl` package has its own built in plotting recipe that provides a very fast and convenient way of visualising the abundance of the two species through time:\n\n::: {#6342db60 .cell execution_count=8}\n``` {.julia .cell-code}\nplot(sol, \n\tylabel = \"Abundance\", \n\txlabel = \"Time\", \n\ttitle = \"Lotka-Volterra\", \n\tlabel = [\"prey\" \"predator\"], \n\tlinestyle = [:dash :dot], \n\tlw = 2) \n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nOne thing to note here, when plotting in Julia you don't need to separate label names (`label = [prey predator]`) or linestyles (`linestyle = [:dash :dot]`) with a comma as you would in R. This will also be case for most plotting options in Julia.\n\n#### Step 5. Play some games\n\nNow that you see how this works, perhaps you can do a bit of an experiment by varying things in the `p =` (parameters) part of the code?\n\n- Can you increase the number of time steps?\n- What happens when you increase `K`?\n- What happens when you increase or decrease `growthrate`?\n- What happens when you change the `ingestrate`\n\n#### EXTRA CREDIT\n\nIf you are really keen.... how about trying to run the model in a loop over 3 values of `growthrate`, collect the final population size of the consumer and resource in a data frame with three columns (`growthrate`, finalCons, finalRes), and plot these values?\n\n## References\n\n::: {#refs}\n:::\n\n", - "supporting": [ - "Tutorial-7_Intro To Differential Equations_files/figure-html" - ], - "filters": [], - "includes": { - "include-in-header": [ - "\n\n\n" - ] - } - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-8_Intro To Eco Net Dyn/execute-results/html.json b/_freeze/Tutorial-8_Intro To Eco Net Dyn/execute-results/html.json deleted file mode 100644 index ec5a75b..0000000 --- a/_freeze/Tutorial-8_Intro To Eco Net Dyn/execute-results/html.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "hash": "ce55e819131c08e94b535a972f33b00f", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 8: Introducing Ecological Network Dynamics (BEFWM2)\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nabstract: |\n This section of the tutorials initiates you into using the Bioenergetic Food Web Model.\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\nbibliography: references.bib\n---\n\n\n\n## Using the Bioenergetic Food Web\n\n### Preamble: The Bioenergetic Food Web.\n\nIt is very worth pausing for a moment and looking at @delmas2017. It describes the BioEnergetic Food Web Model, provides some history of the model, and also showcases how the original `Julia` version of the model worked. This section of the tutorials is designed to introduce a newer, faster and more flexible version of the `Julia` package.\n\nA very basic interpretation of the model is as follows:\n\n1. The model is a model of biomass dynamics, not numbers of individuals.\n2. The model is comprised of an equation for plants (producers) an equation for consumers (herbivores, predators).\n3. Plants have traits that make their biomass grow and sets their carrying capacity; they are eaten by consumers via an equation describing a functional response. To link to ecology courses you have, this can be logistic growth for the plant and a type II functional response.\n4. Consumer have three sets of traits. One is metabolism, which is a rate that describes losses of biomass due to, well, metabolism! The second set of traits correspond to the functional response - for example describing attack rates and handling times of prey items. The third corresponds to the numerical response, or the conversion of biomass they eat into new biomass (e.g. babies)\n5. We can make complex networks and systems of these equations by letting many of these parameters *scale with body size* via the rules of allometry and the Metabolic Theory of Ecology. This *trick* expands the two equations to n = number of species when we provide the toolbox with a list of species biomasses.\n6. Embedded in this process are rules about how to distribute species of different sizes across trophic levels, so that we end up with predators, omnivores, herbivores and plants. We can also designate the body size relationships for different groups of organisms, like producers, invertebrates, endothermic vertebrates and ectothermic vertebrates.\n7. Once we've done this, we can simulate the biomass dynamics of complex communities. And we can summarise things like changes in biodiversity (number of species), stability (coefficient of variation of the time series) and anything about the biomass of species, trophic levels or the community!\n\n### Preamble: Setup\n\nOne of main advantages of running food web models in Julia is that simulations are fast and can be readily stored in your active project. With this in mind, make a new folder in your project called `out_objects` (right click \\> New Folder).\n\nWe will be using the `EcologicalNetworksDynamics.jl` package [@lajaaiti2024] to implement the BEFW. Although we will go through and explain the functionality it may be useful to have both the preprint as well as the complete [documentation](https://beckslab.github.io/EcologicalNetworksDynamics.jl/) on hand for more detailed explanations. You can install `EcologicalNetworksDynamics` as you would any other normal `Julia` package.\n\n::: {#ecb8c4d0 .cell execution_count=2}\n``` {.julia .cell-code}\nPkg.add EcologicalNetworksDynamics\n```\n:::\n\n\n### A first run of the Ecological Network Dynamics model (BEFW)\n\nThere are four major steps when running the BioEnergetic Food Web model in Julia. These should be familiar from our introduction to the `DifferentialEquations` package:\n\n1. Generate an initial food web network\n2. Set the parameters for each species in the network to generate the equations\n3. Simulate the network and equations\n4. Explore output and plot\n\nWhile in the previous example with `Differential Equations` we assumed a simple 2-species network, one of the new activities here is to take advantage of a rich history of theory and tools to construct species rich networks with appropriate structural properties, such as *connectance/complexity* and levels of *generalism/specialism* and things the number of trophic levels and a body size distribution of the species across trophic levels.\n\n#### Step 1: generate an initial network {#sec-step1}\n\n::: {#4611ef2b .cell execution_count=3}\n``` {.julia .cell-code}\n## My first BEFW Modelling\n\n## Packages I need\nusing DataFrames, Plots, Random, Distributions\nusing EcologicalNetworksDynamics\n\n## Time to do some Experiments!\n```\n:::\n\n\nHere we make a foodweb, actually, a food chain, from an *adjacency matrix* using `Foodweb`.\n\n::: {#2e852b27 .cell execution_count=4}\n``` {.julia .cell-code}\nA = [0 0 0; 1 0 0; 0 1 0] # 1 basal producer ⋅ Species 2 eats 1 ⋅ Species 3 eats 2\nfoodweb = Foodweb(A)\n```\n:::\n\n\n#### Step 2: Generate the model parameters\n\nOnce the foodweb is created, the next step is to attribute values to the model parameters. This can be simply done by calling `default_model` with foodweb as an argument.\n\n::: {#b83963a3 .cell execution_count=5}\n``` {.julia .cell-code}\n# construct the equations and fixed parameters\n# see below for body size dependent parameters etc\nparams = default_model(foodweb)\n```\n:::\n\n\nIf we look at our `params` object we can see that it has all the required parameters for the **BEFW**. Later in this tutorial you will see how we can access and modify these parameters.\n\n#### Step 3: Simulate biomass dynamics\n\nEverything is ready to run the simulation, which can be simply done by calling simulate with the model parameters (params) and a vector species' initial biomass (B0).\n\n::: {#0a4b4b22 .cell execution_count=6}\n``` {.julia .cell-code}\n# create body sizes for each species\nB0 = [0.5, 0.5, 0.5]\n# specify number of time steps\nt = 300\n\n# use simulate function\n# builds equations and uses DiffEq to run them!\nsim = simulate(params, B0, t)\n```\n:::\n\n\n#### Step 4: Seeing the outputs!\n\nTo plot the time series, we can use the actual `simulate` object directly.\n\n::: {#ff3043b6 .cell execution_count=7}\n``` {.julia .cell-code}\n plot(sim, label = [\"Producer\" \"Consumer\" \"Top consumer\";])\n```\n:::\n\n\nEventually you may want to plot the biomass dynamics - the trajectory - of your community to see what is happening. For our minimal example, it can be done as follows:\n\n::: {#09154f99 .cell execution_count=8}\n``` {.julia .cell-code}\n# create multiple objects: time = t pulled from the sim.t component\n# and Bx = biomass for each species pulled from the larger sim object\n# note how julia allows multiple things on left of the =\nt, B1, B2, B3 = sim.t, sim[1,:], sim[2,:], sim[3,:] # unpack variables\n\n# Plot the basal species\nplot(t, B1, lw = 3, label=\"Producer\", xlabel = \"Time\", ylabel = \"Biomass\")\n# add the herbivore\nplot!(t, B2, lw = 3, label=\"Consumer\")\n# add the top predator\nplot!(t, B3, lw = 3, label=\"Top consumer\")\n```\n\n::: {.cell-output .cell-output-display execution_count=167}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\n## A More Complex Example\n\n#### Step 1: Generate the initial network\n\nIn order to run the BEFW model with a more complex network, we have to construct an initial food web network (an adjacency matrix) using [the niche model](https://www.nature.com/articles/35004572?cacheBust=1510239451067). The network is characterised by the number of species in the network and its [connectance/complexity](https://en.wikipedia.org/wiki/Ecological_network) value.\n\nNote that we are now using functionality provided by the `EcologicalNetworks` package.\n\n::: {#a3d61301 .cell execution_count=9}\n``` {.julia .cell-code}\nS = 20 # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\n\n# construct the food web\nRandom.seed!(12325) # ensures your network and this one are the same\nfoodweb_niche = Foodweb(:niche; S = S, C = C)\n```\n:::\n\n\n#### Step 2. Setting up the paramters, body masses (species) and running the model!\n\nAs above, our next step is to define a vector of bodymasses and then pass this, and the network to the `simulate` function. Here we combine the `Uniform` function from the *Distributions* package with the `rand` function from the *Random* package.\n\n::: {#afbf0d01 .cell execution_count=10}\n``` {.julia .cell-code}\n# construct the equations and fixed parameters\n# see below for body size dependent parameters etc\nparams_niche = default_model(foodweb_niche)\n\n# define bodymasses between 0 and 1 and get S = 20 of them.\n# this will ensure your plot looks like the one in the document\nRandom.seed!(123)\nB0 = rand(S)\nt = 300\n\n# simulate using params and bodymasses\n# note additional argument tmax for max time steps\n# default is 300\nsim_niche = simulate(params_niche, B0, t)\n```\n:::\n\n\n#### Step 3. Visualising the dynamics\n\nNow we can move to plotting again. Note how we now ask for the time directly from the simulate object and all of the biomasses from that object as well.\n\nNote too how we can supress the legend (which covers some of the time series).\n\n::: {#7d9ccc06 .cell execution_count=11}\n``` {.julia .cell-code}\nplot(sim_niche, legend = false)\n```\n\n::: {.cell-output .cell-output-display execution_count=170}\n```{=html}\n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n \n \n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n```\n:::\n:::\n\n\nOne game to play now is to alter the bodymass distribution. `rand` selects a randon uniform number between 0 and 1. Can you figure out how to make the distribution uniform between 0 and 10? See what that does.\n\n#### A bit more about the process: dissecting the ModelParameters\n\nLet's dissect the `default_model` object a bit, to understand just a bit more about what is going on.\n\n::: {#28ddf918 .cell execution_count=12}\n``` {.julia .cell-code}\nparams_niche\n```\n\n::: {.cell-output .cell-output-display execution_count=171}\n\n::: {.ansi-escaped-output}\n```{=html}\n
Model (alias for EcologicalNetworksDynamics.Framework.System{<inner parms>}) with 17 components:\n  - Species: 20 (:s1, :s2, :s3, :s4, ..., :s20)\n  - Foodweb: 82 links\n  - Body masses: [396.6757314506745, 1000.0, 138.23722273578997, 150.62580571223663, ..., 1.0]\n  - Metabolic classes: [:invertebrate, :invertebrate, :invertebrate, :invertebrate, ..., :producer]\n  - GrowthRate: [·, ·, ·, ·, ..., 1.0]\n  - Carrying capacity: [·, ·, ·, ·, ..., 1.0]\n  - ProducersCompetition: 1.0\n  - LogisticGrowth\n  - Efficiency: 0.45 to 0.85.\n  - MaximumConsumption: [8.0, 8.0, 8.0, 8.0, ..., ·]\n  - Hill exponent: 2.0\n  - Consumers preferences: 0.07692307692307693 to 1.0.\n  - Intra-specific interference: [·, ·, ·, ·, ..., ·]\n  - Half-saturation density: [0.5, 0.5, 0.5, 0.5, ..., ·]\n  - BioenergeticResponse\n  - Metabolism: [0.0703591752903408, 0.05583797347522218, 0.09157425582526797, 0.08963029015067063, ..., 0.0]\n  - Mortality: [0.0, 0.0, 0.0, 0.0, ..., 0.0]
\n```\n:::\n\n:::\n:::\n\n\nWalking through this\n\n> 🚧 This needs to be updated - might be explicitly highlighted in END documentation\n\n1. The `network` component defines the food web and reports the number of species and the links\n2. the `environment` component reports on values of the carrying capacity (K) and the baseline temperature (`T`). Note that K is specified only for the basal species via `[1, 1, ... nothing, nothing]`. All the producers have the same K at this point (1,1,1...). The presence of the `T` suggests that we can ultimately work with climate change by running the model at different temperatures. There is a way to make some of the biorates and components of the functional response (see 3, 4) dependent not only on body mass, but also on temperature.\n3. the `biorates` component contains detail on parameters central to making the model reflect a bit of reality: `d` is ...; `r` is the intrinsic rate of increase (population growth rate) for the producers (plants); `x` and `y` are parameters associated with metabolic rates and consumption rates of the consumers (non-plant species). Finally, `e` is an efficiency/assimilation rate for the consumers eating either plants or other animals.\n4. the `functional_response` component defines the type of *consumption function* being used (e.g. Type I, II, or III sensu classic ecology and Holling). The functional response defines the *interaction strength* between species and how consumers change how much they eat dependent on the amount (density) of resource available.There are two options. The default `Bioenergetic Response` corresponds to a *phenomenological* formulation where there are just two variables that describe how consumer consumption varies with resource density: a *half-saturation* parameter and an *asymptote*. The alternative called `Classic Response` is more *trait based* and includes the parameters *attack rate* and *handling time*. There are several other features of the functional response that can be manipulated, and these are introduced in later tutorials.\n5. the `producer_growth` details the default that all plants are growing logistically.\n6. the `temperature response`componewnt defines the absence or presence of temperature dependence, and when present, the shape of the relationship between biorates and functional response parameters and temperature.\n\n### Helper Functions: What can we do with the outputs?\n\n> 🚧 This should be revised by an END user.\n\nAs noted in the pre-amble, we are most often interested in additional information about the scenarios we build with the models. These include, for example, total biomass, biodiversity and stability. Let's see how we can calculate some of these.\n\n#### How long till steady state?\n\nWe can find out how long the simulations ran to reach steady state - remember that this is a deterministic model that typically reaches equilibrium for all species that survive.\n\n::: {#2d3af7c4 .cell execution_count=13}\n``` {.julia .cell-code}\nsize(sim_niche.t)\n```\n\n::: {.cell-output .cell-output-display execution_count=172}\n```\n(51,)\n```\n:::\n:::\n\n\n#### Who went extinct and when?\n\nWe can also find out who went extinct, and when. You saw some of that detail, I hope, in the output of `simulate`.\n\n::: {#b1265a40 .cell execution_count=14}\n``` {.julia .cell-code}\nget_extinct_species(sim_niche)\n```\n:::\n\n\n#### Biomass, Diversity and Stability\n\nFirst, we can get a measure of total biomass in the community, at equilibrium, and that of each species. Note how you can get the components too.\n\n::: {#11b99ae0 .cell execution_count=15}\n``` {.julia .cell-code}\nsim_niche.u\n```\n\n::: {.cell-output .cell-output-display execution_count=173}\n```\n51-element Vector{Vector{Float64}}:\n [0.906299638797481, 0.44349373245960455, 0.7456733811393941, 0.5120830400366143, 0.2538490889415096, 0.33415153638191886, 0.4273278808735992, 0.867547200255958, 0.09913361484360417, 0.12528740769155033, 0.6922086620547391, 0.13655147513745736, 0.03209667335274724, 0.3505458214588266, 0.9303323763821093, 0.9594335994071538, 0.5819123423876457, 0.3114475007050529, 0.12114752051812694, 0.20452981732035946]\n [0.9169483131714715, 0.444402194534041, 0.7667640455857161, 0.5179071161683636, 0.25596644376248334, 0.3439614083570855, 0.42881389580038637, 0.8404857181508336, 0.10207349613818459, 0.12980979255930417, 0.7045585608788062, 0.14142469702894178, 0.033700254458592344, 0.35322775442579823, 0.9254383246584946, 0.8428424981719224, 0.5353929049386887, 0.2716712297929136, 0.11790964375471776, 0.20588623005171253]\n [0.9372189186622565, 0.446138581295766, 0.8030805319662981, 0.5280429096670912, 0.25960285298532004, 0.36088969827160805, 0.43143000229873113, 0.7941678141517742, 0.107334065965393, 0.13803877097876832, 0.7224846396419364, 0.150274714852675, 0.03655779055568964, 0.35202356186576755, 0.8867871855452475, 0.6561325211685619, 0.45370991951901846, 0.21879863147029777, 0.1144327890249893, 0.21137607850479412]\n [0.963419944890434, 0.4478457678502066, 0.8407656301021255, 0.5394619505769526, 0.26358620538619504, 0.3785307293750754, 0.43443524658702654, 0.7426580903726461, 0.11338938338304744, 0.1475698891121404, 0.7345099631141349, 0.16048747662896795, 0.03959434344670769, 0.3379755377009729, 0.7958692645000881, 0.48283669535781387, 0.36706195693003885, 0.17548000193294144, 0.1136592394878268, 0.22309854306314952]\n [0.995616193064571, 0.44805738727466143, 0.8700643195894429, 0.5512240918443782, 0.2674989824178032, 0.3924051349926597, 0.4375425793363201, 0.6886449125246876, 0.11960335804730916, 0.15695502649258633, 0.7327878032629778, 0.17047486846995694, 0.0420936774665965, 0.3062032871443506, 0.6610340292426684, 0.34855000462048347, 0.2881369319293169, 0.14175624955652485, 0.11666389844136492, 0.24243967254676815]\n [1.0331366869886944, 0.44448629343725343, 0.8788288901686566, 0.5620901047900512, 0.2708572048035862, 0.39695429480179645, 0.44018298027640984, 0.6333401253753693, 0.1252037789780579, 0.1640984843116221, 0.7114983769875807, 0.17795514254857084, 0.04354809380952039, 0.26092610308891634, 0.5154058541922188, 0.25624511921879434, 0.22330145420147088, 0.11586948470233616, 0.12436895504970236, 0.26962910331924905]\n [1.0773089982155897, 0.43396923698721435, 0.8556572961992899, 0.5707904139404543, 0.2731983214483226, 0.38705755776238965, 0.4413794083264426, 0.57197930814629, 0.12978003467017415, 0.16724868374246712, 0.6675169557355778, 0.18101017312972054, 0.04388752925907648, 0.20909394578211202, 0.3805309865842198, 0.19230727005942244, 0.16943175281775166, 0.09443672996682428, 0.13906102138589269, 0.30741066949967055]\n [1.1213743703927337, 0.4149870885160012, 0.7975741540831984, 0.5733620864984142, 0.2733077885606147, 0.36141676843558873, 0.4391552288251882, 0.5071960218562799, 0.13225598133704913, 0.1649144766546638, 0.6093837906327526, 0.17807037605762552, 0.04315159765633695, 0.1631734536430942, 0.2790930366914647, 0.15237925689592774, 0.12890880773111002, 0.0777317468581009, 0.16225155189984958, 0.35425475261372863]\n [1.1573410183305781, 0.3875799067335869, 0.7122633234623346, 0.5656661531044221, 0.2699342224158771, 0.32362037390928877, 0.43151833519945715, 0.43980122366299085, 0.1320832740044849, 0.15754833392958092, 0.5485937790090555, 0.16967851768901068, 0.04155688582593655, 0.12670961646818607, 0.20790093579654878, 0.12919220653556573, 0.09920527144448085, 0.06511083602693121, 0.1957265685332169, 0.40863184877785175]\n [1.1744909386178761, 0.35353525150930704, 0.6130415990319116, 0.5442924204781258, 0.2619765432579562, 0.2797239154423789, 0.41725964546931765, 0.3734718885747243, 0.12906194711831975, 0.14648620822639452, 0.49617455885534983, 0.15734180901650238, 0.039351964038387546, 0.0993990767009241, 0.15977668195469585, 0.1193453433823383, 0.07853078787521317, 0.05684848395648957, 0.23880211323157663, 0.46473430625333423]\n [1.1636651009007108, 0.3155425241026375, 0.5129043599973696, 0.5086210124289895, 0.24908969960788688, 0.23553191470443982, 0.3966456636545259, 0.3124900352369809, 0.12355869405172261, 0.13330212010711523, 0.45885425946835634, 0.14280589051662543, 0.036833828434965285, 0.07940681588029759, 0.1280065867800307, 0.12159259236413968, 0.06534238144397321, 0.053601952458352684, 0.28528412637082984, 0.5126103913127859]\n [1.1215900120487023, 0.2768216752264026, 0.42206636648520485, 0.46189135063482056, 0.23215126320140814, 0.19551978933588599, 0.37144587200796514, 0.26042387609908113, 0.11647562742120145, 0.11955373899209087, 0.4381554894529827, 0.1277697315605396, 0.034397853577932694, 0.06512710102028911, 0.10768752758342186, 0.13551750917697, 0.058102384679568894, 0.055907692857973916, 0.3220846544335181, 0.5412432565515389]\n [1.051674472438156, 0.2396400556460993, 0.34499392466732914, 0.408962875223587, 0.21264909765819076, 0.16158429863184295, 0.3435589630316772, 0.2180232510648064, 0.10878792457246415, 0.10632571872188118, 0.43013574616355804, 0.11339063974249527, 0.03248700163555598, 0.055268908325187105, 0.0946316891444375, 0.1595784203240174, 0.05459709129704919, 0.0631635952778267, 0.33753068620574334, 0.5455404467088186]\n ⋮\n [0.00032755644980272486, 0.00042642730013303957, 0.00024189593390109746, 3.1111688980955344e-5, 0.002186365444974394, 0.0001284836050334962, 0.009392611128074742, 0.2289263661082618, 0.027817843518977224, 0.00011632790937708126, 0.4448717546882417, 0.0001223774188672115, 0.198564855194196, 0.09669339044487263, 0.041438780171243736, 0.21624377256231636, 0.010260398961170272, 0.1106446052574405, 0.30895191650548376, 0.48344362584850714]\n [0.0001996798247022266, 0.0003009378761392906, 0.00015346749983007282, 1.8190449427202614e-5, 0.0017884347223449826, 8.151473534424173e-5, 0.0077101296606787864, 0.23181199431785626, 0.025313811373776522, 7.379449257908107e-5, 0.44476144744230767, 7.763164111187508e-5, 0.19771575290544488, 0.0981753484444294, 0.0415237986113816, 0.21618611797874981, 0.010096001729578499, 0.1107711243020971, 0.3089588621965838, 0.4835526097023227]\n [0.00011328126257715799, 0.0002025145740727682, 9.102676275323986e-5, 9.86615934389697e-6, 0.0014273867429624918, 4.834918126253599e-5, 0.006152674701416408, 0.2345821350465174, 0.022777702555973164, 4.3766536607882777e-5, 0.44485825775398713, 4.604210489119089e-5, 0.19677603845677671, 0.0996135511824476, 0.04163063947534051, 0.21611456663905765, 0.00992313898370846, 0.1108762739174712, 0.30896257460215903, 0.4836121681503955]\n [6.07969185813491e-5, 0.00013150891522278353, 5.122984902532575e-5, 5.0559263528295375e-6, 0.0011197509119850043, 2.721092248119792e-5, 0.004805123705498752, 0.2371493862104039, 0.02034698607033935, 2.4630532478594332e-5, 0.44507776580317365, 2.591108561516969e-5, 0.19582059389086015, 0.10090484291104647, 0.04175110898630074, 0.21605866945798072, 0.009748297718843965, 0.1109547748500005, 0.308965762906422, 0.48361873148098766]\n [2.9540113221979872e-5, 8.00347447973086e-5, 2.6268553079549285e-5, 2.3358462951272875e-6, 0.0008502538978690424, 1.3952641028662382e-5, 0.0036125895986525765, 0.23963412412998863, 0.017924696653654346, 1.2629101514971793e-5, 0.4453417610345992, 1.3285671319358326e-5, 0.19486664345382582, 0.10209874101875081, 0.041891604062307145, 0.2160237975426658, 0.00956208380761516, 0.11101835580249045, 0.3089707135225891, 0.48359145640506035]\n [1.3166616427449579e-5, 4.60961582614326e-5, 1.241859399595492e-5, 9.875013357564836e-7, 0.0006289434801525733, 6.596183545884943e-6, 0.0026293723865516917, 0.24190491545204867, 0.015626334170708748, 5.970359692556319e-6, 0.44560575498650923, 6.280744324641365e-6, 0.19400924653479448, 0.10314206416955765, 0.04204857588531362, 0.2160007866180423, 0.009371522869382096, 0.11107366457263641, 0.3089769794039354, 0.48355133078668755]\n [5.288582093742206e-6, 2.4853056623534485e-5, 5.32431964558186e-6, 3.7495755123700837e-7, 0.0004510237192764804, 2.8280327624688987e-6, 0.0018418173438047715, 0.24395924306889033, 0.013458321791607284, 2.559692577943294e-6, 0.44587256631997335, 2.692763414898462e-6, 0.19326957086896235, 0.10403490013949204, 0.04222157762263886, 0.21597907364688387, 0.009176377022194124, 0.11112583015368675, 0.30898347361961076, 0.4835073952384332]\n [1.960571333984018e-6, 1.2748386630159753e-5, 2.115911956181734e-6, 1.3122771778296083e-7, 0.00031649230625780636, 1.1238747466059242e-6, 0.0012535673852407435, 0.2457433105385709, 0.011504652249667801, 1.0172301703560636e-6, 0.44612733302168156, 1.0701126911743665e-6, 0.19267165202271308, 0.1047507539103007, 0.04240100704365944, 0.21595925499391128, 0.008984468602875842, 0.11117426849212075, 0.30898978378818076, 0.48346305093339226]\n [6.595296475377276e-7, 6.157495485353746e-6, 7.673573735587585e-7, 4.1573174269355544e-8, 0.0002163095240186386, 4.0758481170993133e-7, 0.0008246351715236552, 0.24730063052972948, 0.009744807150823888, 3.6890828571649465e-7, 0.4463589658982419, 3.880865976484553e-7, 0.19219749029253488, 0.10531819548561512, 0.042584771757986466, 0.21594251593637606, 0.008795235529894242, 0.11122083597743129, 0.3089962400343031, 0.48342085434013]\n [2.0108052810226762e-7, 2.8004575219465937e-6, 2.5369560293790977e-7, 1.190656631256341e-8, 0.00014408987057401768, 1.3475139250220505e-7, 0.0005246117248146955, 0.24864251960077316, 0.008183727277329841, 1.2196446538994685e-7, 0.4465625705694917, 1.2830498581813105e-7, 0.19183327165148306, 0.10575941597710509, 0.04276848561656389, 0.21592768854223388, 0.008611086962690943, 0.11126649455166937, 0.30900276016604544, 0.4833835692529364]\n [5.35850498787597e-8, 1.174593201709331e-6, 7.398752912499898e-8, 2.965192061208363e-9, 9.266705935747393e-5, 3.929875986723788e-8, 0.00031929137827090367, 0.24981133030734196, 0.006788855740405869, 3.556958190340493e-8, 0.4467437607797747, 3.7418723667047955e-8, 0.19155285868338037, 0.10610455981258715, 0.04295191471606665, 0.21591384077514106, 0.008430160333184566, 0.1113122756892104, 0.30900934087551246, 0.48335082223348647]\n [3.2821854904203205e-8, 8.406671643638472e-7, 4.6640508998017896e-8, 1.7793663607263053e-9, 7.799523091116062e-5, 2.4773285240091262e-8, 0.0002627973314424048, 0.2502039748903548, 0.00631276636245039, 2.2422472598477954e-8, 0.4468055436036614, 2.358814075481337e-8, 0.19146688286657296, 0.10621159455428622, 0.04301932407939025, 0.21590899888568155, 0.008364030293673712, 0.11132929056683419, 0.3090117977250657, 0.4833397504740079]\n```\n:::\n:::\n\n\n::: {#c2755c37 .cell execution_count=16}\n``` {.julia .cell-code}\n# components\ntotal_biomass(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=174}\n```\n51-element Vector{Float64}:\n 9.035052310145453\n 8.879184522388458\n 8.608521978391984\n 8.302235859798492\n 7.977752408265428\n 7.6479265310498565\n 7.293056293658903\n 6.933942335839723\n 6.569662630859385\n 6.203645482991124\n 5.835689949822736\n 5.4639327723474995\n 5.082524806480722\n ⋮\n 2.180830466139856\n 2.179270649906686\n 2.177861954789722\n 2.1766481390536\n 2.1755648676013255\n 2.174661007473904\n 2.1739250919601236\n 2.1733597626038192\n 2.1729302781639843\n 2.1726139439247745\n 2.172383095801758\n 2.172315739557126\n```\n:::\n:::\n\n\nSecond, we can an estimate of species persistence - how many have gone extinct! Remember that we started with 20, so a value of 0.45 means that there are 12 species left.\n\n::: {#b730739f .cell execution_count=17}\n``` {.julia .cell-code}\n# the percentage that persist\npersistence(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=175}\n```\n51-element Vector{Float64}:\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n ⋮\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n 1.0\n```\n:::\n:::\n\n\n::: {#12caff2b .cell execution_count=18}\n``` {.julia .cell-code}\n# quick calculation of number left (but see richness below!)\n20*persistence(sim_niche) # the numbner left\n```\n\n::: {.cell-output .cell-output-display execution_count=176}\n```\n51-element Vector{Float64}:\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n ⋮\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n 20.0\n```\n:::\n:::\n\n\nThird, we can look at measures of diversity. First, we can get species richness and a measure of diversity, using the Shannon index. This confirms that our persistence estimate (45%) is in line!\n\n::: {#046ece68 .cell execution_count=19}\n``` {.julia .cell-code}\nrichness(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=177}\n```\n51-element Vector{Int64}:\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n ⋮\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n 20\n```\n:::\n:::\n\n\n::: {#b47a729d .cell execution_count=20}\n``` {.julia .cell-code}\nshannon_diversity(sim_niche)\n```\n\n::: {.cell-output .cell-output-display execution_count=178}\n```\n51-element Vector{Float64}:\n 15.838289686150633\n 15.938034479922063\n 16.062630873979742\n 16.120434078447378\n 16.08114076965578\n 15.938487296717936\n 15.697940272210305\n 15.410182133499104\n 15.107012611506958\n 14.810310060152338\n 14.548540861111752\n 14.364162310889597\n 14.284610563485106\n ⋮\n 8.172811865080977\n 8.1142305814134\n 8.05780958633494\n 8.006127953781233\n 7.956790341905648\n 7.911831829238024\n 7.87087151813162\n 7.835016456582986\n 7.803489117438748\n 7.776056823831216\n 7.751865699167424\n 7.743665633968\n```\n:::\n:::\n\n\n> 🚧 This is no longer built in Alain should have some ideas how to address.\n\nFinally, we can look at stability - all built in metrics of stability are based on the coefficient of variation of species biomass. The CV is a measure of standardised variation - the standard deviation / mean (https://en.wikipedia.org/wiki/Coefficient_of_variation). It is not 'stability' in the strict mathematical sense, but an estimation of how variable the dynamics are.\n\ndefined as the average coefficient of variation estimated across all of the coefficients of variation for each species.\n\nThe master function is `coefficient_of_variation` and delivers four results - Coefficient of Variation (CV) of community biomass and its partition into average species CV (`community_cv` above), species mean CV and synchrony, along with the variation of each species; following Thibault & Connolly (2013):\n\n::: {#7c051760 .cell execution_count=21}\n``` {.julia .cell-code}\ncoefficient_of_variation(sim_niche)\n```\n:::\n\n\nNote the warning.... do you understand what it's talking about? Think about the extinctions detail above. You can follow the instructions, right?\n\n::: {#1074ce85 .cell execution_count=22}\n``` {.julia .cell-code}\ncoefficient_of_variation(sim_niche, last = 4)\n```\n:::\n\n\nYou can get parts of this with specific helper functions, such as:\n\n::: {#a6df5e96 .cell execution_count=23}\n``` {.julia .cell-code}\ncommunity_cv(sim_niche, last = 4)\n```\n:::\n\n\n### What's next\n\nThe next section will introduce how to create simulations where we work with multiple networks and collect data across these. We do this using loops, and collect information in a data frame. We then work on how to embed additional changes to parameters in the loops as well.\n\n## References\n\n::: {#refs}\n:::\n\n", - "supporting": [ - "Tutorial-8_Intro To Eco Net Dyn_files" - ], - "filters": [], - "includes": { - "include-in-header": [ - "\n\n\n" - ] - } - } -} \ No newline at end of file diff --git a/_freeze/Tutorial-9_Experiments with the BEFWM2/execute-results/html.json b/_freeze/Tutorial-9_Experiments with the BEFWM2/execute-results/html.json deleted file mode 100644 index 96a9d90..0000000 --- a/_freeze/Tutorial-9_Experiments with the BEFWM2/execute-results/html.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "hash": "e7f984ffc7225e1f2bed62ca18776151", - "result": { - "engine": "jupyter", - "markdown": "---\ntitle: \"Tutorial 9: Experiments with the BEFWM2\"\ndate: now\nauthor: \"Danet and Becks, based on originals by Delmas and Griffiths\"\nformat:\n html:\n embed-resources: true\ntitle-block-banner: true\n---\n\nIn the previous chapter, we learned how to make networks and run a simulation. We did this for a simple tri-trophic chain where we specified the network with a matrix of ones and zeros, and for a more complex network defined by the niche model where we specified species richness and connectance. We also learned how to visualise the simulations and to collect several metrics about the simulations, including detail on biomass, diversity and stability.\n\nIn this tutorial, we are going to learn how to do experiments. We'll learn first how to generate multiple networks and collect information on how network structure impacts our metrics. Then we'll learn how to manipulate parameters in the model, again collecting information on how variation in these parameters impacts our metrics.\n\nFor example, we might be interested in how species richness or connectance impacts biomass and stability. Or how the carrying capacity of the producers impacts biomass and stability of the community (e.g. bottom up processes). We'll look at both of these.\n\n### Getting Setup\n\nAs with our previous exercises, we need to have a few packages that allow making networks, simulating them and collecting the data\n\n::: {#139e8ac0 .cell execution_count=1}\n``` {.julia .cell-code}\nusing DataFrames, Plots, Random, Distributions\nusing EcologicalNetworksDynamics\n```\n:::\n\n\n### Your (re)introduction to loops: making multiple networks example\n\nOne of the tricks to doing experiments is learning how to run a loop. Julia is super-fast with running loops. This is a bit different to R, which has a bad rep for loops. It's not terrible. But Julia is built to do loops fast.\n\nWhat we will do here is build a simple loop that makes 3 networks, each with a different species richness, but the same connectance.\n\nNote here that we introduce the use of the argument `tol_C`. Because the `niche model` produces networks based on probability theory (it uses the beta-distribution), the connectance we ask for is not always the connectance we get. The `tol_C` argument ensure that connectance is within a _tolerance_ range - in this case, having asked for `C = 0.2` and a `tol_C = 0.01` we will get `0.19 < C < 2.01`. This is like embedding a while loop within the `FoodWeb` function! We note too that the function `nichemodel` can take a value of `L` instead of `C`, and there is an associated `tol_L` argument for this choice too.\n\n::: {#e69119a8 .cell execution_count=2}\n``` {.julia .cell-code}\nRandom.seed!(12325) # ensures your network and this one are the same\n\nS = [10,20,30] # define the number of species\nC = 0.2 # define the connectance (complexity) of the network\n\n# collection zone for the networks\nnets = []\n\n# construct the food webs\n# we loop over the 3 values of S\n# we use push!() to add the food webs to nets\n# always start with a for and end with an end.\nfor i in 1:3\n push!(nets, Foodweb(:niche; S = S[i], C = C))\nend\n```\n:::\n\n\nGreat. Let's see if we got what we expected in nets.\n\n::: {#c0d46978 .cell execution_count=3}\n``` {.julia .cell-code}\nnets\n```\n\n::: {.cell-output .cell-output-display execution_count=4}\n```\n3-element Vector{Any}:\n blueprint for Foodweb with 22 trophic links\n blueprint for Foodweb with 81 trophic links\n blueprint for Foodweb with 182 trophic links\n```\n:::\n:::\n\n\nMagnificent, we have three networs and that's a win. We also see that they are each for a different and appropriate S. Win no. 2. We can actually now check to see what the connectances actually are. Again, we'll use a loop, `println` and introduce you to the details of the `FoodWeb` object.\n\nFirst, let's look at one of the networks.\n\n::: {#0eddb9d7 .cell execution_count=4}\n``` {.julia .cell-code}\nnets[1]\n```\n\n::: {.cell-output .cell-output-display execution_count=5}\n```\nblueprint for Foodweb with 22 trophic links:\n A: 10×10 SparseArrays.SparseMatrixCSC{Bool, Int64} with 22 stored entries:\n ⋅ 1 1 1 1 1 1 1 1 1\n ⋅ 1 1 ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ 1 1 1 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 1\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ 1 1 1 ⋅ ⋅\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ 1\n ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅ ⋅\n```\n:::\n:::\n\n\nWe can see that the `A` element is the matrix and you can guess that the `M` is the body `M`asses. We also find tha there are 3 producers and 7 invertebrates and it is derived from the niche model\n\n> a side note on the metabolic classes. The default parameterisation, and nearly all of the published work with the BEFW, uses invertebrates for all the non-producer species. It is possible to include others. But the data, currently, are not helpful (low volume) in supporting robust inference with these types of species.\n\nNow, recall that we can look specifically at the matrix by using `nets[1].A` which grabs the `A` part. We introduce here the function `sum`. As in **R**, `sum()` does what it says on the tin: for a vector, it addes up all the numbers and for a matrix, it does the same! In our case here, when `sum()` is applied to a matrix of ones and zeros, it counts all the 1's.... thus is the estimate of the number of links in the community. \n\nFinally, we note (again?) that `size` applied to the network returns two numbers - the number of rows and the number of columns. For our networks, the matrix is square. So grabbing one of these (rows = [1]) and squaring it delivers our 'potential number of links' (e.g. $species^2$). \n\nWe can put that all together here to define connectance as $Con = links/S^2$. Do be careful to watch where you put the various `[]`'s. One of them is about the _index_ (i.e. `[i]`) and the other is about the dimension (`[1]`) of the matrix.\n\n::: {#f820fb03 .cell execution_count=5}\n``` {.julia .cell-code}\nfor i in 1:3\n println(sum(nets[i].A)/size(nets[i].A)[1]^2)\n end\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n0.22\n0.2025\n0.20222222222222222\n```\n:::\n:::\n\n\n#### Different ways to run loops.\n\nThere is another way to make this set of networks. Here we use a `while` loop to create 3 networks with the same species richness and connectance. We might need to do this to generate _replicates_. This is a good exercise with the **niche model** as it reminds you that it is a probabilistic tool... you can get several networks with the same S and C, but the links will be in slightly different places.\n\n`while` loops work on conditions... for example, if we want three networks, we could ask that the loop keep working to make the networks until we have three. To do this, we need a _monitoring_ variable that lets us assess where we are against our target.\n\nLets see how to do that.\n\n::: {#016cbe80 .cell execution_count=6}\n``` {.julia .cell-code}\n# how many replicates do we want?\nreps = 3\n\nbegin\n\t# list to store networks\n\tglobal networks = []\n\t# monitoring variable l (the letter l)\n\tglobal l = length(networks)\n\n # while loop\n\twhile l < reps # reps is 3 here...\n\t # generate a network\n\t A = Foodweb(:niche; S = 20, C = 0.15)\n\t # add the network to the set\n push!(networks, A)\n # update the monitor\n\t global l = length(networks)\n\tend\nend\n```\n:::\n\n\nThe term `global` means that the obects are made available in our global environment and should be there for us to see. If you look closely at the mini-matrices, you'll see they are all different in micro-structure, despite having the same number of links and the same connectance.\n\n> NOTE: the presentation of the matrix is very specific here... the rows correspond to the predators and the columns the resources. Obstensibly, the ranking is by body size, so small things are at the upper left. This view shows that big things tend to eat small and big things, while small things eat small. Historically, the reflection (pivot around the diagnol) has also been used, where the predators are the columns and the resources the rows. This lead to a 'feature' of real and theoretical networks aligning, call `upper triangularity`. In this latter presentation, most of the links would be in the upper triangle. In the current presentation, the links are in the lower triangle. So we can just call the feature `triangularity`. The niche model reproduces this triangularity.\n\n::: {#a8dfacc5 .cell execution_count=7}\n``` {.julia .cell-code}\nnetworks\n```\n\n::: {.cell-output .cell-output-display execution_count=8}\n```\n3-element Vector{Any}:\n blueprint for Foodweb with 55 trophic links\n blueprint for Foodweb with 63 trophic links\n blueprint for Foodweb with 62 trophic links\n```\n:::\n:::\n\n\n::: {#0a5143a9 .cell execution_count=8}\n``` {.julia .cell-code}\nnetworks[1].A\n```\n\n::: {.cell-output .cell-output-display execution_count=9}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 55 stored entries:\n⎡⠉⠉⠉⣉⡡⠐⠒⠒⠒⠂⎤\n⎢⠀⠀⠀⠀⠀⠔⠒⠒⠒⠂⎥\n⎢⠀⠀⠀⠀⠨⠕⠒⠒⠒⠂⎥\n⎢⠀⠀⠀⠀⠀⠀⠐⠒⠿⡅⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦\n```\n:::\n:::\n\n\n::: {#3a5a796a .cell execution_count=9}\n``` {.julia .cell-code}\nnetworks[2].A\n```\n\n::: {.cell-output .cell-output-display execution_count=10}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 63 stored entries:\n⎡⠉⠩⠭⠉⠉⠁⠀⠀⠀⠒⎤\n⎢⠀⠀⠈⠒⣒⠒⠒⠶⠤⠀⎥\n⎢⠀⠀⠀⠀⠒⠀⠨⣭⣭⡤⎥\n⎢⠀⠀⠀⠀⠀⠀⠀⠤⠤⠉⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠐⠛⎦\n```\n:::\n:::\n\n\n::: {#29bd575c .cell execution_count=10}\n``` {.julia .cell-code}\nnetworks[3].A\n```\n\n::: {.cell-output .cell-output-display execution_count=11}\n```\n20×20 SparseArrays.SparseMatrixCSC{Bool, Int64} with 62 stored entries:\n⎡⣀⣭⣭⣍⣉⣉⡉⠉⠁⠀⎤\n⎢⠀⠀⠀⠉⠉⠁⢠⠤⠤⠤⎥\n⎢⠀⠀⠀⠀⠀⠉⢰⣶⠀⠀⎥\n⎢⠀⠀⠀⠀⠀⠀⠈⠉⡀⠀⎥\n⎣⠀⠀⠀⠀⠀⠀⠀⠀⠀⠈⎦\n```\n:::\n:::\n\n\n### Linking the networks to the Ecological Networks Dynamics\n\nFantastic. Now you are ready for the next steps. We want to run the `EcologicalNetworksDynamics` model on each of these networks. Furthermore, we want to collect the biomass and stability information for all three into a data frame. Let's see how we do that.\n\n#### Step 1: Create the collecting data frame\n\nFirst, we create the holding pen for our information. We'll construct a data frame to collect five pieces of information: the network id (1,2 or 3), species richness at the start (our initial S), species richness at the end, total biomass at the end and stability at the end.\n\n::: {#c677e9ad .cell execution_count=11}\n``` {.julia .cell-code}\noutputs = DataFrame(Network = [], Init_Rich = [], Fin_Rich = [], Tot_biomass = [], Shannon_dic = [])\n```\n\n::: {.cell-output .cell-output-display execution_count=12}\n```{=html}\n
0×5 DataFrame
RowNetworkInit_RichFin_RichTot_biomassShannon_dic
AnyAnyAnyAnyAny
\n```\n:::\n:::\n\n\n#### Step 2: use the pre-defined networks\n\nWe can use our `nets` object from above now. Each of these networks has a different species richness.\n\n::: {#9f867c86 .cell execution_count=12}\n``` {.julia .cell-code}\nfor i in 1:3\n\n # prep: define size of network\n S = size(nets[i].A)[1]\n\n # deliver some progress reporting\n println(\"\\nThis is network: \", i, \"with species richness = \", S,\"\\n\")\n\n # step A: define model paramters\n params = default_model(nets[i])\n\n # step B: define body mass\n B0 = rand(S)\n\n # step C: set number of timestamps\n t = 300\n\n # step D: simulate\n out = simulate(params, B0, t)\n\n # steps D: calculate metrics\n fin_rich = richness(out)\n fin_biomass = total_biomass(out)\n s_div = shannon_diversity(out)\n\n # step E: add things to the data frame\n # note the first arg is the data frame and then\n # the values we want allocated to the five slots\n # are in []\n push!(outputs, [i, S, fin_rich, fin_biomass, s_div])\nend\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n\nThis is network: 1with species richness = 10\n\n\nThis is network: 2with species richness = 20\n\n\nThis is network: 3with species richness = 30\n\n```\n:::\n:::\n\n\nAmazing. Let's see if what we wanted collected has ended up in our data frame. Wonderful! Splendiferous. Fantabulous.\n\n::: {#4e81e1db .cell execution_count=13}\n``` {.julia .cell-code}\nprintln(outputs)\n```\n\n::: {.cell-output .cell-output-stdout}\n```\n3×5 DataFrame\n Row │ Network Init_Rich Fin_Rich Tot_biomass Shannon_dic \n │ Any Any Any Any Any \n─────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────\n 1 │ 1 10 [10, 10, 10, 10, 10, 10, 10, 10,… [4.70537, 4.63199, 4.53209, 4.42… [8.375, 8.40912, 8.44306, 8.4699…\n 2 │ 2 20 [20, 20, 20, 20, 20, 20, 20, 20,… [8.52201, 8.4081, 8.26162, 8.102… [15.0407, 15.0769, 15.1077, 15.1…\n 3 │ 3 30 [30, 30, 30, 30, 30, 30, 30, 30,… [14.7649, 14.5082, 14.2062, 13.8… [24.3797, 24.4948, 24.5777, 24.6…\n```\n:::\n:::\n\n\n#### Dissecting more from simulate\n\nNote the details on extinctions that comes from a model run. For example, let's revisit our `sim_niche` object (you won't necessarily have to re-run this if you are working in one big script)\n\n::: {#44467678 .cell execution_count=14}\n``` {.julia .cell-code}\nS = 20; # define the number of species\nC = 0.2; # define the connectance (complexity) of the network\n\n# construct the food web\nRandom.seed!(12325) # ensures your network and this one are the same\nfoodweb_niche = Foodweb(:niche; S = S, C = C)\n\n# construct the equations and fixed parameters\nparams_niche = default_model(foodweb_niche)\n\n# define bodymasses between 0 and 1 and get S = 20 of them.\nRandom.seed!(123)\nB0 = rand(S)\n\n# simulate using params and bodymasses\n# specify number of time steps\nt = 300\nsim_niche = simulate(params_niche, B0, t)\n```\n\n::: {.cell-output .cell-output-display execution_count=15}\n```\nretcode: Success\nInterpolation: 3rd order Hermite\nt: 51-element Vector{Float64}:\n 0.0\n 0.0983252574499891\n 0.28544083243480267\n 0.5267982237043161\n 0.8245753364604138\n 1.181896742988936\n 1.6418353914084878\n 2.203829100924959\n 2.893464061893281\n 3.729699102007749\n 4.728753111889612\n 5.890702747756841\n 7.2218772360496395\n ⋮\n 136.70283821576533\n 145.48441982502288\n 155.57070934467725\n 166.67876410920994\n 179.5612866567586\n 193.9800038364207\n 210.21105297520486\n 227.83156289127072\n 247.0838336915681\n 267.94281052881126\n 290.8959793077713\n 300.0\nu: 51-element Vector{Vector{Float64}}:\n [0.906299638797481, 0.44349373245960455, 0.7456733811393941, 0.5120830400366143, 0.2538490889415096, 0.33415153638191886, 0.4273278808735992, 0.867547200255958, 0.09913361484360417, 0.12528740769155033, 0.6922086620547391, 0.13655147513745736, 0.03209667335274724, 0.3505458214588266, 0.9303323763821093, 0.9594335994071538, 0.5819123423876457, 0.3114475007050529, 0.12114752051812694, 0.20452981732035946]\n [0.9169483131714715, 0.444402194534041, 0.7667640455857161, 0.5179071161683636, 0.25596644376248334, 0.3439614083570855, 0.42881389580038637, 0.8404857181508336, 0.10207349613818459, 0.12980979255930417, 0.7045585608788062, 0.14142469702894178, 0.033700254458592344, 0.35322775442579823, 0.9254383246584946, 0.8428424981719224, 0.5353929049386887, 0.2716712297929136, 0.11790964375471776, 0.20588623005171253]\n [0.9372189186622565, 0.446138581295766, 0.8030805319662981, 0.5280429096670912, 0.25960285298532004, 0.36088969827160805, 0.43143000229873113, 0.7941678141517742, 0.107334065965393, 0.13803877097876832, 0.7224846396419364, 0.150274714852675, 0.03655779055568964, 0.35202356186576755, 0.8867871855452475, 0.6561325211685619, 0.45370991951901846, 0.21879863147029777, 0.1144327890249893, 0.21137607850479412]\n [0.963419944890434, 0.4478457678502066, 0.8407656301021255, 0.5394619505769526, 0.26358620538619504, 0.3785307293750754, 0.43443524658702654, 0.7426580903726461, 0.11338938338304744, 0.1475698891121404, 0.7345099631141349, 0.16048747662896795, 0.03959434344670769, 0.3379755377009729, 0.7958692645000881, 0.48283669535781387, 0.36706195693003885, 0.17548000193294144, 0.1136592394878268, 0.22309854306314952]\n [0.995616193064571, 0.44805738727466143, 0.8700643195894429, 0.5512240918443782, 0.2674989824178032, 0.3924051349926597, 0.4375425793363201, 0.6886449125246876, 0.11960335804730916, 0.15695502649258633, 0.7327878032629778, 0.17047486846995694, 0.0420936774665965, 0.3062032871443506, 0.6610340292426684, 0.34855000462048347, 0.2881369319293169, 0.14175624955652485, 0.11666389844136492, 0.24243967254676815]\n [1.0331366869886944, 0.44448629343725343, 0.8788288901686566, 0.5620901047900512, 0.2708572048035862, 0.39695429480179645, 0.44018298027640984, 0.6333401253753693, 0.1252037789780579, 0.1640984843116221, 0.7114983769875807, 0.17795514254857084, 0.04354809380952039, 0.26092610308891634, 0.5154058541922188, 0.25624511921879434, 0.22330145420147088, 0.11586948470233616, 0.12436895504970236, 0.26962910331924905]\n [1.0773089982155897, 0.43396923698721435, 0.8556572961992899, 0.5707904139404543, 0.2731983214483226, 0.38705755776238965, 0.4413794083264426, 0.57197930814629, 0.12978003467017415, 0.16724868374246712, 0.6675169557355778, 0.18101017312972054, 0.04388752925907648, 0.20909394578211202, 0.3805309865842198, 0.19230727005942244, 0.16943175281775166, 0.09443672996682428, 0.13906102138589269, 0.30741066949967055]\n [1.1213743703927337, 0.4149870885160012, 0.7975741540831984, 0.5733620864984142, 0.2733077885606147, 0.36141676843558873, 0.4391552288251882, 0.5071960218562799, 0.13225598133704913, 0.1649144766546638, 0.6093837906327526, 0.17807037605762552, 0.04315159765633695, 0.1631734536430942, 0.2790930366914647, 0.15237925689592774, 0.12890880773111002, 0.0777317468581009, 0.16225155189984958, 0.35425475261372863]\n [1.1573410183305781, 0.3875799067335869, 0.7122633234623346, 0.5656661531044221, 0.2699342224158771, 0.32362037390928877, 0.43151833519945715, 0.43980122366299085, 0.1320832740044849, 0.15754833392958092, 0.5485937790090555, 0.16967851768901068, 0.04155688582593655, 0.12670961646818607, 0.20790093579654878, 0.12919220653556573, 0.09920527144448085, 0.06511083602693121, 0.1957265685332169, 0.40863184877785175]\n [1.1744909386178761, 0.35353525150930704, 0.6130415990319116, 0.5442924204781258, 0.2619765432579562, 0.2797239154423789, 0.41725964546931765, 0.3734718885747243, 0.12906194711831975, 0.14648620822639452, 0.49617455885534983, 0.15734180901650238, 0.039351964038387546, 0.0993990767009241, 0.15977668195469585, 0.1193453433823383, 0.07853078787521317, 0.05684848395648957, 0.23880211323157663, 0.46473430625333423]\n [1.1636651009007108, 0.3155425241026375, 0.5129043599973696, 0.5086210124289895, 0.24908969960788688, 0.23553191470443982, 0.3966456636545259, 0.3124900352369809, 0.12355869405172261, 0.13330212010711523, 0.45885425946835634, 0.14280589051662543, 0.036833828434965285, 0.07940681588029759, 0.1280065867800307, 0.12159259236413968, 0.06534238144397321, 0.053601952458352684, 0.28528412637082984, 0.5126103913127859]\n [1.1215900120487023, 0.2768216752264026, 0.42206636648520485, 0.46189135063482056, 0.23215126320140814, 0.19551978933588599, 0.37144587200796514, 0.26042387609908113, 0.11647562742120145, 0.11955373899209087, 0.4381554894529827, 0.1277697315605396, 0.034397853577932694, 0.06512710102028911, 0.10768752758342186, 0.13551750917697, 0.058102384679568894, 0.055907692857973916, 0.3220846544335181, 0.5412432565515389]\n [1.051674472438156, 0.2396400556460993, 0.34499392466732914, 0.408962875223587, 0.21264909765819076, 0.16158429863184295, 0.3435589630316772, 0.2180232510648064, 0.10878792457246415, 0.10632571872188118, 0.43013574616355804, 0.11339063974249527, 0.03248700163555598, 0.055268908325187105, 0.0946316891444375, 0.1595784203240174, 0.05459709129704919, 0.0631635952778267, 0.33753068620574334, 0.5455404467088186]\n ⋮\n [0.00032755644980272486, 0.00042642730013303957, 0.00024189593390109746, 3.1111688980955344e-5, 0.002186365444974394, 0.0001284836050334962, 0.009392611128074742, 0.2289263661082618, 0.027817843518977224, 0.00011632790937708126, 0.4448717546882417, 0.0001223774188672115, 0.198564855194196, 0.09669339044487263, 0.041438780171243736, 0.21624377256231636, 0.010260398961170272, 0.1106446052574405, 0.30895191650548376, 0.48344362584850714]\n [0.0001996798247022266, 0.0003009378761392906, 0.00015346749983007282, 1.8190449427202614e-5, 0.0017884347223449826, 8.151473534424173e-5, 0.0077101296606787864, 0.23181199431785626, 0.025313811373776522, 7.379449257908107e-5, 0.44476144744230767, 7.763164111187508e-5, 0.19771575290544488, 0.0981753484444294, 0.0415237986113816, 0.21618611797874981, 0.010096001729578499, 0.1107711243020971, 0.3089588621965838, 0.4835526097023227]\n [0.00011328126257715799, 0.0002025145740727682, 9.102676275323986e-5, 9.86615934389697e-6, 0.0014273867429624918, 4.834918126253599e-5, 0.006152674701416408, 0.2345821350465174, 0.022777702555973164, 4.3766536607882777e-5, 0.44485825775398713, 4.604210489119089e-5, 0.19677603845677671, 0.0996135511824476, 0.04163063947534051, 0.21611456663905765, 0.00992313898370846, 0.1108762739174712, 0.30896257460215903, 0.4836121681503955]\n [6.07969185813491e-5, 0.00013150891522278353, 5.122984902532575e-5, 5.0559263528295375e-6, 0.0011197509119850043, 2.721092248119792e-5, 0.004805123705498752, 0.2371493862104039, 0.02034698607033935, 2.4630532478594332e-5, 0.44507776580317365, 2.591108561516969e-5, 0.19582059389086015, 0.10090484291104647, 0.04175110898630074, 0.21605866945798072, 0.009748297718843965, 0.1109547748500005, 0.308965762906422, 0.48361873148098766]\n [2.9540113221979872e-5, 8.00347447973086e-5, 2.6268553079549285e-5, 2.3358462951272875e-6, 0.0008502538978690424, 1.3952641028662382e-5, 0.0036125895986525765, 0.23963412412998863, 0.017924696653654346, 1.2629101514971793e-5, 0.4453417610345992, 1.3285671319358326e-5, 0.19486664345382582, 0.10209874101875081, 0.041891604062307145, 0.2160237975426658, 0.00956208380761516, 0.11101835580249045, 0.3089707135225891, 0.48359145640506035]\n [1.3166616427449579e-5, 4.60961582614326e-5, 1.241859399595492e-5, 9.875013357564836e-7, 0.0006289434801525733, 6.596183545884943e-6, 0.0026293723865516917, 0.24190491545204867, 0.015626334170708748, 5.970359692556319e-6, 0.44560575498650923, 6.280744324641365e-6, 0.19400924653479448, 0.10314206416955765, 0.04204857588531362, 0.2160007866180423, 0.009371522869382096, 0.11107366457263641, 0.3089769794039354, 0.48355133078668755]\n [5.288582093742206e-6, 2.4853056623534485e-5, 5.32431964558186e-6, 3.7495755123700837e-7, 0.0004510237192764804, 2.8280327624688987e-6, 0.0018418173438047715, 0.24395924306889033, 0.013458321791607284, 2.559692577943294e-6, 0.44587256631997335, 2.692763414898462e-6, 0.19326957086896235, 0.10403490013949204, 0.04222157762263886, 0.21597907364688387, 0.009176377022194124, 0.11112583015368675, 0.30898347361961076, 0.4835073952384332]\n [1.960571333984018e-6, 1.2748386630159753e-5, 2.115911956181734e-6, 1.3122771778296083e-7, 0.00031649230625780636, 1.1238747466059242e-6, 0.0012535673852407435, 0.2457433105385709, 0.011504652249667801, 1.0172301703560636e-6, 0.44612733302168156, 1.0701126911743665e-6, 0.19267165202271308, 0.1047507539103007, 0.04240100704365944, 0.21595925499391128, 0.008984468602875842, 0.11117426849212075, 0.30898978378818076, 0.48346305093339226]\n [6.595296475377276e-7, 6.157495485353746e-6, 7.673573735587585e-7, 4.1573174269355544e-8, 0.0002163095240186386, 4.0758481170993133e-7, 0.0008246351715236552, 0.24730063052972948, 0.009744807150823888, 3.6890828571649465e-7, 0.4463589658982419, 3.880865976484553e-7, 0.19219749029253488, 0.10531819548561512, 0.042584771757986466, 0.21594251593637606, 0.008795235529894242, 0.11122083597743129, 0.3089962400343031, 0.48342085434013]\n [2.0108052810226762e-7, 2.8004575219465937e-6, 2.5369560293790977e-7, 1.190656631256341e-8, 0.00014408987057401768, 1.3475139250220505e-7, 0.0005246117248146955, 0.24864251960077316, 0.008183727277329841, 1.2196446538994685e-7, 0.4465625705694917, 1.2830498581813105e-7, 0.19183327165148306, 0.10575941597710509, 0.04276848561656389, 0.21592768854223388, 0.008611086962690943, 0.11126649455166937, 0.30900276016604544, 0.4833835692529364]\n [5.35850498787597e-8, 1.174593201709331e-6, 7.398752912499898e-8, 2.965192061208363e-9, 9.266705935747393e-5, 3.929875986723788e-8, 0.00031929137827090367, 0.24981133030734196, 0.006788855740405869, 3.556958190340493e-8, 0.4467437607797747, 3.7418723667047955e-8, 0.19155285868338037, 0.10610455981258715, 0.04295191471606665, 0.21591384077514106, 0.008430160333184566, 0.1113122756892104, 0.30900934087551246, 0.48335082223348647]\n [3.2821854904203205e-8, 8.406671643638472e-7, 4.6640508998017896e-8, 1.7793663607263053e-9, 7.799523091116062e-5, 2.4773285240091262e-8, 0.0002627973314424048, 0.2502039748903548, 0.00631276636245039, 2.2422472598477954e-8, 0.4468055436036614, 2.358814075481337e-8, 0.19146688286657296, 0.10621159455428622, 0.04301932407939025, 0.21590899888568155, 0.008364030293673712, 0.11132929056683419, 0.3090117977250657, 0.4833397504740079]\n```\n:::\n:::\n\n\nWe've constructed a helper function to get information on which species go extinct and when they do.\n\n::: {#b5cfdc48 .cell execution_count=15}\n``` {.julia .cell-code}\n# collect and organise extinctions\nextinctions = get_extinct_species(sim_niche)\n```\n:::\n\n\nThis is a `Dict` object. The numbers on the left of the `=>` are known as the `keys` and the numbers on the right are `values`. We can create a mini- data frame out of this with the following code. `key` and `values` are actually _extractor_ functions and `collect` is translating the extracted information into a vector.\n\n::: {#b095adfd .cell execution_count=16}\n``` {.julia .cell-code}\n# create a data frame of extinctions\nee1 = DataFrame(who = collect(keys(extinctions)), when = collect(values(extinctions)))\n```\n:::\n\n\nNow we can try and add this information to the plot. For the time being, we'll focus on adding the times that each of these species goes extinct to our figure. To do this we need to access the extinction time column (`when`), add a bit of noise/jitter so that times that are really close together can be seen on our x-axis, and then plot these as points with coordinates `x = when` and `y = 0`.\n\n::: {#d95429bf .cell execution_count=17}\n``` {.julia .cell-code}\n# add some jitter for close together events\nexts = ee1[:,2] .+rand.()\n\n# plot\nplot(sim_niche)\n# add jittered extinction events.\nplot!(exts, zeros(size(ee1[:,1])), seriestype = :scatter, legend = false)\n```\n:::\n\n\nPretty cool!\n\n### What's next\n\nIn the next chapter, you'll be creating larger experiments with loops over actual parameters in the model, including the predator-prey size ratio, values of carry capacity and the predator-prey size ratio.\n\n", - "supporting": [ - "Tutorial-9_Experiments with the BEFWM2_files/figure-html" - ], - "filters": [], - "includes": { - "include-in-header": [ - "\n\n\n" - ] - } - } -} \ No newline at end of file