- Removed used of
|>
and\(.)
to bump down from R (>= 4.1) to R (>= 2.10) - Cleaned non-script files and folder
- Releasing to Zenodo
- Added
scanList2igraph()
andigraph2scanList()
conversion functions:- does what their names implies
- but also carries over the
attrs
attributes list
- Added
weightedAdj()
to convert back aweightedAdj
scanList
to its 3D binary array form. copy_attrs_to()
: added an option to by-pass class modifications. Ifcopy.class
is set toFALSE
, onlyattrs
attribute is copied.
$
methods added forscanList
to retrieve attributes inattrs
:- Users can now use
sL$name
, e.g.sL$edge.Prob
as a shortcut forattrs(sL,"edge.Prob")
.
- Users can now use
[
methods added forscanList
to subset scans:sL[,,vec]
is now also a scanList withattrs
copied fromsL
.
customize_sampling()
renamed intodesign_sampling()
, with additional internal changes:- Now returns
expDesign
objects as the name suggests, and not just functions. - Removes the need to nest/chain
design_exp()
andcustomize_sampling()
: now a singledesign_sampling()
is enough, althoughdesign_exp(design_sampling())
would return an equivalentexpDesign
anyway.
- Now returns
design_exp()
can now take combinations of previously created expDesign objects and functions, either named or anonymous (renamed intocustom.FUN_X
for now on):NamedList()
function added and used indesign_exp()
to keep track of function names input.expDesign
now prints the sequence of functions as a sequence of their names (more human-readable)
print
method is cleaner foredgeProb
and newly introducededgeProbMat
classes:edgeProbMat
is the matrix itself stored inedgeProb
object (their$P
), with attributeBeta prior
print
methods are cleaner for SimuNet specific objects: *scanList
objects printing now relies on MatrixsparseMatrix
class- so do their "collapsed" weighted adjacency relative:
weightedAdj
(see below).
- so do their "collapsed" weighted adjacency relative:
- class
sum
(obtained viasum_scans()
) has been renamed toweightedAdj
:Adj
stored inattrs
(and created bygenerate_edgeProb()
) are now of classweightedAdj
.- This change allows for homogeneous printing of weighted adjacency matrices
- pkgdown is now used to update the website's package. Related files are in master branch's
docs/
folder
- enclosed asnr related example in \dontrun{} because some example were sometime not passing on unix systems
- small edit in import_from_asnr()'s doc: now should pass R CMD check across systems (windows and unix)
- Switch internal simulation framework to one relying on Bayesian inference:
edgeProb
: edge presence probability matrices, renamed frompresenceProb
, are now drawn before each simulations from a posterior Beta distribution:- inferred from the observed weighted adjacency matrix and a prior Beta distribution (at the
moment with
alpha.prior = beta.prior = 0.5
, i.e. Jeffrey's prior). Specifically, from a distributionBeta(Adj + alpha.prior,samp.effort - Adj + beta.prior)
edgeProb
is drawn before each simulation: differentedgeProb
s will be obtained from a givenAdj
andsamp.effort
, but all of them come from this common posterior Beta distribution- This process of randomly drawing an
edgeProb
from a Beta distribution that would be used for all subsequent scans of a given simulation is akin to a Beta-Binomial process. However, "simply" drawing from a Beta-Binomial distribution would only provide a new weighted adjacency matrix, and not multiple binary scans that represent each scan, which is not desirable - Now, the desired behavior of having uncertainty and sampling effort included in the simulation should be attained
- inferred from the observed weighted adjacency matrix and a prior Beta distribution (at the
moment with
- Uncertainty inherent from this Bayesian inference paradigm can be assessed via replicating
many simulations, for which different
edgeProb
will be drawn
- Switch from list of scans (list of 2D matrices) to 3 dimensional arrays:
- the first 2 dimensions are the binary adjacency matrices for each scan
- the 3rd dimension is the scan index
This provides faster simulation and manipulations, but required an important rewriting of internal functions. Reliance on a new S3 class,scanList
, should allow for fairly transparent manipulation, however
- New
scanList
object are the new class of object returned by the new main wrapper, renamedsimunet()
. They now consist in 2 mains components:- the 3D array representing the edges at each scans, the actual object
- a single attribute
attrs
, which is a list, containing all relevant attributes to keep track of - Operations/functions applied to
scanList
object should default to being applied to the 3D array. This approach (not having scanList object being primary a list) was used for intuitiveness scanList
attributes listattrs
can be accessed via the new functionattrs()
, analogous tobase
'sattr()
- Empiricism and empirical
scanList
s have been rethought:- They now rely on a new class of objects and two main functions:
expDesign
objects which consist in function sequences to apply to a theoreticalscanList
to obtain an empirical one. These functions can be viewed as experimental manipulations of interest to simulate, e.g. node removal, observation error, etc.design_exp()
: used to createexpDesign
objects. Inputted functions are chained viapurrr
'sinvoke()
function.perform_exp()
: used to apply anexpDesign
objects toscanList
objectssimunet()
is now overall a wrapper to generateedgeProb
, simulate a theoreticalscanList
, and can handleexpDesign
objects to directly obtain empiricalscanList
s. Otherwise, users can first generate a theoretical scanList and later applyexpDesign
to them viaperform_exp()
- In a similar fashion to data manipulation with tidyverse's functions, or similarly to how
image editors can rely on layers,
expDesign
objects expect experimental manipulations to be chained and combined. Therefore, they should acceptscanList
objects as their first argument, and return a modifiedscanList
onto which other manipulation could be applied. Special cases like collapsing binary scans into their sum within a weighted adjacency matrix (sum_scans()
), or their scaled equivalent (scale_scans()
), can also be used at the end of the function sequence. - Common manipulations are included in the package a experimental design "building blocks". Such
include so far:
add_scans()
: draws additional scans based on the inputtedscanList
's edge.Prob. For instance, to compensate expectable sampling effort difference between two experimental designsremove_mostPeripheral()
, to remove the overall most peripheral individual from all scanssum_scans()
andscale_scans()
, to be use to collapse binary scans into weighted adjacency matrices, for instance at the end of a manipulation sequence
- Empirical sampling, with group-scan and focal-scan sampling, are now handled as (part of)
experimental designs passed as
expDesign
objects, as such "building blocks":- the function
customize_sampling()
can be used to define commonly defined group and focal sampling method, and can accept like previously:- in the case of group-scan sampling:
- constant or random probabilities of observing an edge
- observation probabilities derived from user-defined functions
- in the case of focal-scan sampling:
- even or random probabilities of observing an edge
- focal selection probabilities derived from user-defined functions
- in the case of group-scan sampling:
customize_sampling()
returns a function that can be used as a design "building block" withindesign_exp()
- the function
- These "building blocks", as functions of
scanList
s returningscanList
s, do not need to be used withinexpDesign
object, but can verbosely chained/piped fromscanList
object (taking advantage of base's new pipe|>
for instance). This is particularly useful forsum_scans()
andscale_scans()
for instance - Provided "building blocks" are also written to handle list of
scanList
s, i.e. list of classsLlist
, and return a list of what they would have return. This allow for simple design of severalexpDesign
objects passed simultaneously to be applied to ascanList
object throughperform_exp()
, to later be able to compare their outputs.
- They now rely on a new class of objects and two main functions:
- Otherwise rework done on the whole code from the ground up, documentation improved with links, and generally attempt at optimization here and there
- WIP: started writing tools to interact with the
ANTs
package. Barely started.
- Added a homemade class of packed matrices:
snPackMat
(SimuNet Packed Matrix) that stores only a vector of the relevant data, as well as a way to unpack the matrix to a regular one. Especially designed to avoid storing empry matrix triangles and performing useless operations on them. Nowsimu_scan
has an optional use.snPackMat logical argument (FALSE
by default). Early benchmarks are promising - Added two user-friendly functions to interact with the Animal Social Network
Repository:
import_from_asnr
can mostly be used with:- the Class and species folder (in the Networks folder of the github repository), and possibly graphml file name, as character strings
- the URL of a graphml object within the repository
an option allows the user to easily retrieve a igraph network object, or an adjacency matrix, from the graphml file
asnr_network_df
retrieve the list (into a dataframe) of graphml file in the asnr repository. Internally used byimport_from_asnr
- Switched internally to integer matrices instead of numeric matrices: significant improvement of
-10% computation time and -30% memory allocation on a
n = 21
total_scan = 9000
empirical network - Added dependency/reliance on the
Matrix
package, notably for its printing of sparse matrices
- implemented a plot method for
scan
andempiScan
objects. Internal code probably cleanable, but working for now:plot()
can be used either on ascan
/empiScan
object (which will be passed throughsummary()
) or on asummary.scan
/summary.empiScan
one. Notableplot
arguments available:method
to choose withinc("both","theoretical","group","focal")
forempiScan
objects. Special case of thelayout
argument used to pass igraphslayout
orlayout_
functions internally. This way, a layout is determined before callingplot.igraph
(wrapped inplot_emprical
) in the case ofmethod = "both"
, to ensure that all networks rely on the same layout to ease visual comparison.
- fixed some ugly print outputs for long
focalList
objects
- v1.0.0 Release of a fully functional and documented version of this network simulation framework, including a shift toward OOP internally
- Added track of
X.scaled
(X being"theoretical"
,"group"
, or"focal"
) forsummary.scan
andsummary.empiScan
objects
- Renamed more explicitely the
X.scan
components of scan and empiScan object, to make way forX.sum
andX.sampled
new matrices (cf. below). - The
summary
method used onscan
andempiScan
objects can now be used to create objects of newsummary.scan
andsummary.empiScan
objects, storingX.sum
andX.sampled
(X being"theoretical"
,"group"
, or"focal"
), and with dedicated print methods Adj
andtotal_scan
arguments are now optional whensampling.param
is passed when usingsimu_scan
- Added several required function for this purpose:
sum_scan.list
is an equivalent of previoussum_up.scan(s)
, but cleaner. It sums up any list of scans countingNA
s as zeros.- added
resolve_NA
, which is called beforesum_scan.list
in the case of empirical scans. Moved allNA
s related functions toempirical_NA_tools.R
- added
sum_scan.sampled
andcount_NA
functions to also count sampled (non-NA
) edges
- Included
scans.to.do
variable (a scan index or a vector of1:total_scan
) in wrappers and nested functions to generatescan
andempiScan
objects. Nowscans.to.do
is stored in several internal and output objects - Vectorized wrappers and nested functions to produce lists of scans (
raw.scan
,theoretical.scan
,group.scan
orfocal.scan
empirical scans) - Updated several print methods to display vectorized or list components of
scan
,empiScan
andsamplingParam
objects, truncate them when required to not overload output
- Added a wrapper to
generate_samplingParam
. User should interact withsimu_samplingParam
to createsamplingParam
objects for their simulations. - Vectorized the
focal
andscans.to.do
(which now replacescan.number
for more transparency) components offocal
objects. Next version should also vectorize some components ofsamplingParam
,obsProb
,scan
, andempiScan
objects - Finalized a working version of
simu_scan
for single theoretical and empirical scan. Next version should allow the user to directly usesimu_scan
to generate a list of either types of scans (thus superseding formeriterate_scans
). - Homogenize some function and variable names.
- First shift toward integration of OOP elements into the simulation framework:
- Revamp from the ground up of the
do.scan
part of the non-OOP previous version - Attempt at homogenizing SimuNet's internal syntax:
- the wrappers - to perform the whole network simulations (former
Boot_scan()
), iterate single scans into weighted adjacency matrix (formeriterate_scans()
), and draw a single random binary scan (formerdo.scan()
) - will now follow the syntaxsimu_*()
(starting with thesimu_scan()
wrapper to supersededo.scan()
) - new simulation internal objects (cf. below) will have generator following the syntax
generate_className()
, and as neededprint.className()
and other relevant S3 class methods. - presently, their related code use variable names distinct from their
className
syntax, rather favoring avariable = class.name
syntax internally - function names including internal ones are (hopefully) more explicit, and are now action verbs to follow coding "grammar" recommendations
- the wrappers - to perform the whole network simulations (former
- Revamp from the ground up of the
- For the OOP-transition purpose, creation of several simulation objects (S3 class):
presenceProb
objects, generator and related S3 methods: calculate and store infos on the presence probabilityP
of a tie at each scan for each dyad, from inputted adjacency matrix (Adj
), sampling effort (total_scan
), and igraph networkmode
samplingParam
objects, generator and related S3 methods: store all usefull parameters, some in the form of new object classes (S3), related to the empirical aspect of the network simulation. Presently, stores what's needed for a single binary focal scan, i.e. infos on a single focal (out of a list of focals). Specifically,samplingParam
objects store:method
: a character scalar between"group"
,"focal"
and"both"
, indicating the chosen scan sampling method.mode
: a character scalar representing the igraph networkmode
.obsProb
objects (cf. below)focal
objects (cf. below)
obsProb
objects, generator and related S3 methods: calculate and store a probability of observationP
of an edge at each scan sampling for each dyad, from inputted user-defined functionobs.prob_fun
of(i,j,Adj)
(that can also be used to pass a single [0,1] numeric to use as a constant, or the string"random"
to have all dyad probability drawn fromrunif(n*n,0,1)
)focalList
objects, generator and related S3 methods: draw and store a listfocals
oftotal_scan
focals (used internally as their indices, but also keep track of their names), from inputted user-defined functionfocal.prob_fun
of(n,Adj)
(that should return a vector ofn
probability for each node to be drawn at each scan, but that can also be used to pass as the strings"random"
or"even"
to have them drawn fromsample()
or to maximize the evenness of drawn focals in the focal list)focal
objects, generator and related S3 methods (includingplot.scan
S3 method to plot the network relying onplot.igraph
): determine and store whichfocal
to sample, from inputtedfocalList
object (cf. above) andscan.number
(out of the sampling efforttotal_scan
)scan
objects, generator and related S3 methods: draw and store, from inputtedpresenceProb
object:- a
raw
scan: directed binary matrix drawn from the probability of presence of edges contained in apresenceProb
object - a
theoretical
scan: theraw
scan to which the selected mode has been applied - a
scan.type
scan string: forscan
object not sampled from yet (i.e. not empirical scans of theempiScan
class (cf.below)),scan$scan.type = "theoretical"
, but later in the process can become"empirical"
- the original adjacency matrix
Adj
, sampling efforttotal_scan
, selected igraph networkmode
, the probability matrixpresence.prob
(frompresenceProb$P
), and other parameters mostly for internal use
- a
empiScan
objects, generator and related S3 methods: draw and store, from inputtedscan
andsamplingParam
objects:- inherits from the
scan
S3 class - but have their
scan.type = "empirical"
- a
method
string fromsamplingParam$method
- and both/either a
group
and/orfocal
scan: matrix/matrices containing*0
,1
, orNA
, which represents an edge that hasn't been sampled. Internally sample fromscan$theoretical
, to which the igraph networkmode
was already applied, and is set to keepNA
s where they were drawn (relevant for"group"
scan sampling), even if this result in a undirected adjacency matrix whereNA
s are non-symetrical. A function to minimize solvableNA
s will be soon introduced: formode = "max"
, this is e.g. whenscan$raw[i,j] = 1
andscan$raw[j,i] = NA
or inversly, for which both values can be set to1
; formode = "min"
, this is e.g. whenscan$raw[i,j] = 0
andscan$raw[j,i] = NA
or inversly, for which both values can be set to0
. *: withmode = "plus"
, possible values also include2
- inherits from the
- Revamping from the ground up as the new object were formalized and introduced in the algorithm,
the internal code also got cleaned and fixed in some places as code was recycled from its previous
non-OOP state:
- Some functions were updated to split some of their overall work into additional more explicit
and more "single-step/purpose" functions (e.g.
generate_obsProb
now relies ondetermine_obs.prob_type
andcalculate_obs.prob
instead of containing all the code in itself) empiScan$focal
now show not only the line of thefocal
sampled, but also its column- rethinking of the way the igraph network
mode
is applied:apply_mode
now keep track of an always"directed"
raw
scan, makes it symmetrical into atheoretical
scan if an undirectedmode
is selected ("undirected"
,"max"
,"min"
, or"plus"
), from which afocal
andgroup
scans are sampled throughsample_from_scan
(that internally relies ongroup_sample
andfocal_sample
). Through this changes, internal algorithm changed significantly, especially in howNA
s are handled ingroup
scans. Also,zero_NA
has been generalized intoreplace_NA
, with subsequent changes incompare_with_transposed
, but these are not used anymore withinapply_mode
and are kept for now just in case. - removed normally-superseded
*.R
files (focal.list.R
,obs.prob_._tools
), renameddo.scan.R
intodo.scan.old.R
- Some functions were updated to split some of their overall work into additional more explicit
and more "single-step/purpose" functions (e.g.
- Imported simulation-oriented functions from ConfiNet
- Structure package till it checks ok on its own
- Commented and removed mention of
decide_use.rare.opti()
for now till this routine is cleaned. Updated examples inBoot_scans()
and bootstrap tools to not call for this function through settinguse.rare.opti = FALSE
- Added a
NEWS.md
file to track changes to the package.