unmarked
Follow the steps in this guide to
add a new model to the unmarked
package. Note that the
order can be adjusted based on your preferences. For instance, you can
start with the likelihood
function, as it forms the core of adding a model to unmarked, and
then build the rest of the code around it. In this document, the steps
are ordered as they would occur in an unmarked
analysis
workflow.
This guide uses the recently developed gdistremoval
function for examples, mainly because most of the relevant code is in a
single file instead of spread around. It also uses occu
functions to show simpler examples that may be easier to understand.
Before you start coding, you should use git to version your code:
unmarked
repository on Githubunmarked
uses S4 for objects and methods - if you
aren’t familiar with S4 you may want to consult a book or tutorial such
as this
one.
If you are unfamiliar with building a package in R, here are two tutorials that may help you: Karl Broman’s guide to building packages and the official R-project guide. If you are using RStudio, their documentation on writing package could also be useful, especially to understand how to use the Build pane.
To avoid complex debugging in the end, I suggest you to regularly install and load the package as you add new code. You can easily do so in RStudio in the Build pane, by clicking on “Install > Clean and install”. This will also allow you to test your functions cleanly.
Write tests and documentation as you add new functions, classes, and methods. This eases the task, avoiding the need to write everything at the end.
unmarkedFrame
objectMost model types in unmarked have their own
unmarkedFrame
, a specialized kind of data frame. This is an
S4 object which contains, at a minimum, the response (y). It may also
include site covariates, observation covariates, primary period
covariates, and other info related to study design (such as distance
breaks).
In some cases you may be able to use an existing
unmarkedFrame
subclass. You can list all the existing
unmarkedFrame
subclasses by running the following code:
## Class "unmarkedFrame" [package "unmarked"]
##
## Slots:
##
## Name: y obsCovs siteCovs mapInfo
## Class: matrix optionalDataFrame optionalDataFrame optionalMapInfo
##
## Name: obsToY
## Class: optionalMatrix
##
## Extends: "unmarkedFrameOrNULL"
##
## Known Subclasses:
## Class "unmarkedMultFrame", directly
## Class "unmarkedFrameDS", directly
## Class "unmarkedFrameOccu", directly
## Class "unmarkedFrameOccuFP", directly
## Class "unmarkedFrameOccuMulti", directly
## Class "unmarkedFramePCount", directly
## Class "unmarkedFrameMPois", directly
## Class "unmarkedFrameOccuCOP", directly
## Class "unmarkedFrameOccuMS", by class "unmarkedMultFrame", distance 2
## Class "unmarkedFrameOccuTTD", by class "unmarkedMultFrame", distance 2
## Class "unmarkedFrameG3", by class "unmarkedMultFrame", distance 2
## Class "unmarkedFramePCO", by class "unmarkedMultFrame", distance 2
## Class "unmarkedFrameGDR", by class "unmarkedMultFrame", distance 2
## Class "unmarkedFrameGMM", by class "unmarkedMultFrame", distance 3
## Class "unmarkedFrameGDS", by class "unmarkedMultFrame", distance 3
## Class "unmarkedFrameGPC", by class "unmarkedMultFrame", distance 3
## Class "unmarkedFrameGOccu", by class "unmarkedMultFrame", distance 3
## Class "unmarkedFrameMMO", by class "unmarkedMultFrame", distance 4
## Class "unmarkedFrameDSO", by class "unmarkedMultFrame", distance 4
You can have more information about each unmarkedFrame
subclass by looking at the documentation of the function that was
written to create the unmarkedFrame
object of this
subclass, for example with ?unmarkedFrameGDR
, or on the package’s
website.
unmarkedFrame
subclass for this modelunmarkedFrame
subclasses are children of the
umarkedFrame
class, defined here.occu
gdistremoval
unmarkedFrame
subclasses need to pass the validunmarkedFrame
validity check. You may want to add complementary validity check, like,
for example, the `unmarkedFrameDS
subclass.unmarkedFrame
objectunmarkedFrame
objectNote that you may not have to write all of the S4 methods below. Most
of them will work without having to re-write them, but you should test
it to verify it. All the methods associated with
unmarkedFrame
objects are listed in the unmarkedFrame
class documentation accessible with
help("unmarkedFrame-class")
.
Here are methods you probably will have to rewrite.
unmarkedFrame
object:
umf[i, ]
, umf[, j]
and umf[i, j]
occu
: code
for unmarkedFrame
mother class, as used to subset an
unmarkedFrameOccu
object.gdistremoval
: umf[i, ]
when i
is numeric, umf[i, ]
when i
is logical, umf[i, j]
Here are methods that you should test but probably will not have to
rewrite. They are defined in the unmarkedFrame.R
file, for the unmarkedFrame
mother class.
coordinates
getY
numSites
numY
obsCovs
obsCovs<-
obsNum
obsToY
obsToY<-
plot
projection
show
siteCovs
siteCovs<-
summary
You may also need to add specific methods to allow users to access an
attribute you added to your unmarkedFrame
subclass.
getL
for
unmarkedFrameOccuCOP
The fitting function can be declined into three main steps: reading
the unmarkedFrame
object, maximising the likelihood, and
formatting the outputs.
gdistremoval
does it) instead of a
combined formula (e.g. the way occu
does it).data
for the unmarkedFrame
optim
: optimisation algorithm
(method
), initial parameters, and other parameters
(...
)engine
parameter to call one of the implemented
likelihood functionsunmarkedFrame
object: write the
getDesign
methodMost models have their own getDesign
function, an S4
method. The purpose of this method is to convert the information in the
unmarkedFrame
into a format usable by the likelihood
function.
unmarkedFrame
.Writing the getDesign
method is frequently the most
tedious and difficult part of the work adding a new function.
occu
, as used for occu
gdistremoval
optim()
functionengine
argument of
the fitting function.If you are mainly used to coding in R, you should probably start here. If users want to dig deeper into the likelihood of a model, it may be useful for them to be able to read the R code to calculate likelihood, as they may not be familiar with other languages. This likelihood function can be used only for fixed-effects models.
occu
gdistremoval
doesn’t have an R version of the
likelihood functionThe C++ likelihood function is essentially a C++ version of the R
likelihood function, also designed exclusively for fixed-effects
models. This function uses the RcppArmadillo
R
package, presented
here. In the C++ code, you can use functions of the
Armadillo
C++ library, documented here.
Your C++ function should be in a .cpp
file in the
./src/
folder of the package. You do not need to write a
header file (.hpp
), nor do you need to compile the code by
yourself as it is all handled by the RcppArmadillo
package.
To test if your C++ function runs and gives you the expected result, you
can compile and load the function with
Rcpp::sourceCpp(./src/nll_yourmodel.cpp)
, and then use it
like you would use a R function:
nll_yourmodel(params=params, arg1=arg1)
.
unmarkedEstimate
objects per submodelOutputs from optim
should be organized unto
unmarkedEstimate
(S4) objects, with one
unmarkedEstimate
per submodel (e.g. state,
detection). These objects include the parameter estimates and other
information about link functions etc.
The unmarkedEstimate
class is defined here
in the unmarkedEstimate.R
file, and the
unmarkedEstimate
function is defined here,
and is used to create new unmarkedEstimate
objects. You
normally will not need to create unmarkedEstimate
subclass.
unmarkedFit
objectYou’ll need to create a new unmarkedFit
subclass for
your model. The main component of unmarkedFit
objects is a
list of the unmarkedEstimates
described above.
unmarkedFit
mother classunmarkedFitOccu
subclass definitionunmarkedFitGDR
subclass definitionAfter you defined your unmarkedFit
subclass, you can
create the object in your fitting function.
The fitting function return this unmarkedFit
object.
unmarkedFrame
unmarkedFrame
, other options to your
draft fitting functiongetDesign
getDesign
as inputs to your
likelihood functionunmarkedFit
objectDevelop methods specific to your unmarkedFit
type for
operating on the output of your model. Like for the methods associated
with an unmarkedFrame
object above, you probably will not have to
re-write all of them, but you should test them to see if they work. All
the methods associated with unmarkedFit
objects are listed
in the unmarkedFit
class documentation accessible with
help("unmarkedFit-class")
.
Those are methods you will want to rewrite, adjusting them for your model.
getP
The getP
method (defined
here) “back-transforms” the detection parameter (p the detection probability or λ the detection rate, depending on
the model). It returns a matrix of the estimated detection parameters.
It is called by several other methods that are useful to extract
information from the unmarkedFit
object.
occu
, the generic method for
unmarkedFit
objects is called.gdistremoval
simulate
The generic simulate
method (defined
here) calls the simulate_fit
method that depends on the
class of the unmarkedFit
object, which depends on the
model.
The simulate
method can be used in two ways:
simulate(object = my_unmarkedFit_object)
).You should test both ways with your model.
plot
This method plots the results of your model. The generic
plot
method for unmarkedFit
(defined
here) plot the residuals of the model.
occu
, the generic method for
unmarkedFit
objects is called.gdistremoval
Here are methods that you should test but probably will not have to
rewrite. They are defined in the unmarkedFit.R
file, for the unmarkedFit
mother class.
[
backTransform
coef
confint
fitted
getData
hessian
linearComb
mle
names
nllFun
parboot
nonparboot
predict
profile
residuals
sampleSize
SE
show
summary
update
vcov
logLik
LRT
You may also need to add specific methods to allow users to access an
attribute you added to your unmarkedFit
subclass.
For example, some methods are relevant for some type of models only:
getFP
for occupancy models that account for false
positivesgetB
for occupancy models that account for false
positivessmoothed
for colonization-extinction modelsprojected
for colonization-extinction modelsNAMESPACE
fileunmarkedFrame
,
unmarkedFit
) to the classes export hereunmarkedFrame
object to the functions export hereUsing testthat
package, you need to write tests for your
unmarkedFrame
function, your fitting function, and methods
described above. The tests should be fast, but cover all the key
configurations.
Write your tests in the ./tests/testthat/
folder,
creating a R file for your model. If you are using RStudio, you can run
the tests of your file easily by clicking on the “Run tests” button. You
can run all the tests by clicking on the “Test” button in the Build
pane.
You need to write the documentation files for the new classes and
functions you added. Documentation .Rd
files are stored in
the man
folder. Here is a documentation on how to
format your documentation.
unmarkedFrame
constructor function
unmarkedFit
class to predict-methods.RdgetP
method for the signature of you
unmarkedFitList
object in getP-methods.Rd.Depending on how much you had to add, you may also need to update existing files:
unmarkedFrame
class: add them to unmarkedFrame-class.RdunmarkedFit
class: add them to unmarkedFit-class.Rd.
The same goes for your new unmarkedFitList
class in unmarkedFitList-class.Rd.unmarked