From 919087d468f4b22629449620864e4369b7751fb2 Mon Sep 17 00:00:00 2001 From: Phillip Alday Date: Thu, 13 May 2021 18:32:36 +0000 Subject: [PATCH] Compatibility updates and online documentation (#9) * add documentation + GH workflows * MixedModels 3.x compat * online documentation and examples * remove shrinkage2d from docs * sample plot tweaks * run CI on main * the null test * compat bounds * workflow lint * update readme --- .github/workflows/ci.yml | 59 +++++++++++++++++++++++++ .github/workflows/documenter.yml | 22 ++++++++++ Project.toml | 4 +- README.md | 19 ++++++++ docs/Project.toml | 9 ++++ docs/make.jl | 15 +++++++ docs/src/api.md | 74 ++++++++++++++++++++++++++++++++ docs/src/examples.md | 0 docs/src/index.md | 18 ++++++++ src/MixedModelsMakie.jl | 1 + src/caterpillar.jl | 9 ++-- src/shrinkage.jl | 13 ++++-- test/runtests.jl | 4 +- 13 files changed, 237 insertions(+), 10 deletions(-) create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/documenter.yml create mode 100644 docs/Project.toml create mode 100644 docs/make.jl create mode 100644 docs/src/api.md create mode 100644 docs/src/examples.md create mode 100644 docs/src/index.md diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..51f743f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,59 @@ +name: continuous-integration +on: + push: + branches: + - master + - main + paths-ignore: + - 'LICENSE.md' + - 'README.md' + - 'examples/**' + pull_request: + branches: + - master + - main + paths-ignore: + - 'LICENSE.md' + - 'README.md' + - 'examples/**' +jobs: + ci: + runs-on: ${{ matrix.os }} + strategy: + matrix: + version: [1.5, 1] + arch: [x64] + os: [ubuntu-18.04] # macos-10.15, windows-2019 + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Julia Setup + uses: julia-actions/setup-julia@v1 + with: + version: ${{ matrix.version }} + arch: ${{ matrix.arch }} + - name: Cache + uses: actions/cache@v1 + env: + cache-name: cache-artifacts + with: + path: ~/.julia/artifacts + key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }} + restore-keys: | + ${{ runner.os }}-test-${{ env.cache-name }}- + ${{ runner.os }}-test- + ${{ runner.os }}- + - name: Build + uses: julia-actions/julia-buildpkg@v1 + - name: Test + uses: julia-actions/julia-runtest@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Coverage Process + uses: julia-actions/julia-processcoverage@v1 + if: ${{ startsWith(matrix.os, 'ubuntu') && (matrix.version == '1') }} + - name: Coverage Upload + uses: codecov/codecov-action@v1 + if: ${{ startsWith(matrix.os, 'ubuntu') && (matrix.version == '1') }} + with: + file: lcov.info diff --git a/.github/workflows/documenter.yml b/.github/workflows/documenter.yml new file mode 100644 index 0000000..648da4d --- /dev/null +++ b/.github/workflows/documenter.yml @@ -0,0 +1,22 @@ +name: Documenter +on: + push: + branches: + - master + - main + tags: [v*] + pull_request: + branches: + - master + - main +jobs: + Documenter: + name: Documentation + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: julia-actions/julia-buildpkg@latest + - uses: julia-actions/julia-docdeploy@latest + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }} diff --git a/Project.toml b/Project.toml index 1810d81..6da97fd 100644 --- a/Project.toml +++ b/Project.toml @@ -11,8 +11,8 @@ MixedModels = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316" [compat] AbstractPlotting = "0.18" -DataFrames = "1.1" -MixedModels = "3.6,4" +DataFrames = "1" +MixedModels = "3.6, 4" julia = "1.5" [extras] diff --git a/README.md b/README.md index b087196..a08dc17 100644 --- a/README.md +++ b/README.md @@ -1 +1,20 @@ # MixedModelsMakie + +[![Project Status: WIP – Initial development is in progress, but there has not yet been a stable, usable release suitable for the public.](https://www.repostatus.org/badges/latest/wip.svg)](https://www.repostatus.org/#wip) +[![Stable Docs][docs-stable-img]][docs-stable-url] +[![Dev Docs][docs-dev-img]][docs-dev-url] +[![Codecov](https://codecov.io/gh/palday/MixedModelsMakie.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/palday/MixedModelsMakie.jl) + +[docs-dev-img]: https://img.shields.io/badge/docs-dev-blue.svg +[docs-dev-url]: https://palday.github.io/MixedModelsMakie.jl/dev + +[docs-stable-img]: https://img.shields.io/badge/docs-stable-blue.svg +[docs-stable-url]: https://palday.github.io/MixedModelsMakie.jl/stable + +`MixedModelsMakie.jl` is a Julia package providing plotting capabilities for models fit with [MixedModels.jl](https://juliastats.org/MixedModels.jl/stable/). +Plotting is performed using the [Makie ecoysystem](https://makie.juliaplots.org/stable/), with the interface defined using `AbstractPlotting.jl` for compatibility across all Makie backends. + +Note that the functionality here is currently early alpha development and so breaking changes are expected as we refine the interface. +Following [SemVer](https://semver.org/), these minor releases before 1.0 can introduce these breaking changes. +The release of 1.0 will be indication that we believe the interface is reasonably stable. +Minor refinements of graphical displays without changing the API are considered non-breaking. diff --git a/docs/Project.toml b/docs/Project.toml new file mode 100644 index 0000000..0ec1390 --- /dev/null +++ b/docs/Project.toml @@ -0,0 +1,9 @@ +[deps] +CairoMakie = "13f3f980-e62b-5c42-98c6-ff1f3baf88f0" +Documenter = "e30172f5-a6a5-5a46-863b-614d45cd2de4" +MixedModels = "ff71e718-51f3-5ec2-a782-8ffcbfa3c316" +MixedModelsMakie = "b12ae82c-6730-437f-aff9-d2c38332a376" + +[compat] +CairoMakie = "0.4.7" +Documenter = "0.26" diff --git a/docs/make.jl b/docs/make.jl new file mode 100644 index 0000000..80cfd49 --- /dev/null +++ b/docs/make.jl @@ -0,0 +1,15 @@ +using Documenter +using MixedModelsMakie + +makedocs(; + root = joinpath(dirname(pathof(MixedModelsMakie)), "..", "docs"), + sitename = "MixedModelsMakie", + doctest = true, + checkdocs = :exports, + pages = [ + "index.md", + "api.md", + ], +) + +deploydocs(repo = "github.com/palday/MixedModelsMakie.jl.git", push_preview = true) diff --git a/docs/src/api.md b/docs/src/api.md new file mode 100644 index 0000000..b8707d1 --- /dev/null +++ b/docs/src/api.md @@ -0,0 +1,74 @@ +```@meta +CurrentModule = MixedModelsMakie +DocTestSetup = quote + using MixedModelsMakie +end +DocTestFilters = [r"([a-z]*) => \1", r"getfield\(.*##[0-9]+#[0-9]+"] +``` + +# MixedModelsMakie.jl API + +## Caterpillar Plots + +```@docs +RanefInfo +``` + +```@docs +ranefinfo +``` + +```@docs +caterpillar +``` + +```@docs +caterpillar! +``` + +```@example Caterpillar +using CairoMakie +CairoMakie.activate!(type = "svg") +using MixedModels +using MixedModelsMakie +sleepstudy = MixedModels.dataset(:sleepstudy) + +fm1 = fit(MixedModel, @formula(reaction ~ 1 + days + (1 + days|subj)), sleepstudy) +subjre = ranefinfo(fm1)[:subj] + +caterpillar!(Figure(; resolution=(800,600)), subjre) +``` + +```@example Caterpillar +caterpillar!(Figure(; resolution=(800,600)), subjre; orderby=2) +``` + +## Shrinkage Plots + +```@docs +CoefByGroup +``` + +```@docs +shrinkage +``` + +```@docs +shrinkageplot +``` + +```@docs +shrinkageplot! +``` + +```@example Shrinkage +using CairoMakie +using MixedModels +using MixedModelsMakie +sleepstudy = MixedModels.dataset(:sleepstudy) + +fm1 = fit(MixedModel, @formula(reaction ~ 1 + days + (1 + days|subj)), sleepstudy) +shrink = shrinkage(fm1)[:subj] + +shrinkageplot!(Figure(; resolution=(800,600)), shrink) +``` diff --git a/docs/src/examples.md b/docs/src/examples.md new file mode 100644 index 0000000..e69de29 diff --git a/docs/src/index.md b/docs/src/index.md new file mode 100644 index 0000000..814f3b7 --- /dev/null +++ b/docs/src/index.md @@ -0,0 +1,18 @@ +# MixedModelsMakie.jl Documentation + +```@meta +CurrentModule = MixedModelsMakie +``` + +*MixedModelsMakie.jl* is a Julia package providing plotting capabilities for models fit with [MixedModels.jl](https://juliastats.org/MixedModels.jl/stable/). + +Note that the functionality here is currently early alpha development and so breaking changes are expected as we refine the interface. +Following [SemVer](https://semver.org/), these minor releases before 1.0 can introduce these breaking changes. +The release of 1.0 will be indication that we believe the interface is reasonably stable. + +```@contents +Pages = [ + "api.md", +] +Depth = 1 +``` diff --git a/src/MixedModelsMakie.jl b/src/MixedModelsMakie.jl index cc1f010..6881962 100644 --- a/src/MixedModelsMakie.jl +++ b/src/MixedModelsMakie.jl @@ -13,6 +13,7 @@ module MixedModelsMakie ranefinfo, shrinkage, shrinkageplot, + shrinkageplot!, simplelinreg include("shrinkage.jl") diff --git a/src/caterpillar.jl b/src/caterpillar.jl index 8272050..0235ae7 100644 --- a/src/caterpillar.jl +++ b/src/caterpillar.jl @@ -3,7 +3,10 @@ Information on random effects conditional modes/means, variances, etc. -Used for creating caterpillar plots +Used for creating caterpillar plots. + +!!! note + This functionality may be moved upstream into MixedModels.jl in the near future. """ struct RanefInfo{T<:AbstractFloat} cnames::Vector{String} @@ -22,7 +25,7 @@ function ranefinfo(m::LinearMixedModel{T}) where {T} val = sizehint!(RanefInfo[], length(fn)) for (re, eff, cv) in zip(m.reterms, ranef(m), condVar(m)) push!( - val, + val, RanefInfo( re.cnames, re.levels, @@ -72,4 +75,4 @@ of the random effects. """ function caterpillar(m::LinearMixedModel, gf::Symbol=first(fnames(m))) caterpillar!(Figure(resolution=(1000,800)), ranefinfo(m)[gf]) -end \ No newline at end of file +end diff --git a/src/shrinkage.jl b/src/shrinkage.jl index 44a91df..bac1cfb 100644 --- a/src/shrinkage.jl +++ b/src/shrinkage.jl @@ -9,6 +9,9 @@ Fields include: - `fixed`: `AbstractVector{T}` of the global OLS estimates for the coefficients in `cnames` only. - `condmodes`: `AbstractMatrix{T}` of size `length(levels) x length(cnames)` of the conditional means/modes for the random effects - `grpest`: similar to `condmodes` but allowing for `Missing` values, giving the within group OLS estimates of the coefficients. + +!!! note + This functionality may be moved upstream into MixedModels.jl in the near future. """ struct CoefByGroup{T<:AbstractFloat} cnames::Vector{String} @@ -24,14 +27,18 @@ end Return a `NamedTuple{fnames(m), NTuple(k, CoefByGroup)}` of the coefficients by group for the grouping factors """ function shrinkage(m::LinearMixedModel{T}) where {T} - fenms = m.feterm.cnames - yvec = view(m.Xymat, :, size(m.Xymat, 2)) + # should this be fixefnames or coefnames? + # need to think about when pivoting is occuring + fenms = fixefnames(m) + # returns a view from Xymat in MM4, or just the response vec in MM3.x + yvec = response(m) ranefs = ranef(m) cvec = sizehint!(CoefByGroup[], length(ranefs)) for (j, re) in enumerate(m.reterms) cnms = re.cnames cnms ⊆ fenms || throw(ArgumentError("No corresponding fixed effect for random effects $(setdiff(cnms, fenms)): there is no estimated grand mean to measure shrinkage towards")) - Xmat = view(m.Xymat, :, [findfirst(==(nm), fenms) for nm in cnms]) + # XXX Should m.X return a view into m.Xymat? + Xmat = view(m.X, :, [findfirst(==(nm), fenms) for nm in cnms]) levs = re.levels refs = re.refs grpest = Matrix{Union{Missing,T}}(missing, (length(levs), length(cnms))) diff --git a/test/runtests.jl b/test/runtests.jl index a30c259..2d72d36 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -1,6 +1,6 @@ using MixedModelsMakie using Test -@testset "MixedModelsMakie.jl" begin - # Write your tests here. +@testset "There are no tests" begin + @test true end