R Observatory
Search
install.packages("lotri")
CRAN 30-day downloads, method
2,560+0.99% up on the 30 days before, the better direction

Provides a simple mechanism to specify a symmetric block diagonal matrices (often used for covariance matrices). This is based on the domain specific language implemented in 'nlmixr2' but expanded to create matrices in R generally instead of specifying parts of matrices to estimate.

Full description

Provides a simple mechanism to specify a symmetric block diagonal matrices (often used for covariance matrices). This is based on the domain specific language implemented in 'nlmixr2' but expanded to create matrices in R generally instead of specifying parts of matrices to estimate. It has expanded to include some matrix manipulation functions that are generally useful for 'rxode2' and 'nlmixr2'.

Maintainer
Matthew L. Fidler
Licence
GPL (>= 2)
Latest release
11 Sep 2026
First release
14 May 2019

Compare with another package

More details
Releases
14
Needs compilation
Yes
Needs R
>= 3.4.0
Config/roxygen2/version
8.1.0
Config/testthat/edition
3
Language
en-US
Subjects (1) Method, Subjects
Cite

Package

Run in R for the authors' preferred citation:

citation("lotri")
APA
Fidler, M. L., Denney, B., & Vargas Sepulveda, M. (2026). lotri: A Simple Way to Specify Symmetric, Block Diagonal Matrices (Version 1.0.5) [Computer software]. https://doi.org/10.32614/CRAN.package.lotri
About

This package has no citation file, so citation() returns this entry built from DESCRIPTION.

R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

APA
Balamuta, J. J. (2026). R Observatory: Metrics for lotri version 1.0.5 [Data set]. HJJB, LLC. Data release v2026-10-26. https://doi.org/10.5281/zenodo.21843040
About

From data release v2026-10-26, which the citation names so these numbers can be found later.

All 13 check platforms pass.

  • r-devel-linux-x86_64-debian-clang

    The unreleased R on Linux, x86_64, debian-clang

    OK

    Version checked
    1.0.5
    Time taken
    121 s
  • r-devel-linux-x86_64-debian-gcc

    The unreleased R on Linux, x86_64, debian-gcc

    OK

    Version checked
    1.0.5
    Time taken
    88 s
  • r-devel-linux-x86_64-fedora-clang

    The unreleased R on Linux, x86_64, fedora-clang

    OK

    Version checked
    1.0.5
    Time taken
    80 s
  • r-devel-linux-x86_64-fedora-gcc

    The unreleased R on Linux, x86_64, fedora-gcc

    OK

    Version checked
    1.0.5
    Time taken
    87 s
  • r-devel-windows-x86_64

    The unreleased R on Windows, x86_64

    OK

    Version checked
    1.0.5
    Time taken
    273 s
  • r-oldrel-macos-arm64

    The previous release of R on macOS, arm64

    OK

    Version checked
    1.0.5
    Time taken
    33 s
  • r-oldrel-macos-x86_64

    The previous release of R on macOS, x86_64

    OK

    Version checked
    1.0.5
    Time taken
    130 s
  • r-oldrel-windows-x86_64

    The previous release of R on Windows, x86_64

    OK

    Version checked
    1.0.5
    Time taken
    184 s
  • r-patched-linux-x86_64

    The patched release of R on Linux, x86_64

    OK

    Version checked
    1.0.5
    Time taken
    108 s
  • r-release-linux-x86_64

    The current release of R on Linux, x86_64

    OK

    Version checked
    1.0.5
    Time taken
    106 s
  • r-release-macos-arm64

    The current release of R on macOS, arm64

    OK

    Version checked
    1.0.5
    Time taken
    39 s
  • r-release-macos-x86_64

    The current release of R on macOS, x86_64

    OK

    Version checked
    1.0.5
    Time taken
    131 s
  • r-release-windows-x86_64

    The current release of R on Windows, x86_64

    OK

    Version checked
    1.0.5
    Time taken
    155 s
  • 13 OK

Over time

No change since 17 Sep 2026

As a list (3)
ChangedWorst statusOKNotesWarningsErrors
17 Sep 2026OK13000
16 Jul 2026Note11200
10 Mar 2026OK14000

Since March 2026

Check results on CRAN

Total downloads in the last 30 days
5,166+21.9% up on the 30 days before, the better directionIt is the sum of 5 channels: CRAN, r2u, autoCRAN, conda-forge and c2d4u.

CRAN rank

2,261 of 26,529

CRAN

2,560 downloads in the last 30 days

Rank
2,261 of 26,529
Change
+0.99% up on the 30 days before, the better direction

It is in the total. Take it out

r2u

226 downloads in the last 30 days

