Skip to content

Commit 4a2face

Browse files
authored
documentation; small fix; addleaf! returns leaf; ready for v0.16.4 (JuliaPhylo#212)
fix: r2 corrected in ftest addleaf! output new leaf node, not net: breaking change, but internal function documentation: - workflow - badges - workshop link - ftest warnings explained - typo fix in doc for slurm
1 parent a4f8086 commit 4a2face

14 files changed

+134
-78
lines changed

.github/workflows/ci.yml

+14-37
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,13 @@ on:
77
push:
88
branches:
99
- master
10-
tags: '*'
10+
tags: ['*']
11+
12+
concurrency:
13+
# Skip intermediate builds: always.
14+
# Cancel intermediate builds: only if it is a pull request build.
15+
group: ${{ github.workflow }}-${{ github.ref }}
16+
cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }}
1117

1218
jobs:
1319
test:
@@ -17,53 +23,24 @@ jobs:
1723
fail-fast: false
1824
matrix:
1925
version:
20-
- '1' # will expand to the latest stable 1.x release of Julia.
26+
- '1'
2127
os:
2228
- ubuntu-latest
2329
- macos-latest
2430
- windows-latest
2531
arch:
2632
- x64
2733
steps:
28-
- uses: actions/checkout@v2
29-
- uses: julia-actions/setup-julia@v1
34+
- uses: actions/checkout@v4
35+
- uses: julia-actions/setup-julia@latest
3036
with:
3137
version: ${{ matrix.version }}
3238
arch: ${{ matrix.arch }}
33-
- uses: actions/cache@v1
34-
env:
35-
cache-name: cache-artifacts
36-
with:
37-
path: ~/.julia/artifacts
38-
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
39-
restore-keys: |
40-
${{ runner.os }}-test-${{ env.cache-name }}-
41-
${{ runner.os }}-test-
42-
${{ runner.os }}-
39+
- uses: julia-actions/cache@v2
4340
- uses: julia-actions/julia-buildpkg@v1
4441
- uses: julia-actions/julia-runtest@v1
4542
- uses: julia-actions/julia-processcoverage@v1
46-
- uses: codecov/codecov-action@v2
47-
with:
48-
file: lcov.info
49-
docs:
50-
name: Documentation
51-
runs-on: ubuntu-latest
52-
steps:
53-
- uses: actions/checkout@v2
54-
- uses: r-lib/actions/setup-r@v2
55-
- run: echo "LD_LIBRARY_PATH=$(R RHOME)/lib" >> $GITHUB_ENV
56-
- uses: julia-actions/setup-julia@v1
43+
- uses: codecov/codecov-action@v4
5744
with:
58-
version: '1'
59-
- name: install dependencies
60-
run: |
61-
julia --project=docs -e '
62-
using Pkg
63-
Pkg.develop(PackageSpec(path=pwd()))
64-
Pkg.instantiate()'
65-
- name: make docs
66-
run: julia --project=docs docs/make.jl
67-
env:
68-
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
69-
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}
45+
files: lcov.info
46+
token: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/doccleanup.yml

+20-15
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,33 @@
1-
name: Doc Preview Cleanup
1+
name: doc preview cleanup
22

33
on:
44
pull_request:
55
types: [closed]
66

7+
# ensure that only one "doc preview cleanup" workflow is force-pushing at a time
8+
concurrency:
9+
group: doc-preview-cleanup
10+
cancel-in-progress: false
11+
712
jobs:
813
doc-preview-cleanup:
914
runs-on: ubuntu-latest
15+
permissions:
16+
contents: write
1017
steps:
11-
- name: Checkout gh-pages branch
12-
uses: actions/checkout@v2
18+
- name: checkout gh-pages branch
19+
uses: actions/checkout@v4
1320
with:
1421
ref: gh-pages
15-
16-
- name: Delete preview and history
22+
- name: delete preview and history + push changes
1723
run: |
18-
git config user.name "Documenter.jl"
19-
git config user.email "[email protected]"
20-
git rm -rf "previews/PR$PRNUM"
21-
git commit -m "delete preview"
22-
git branch gh-pages-new $(echo "delete history" | git commit-tree HEAD^{tree})
24+
if [ -d "${preview_dir}" ]; then
25+
git config user.name "Documenter.jl"
26+
git config user.email "[email protected]"
27+
git rm -rf "${preview_dir}"
28+
git commit -m "delete preview"
29+
git branch gh-pages-new $(echo "delete history" | git commit-tree HEAD^{tree})
30+
git push --force origin gh-pages-new:gh-pages
31+
fi
2332
env:
24-
PRNUM: ${{ github.event.number }}
25-
26-
- name: Push changes
27-
run: |
28-
git push --force origin gh-pages-new:gh-pages
33+
preview_dir: previews/PR${{ github.event.number }}

