From 1eb683c819f59eb7b0f4450d88e994f473d159be Mon Sep 17 00:00:00 2001 From: Gabriele Bozzola Date: Thu, 14 Dec 2023 12:03:21 -0800 Subject: [PATCH] Move readme to docs --- README.md | 158 +-------------------------------------------- docs/Project.toml | 1 + docs/make.jl | 16 ++++- docs/src/api.md | 56 ++++++++++++++++ docs/src/index.md | 159 ++++++++++++++++++++++++++++++++++++++++++++++ src/OutputVar.jl | 3 + src/Visualize.jl | 2 - 7 files changed, 236 insertions(+), 159 deletions(-) create mode 100644 docs/src/api.md create mode 100644 docs/src/index.md diff --git a/README.md b/README.md index be017863..de0121f7 100644 --- a/README.md +++ b/README.md @@ -4,165 +4,13 @@

Analyzing and visualizing ClimaAtmos simulations

-[![Test](https://github.com/Sbozzolo/ClimaAnalysis.jl/actions/workflows/ClimaAnalysis.yml/badge.svg)](https://github.com/Sbozzolo/ClimaAnalysis.jl/actions/workflows/ClimaAnalysis.yml) +[![Test](https://github.com/Sbozzolo/ClimaAnalysis.jl/actions/workflows/CI.yml/badge.svg)](https://github.com/Sbozzolo/ClimaAnalysis.jl/actions/workflows/CI.yml) +[![Docs](https://github.com/Sbozzolo/ClimaAnalysis.jl/actions/workflows/Documentation.yml/badge.svg)](https://github.com/Sbozzolo/ClimaAnalysis.jl/actions/workflows/Documentation.yml) `ClimaAnalysis.jl` is a Julia library to post-process and visualize `ClimaAtmos` simulations. -## Quick start - -### `SimDir` - -Suppose you ran a `ClimaAtmos` simulation, and the output is saved in the folder -`simulation_output`. The first step in using `ClimaAnalysis` is to instantiate a -`SimDir`: -``` julia -import ClimaAnalysis - -simdir = ClimaAnalysis.SimDir("simulation_output") -``` -`ClimaAnalysis.SimDir` scans the `simulation_output`, finds all the output -files, and organizes them. - -> [!NOTE] -> As of version `0.1.0`, `ClimaAnalysis` uses file names to identify files and -> variables. In this, `ClimaAnalysis` assumes that the default names for outputs -> are used in `ClimaAtmos` (i.e., -> `__.nc`, as in `ta_1h_max.nc`, or -> `_inst.nc`). - -Once you have a `SimDir`, you can inspect the output. For example, to find what -variables are available: -``` julia-repl -julia> println(summary(simdir)) -Output directory: simulation_output -Variables: -- va - average (2.0h) -- ua - average (6.0h) -- orog - inst -- ta - average (3.0h) - max (4.0h, 3.0h) - min (3.0h) -- ts - max (1.0h) -``` -Now, you can access any given variable -``` julia-repl -ta_max = get(simdir; short_name = "t12", reduction = "max", period = "3.0h") -``` -`ta_max` is a ` OutputVar`, a type that contains the variable as -well as some metadata. - -Let us learn about ` OutputVar`s - -### `OutputVar` - -` OutputVar`s contain the raw data (in `.data`), the attributes read from the -file, and the information regarding the dimension over which the variable is -defined. -``` julia-repl -julia> ts_max.dims -OrderedCollections.OrderedDict{String, Vector{Float32}} with 4 entries: - "time" => [10800.0, 21600.0, 32400.0, 43200.0] - "lon" => [-180.0, -177.989, -175.978, -173.966, -171.955, -169.944, -167.933, -165.922… - "lat" => [-80.0, -77.9747, -75.9494, -73.924, -71.8987, -69.8734, -67.8481, -65.8228, … - "z" => [0.0, 5000.0, 10000.0, 15000.0, 20000.0, 25000.0, 30000.0, 35000.0, 40000.0, … -``` -Here we have the dimensions and their values. The dimensions are ordered as in -the file, so that the first index of `.data` is `time`, and so on. - -We can find the attributes of the dimensions in `.attributes`: -``` julia-repl -julia> ts_max.dim_attributes["lon"] - "lon" => Dict("units"=>"degrees_east") -``` - -Given an `OutputVar`, we can perform manipulations. For instance, we can take -the average over latitudes: -``` julia-repl -ts_max_lat_averaged = ClimaAnalysis.average_lat(ts_max) -``` -Now, -``` julia-repl -ts_max_lat_averaged.dims = -OrderedCollections.OrderedDict{String, Vector{Float32}} with 3 entries: - "time" => [10800.0, 21600.0, 32400.0, 43200.0] - "lon" => [-180.0, -177.989, -175.978, -173.966, -171.955, -169.944, -167.933, -165.922… - "z" => [0.0, 5000.0, 10000.0, 15000.0, 20000.0, 25000.0, 30000.0, 35000.0, 40000.0, … -``` -We can also take a time/altitude slice, for example, the plane with altitude closest to 8000 meters. -``` julia-repl -ts_max_lat_averaged_sliced = ClimaAnalysis.slice_z(ts_max_lat_averaged_sliced, 8_000) -``` -Now, -``` julia-repl -ts_max_lat_averaged_sliced.dims = -OrderedCollections.OrderedDict{String, Vector{Float32}} with 2 entries: - "time" => [10800.0, 21600.0, 32400.0, 43200.0] - "lon" => [-180.0, -177.989, -175.978, -173.966, -171.955, -169.944, -167.933, -165.922… - ``` - -We can directly visualize these quantities. - -### `Visualize` - -If `CairoMakie` is available, `ClimaAnalysis` can be used for plotting. -Importing `CairoMakie` and `ClimaAnalysis` in the same session automatically -loads the necessary `ClimaAnalysis` plotting modules. - -If we want to make a heatmap for `ta_max` at time of 100 s at altitude `z` of 30000 meters: - -``` julia -import CairoMakie -import ClimaAnalysis: Visualize - -fig = CairoMakie.Figure(resolution = (400, 600)) - -viz.plot!( - fig, - ta_max, - time = 100.0, - z = 30_000.0 -) - -CairoMakie.save("ta_max.png", fig) -``` - -If we want to have a line plot, we can simply add another argument (e.g., `lat = -30`), to slice through that value. - -If you want to customize some of the properties, you can pass the `plot_kwargs` -and `cb_kwargs` fields to the `plot!` function. For instance, to choose the -colormap for the colorbar to viridis - -colormap = :viridis - -``` julia -viz.plot!( - fig, - ta_max, - time = 100.0, - z = 30_000.0, - cb_kwargs = [:colormap => :viridis] -) -``` -Note the `Symbol` in colormap!. `cb_kwargs` has to be a mapping of `Symbol`s and values. `ClimaAnalysis` has a convenience function `kwargs` to more easily pass down the -keyword arguments avoiding this step. With that, the above example becomes -``` julia -import ClimaAnalysis: Utils -viz.plot!( - fig, - ta_max, - time = 100.0, - z = 30_000.0, - plot_kwargs = Utils.kwargs(colormap = :inferno) -) -``` -With `Utils.kwargs`, you can just pass the arguments as you would pass them to the constructor. +Check out the documentation for more information and tutorials. ## Features diff --git a/docs/Project.toml b/docs/Project.toml index ee92e83f..1d9954d9 100644 --- a/docs/Project.toml +++ b/docs/Project.toml @@ -1,4 +1,5 @@ [deps] +ClimaAnalysis = "29b5916a-a76c-4e73-9657-3c8fd22e65e6" CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" diff --git a/docs/make.jl b/docs/make.jl index 9614496f..6233ecf6 100644 --- a/docs/make.jl +++ b/docs/make.jl @@ -1,8 +1,19 @@ using ClimaAnalysis using Documenter +import CairoMakie + +DocMeta.setdocmeta!( + ClimaAnalysis, + :DocTestSetup, + :(using ClimaAnalysis.Utils); + recursive = true, +) makedocs(; - modules = [ClimaAnalysis], + modules = [ + ClimaAnalysis, + Base.get_extension(ClimaAnalysis, :CairoMakieExt), + ], authors = "Climate Modelling Alliance", repo = "https://github.com/Sbozzolo/ClimaAnalysis.jl", sitename = "ClimaAnalysis.jl", @@ -10,7 +21,8 @@ makedocs(; prettyurls = get(ENV, "CI", "false") == "true", canonical = "https://sbozzolo.github.io/ClimaAnalysis.jl", ), - pages = ["Home" => "index.md"], + checkdocs = :exports, + pages = ["Home" => "index.md", "APIs" => "api.md"], ) deploydocs(; repo = "github.com/Sbozzolo/ClimaAnalysis.jl") diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 00000000..7c6e987b --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,56 @@ +# API + +```@meta +CurrentModule = ClimaAnalysis +``` + +## SimDir + +```@docs +SimDir +Base.get +available_vars +available_reductions +available_periods +``` + +## OutputVar + +```@docs +OutputVar +read_var +slice_general +slice_x +slice_y +slice_z +slice_lon +slice_lat +slice_time +average_lat +average_lon +average_time +``` + + +## Utilities + +For development and not + +```@docs +Utils.match_nc_filename +Utils.squeeze +Utils.nearest_index +Utils.kwargs +``` + +## CairoMakie + +```@docs +Visualize.heatmap2D! +Visualize.sliced_heatmap! +Visualize.heatmap! +Visualize.line_plot1D! +Visualize.sliced_line_plot! +Visualize.sliced_plot! +Visualize.plot! +``` diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 00000000..5d8829c2 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,159 @@ +# ClimaAnalysis + +`ClimaAnalysis`, your one-stop-shop for all your CliMA analysis needs. + +## Quick start + +### `SimDir` + +Suppose you ran a `ClimaAtmos` simulation, and the output is saved in the folder +`simulation_output`. The first step in using `ClimaAnalysis` is to instantiate a +`SimDir`: +``` julia +import ClimaAnalysis + +simdir = ClimaAnalysis.SimDir("simulation_output") +``` +`ClimaAnalysis.SimDir` scans the `simulation_output`, finds all the output +files, and organizes them. + +As of version `0.1.0`, `ClimaAnalysis` uses file names to identify files and +variables. In this, `ClimaAnalysis` assumes that the default names for outputs +are used in `ClimaAtmos` (i.e., +`__.nc`, as in `ta_1h_max.nc`, or +`_inst.nc`). + +Once you have a `SimDir`, you can inspect the output. For example, to find what +variables are available: +``` julia-repl +julia> println(summary(simdir)) +Output directory: simulation_output +Variables: +- va + average (2.0h) +- ua + average (6.0h) +- orog + inst +- ta + average (3.0h) + max (4.0h, 3.0h) + min (3.0h) +- ts + max (1.0h) +``` +Now, you can access any given variable +``` julia +ta_max = get(simdir; short_name = "t12", reduction = "max", period = "3.0h") +``` +`ta_max` is a ` OutputVar`, a type that contains the variable as +well as some metadata. + +Let us learn about ` OutputVar`s + +### `OutputVar` + +` OutputVar`s contain the raw data (in `.data`), the attributes read from the +file, and the information regarding the dimension over which the variable is +defined. +``` julia-repl +julia> ts_max.dims +OrderedCollections.OrderedDict{String, Vector{Float32}} with 4 entries: + "time" => [10800.0, 21600.0, 32400.0, 43200.0] + "lon" => [-180.0, -177.989, -175.978, -173.966, -171.955, -169.944, -167.933, -165.922… + "lat" => [-80.0, -77.9747, -75.9494, -73.924, -71.8987, -69.8734, -67.8481, -65.8228, … + "z" => [0.0, 5000.0, 10000.0, 15000.0, 20000.0, 25000.0, 30000.0, 35000.0, 40000.0, … +``` +Here we have the dimensions and their values. The dimensions are ordered as in +the file, so that the first index of `.data` is `time`, and so on. + +We can find the attributes of the dimensions in `.attributes`: +``` julia-repl +julia> ts_max.dim_attributes["lon"] + "lon" => Dict("units"=>"degrees_east") +``` + +Given an `OutputVar`, we can perform manipulations. For instance, we can take +the average over latitudes: +``` julia +ts_max_lat_averaged = ClimaAnalysis.average_lat(ts_max) +``` +Now, +``` julia +ts_max_lat_averaged.dims = +OrderedCollections.OrderedDict{String, Vector{Float32}} with 3 entries: + "time" => [10800.0, 21600.0, 32400.0, 43200.0] + "lon" => [-180.0, -177.989, -175.978, -173.966, -171.955, -169.944, -167.933, -165.922… + "z" => [0.0, 5000.0, 10000.0, 15000.0, 20000.0, 25000.0, 30000.0, 35000.0, 40000.0, … +``` +We can also take a time/altitude slice, for example, the plane with altitude closest to 8000 meters. +``` julia +ts_max_lat_averaged_sliced = ClimaAnalysis.slice_z(ts_max_lat_averaged_sliced, 8_000) +``` +Now, +``` julia +ts_max_lat_averaged_sliced.dims = +OrderedCollections.OrderedDict{String, Vector{Float32}} with 2 entries: + "time" => [10800.0, 21600.0, 32400.0, 43200.0] + "lon" => [-180.0, -177.989, -175.978, -173.966, -171.955, -169.944, -167.933, -165.922… +``` + +We can directly visualize these quantities. + +### `Visualize` + +If `CairoMakie` is available, `ClimaAnalysis` can be used for plotting. +Importing `CairoMakie` and `ClimaAnalysis` in the same session automatically +loads the necessary `ClimaAnalysis` plotting modules. + +If we want to make a heatmap for `ta_max` at time of 100 s at altitude `z` of 30000 meters: + +``` julia +import CairoMakie +import ClimaAnalysis: Visualize + +fig = CairoMakie.Figure(resolution = (400, 600)) + +viz.plot!( + fig, + ta_max, + time = 100.0, + z = 30_000.0 +) + +CairoMakie.save("ta_max.png", fig) +``` + +If we want to have a line plot, we can simply add another argument (e.g., `lat = +30`), to slice through that value. + +If you want to customize some of the properties, you can pass the `plot_kwargs` +and `cb_kwargs` fields to the `plot!` function. For instance, to choose the +colormap for the colorbar to viridis + +colormap = :viridis + +``` julia +viz.plot!( + fig, + ta_max, + time = 100.0, + z = 30_000.0, + cb_kwargs = [:colormap => :viridis] +) +``` +Note the `Symbol` in colormap!. `cb_kwargs` has to be a mapping of `Symbol`s and values. `ClimaAnalysis` has a convenience function `kwargs` to more easily pass down the +keyword arguments avoiding this step. With that, the above example becomes +``` julia +import ClimaAnalysis: Utils +viz.plot!( + fig, + ta_max, + time = 100.0, + z = 30_000.0, + plot_kwargs = Utils.kwargs(colormap = :inferno) +) +``` +With `Utils.kwargs`, you can just pass the arguments as you would pass them to the constructor. + + diff --git a/src/OutputVar.jl b/src/OutputVar.jl index 73eb9322..c5494d37 100644 --- a/src/OutputVar.jl +++ b/src/OutputVar.jl @@ -15,6 +15,9 @@ export OutputVar, slice_lon, slice_lat +""" + Representing an output variable +""" struct OutputVar{ T <: AbstractArray, A <: AbstractArray, diff --git a/src/Visualize.jl b/src/Visualize.jl index 35fc6831..0029d94c 100644 --- a/src/Visualize.jl +++ b/src/Visualize.jl @@ -12,8 +12,6 @@ function sliced_line_plot! end function line_plot! end -function sliced_line! end - function sliced_plot! end function plot! end