Rank
1,617 of 30,526
Change
+96.5% up on the 30 days before, the better direction

It is in the total. Take it out

autoCRAN

6 downloads in the last 30 days

Rank
7,678 of 29,130
Change
−66.7% down on the 30 days before, the worse direction

It is in the total. Take it out

conda-forge

2,369 downloads in the last 30 days

Rank
642 of 3,828
Change
+51.8% up on the 30 days before, the better direction

It is in the total. Take it out

c2d4u, no longer updated

5 downloads in the last 30 days

Rank
3,123 of 7,575
Change
−50% down on the 30 days before, the worse direction

It is in the total. Take it out

Over time

Compare downloads

Needs
7
Dependent packages
8
Suggested by
2
Needs (7)
Installing it adds
5 packages, 1.5 MB of source
Of those, need compilation
2
Optional extras (7)
Dependent packages (8)
PackageTitleDownloads in 30 days
rxode2Facilities for Simulating from ODE-Based Models3,706
nlmixr2estNonlinear Mixed Effects Models in Population PK/PD, Estimation Routines2,351
nlmixr2extraNonlinear Mixed Effects Models in Population PK/PD, Extra Support Functions1,750
nlmixr2Nonlinear Mixed Effects Models in Population PK/PD1,602
nonmem2rxConverts 'NONMEM' Models to 'rxode2'1,030
babelmixr2Use 'nlmixr2' to Interact with Open Source and Commercial Software815
monolix2rxConverts 'Monolix' Models to 'rxode2'461
nlmixr2scmStepwise Covariate Modeling for 'nlmixr2' Models413
Functions
187
Public exports
17
Lines of R code
6,310
Median complexity
4
Functions (187)
Size and composition

Lines by kind (18,543)

KindLinesShare
R code6,31034%
Tests8,38845%
Documentation9235%
Guides1,0596%
Compiled code1,86310%

Lines by language

LanguageLinesShare
R14,56479%
C1,5108%
Vignettes1,0596%
Rd9235%
C++3532%
Markdown1340.7%

Languages are counted from file extensions.

Files
107
R functions
137
Compiled functions
50
Object systems
S3: 11 methods
Complexity
Median
4
Mean
7.54
Highest
66
Median lines per function
14
About complexity

Cyclomatic complexity counts the independent paths through a function: 1 is a straight line, higher is harder to test. R functions only.

Call graph figures
R functions
137
Calls
208
Unconnected
13
Groups
2
Growth (14 releases)
Total lines by release
430 on 14 May 201918,543 on 11 Sep 2026
Release changes

The package could not be built for the coverage run.

Test cases
293
Lines of tests
8,388
Exports named in tests
94.1%
Test suite
Has tests
Yes
Test frameworks
testthat
Test cases
293
Snapshot tests
4
Test lines per line of code
1.33
Exports documented
100%
Arguments documented
98.3%
Return value documented
92.9%
Help pages with examples
85.7%
Examples run in checks
100%
Guides (3)
Other documentation
README
Yes, 1,342 words
Release notes file
Yes
Help pages
14
Lines of documentation
923

nlmixr2 / lotri on github.com

Stars
7
Forks
3
Open issues
5
Last commit
11 Sep 2026
Activity
Commits
490
Open pull requests
4
Tagged releases
9
Latest tagged release
v1.0.5, 11 Sep 2026
Issues closed in
2 days (median)
Pull requests closed in
0 days (median)
Pull requests merged
92%
Created
1 Dec 2021
Licence file reads as
–
Development practices (10)
KindFound
Continuous integrationGitHub Actions, R CMD check workflow
The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel
Docs sourceREADME.Rmd, pkgdown
GitHub Pages site last deployed 2026-09-11
The repository has a site deploy workflow
pkgdown site last built 2026-09-11
CoverageCoverage reporting (Codecov)
CRAN release processcran-comments.md, CRAN-SUBMISSION
Lint, format, editorlintr

Method, repository practices

Across nlmixr2

Claude Codeat least 5 crediting itClaude CodeFirst seen 2 Apr 2026at least 5 crediting it
Claude Opus 4.8Claude Opus 4.815 Jun 20262 commits
Claude Sonnet 4.6Claude Sonnet 4.62 Apr 20263 commits
GitHub Copilot1 commit by itGitHub CopilotFirst seen 3 Apr 20261 commit by it
AntigravityAntigravityFirst seen 13 May 2026

Tools

ToolFirst seenFoundCommits by itCommits crediting it
Claude Code2 Apr 2026Seen in the repositoryCLAUDE.mdNamed in .Rbuildignore.claudeCLAUDE.mdPull request it wrote: opened by a project member5 at least
GitHub Copilot3 Apr 20261
Antigravity13 May 2026Named in .Rbuildignore.antigravity
  • Seen in the repository
  • Named in .Rbuildignore
  • Pull request