.github/workflows/documentation.yml

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
name: Documenter
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
tags: '*'
8+
pull_request:
9+
10+
jobs:
11+
Documenter:
12+
name: documentation
13+
permissions:
14+
contents: write
15+
pull-requests: read
16+
statuses: write
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
- uses: r-lib/actions/setup-r@v2
21+
- run: echo "LD_LIBRARY_PATH=$(R RHOME)/lib:$LD_LIBRARY_PATH" >> $GITHUB_ENV
22+
- uses: julia-actions/setup-julia@v2
23+
with:
24+
version: '1'
25+
- uses: julia-actions/cache@v2
26+
- uses: julia-actions/julia-buildpkg@latest
27+
- uses: julia-actions/julia-docdeploy@latest
28+
env:
29+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30+
DOCUMENTER_KEY: ${{ secrets.DOCUMENTER_KEY }}

Project.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PhyloNetworks"
22
uuid = "33ad39ac-ed31-50eb-9b15-43d0656eaa72"
33
license = "MIT"
4-
version = "0.16.3"
4+
version = "0.16.4"
55

66
[deps]
77
BioSequences = "7e6ae17a-c86d-528c-b3b9-7f778a29fe59"

README.md

+10-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
# PhyloNetworks: analysis for phylogenetic networks <img src="docs/src/logo_text.png" align=right>
22

