# Roxygen documentation generated programatically -------------------
#'
#'
#' This is based on the problem and solution outlined in my book on pl...
#'
#' This is based on the problem and solution outlined in my book on plot methods
#' (Condit, 1998). Each of N stakes i has an estimated height `E[i]` and a true
#' height `e[i]`.
#' Pairs of stakes have a height difference `d[i, j]`, where
#' `e[i] + d[i, j] = e[j]`, but only estimated height differences `D[i, j]` are
#' known.
#' The least-squares estimate `E[i]` of `e[i]` can be written as the mean of the
#' `n[i]` points j for which `D[i, j]` was measured:
#' `E[i] = mean(E[j] - D[i, j]) =`
#' `(1 / n[i]) * sum(E[j]) - (1 / n[i]) * sum(D[i, j])`, and
#' `n[i] * E[i] - sum(E[j]) = -sum(D[i, j])`.
#' The latter produces N equations in N unknowns, but they are exactly singular.
#' One of the points must be assigned a value, and it's easiest to set
#' `e[1] = 0`.
#' The effect is to exclude the equation for `i = 0`, but all j for which
#' `D[0, j]` was measured have unchanged equations (`D[0, j]` are included).
#' The equations are written in matrix form. The coefficients are a matrix M
#' whose diagonal elements are the `n[i]`, so `M[i, i] = n[i]` for all i.
#' All other entries are `-1` where `D[i, j]` was measured otherwise zero.
#' The estimated `E[i]` are a vector, and the vector `V[i] = -sum(D[i, j])`,
#' where the summation is over j only. Then `M *PERCENT* E = V`, `Minv` is the
#' inverse of M, and `E = Minv *PERCENT* V`.
#'
#' In theory, the program will accept duplicate measures of the same pair of
#' plots. They are treated as replicates with equal weight to all other
#' estimates. There would be -2 or -3 etc. off the diagonal. The data are in
#' columns. One column has the label of one stake (column header pt1), the
#' second has the label of the second stake (column header pt2), and the final
#' column has the height difference at pt2 minus pt1 (column header diff). The
#' point labelled basept is assigned elevation baseelev. The last 5 arguments
#' allow those column headers to be reassigned.
#'
#' The name solve.topo clashed with an S3 method, so it was replaced by
#' solve_topo.
#'
#' @template debug
#'
#' @examples
#' \dontrun{
#' # See topography tutorial
#' }
#'
'solve_topo'
#' This is solely for use by solve_topo. It finds all points linked vi...
#'
#' @description
#'
#' This is solely for use by solve_topo. It finds all points linked via a sighting to a given point.
'getTopoLinks'
#' Takes a table of survey sightings with columns of x and y locations...
#'
#' @description
#' Takes a table of survey sightings with columns of x and y locations of two
#' points, and converts it to the format required by solve_topo. The input table
#' must have columns x1, y1, x2, and y2. The return value is a list consisting
#' of two dataframes:
#' - all points found in the input table, with an integer designation assigned
#' to each. The designation is called pt.
#' - the second table matches the input table, but instead of x-y coordinates
#' for the two points, only columns pt1 and pt2 are included to indicate the two
#' points between which a sighting was taken.
#'
'rearrangeSurveyData'
# Source code and original documentation ----------------------------
# Topographic calculation based on stake and the height difference between them.
# <function>
# <name>
# solve_topo
# </name>
# <description>
# This is based on the problem and solution outlined in my book on plot methods (1998):
# Each of N stakes i has an estimated height E[i] and a true height e[i].
# Pairs of stakes have a height difference d[i,j], where e[i]+d[i,j]=e[j],
# but only estimated height differences D[i,j] are known.<br><br>
# The least-squares estimate E[i] of e[i] can be written as the mean of the n[i]
# points j for which D[i,j] was measured:
# <ul>
# <li> E[i]=mean(E[j]-D[i,j]) = (1/n[i])*sum(E[j]) - (1/n[i])*sum(D[i,j])
# <li> n[i]*E[i]-sum(E[j]) = -sum(D[i,j])
# </ul>
# The latter produces N equations in N unknowns, but they are exactly singular.
# One of the points must be assigned a value, and it's easiest to set e[1] = 0.
# The effect is to exclude the equation for i=0, but all j for which D[0,j] was
# measured have unchanged equations (D[0,j] are included).<br><br>
# The equations are written in matrix form. The coefficients are a matrix M whose
# diagonal elements are the n[i], so M[i,i] = n[i] for all i. All other entries are -1
# where D[i,j] was measured otherwise zero. The estimated E[i] are a vector, and the
# vector V[i] = -sum(D[i,j]), where the summation is over j only. Then M*%*E=V, Minv
# is the inverse of M, and E=Minv*%*V.<br><br>
# In theory, the program will accept duplicate measures of the same pair of plots.
# They are treated as replicates with equal weight to all other estimates.
# There would be -2 or -3 etc off the diagonal.<br><br>
# The data are in columns. One column has the label of one stake (column header pt1), the second
# has the label of the second stake (column header pt2), and the final column has the height
# difference at pt2 minus pt1 (column header diff). The point labelled basept is assigned elevation baseelev.
# The last 5 arguments allow those column headers to be reassigned.
# </description>
# <arguments>
#
# </arguments>
# <sample>
# See topography tutorial
# </sample>
# <source>
#' @export
solve_topo=function(coldata,column1="pt1",column2="pt2",diffcolumn="htdiff",basept="1",baseelev=0,debug=NULL)
{
fromcol=which(colnames(coldata)==column1)
tocol=which(colnames(coldata)==column2)
Dcol=which(colnames(coldata)==diffcolumn)
pt1=coldata[,fromcol]
pt2=coldata[,tocol]
D=coldata[,Dcol]
coldata=data.frame(pt1,pt2,D)
ptLabels=sort(unique(c(pt1,pt2)))
nopts=length(ptLabels)
M=matrix(0,nrow=nopts,ncol=nopts)
rownames(M)=colnames(M)=ptLabels
V=numeric(nopts)
names(V)=ptLabels
for(i in 1:nopts)
{
links2=getTopoLinks(index=i,labels=ptLabels,data=coldata,from=fromcol,to=tocol,backward=FALSE)
links1=getTopoLinks(index=i,labels=ptLabels,data=coldata,from=tocol,to=fromcol,backward=TRUE)
if(links2$error | links1$error) return("remove sightings from any point to itself")
if(!is.null(debug)) if(ptLabels[i]==debug) browser()
V[i]=-(links2$diff+links1$diff)
M[i,i]=sum(links2$count)+sum(links1$count)
M[i,links2$indices]=M[i,links2$indices]-links2$count
M[i,links1$indices]=M[i,links1$indices]-links1$count
if(i%%100==1) cat("at point ", i, "\n")
}
baseIndex=which(ptLabels==basept)
if(length(baseIndex)==0) { cat("Error: You must supply a valid base point\n"); return(NULL) }
Mcorr=M[-baseIndex,-baseIndex]
Vcorr=V[-baseIndex]
Minv=solve(Mcorr)
elev=Minv%*%Vcorr
result=data.frame(label=I(c(basept,names(Vcorr))),elev=c(baseelev,elev))
return(result)
}
# </source>
# </function>
#
#
#
# <function>
# <name>
# getTopoLinks
# </name>
# <description>
# This is solely for use by solve_topo. It finds all points linked via a sighting to a given point.
# </description>
# <arguments>
#
# </arguments>
# <sample>
#
# </sample>
# <source>
#' @export
getTopoLinks=function(index,labels,data,from,to,backward=FALSE)
{
focalLabel=labels[index]
oneptSightings=subset(data,data[,from]==focalLabel)
if(dim(oneptSightings)[1]==0) return(list(name=NA,count=numeric(0),diff=0,error=FALSE))
allLinkLabels=oneptSightings[,to]
linkIndices=match(allLinkLabels,labels)
m=match(index,linkIndices)
if(length(m[!is.na(m)])>0) return(list(error=TRUE))
linkCount=table(linkIndices)
# if(length(which(linkCount>1))>0) browser()
uniqueLinkIndices=as.numeric(names(linkCount))
distsum=sum(oneptSightings$D)
if(backward) distsum=(-distsum)
# browser()
return(list(indices=uniqueLinkIndices,labels=allLinkLabels,count=linkCount,diff=distsum,error=FALSE))
}
# </source>
# </function>
#
#
# <function>
# <name>
# rearrangeSurveyData
# </name>
# <description>
# Takes a table of survey sightings with columns of x and y locations of two points, and converts it to the format
# required by solve_topo. The input table must have columns x1, y1, x2, and y2. The return value is a list consisting of two dataframes:
# <ul>
# <li> all points found in the input table, with an integer designation assigned to each. The designation is called pt.
# <li> the second table matches the input table,
# but instead of x-y coordinates for the two points, only columns pt1 and pt2 are included to
# indicate the two points between which a sighting was taken.
# </ul>
# </description>
# <arguments>
#
# </arguments>
# <sample>
#
# </sample>
# <source>
#' @export
rearrangeSurveyData=function(inputtable)
{
startpts=inputtable[,c('x1','y1')]
endpts=inputtable[,c('x2','y2')]
colnames(startpts)=colnames(endpts)=c('x','y')
allpt=unique(rbind(startpts,endpts))
allpt$pt=1:dim(allpt)[1]
m=match.dataframe(inputtable[,c('x1','y1')],allpt[,c('x','y')])
inputtable$pt1=allpt$pt[m]
m=match.dataframe(inputtable[,c('x2','y2')],allpt[,c('x','y')])
inputtable$pt2=allpt$pt[m]
outputcol=unique(c('pt1','pt2',colnames(inputtable)))
remove=outputcol %in% c('x1','y1','x2','y2')
result=subset(inputtable,select=outputcol[!remove])
return(list(allpt=allpt,IDtable=result))
}
# </source>
# </function>
#
#
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.