E003 – příloha 1

advertisement
Vývoj metody a konstrukce přístroje pro rychlé
monitorování vysokoteplotní stability rostlin
E003 – příloha 1:
Skripty pro anlýzu kritických bodů fluorescenční a vodivostní křivky
V Drásově dne 19.12.2013
do_curvature.R:
#column vectors:
#temp
- vector of temperature series (column “temp” of *.txt ProfileCon result file)
#Ft – vector of Ft measurements (column “Ft” of *.txt ProfileCon result file)
#Cond - vector of Conductivity.MV1 measurements (column “Conductivity.MV1“ of *.txt ProfileCon result file)
# must be defined in global environment before running this script
source("fc_curv.r")
source("fc_import.r")
version<-"1.0.0.2"
#1.0.0.2 - without normalization in fc_curv.r
fitrange<-function(rng,config_rng){
if(rng[1]<config_rng[1]){
a<-config_rng[1]
}else{
a<-rng[1]
}
if(rng[2]>config_rng[2]){
b<-config_rng[2]
}else{
b<-rng[2]
}
c(a,b)
}
param<-ParImport("config.ini") #read Analyse parameters
rng<-c(min(param["rangeC1"],param["rangeF1"]),max(param["rangeC2"],param["rangeF2"]))
#resample and normalize
rng_data<-fitrange(rng,c(min(temp),max(temp)))
dat<-DataResample(range=rng_data,temp=temp,Ft=Ft,Cond=Cond)
# #--------------------------------------#
# #add columns with circle fits
rng<-fitrange(rng_data,c(param["rangeF1"],param["rangeF2"])) #vezmi jen okno dle configu pro Ft
winsize<-param["winsizeF"]
Ft.curv<-CreateCircle("Ft",dat,rng)
rng<-fitrange(rng_data,c(param["rangeC1"],param["rangeC2"])) #vezmi jen okno dle configu pro Ft
winsize<-param["winsizeC"]
Cond.curv<-CreateCircle("Conductivity.MV1",dat,rng)
normdat<-cbind(dat,Ft.curv,Cond.curv)
# #throw out NA's
Ftres<-normdat[!is.na(normdat$Ft.r),]
#
# #find extrems
#fileerror<-file("rlog.log")
#sink(fileerror)
Ft.ex<-LocalExtrems("Ft",Ftres)
#write(geterrmessage(),file="rlog.tmp")
# #plotcurves("Ft",normdat,Ft.ex,file)
#
# #find extrems on conductivity
Condres<-normdat[!is.na(normdat$Conductivity.MV1.r),]
Cond.ex<-LocalExtrems("Conductivity.MV1",Condres)
# #plotcurves("Conductivity.MV1",normdat,Cond.ex,file)
#
normdat<-normdat[!is.na(normdat$Conductivity.MV1.r),]
#output in data.table „normdat“ placed in global environment
fc_curv.R:
#ver 1.0 by Michal Sicner
library("pracma") # need to be downloaded from r-project.org
#******************************************************************
circlefit <- function (X, z, r) {
#source: W.Gander et al. - Least squares fitting of circles and Ellipses
#circlefit
Geometric circle fit
#
# [z,r] <- circlefit (X, z, r)
# fits the best circle by nonlinear least squares
# for true geometric distance.
#
# X: given points <X(i,1), X(i,2)> - <temp or time,conductivity>
# z, r: starting values for circle solution
#
# z, r: parameters for circle found
u <- rbind(z1=z[1],z2= z[2] , r) # Starting values
h <- u
i<-0
#h[1,1]<-0
while (norm(h) > norm(u)*1e-10) {
a <- u[1]-X[,1]
b <- u[2]-X[,2]
fak <- sqrt(diag(a%o%a) + diag(b%o%b))
J <- cbind(a/fak,b/fak,rep(-1,length(a)))
f <- fak -u[3];
h <- mldivide(-J,f)
#h[1,1]<-0
u <- u + h
i<-i+1
}
z <- u[1:2]
r <- u[3]
u
}
#******************************************************************
algebraic_circle<-function(X){
#source: W.Gander et al. - Least squares fitting of circles and Ellipses
#algebraic_circle Algebraic circle fit
#
# [z, r] = algebraic_circle (X);
# fits a circle by minimizing the "algebraic distance"
# in the least squares sense a x'x + b'x + c = 0
#
# X : given points <X(i,1, X(i,2)>
#
# z, r: center and radius of the found circle
x<-X[,1]
y<-X[,2]
B<-cbind(diag(x%o%x)+diag(y%o%y),x,y,rep(1,length(x)))
res<-svd(B) #[U,S,V]
u<-res$v[,4]
a<-u[1]
b<-c(u[2],u[3])
c<-u[4]
z<- -b/2/a
r<- sqrt(norm(z,type="2")^2 - c/a)
c("z"=z,"r"=r)
}
#******************************************************************
CreateCircle <- function (what,dat,range) {
#matrix for whole the data
circle_coord<-matrix(nrow=length(dat$temp),ncol=3)
#calculate only for defined range
n<-which(dat$temp==max(dat[dat$temp<=range[2],"temp"]))
i<-which(dat$temp==min(dat[dat$temp>=range[1],"temp"]))
#calculate osculating circle for all moving windows
while(i<n-winsize-1){
#fit points coordinates
X<-cbind(dat[i:(i+winsize),"temp"],dat[i:(i+winsize),what])
#get first starting point from algebraic circle fit
alg<-algebraic_circle(X)
#geometric fit
circle_coord[i+winsize/2,]<-circlefit(X,c(alg["z1"],alg["z2"]),alg["r"])
i<-i+5
}
v<-data.frame(circle_coord)
colnames(v)<-c(paste0(what,".z1"),paste0(what,".z2"),paste0(what,".r"))
1/v
}
#******************************************************************
DataResample<-function(range=c(35,70),temp=NA,Ft=NA,Conductivity.MV1=NA) {
# resample the measured signal for points xi
interpolate <- function(what,dat,xi){
# not extrapolating
# interp1(x=as.numeric(dat[,"temp"]),
#
y=as.numeric(dat[,what]),
#
xi=xi,
#
method="linear")
a<-spline(x=as.numeric(dat[,"temp"]),
y=as.numeric(dat[,what]),
xout=xi)
a$y
}
t<-data.frame(temp,Ft,Conductivity.MV1)
# TAKE ONLY THE REQUIRED RANGE MINMAX
u<-subset(t,subset=(temp<=range[2]&temp>=range[1]))
#remove duplicates in temperature by averaging the values
v<-aggregate(u,by=list(u[,"temp"]),FUN=mean)
#create linear temerature scaled vector
temp <- seq(range[1],range[2],by=.02)
w<-as.data.frame(sapply(c("Ft","Conductivity.MV1"),interpolate,v,temp))
#normalize data
Ft.norm<-normalize(w$Ft,range)
Cond.norm<-normalize(w$Conductivity.MV1,range)
a<-as.data.frame(cbind(temp,Ft=Ft.norm,Conductivity.MV1=Cond.norm))
a
}
#******************************************************************
normalize<-function(dat,range){
#set the same scaling factor for X and Y axis
#scale <- (range[2]-range[1])/2
#scale*(dat-min(dat))/(max(dat)-min(dat))
dat
}
#******************************************************************
readrules<-function(configfile=""){
}
#******************************************************************
#localize extrems of the function
LocalExtrems<-function(what,dat){
u<-data.frame(matrix(nrow=5,ncol=3))
intervals<-vector(mode="numeric",length=5)
intervals[1]<-min(dat[,"temp"])
if(what=="Ft"){
colnames(u)<-c("bounds","Ft","CurvFt")
#maximum Ft curve
intervals[5]<-max(dat[,"temp"])
idxmax<-which(dat[,what]==max(dat[,what],na.rm=T))
if(idxmax>40){ #40 is 0.1degC*40=4degC in temperature
#first interval rage to 2 degrees below the Ftmaximum
intervals[2]<-dat[idxmax,"temp"]-3
m<-subset(dat,subset=dat[,"temp"]<intervals[2])
u[1,"Ft"]<-m[which(m[,"Ft.r"]==max(m[,"Ft.r"],na.rm=T)),"temp"]
u[1,"CurvFt"]<-m[which(m[,"Ft.r"]==max(m[,"Ft.r"],na.rm=T)),"Ft.r"]
#first interval rage to 4 degrees above the maximum
intervals[3]<-intervals[2]+6
m<-subset(dat,subset=dat[,"temp"]>intervals[2]&dat[,"temp"]<intervals[3])
u[2,"Ft"]<-m[which(m[,"Ft.r"]==max(m[,"Ft.r"],na.rm=T)),"temp"]
u[2,"CurvFt"]<-m[which(m[,"Ft.r"]==max(m[,"Ft.r"],na.rm=T)),"Ft.r"]
# find next local radius min behind Ftmax
m<-subset(dat,subset=dat[,"temp"]>intervals[3])
if(dim(m)[1] != 0){
idxmin<-which(m[,"Ft.r"]==max(m[,"Ft.r"],na.rm=T))
u[4,"Ft"]<-m[idxmin,"temp"]
u[4,"CurvFt"]<-m[idxmin,"Ft.r"]
# 4 degrees before Ft curve max
intervals[4] <- m[idxmin,"temp"]-4
#find radius min between ftmax and radiusmin last
m<-subset(m,subset=m[,"temp"]<intervals[4])
if(dim(m)[1] != 0) {
idxmin<-which(m[,"Ft.r"]==max(m[,"Ft.r"],na.rm=T))
u[3,"Ft"]<-m[idxmin,"temp"]
u[3,"CurvFt"]<-m[idxmin,"Ft.r"]
}else{
u[3,"Ft"]<-u[4,"Ft"]
u[3,"CurvFt"]<-u[4,"CurvFt"]
u[4,"Ft"]<-NA
u[4,"CurvFt"]<-NA
intervals[4]<-intervals[5]
}
}
}else{
#last temperature = all temperatures
intervals[2]<-max(dat[,"temp"])
}
}
if(what=="Conductivity.MV1"){
colnames(u)<-c("bounds","Cond","CurvCond")
intervals[2]<-max(dat[,"temp"],na.rm=T)
idxmin<-which(dat[,"Conductivity.MV1.r"]==max(dat[,"Conductivity.MV1.r"],na.rm=T))
u[1,"Cond"]<-dat[idxmin,"temp"]
u[1,"CurvCond"]<-dat[idxmin,"Conductivity.MV1.r"]
intervals[3:5]<-NA
}
u[,1]<-intervals
u
}
#******************************************************************
fc_import.R:
DataImport <-function(file =""){
colread<-function(colname,datatable){
datatable[,colname]
}
#file <- "c:/PSI/ProfileCon/Analysis/final.txt"
#read data and resample
#dat<-ReadRaw(file,what,range)
#------------- read from file - example data-----------if (file.exists(file)){
a<-scan(file,what = "character",sep = "\n",blank.lines.skip=FALSE)
# set decimal point type
#p<-grep("Culture",a)
#culture<-read.table(file,sep = "\t",skip=p-1,header=FALSE,nrows=1 )[2]
decpoint<- "."
#if(culture=="en-GB") {
# decpoint<-"."
#}
#read culumn names and data
idx_first <- grep("<DATA>", a)+2 #first row index of data
lines <- grep("</DATA>", a)-idx_first #number of data rows
units <-read.table(file,sep = "\t",skip=idx_first-2,header=TRUE,nrows=1 )
data <- read.table(file,sep = "\t",skip=idx_first,header=FALSE,nrows= lines-3,dec=decpoint)
t<-data.frame(temp=data[,2],Ft=data[,5],Conductivity.MV1=data[,4])
}
#return dataframe
t
}
ParImport<-function(file="config.ini"){
def_range <- c(35,70) #default range for analysis
def_filter<-100
if(file.exists(file)){
a<-try(scan(file,what = "character",sep = "\n",blank.lines.skip=FALSE),silent=T)
#read range size
r<-grep("Con_Range",a,value=TRUE) #first row index of data
if(!length(r)) {
warning("Con_Range=range_min,range_max not found in config.ini")
rangeC<-def_range
}else{
rmin<-as.numeric(sub(pattern=",","",regmatches(r,regexpr("[0-9]*,",r))))
rmax<-as.numeric(sub(pattern=",","",regmatches(r,regexpr(",[0-9]*",r))))
if(length(rmin)==0 || length(rmax)==0 || is.na(rmin) || is.na(rmax)){
warning("Con_Range has wrong format of data")
rangeC<-def_range
}else{
rangeC<-c(rmin,rmax)
}
}
#read range size
r<-grep("Ft_Range",a,value=TRUE) #first row index of data
if(!length(r)) {
warning("Ft_Range=range_min,range_max not found in config.ini")
rangeF<-def_range
}else{
rmin<-as.numeric(sub(pattern=",","",regmatches(r,regexpr("[0-9]*,",r))))
rmax<-as.numeric(sub(pattern=",","",regmatches(r,regexpr(",[0-9]*",r))))
if(length(rmin)==0 || length(rmax)==0 || is.na(rmin) || is.na(rmax)){
warning("Ft_Range has wrong format of data")
rangeF<-def_range
}else{
rangeF<-c(rmin,rmax)
}
}
#read filter window size
r<-grep("Con_FilterWindow",a,value=TRUE) #first row index of data
if(!length(r)) {
warning("Con_FilterWindow=filetrsize not found in config.ini")
windowC<-def_filter
}else{
f<-as.numeric(regmatches(r,regexpr("[0-9]*$",r)))
if(is.na(f)){
warning("Con_FilterWindow has wrong format of data")
windowC<-def_filter
}else{
windowC<-f
}
}
#read filter window size
r<-grep("Ft_FilterWindow",a,value=TRUE) #first row index of data
if(!length(r)) {
warning("Ft_FilterWindow=filetrsize not found in config.ini")
windowF<-def_filter
}else{
f<-as.numeric(regmatches(r,regexpr("[0-9]*$",r)))
if(is.na(f)){
warning("Ft_FilterWindow has wrong format of data")
windowF<-def_filter
}else{
windowF<-f
}
}
}else{
rangeC<-def_range
rangeF<-def_range
windowC<-def_filter
windowF<-def_filter
warning("config.ini file not found in current directory")
}
c(rangeC=rangeC,rangeF=rangeF,winsizeC=windowC,winsizeF=windowF)
}
Download