3+
[![doc stable](https://img.shields.io/badge/docs-stable-blue.svg)](https://crsl4.github.io/PhyloNetworks.jl/stable)
4+
[![doc dev](https://img.shields.io/badge/docs-dev-blue.svg)](https://crsl4.github.io/PhyloNetworks.jl/dev)
35
[![Build status](https://github.com/crsl4/PhyloNetworks.jl/workflows/CI/badge.svg?branch=master)](https://github.com/crsl4/PhyloNetworks.jl/actions/workflows/ci.yml)
4-
[![](https://img.shields.io/badge/docs-stable-blue.svg)](https://crsl4.github.io/PhyloNetworks.jl/stable)
5-
[![](https://img.shields.io/badge/docs-dev-blue.svg)](https://crsl4.github.io/PhyloNetworks.jl/dev)
6-
[![codecov](https://codecov.io/gh/crsl4/PhyloNetworks.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/crsl4/PhyloNetworks.jl)
6+
[![coverage](https://codecov.io/gh/crsl4/PhyloNetworks.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/crsl4/PhyloNetworks.jl)
7+
[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-4495d1.svg)](https://github.com/invenia/BlueStyle)
8+
[![ColPrac: Contributor's Guide on Collaborative Practices for Community Packages](https://img.shields.io/badge/ColPrac-Contributor's%20Guide-blueviolet)](https://github.com/SciML/ColPrac)
9+
[![PkgEval](https://JuliaCI.github.io/NanosoldierReports/pkgeval_badges/P/PhyloNetworks.svg)](https://JuliaCI.github.io/NanosoldierReports/pkgeval_badges/report.html)
710

811
## Overview
912

@@ -18,7 +21,7 @@ PhyloNetworks is a [Julia](http://julialang.org) package with utilities to:
1821
(Robinson-Foulds distance on trees)
1922
- summarize samples of bootstrap networks (or trees)
2023
with edge and node support
21-
- estimate species networks from multilocus data (see below)
24+
- estimate species networks from multilocus data: SNaQ
2225
- phylogenetic comparative methods for continuous trait evolution
2326
on species networks / trees
2427
- plot networks (and trees), via the companion package
@@ -28,7 +31,9 @@ To get help, check
2831

2932
- the [latest documentation](https://crsl4.github.io/PhyloNetworks.jl/dev)
3033
- the [wiki](https://github.com/crsl4/PhyloNetworks.jl/wiki) for a step-by-step tutorial
31-
(July 2018) with background on networks
34+
with background on networks (last revised 2022)
35+
- [tutorial](https://cecileane.github.io/networkPCM-workshop/) for
36+
comparative methods, including network calibration (2023 workshop)
3237
- the [google group](https://groups.google.com/forum/#!forum/phylonetworks-users)
3338
for common questions. Join the group to post/email your questions,
3439
or to receive information on new versions, bugs fixed, etc.

docs/make.jl

+6-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ makedocs(
1313
modules = [PhyloNetworks], # to list methods from PhyloNetworks only, not from Base etc.
1414
format = Documenter.HTML(
1515
prettyurls = get(ENV, "CI", nothing) == "true", # easier local build
16-
size_threshold = 600 * 2^10, size_threshold_warn = 500 * 2^10), # 600 KiB
16+
size_threshold = 600 * 2^10,
17+
size_threshold_warn = 500 * 2^10, # 600 KiB
18+
canonical="https://crsl4.github.io/PhyloNetworks.jl/stable/",
19+
edit_link="master",
20+
),
1721
# exception, so warning-only for :missing_docs. List all others:
1822
warnonly = Documenter.except(:autodocs_block, :cross_references, :docs_block,
1923
:doctest, :eval_block, :example_block, :footnote, :linkcheck_remotes,
@@ -46,4 +50,5 @@ makedocs(
4650
deploydocs(
4751
repo = "github.com/crsl4/PhyloNetworks.jl.git",
4852
push_preview = true,
53+
devbranch = "master",
4954
)

docs/readme.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
# notes to maintain documentation
22

3-
- built with [Documenter](https://juliadocs.github.io/Documenter.jl).
3+
- built with [Documenter](https://documenter.juliadocs.org/stable/).
44
- deployed [here](https://crsl4.github.io/PhyloNetworks.jl/)
55
(go to `dev/` or `stable/`)
66
using GitHub and files committed to the `gh-pages` branch.
77

88
## how it works: overview
99

10-
- `.github/workflows/ci.yml` asks to start the doc project
10+
- `.github/workflows/documentation.yml` asks to start the doc project
1111
(installs R and dependencies like `PhyloPlots` & `Documenter`) and
1212
run `./docs/make.jl` after a successful test & build.
1313
- the julia script `docs/make.jl` has these steps:

docs/src/index.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,10 @@ and their use for trait evolution.
1010
**How to get help**
1111

1212
- the package [wiki](https://github.com/crsl4/PhyloNetworks.jl/wiki) has a step-by-step
13-
tutorial, done for the 2019 MBL workshop, with background on networks and
13+
tutorial, done for the MBL workshop (last revised 2022), with background on networks and
1414
explanations.
15+
- [tutorial](https://cecileane.github.io/networkPCM-workshop/) for
16+
comparative methods, including network calibration (2023 workshop)
1517
- the [google group](https://groups.google.com/forum/#!forum/phylonetworks-users)
1618
has answers to common questions.
1719
- the [Manual](@ref) below has a quick tutorial (navigation on the left).

docs/src/man/netmanipulation.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,10 @@ To modify a network, for example:
3636
[`deleteaboveLSA!`](@ref) (the "least stable ancestor" may be different from the root)
3737
- [`deleteHybridThreshold!`](@ref) to simplify a network by deleting edges with small γ's
3838
- [`removedegree2nodes!`](@ref), [`shrink3cycles!`](@ref), [`shrink2cycles!`](@ref),
39-
[`PhyloNetworks.shrinkedge!`](@ref)]
39+
[`PhyloNetworks.shrinkedge!`](@ref)
4040
- [`PhyloNetworks.addleaf!`](@ref),
41-
[`PhyloNetworks.deletehybridedge!`](@ref), [`PhyloNetworks.addhybridedge!`](@ref)
41+
[`PhyloNetworks.deletehybridedge!`](@ref),
42+
[`PhyloNetworks.addhybridedge!`](@ref)
4243
- [`nni!`](@ref) (nearest neighbor interchange),
4344
[`PhyloNetworks.fliphybrid!`](@ref) to flip the direction of a hybrid edge
4445
- [`PhyloNetworks.unzip_canonical!`](@ref) to "unzip" (or zip down) all

docs/src/man/snaq_plot.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ Then log out of the cluster and go for coffee.
261261
echo "slurm task ID = $SLURM_ARRAY_TASK_ID used as hmax"
262262
echo "start of SNaQ parallel runs on $(hostname)"
263263
# finally: launch the julia script, using Julia executable appropriate for slurm, with full paths:
264-
/workspace/software/bin/julia --history-file=no -- runSNaQ.jl $SLURM_ARRAY_TASK_ID 30 > net$SLURM_ARRAY_TASK_ID_30runs.screenlog 2>&1
264+
/workspace/software/bin/julia --history-file=no -- runSNaQ.jl $SLURM_ARRAY_TASK_ID 30 > net${SLURM_ARRAY_TASK_ID}_30runs.screenlog 2>&1
265265
echo "end of SNaQ run ..."
266266
```
267267

docs/src/man/trait_tree.md

+15-1
Original file line numberDiff line numberDiff line change
@@ -508,10 +508,24 @@ complex cases, it is possible to do a Fisher F test, thanks to the `GLM`
508508
function `ftest`.
509509
```@example tree_trait
510510
fit_null = phylolm(@formula(trait ~ 1), dat, truenet) # fit against the null (no shift)
511-
ftest(fit_sh, fit_null) # nested models
511+
ftest(fit_null, fit_sh) # nested models
512512
```
513513
Here, this test is equivalent to the Fisher F test, and gives the same p-value.
514514

515+
!!! note "Warnings from GLM"
516+
A warning may appear, saying
517+
"Starting from GLM.jl 1.8, null model is defined as having no predictor at all when a model without an intercept is passed."
518+
- Why? `ftest` is inherited from the GLM package, which does not know that
519+
the intercept term is not a column of ones after transformation to remove
520+
the phylogenetic correlation. This is why `ftest` sends a warning for
521+
each model, when multiple models are compared.
522+
- These specific warnings can be ignored:
523+
* F values and p-values are correct
524+
* R² values are also correct: they are obtained with the
525+
`r2` function for phylogenetic linear models.
526+
A future version of the package will attempt to remove these warnings
527+
specifically.
528+
515529
Note that models need to be ordered by complexity, when given to `ftest`:
516530
either from most complex to most simple, or from most simple to most complex.
517531
In the output table, models are listed in the order in which they were given.

src/manipulateNet.jl

+5-4
Original file line numberDiff line numberDiff line change
@@ -567,6 +567,8 @@ Add a new external edge between `node` or between the "middle" of `edge`
567567
and a newly-created leaf, of name `leafname`.
568568
By default, the new edge length is missing (-1).
569569
570+
output: newly created leaf node.
571+
570572
# examples
571573
572574
```jldoctest
@@ -616,13 +618,12 @@ function addleaf!(net::HybridNetwork, speciesnode::Node, leafname::String, edgel
616618
net.numTaxa -= 1
617619
end
618620
pushNode!(net, newleaf) # push node into network (see auxillary.jl)
619-
return net
621+
return newleaf
620622
end
621623

622624
function addleaf!(net::HybridNetwork, startingedge::Edge, leafname::String, edgelength::Float64=-1.0)
623-
newnode, newedge = breakedge!(startingedge, net)
624-
addleaf!(net, newnode, leafname, edgelength)
625-
return net
625+
newnode, _ = breakedge!(startingedge, net)
626+
return addleaf!(net, newnode, leafname, edgelength)
626627
end
627628

628629

src/traits.jl

+16-2
Original file line numberDiff line numberDiff line change
@@ -3019,14 +3019,28 @@ isnested(::Union{PagelLambda,ScalingHybrid}, ::BM) = false
30193019
isnested(::ScalingHybrid,::PagelLambda) = false
30203020
isnested(::PagelLambda,::ScalingHybrid) = false
30213021

3022-
## ANOVA using ftest from GLM - need version 0.8.1
3022+
#= ANOVA using ftest from GLM - need version 0.8.1
3023+
As of GLM v1.8, ftest throws a warning on typical BM models, one per model:
3024+
"Starting from GLM.jl 1.8, null model is defined as having no predictor at all when a model without an intercept is passed."
3025+
This is because after transforming the data to de-correlate the residuals,
3026+
the transformed intercept vector is not proportional to the constant vector 1.
3027+
The warning is from: ftest → r2(phylomodel.lm) → nulldeviance(phylomodel.lm) → warning.
3028+
R² by GLM is wrong: assume *no* intercept, and are based on the transformed data.
3029+
R² corrected them below: r2(phylomodel) reimplemented here.
3030+
But nulldeviance(phylomodel) does *not* call nulldeviance(phylomodel.lm),
3031+
instead re-implemented here to use the intercept properly.
3032+
Keep the warnings: unless they can be suppressed with specificity
3033+
Ideally: modify `ftest` here or in GLM.
3034+
=#
30233035
function GLM.ftest(objs::PhyloNetworkLinearModel...)
30243036
if !all( isa(o.evomodel,BM) && isnothing(o.model_within) for o in objs)
30253037
throw(ArgumentError("""F test is only valid for the vanilla BM model.
30263038
Use a likelihood ratio test instead with function `lrtest`."""))
30273039
end
30283040
objslm = [obj.lm for obj in objs]
3029-
return ftest(objslm...)
3041+
resGLM = ftest(objslm...)
3042+
resGLM.r2 = r2.(objs)
3043+
return resGLM
30303044
end
30313045
## ANOVA: old version - kept for tests purposes - do not export
30323046
"""

test/test_lm.jl

+8-6
Original file line numberDiff line numberDiff line change
@@ -210,19 +210,21 @@ modnull = phylolm(@formula(trait ~ 1), dfr, net)
210210
@test sigma2_phylo(modnull) 0.6517876326943942 atol=1e-6 # using REML
211211
modhom = phylolm(@formula(trait ~ sum), dfr, net)
212212
modhet = phylolm(@formula(trait ~ sum + shift_8), dfr, net)
213-
table1 = ftest(modhet, modhom, modnull)
213+
#= 3 warnings thrown by ftest, one for each model, because after transforming the
214+
data to de-correlate the results, the intercept vector is not ∝ 1.
215+
Keep the warnings: because incorrect R² values in the ftest output
216+
=#
217+
table1 = redirect_stdio(stderr=devnull) do # to avoid seeing the warnings
218+
ftest(modhet, modhom, modnull)
219+
end
214220
table2 = PhyloNetworks.anova(modnull, modhom, modhet)
215221

216222
@test table1.fstat[2] table2[2,:F]
217223
@test table1.fstat[3] table2[1,:F]
218224
@test table1.pval[2] table2[2,Symbol("Pr(>F)")]
219225
@test table1.pval[3] table2[1,Symbol("Pr(>F)")]
220226
@test hasintercept(modnull) && hasintercept(modhom) && hasintercept(modhet)
221-
# ## Replace next 4 lines with previous ones when GLM.ftest available
222-
# @test table1[:F][2] ≈ table2[:F][2]
223-
# @test table1[:F][1] ≈ table2[:F][1]
224-
# @test table1[Symbol("Pr(>F)")][1] ≈ table2[Symbol("Pr(>F)")][1]
225-
# @test table1[Symbol("Pr(>F)")][2] ≈ table2[Symbol("Pr(>F)")][2]
227+
@test all(isapprox.(table1.r2, (0.8398130376214782, 0.006032952123011026, 0), atol=1e-15))
226228

227229
# Check that it is the same as doing shift_8 + shift_17
228230
modhetbis = phylolm(@formula(trait ~ shift_8 + shift_17), dfr, net)

0 commit comments

Comments
 (0)