Models

ModelCommitsFirst commitLast commitCredit lines of
Claude Opus 4.8215 Jun 202615 Jun 2026Claude Code
Claude Sonnet 4.632 Apr 20262 Apr 2026Claude Code

Across nlmixr2

R releases
  • On CRAN
  • Facing archival
  • Release
VersionReleasedREvents
1.0.5 current11 Sep 20264.6.1Fix due 11 Sep 2026
The checks were fixed and the deadline was lifted.
1.0.414 May 20264.6.0
1.0.311 Mar 20264.5.3
1.0.229 Aug 20254.5.1
1.0.118 Jul 20254.5.1
1.0.018 Sep 20244.4.1
0.4.320 Mar 20234.2.3
0.4.218 Jun 20224.2.0
Earlier versions (6)
VersionReleasedR
0.4.121 Apr 20224.1.3
0.4.015 Apr 20224.1.3
0.3.15 Jan 20214.0.3
0.2.229 May 20204.0.0
0.2.112 Feb 20203.6.2
0.1.114 May 20193.6.0
Release notes (1.0.5)

New features

  • A block can now be repeated with same(), which is NONMEM's $OMEGA BLOCK(n) SAME:

```r

lotri({

iov.cl1 + iov.v1 ~ c(0.1,

0.01, 0.2)

iov.cl2 + iov.v2 ~ same()

iov.cl3 + iov.v3 ~ same()

})

```

This is one estimated 2x2 covariance shared by three blocks, which is

how inter-occasion variability is parameterized when every occasion

draws its own random effects from one shared covariance -- and it is

what lets those random effects be *correlated*.

same() repeats the immediately preceding block under new names and

takes no arguments. A further same() repeats that same original

block rather than the copy, the way NONMEM chains SAME. It works

with a condition (iov.cl2 + iov.v2 ~ same() | occ), it inherits the

fixed flags of the block it repeats, and it composes with the

cnd(same = n) nesting property that lotriSep() uses.

  • The `condition` column can now carry a `:same:` suffix. Rather than adding a column to the data frame from as.data.frame(), a repeated block records the element it mirrors in the existing condition column, naming it: `` <baseCondition>:same:<masterEta> # diagonal row <baseCondition>:same:<masterEta1>:<masterEta2> # covariance row ` The master is named rather than indexed because neta1/neta2 are renumbered whenever parameters are added, dropped or reordered. A copy keeps its master's est and fix, so a consumer that does not understand the suffix still sees a numerically correct matrix -- just with more free parameters than the model really has. Four helpers are exported for reading that column, and code that compares condition directly (condition == "id"`) should move to them, since such a test misclassifies a repeated block:
  • lotriBaseCondition() strips the suffix,
  • lotriIsSame() says whether a row mirrors another,
  • lotriSameMap() maps each eta to the eta it mirrors,
  • lotriSameBreak() drops the linkage for a block that has been structurally changed.

same() round trips through as.data.frame(), as.lotri() and

as.expression(), and the linkage is carried across lotriMat().

A repetition that no longer describes a real mirror -- because the

blocks it was built from were reordered or dropped, or because it

carries something same() cannot express -- is written out with its

explicit values instead. That loses the annotation, never the

numbers.

A prior cannot be put on a repeated block -- it is not a parameter of

its own, so the prior belongs on the block it mirrors. Without this

a model could carry two different priors on what is one estimated

parameter.

same() cannot be combined with a cov function, nor with

rcm=TRUE on a matrix the permutation would actually reorder; both

would move a repeated block away from the block it repeats, and are

refused rather than silently producing a matrix whose repetition is

no longer true. A same() matrix that is already block diagonal is

left alone, since there rcm is a no-op, which keeps rxode2's

ini({}) -- which always passes rcm=TRUE -- working.

  • Prior distributions can now be specified in a lotri({}) (and therefore ini({})) block with prior(name) ~ dist(...), ie:

```r

lotri({

tka <- 0.45

tcl <- c(0, 1, 10)

eta.cl + eta.v ~ c(0.1,

0.01, 0.2)

prior(tka) ~ dnorm(0, 10)

prior(tcl) ~ dlnorm(1, 0.5)

prior(eta.cl, eta.v) ~ lkjCorr(2)

})

```

Because the statement names its target, prior lines may be given

anywhere in the block. Priors may be put on population estimates,

on individual etas, and on whole covariance blocks (with the

matrix-valued distributions like lkjCorr() and invWishart()).

Every distribution has three accepted spellings: the R name where R