Created
June 25, 2015 12:29
-
-
Save fxi/22518690f3834824c677 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#'amReferralTable | |
#'@export | |
amReferralTable<-function(session=shiny:::getDefaultReactiveDomain(),inputSpeed,inputFriction,inputHf,inputHfTo,inputTblHf,inputTblHfTo,idField,idFieldTo,labelField,labelFieldTo,typeAnalysis,resol,dbCon, unitCost=c('s','m','h'),unitDist=c('m','km'),outReferral,outNearestDist,outNearestTime){ | |
# check the clock | |
timeCheckAll<-system.time({ | |
# set increment for the progress bar. | |
incN=0 | |
inc=90/nrow(inputTblHf) | |
# set output table header label | |
hIdField <- paste0('from','__',amSubPunct(idField)) # amSubPunt to avoid unwanted char (accent, ponctuation..) | |
hLabelField <- paste0('from','__',amSubPunct(labelField)) | |
hIdFieldTo <- paste0('to','__',amSubPunct(idFieldTo)) | |
hLabelFieldTo <- paste0('to','__',amSubPunct(labelFieldTo)) | |
hIdFieldNearest <- paste0('nearest','__',amSubPunct(idFieldTo)) | |
hLabelFieldNearest <- paste0('nearest','__',amSubPunct(labelFieldTo)) | |
hDistUnit <-paste0('distance','_',unitDist) | |
hTimeUnit <- paste0('time','_',unitCost) | |
# Create destination HF subset (To). | |
# NOTE: this has already be done outside for other functions.. but for coherence with origin HF (From) map, which need to be subseted in the loop, we also subset destination HF here. | |
qSqlTo<-paste("cat IN (",paste0(inputTblHfTo$cat,collapse=','),")") | |
execGRASS("v.extract",flags=c('overwrite'),input=inputHfTo,where=qSqlTo,output='tmp_ref_to') | |
# cost and dist from one to all selected in table 'to' | |
for(i in inputTblHf$cat){ | |
timeCheck<-system.time({ | |
incN=incN+1 | |
qSqlFrom<-paste("cat==",i) | |
# create temporary origine facility map (from) | |
execGRASS("v.extract",flags=c('overwrite'),input=inputHf,where=qSqlFrom,output='tmp__ref_from') | |
# NOTE: only extract coordinate instead ? No.. we need points in network. | |
# create cumulative cost map for each hf : iso or aniso | |
switch(typeAnalysis, | |
'anisotropic'=amAnisotropicTravelTime( | |
inputSpeed=inputSpeed, | |
inputHf='tmp__ref_from', | |
inputStop='tmp_ref_to', | |
outputCumulative='tmp__cost', | |
outputDir='tmp__ref_dir', | |
returnPath=FALSE, | |
maxCost=0 | |
), | |
'isotropic'=amIsotropicTravelTime( | |
inputFriction=inputFriction, | |
inputHf='tmp__ref_from', | |
inputStop='tmp_ref_to', | |
outputCumulative='tmp__cost', | |
outputDir='tmp__ref_dir', | |
maxCost=0 | |
) | |
) | |
# extract time cost V1 = hf cat dest; V2 = time to reach hf | |
refTime=execGRASS( | |
'v.what.rast', | |
map='tmp_ref_to', | |
raster='tmp__cost', | |
flags='p', | |
intern=T | |
)%>% | |
gsub('\\*',NA,.) %>% | |
na.omit %>% | |
read.table(text=.,sep='|') | |
# rename grass output | |
names(refTime)<-c('tcat',hTimeUnit) | |
#unit transformation | |
if(!unitCost =='s'){ | |
div<-switch(unitCost, | |
'm'=60, | |
'h'=3600, | |
'd'=86400 | |
) | |
refTime[hTimeUnit]<-refTime[hTimeUnit]/div | |
} | |
refTime$cat=i | |
# extract network to compute distance | |
execGRASS('r.drain', | |
input='tmp__cost', | |
direction='tmp__ref_dir', | |
output='tmp__drain', | |
drain='tmp__drain', | |
flags=c('overwrite','c','d'), | |
start_points='tmp_ref_to' | |
) | |
# create new layer with start point as node | |
execGRASS('v.net', | |
input='tmp__drain', | |
points='tmp__ref_from', | |
output='tmp__net_from', | |
node_layer='2', | |
operation='connect', | |
threshold=resol-1, | |
flags='overwrite' | |
) | |
# create new layer with stop points as node | |
execGRASS('v.net', | |
input='tmp__net_from', | |
points='tmp_ref_to', | |
output='tmp__net_all', | |
node_layer='3', | |
operation='connect', | |
threshold=resol-1, | |
flags='overwrite' | |
) | |
# extrad distance for each end node. | |
execGRASS('v.net.distance', | |
input='tmp__net_all', | |
output='tmp__net_dist', | |
from_layer='3', # calc distance from all node in 3 to layer 2 (start point) | |
to_layer='2', | |
intern=T, | |
flags='overwrite' | |
) | |
# read attribute table of distance network. | |
refDist<-dbReadTable(dbCon,'tmp__net_dist') | |
# rename grass output | |
names(refDist)<-c('tcat','cat',hDistUnit) | |
# distance conversion | |
if(!unitDist=='m'){ | |
div<-switch(unitDist, | |
'km'=1000 | |
) | |
refDist[hDistUnit]<-refDist[hDistUnit]/div | |
} | |
# using data.table. TODO: convert previouse data.frame to data.table. | |
refTime<-as.data.table(refTime) | |
setkey(refTime,cat,tcat) | |
refDist<-as.data.table(refDist) | |
setkey(refDist,cat,tcat) | |
refTimeDist <- refDist[refTime] | |
#create or update table | |
if(incN==1){ | |
ref=refTimeDist | |
}else{ | |
ref<-rbind(ref,refTimeDist) | |
} | |
# remove tmp map | |
rmRastIfExists('tmp__*') | |
rmVectIfExists('tmp__*') | |
}) | |
amUpdateProgressBar(session,'cumulative-progress',inc*incN) | |
print(timeCheck) | |
} | |
# set key to ref | |
setkey(ref,cat,tcat) | |
# Remove tmp map | |
rmVectIfExists('tmp_*') | |
# mergin from hf subset table and renaming. | |
valFrom<-inputTblHf[inputTblHf$cat %in% ref$cat, c('cat',idField,labelField)] | |
names(valFrom)<-c('cat',hIdField,hLabelField) | |
valFrom<-as.data.table(valFrom) | |
setkey(valFrom,cat) | |
valTo<-inputTblHfTo[inputTblHfTo$cat %in% ref$tcat,c('cat',idFieldTo,labelFieldTo)] | |
names(valTo)<-c('tcat',hIdFieldTo,hLabelFieldTo) | |
valTo<-as.data.table(valTo) | |
setkey(valTo,'tcat') | |
setkey(ref,cat) | |
ref<-ref[valFrom] | |
setkey(ref,tcat) | |
ref<-ref[valTo] | |
# set column subset and order | |
#refOut<-ref[,c(hIdField,hIdFieldTo,hDistUnit,hTimeUnit,hLabelField,hLabelFieldTo),with=F] | |
refOut<-ref[,c( | |
hIdField, | |
hLabelField, | |
hIdFieldTo, | |
hLabelFieldTo, | |
hDistUnit, | |
hTimeUnit | |
),with=F] | |
# set expression to evaluate nested query by group | |
expD<-parse(text=paste0(".SD[which.min(",hDistUnit,")]")) | |
expT<-parse(text=paste0(".SD[which.min(",hTimeUnit,")]")) | |
# Extract nearest feature by time and distance. | |
refNearestDist<-refOut[,eval(expD),by=hIdField] | |
refNearestTime<-refOut[,eval(expT),by=hIdField] | |
}) | |
# Return meta data | |
meta<-list( | |
'Function'='amReferralTable', | |
'AccessMod revision'=amGetVersionLocal(), | |
'Date'=amSysTime(), | |
'Timing'=as.list(timeCheckAll)$elapsed, | |
'Iterations'=nrow(inputTblHf), | |
'Arguments'=list( | |
'input'=list( | |
'map'=list( | |
'cost'=list( | |
'speed'=inputSpeed, | |
'friction'=inputFriction | |
), | |
'facilities'=list( | |
'from'=inputHf, | |
'to'=inputHfTo | |
) | |
), | |
'table'=list( | |
'cat'=list( | |
'from'=inputTblHf$cat, | |
'to'=inputTblHfTo$cat | |
), | |
'names'=list( | |
'from'=names(inputTblHf), | |
'to'=names(inputTblHfTo) | |
) | |
) | |
), | |
'analysis'=typeAnalysis, | |
'unit'=list( | |
'distance'=unitDist, | |
'cost'=unitCost | |
), | |
'resol'=resol | |
), | |
'Output'=list( | |
outReferral, | |
outNearestDist, | |
outNearestTime | |
) | |
) | |
dbWriteTable(dbCon,outReferral,refOut,overwrite=T,row.names=F) | |
dbWriteTable(dbCon,outNearestDist,refNearestDist,overwrite=T,row.names=F) | |
dbWriteTable(dbCon,outNearestTime,refNearestTime,overwrite=T,row.names=F) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment