#StalAge_1.0 #StalAge is an age modelling software developed by Denis Scholz & Dirk Hoffmann #Contact: Denis Scholz, Institute for Geosciences, University of Mainz, Becherweg 21, 55128 Mainz, Germany #Email: scholzd@uni-mainz.de age_model<-function(Daten, x_raw) { library(Hmisc) attach(Daten) x11() errbar(depth, age, age+error, age-error, xlab="Distance from top [mm]", ylab="Age [a]") #Plotten der Daten title(main="Age modelling") iter<-300 #Anzahl der Iterationen anz<-length(age) #Bestimmung der Anzahl der Alter l<-0 #counter up<-0 low<-0 x_raw<-sort(x_raw) #Sortiert Vektor mit Tiefen der Proxymessungen nach der Tiefe if (x_raw[length(x_raw)]>depth[length(depth)]) up<-x_raw[length(x_raw)]+100 else up<-depth[length(depth)]+100 #Suche Maximum und Minimum des Tiefen- und Datierungsvektors if (x_raw[1]age[k]+error[k] || age_fit[k]0) { #nur positive Steigungen werden zugelassen for (k in j:(j+(i-1))) results2[k, l, m]<-fit$coefficients[2]*depth[k]+fit$coefficients[1] #Schreiben der Daten ins Feld if (j==1) dist1<-depth[j]-x[1] else dist1<-depth[j]-depth[j-1] if (j+(i-1)==length(depth)) dist2<-x[length(x)]-depth[j+(i-1)] else dist2<-depth[j+(i-1)]-depth[j+(i-1)-1] x_start<-rnorm(1, depth[j]-dist1/2, dist1/6) x_end<-rnorm(1, depth[j+(i-1)]+dist2/2, dist2/6) if (j+(i-1)!=length(depth)) { if (fit$coefficients[2]*x_end+fit$coefficients[1]>=min(age[(j+i):length(age)]+3*error[(j+i):length(age)]/2)) x_end<-(min(age[(j+i):length(age)]+3*error[(j+i):length(age)]/2)-fit$coefficients[1])/fit$coefficients[2] #wenn oberes Ende des Fits > 3-sigma Obergrenze der nächsten Punkte, schneide ab if (x_enddepth[j+i]) x_end<-depth[j+i] #wenn Fit über den nächsten Punkt hinausgeht, schneide dort ab if (x_end==depth[j+i] && fit$coefficients[2]*x_end+fit$coefficients[1]<=age[j+i]-3*error[j+i]/2) next #wenn Fit nächsten Punkt schneidet und < 3-sigma Untergrenze, überspringe den Fit } if (j!=1) { if (fit$coefficients[2]*x_start+fit$coefficients[1]<=max(age[1:(j-1)]-3*error[1:(j-1)]/2)) x_start<-(max(age[1:(j-1)]-3*error[1:(j-1)]/2)-fit$coefficients[1])/fit$coefficients[2] #wenn unteres Ende des Fits < 3-sigma Untergrenze der vorherigen Punkte, schneide ab if (x_start>x_end) next #wenn Startpunkt durch obigen Test vor Endpunkt geschoben wird, überspringe den Fit if (x_start=age[j-1]+3*error[j-1]/2) next #wenn Fit vorherigen Punkt schneidet und > 3-sigma Obergrenze, überspringe den Fit } curve(fit$coefficients[2]*x+fit$coefficients[1], from=x_start, to=x_end, add=TRUE, col=i) #Plotten des Fits for (k in 1:length(x)) if (x[k]>=x_start && x[k]<=x_end) y[(l-1)*iter+m, k]<-fit$coefficients[2]*x[k]+fit$coefficients[1] } } } else next } } for (i in (1:anz)) { #Berechnen der Mittelwerte und Konfidenzintervalle results3[i,1]<-median(results2[i,,], na.rm=TRUE) results3[i,2]<-quantile(results2[i,,], probs=0.975, na.rm=TRUE, names=FALSE)-results3[i,1] results3[i,3]<-results3[i,1]-quantile(results2[i,,], probs=0.025, na.rm=TRUE, names=FALSE) } for (i in (1:length(x))) { results4[i,1]<-median(y[,i], na.rm=TRUE) results4[i,2]<-quantile(y[,i], probs=0.975, na.rm=TRUE, names=FALSE)-results4[i,1] results4[i,3]<-results4[i,1]-quantile(y[,i], probs=0.025, na.rm=TRUE, names=FALSE) } x<-x[46:(length(x)-44)] results5[, 1]<-results4[46:(length(results4[, 1])-44), 1] results5[, 2]<-results4[46:(length(results4[, 2])-44), 2] results5[, 3]<-results4[46:(length(results4[, 3])-44), 3] results6[, 1]<-results5[, 1] results6[, 2]<-results5[, 1]+results5[, 2] results6[, 3]<-results5[, 1]-results5[, 3] results7[,1]<-spline(x=x, y=results6[,1], xout=x_raw)$y #Spline über das Altersmodell results7[,2]<-spline(x=x, y=results6[,2], xout=x_raw)$y #Spline über den oberen Fehler des Altersmodells results7[,3]<-spline(x=x, y=results6[,3], xout=x_raw)$y #Spline über den unteren Fehler des Altersmodells for (i in (1:(length(results7[,1])-1))) if (results7[i+1,1]upper[i-1]) upper[i]<-results7[i, 1] else upper[i]<-upper[i-1] #Wenn nicht monoton, dann nutze lokales Maximum } for (i in (length(results7[,1])-1):1) { #Durchgehen des Ergebnis-Vektors von oben if (results7[i, 1]upper[i-1]) upper[i]<-results7[i, 2] else upper[i]<-upper[i-1] #Wenn nicht monoton, dann nutze lokales Maximum } for (i in (length(results7[,2])-1):1) { #Durchgehen des Ergebnis-Vektors von oben if (results7[i, 2]upper[i-1]) upper[i]<-results7[i, 3] else upper[i]<-upper[i-1] #Wenn nicht monoton, dann nutze lokales Maximum } for (i in (length(results7[,3])-1):1) { #Durchgehen des Ergebnis-Vektors von oben if (results7[i, 3]max) { #Gehe Zeilen durch ... max<-sum(test[i,], na.rm=TRUE) max_pos<-i } if (sum(test[,i], na.rm=TRUE)>max) { #Gehe Spalten durch ... max<-sum(test[,i], na.rm=TRUE) max_pos<-i } } if (max>1) { #Wenn ein Punkt mit mehr als einem anderen nicht passt, Abfrage, was getan werden soll x11() errbar(depth, age, age+error, age-error, xlab="Distance from top [mm]", ylab="Age [a]") title(main="Screening age data for major outliers") radius<-(depth[length(depth)]-depth[1])/(age[length(depth)]-age[1])*error[max_pos] draw.circle(x=depth[max_pos], y=age[max_pos], radius=radius, border="red") panel<-rp.control(size=c(500, 120), title=paste("Point", max_pos, "is an outlier! What do you want to do?"), max_pos=max_pos) rp.button(panel, action=delete, title="Delete!", quitbutton=TRUE, pos=c(0,0,500, 40)) rp.button(panel, action=enlarge, title="Enlarge!", quitbutton=TRUE, pos=c(0,41,500, 40)) rp.button(panel, action=close, title="Close", quitbutton=TRUE, pos=c(0,81,500, 40)) rp.block(panel) if (choice==1) { #Auswahl: Lösche Punkt! test[max_pos,]<-NA test[,max_pos]<-NA age[max_pos]<-NA errbar(depth, age, age+error, age-error, xlab="Distance from top [mm]", ylab="Age [a]") title(main="Screening age data for major outliers") } if (choice==2) { #Auswahl: Vergrößere Fehler! if (max(test[max_pos,], na.rm=TRUE)==1) { hilf<-age[max_pos] for (i in (max_pos+1):length(depth)) { if (is.na(test[max_pos, i])) next if (test[max_pos, i]==1 && age[i]hilf) hilf<-age[i] #; print(hilf) error[max_pos]<-hilf-age[max_pos] } } test[max_pos,]<-NA test[,max_pos]<-NA errbar(depth, age, age+error, age-error, xlab="Distance from top [mm]", ylab="Age [a]") title(main="Screening age data for major outliers") } if (choice==3) { #Auswahl: Weder noch -> Hinweis, dass das nicht möglich ist! rp.messagebox("This is not possible. Select another option, please!", title = "STOP!") } } if (max==1) break max<-1 } test[is.na(test)]<-0 #Ersetze NA's in Matrix durch Nullen. x11() errbar(depth, age, age+error, age-error, xlab="Distance from top [mm]", ylab="Age [a]") title(main="Age data screened for major outliers") depth<-depth[!is.na(age)] #Lösche rausgeworfene Punkte error<-error[!is.na(age)] age<-age[!is.na(age)] Daten<-data.frame(depth=depth, age=age, error=error) #Speichere Punkte in Dataframe return(Daten) } #--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- slope<-function(depth, age, error) { iter<-200 count<-0 age_sim<-0 for (i in 1:iter) { for (k in 1:3) age_sim[k]<-rnorm(1, age[k], error[k]/2) #Simulation der Alter fit<-lm(age_sim[1:3] ~ depth [1:3]) #Fit über simulierte Alter attr(fit$coefficients, "names")<-NULL if (fit$coefficients[2]>0) count<-count+1 #wenn Steigung positiv, zähle eins hoch } #print(count/iter) return(count/iter) } #--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- scan_fine<-function(Daten){ attach(Daten) x11() errbar(depth, age, age+error, age-error, xlab="Distance from top [mm]", ylab="Age [a]") #Plotten der Daten title(main="Screening for minor outliers") #print(error) Anteil<-0 #Vektoren für das Testen der Fits counter<-0 part<-0 part[1]<-1 #Definition des Beteiligungs-Vektors part[length(depth)]<-1 part[2]<-2 part[length(depth)-1]<-2 for (i in 3:(length(depth)-2)) part[i]<-3 #print(part) test<-0 #Pruefvariable für übergeordneten Test pruef<-0 #Pruefvariable für andere Tests while (test==0) { #Schleife für Iteration bis Fehler alle passen test<-1 #Setzen der allgemeinen Prüfvariable auf 1 for (i in 1:length(depth)) Anteil[i]<-0 #Nullsetzen von Anteil for (i in 1:length(depth)) counter[i]<-0 #Nullsetzen von counter for (i in 1:(length(depth)-2)) { #print(i) fit<-lm(age[i:(i+2)] ~ depth [i:(i+2)], weights=1/error[i:(i+2)]) #Fit über 3-Punkt-Intervall attr(fit$coefficients, "names")<-NULL curve(fit$coefficients[2]*x+fit$coefficients[1], from=depth[i], to=depth[i+2], add=TRUE, col=i) #Plotten des Fits age_fit<-0 #Bestimmung des Alters des Fits an den jeweiligen Punkten age_fit[i:(i+2)]<-fit$fitted.values pruef<-0 #Null-Setzen der Prüfvariable for (k in i:(i+2)) { #Test ob linearer Fit möglich if (age_fit[k]>age[k]+error[k] || age_fit[k]0) { counter[i:(i+2)]<-counter[i:(i+2)]+1 #wenn der Fit nicht geht, setze counter um 1 hoch } else { if (fit$coefficients[2]<0) { #wenn die Steigung des Fits negativ ist if (slope(depth[i:(i+2)], age[i:(i+2)], error[i:(i+2)])<0.2) counter[i:(i+2)]<-counter[i:(i+2)]+1 #wenn weniger als 30% der Fits eine positive Steigung haben, setze counter um 1 hoch } } } #print(counter) Anteil<-counter/part #print(Anteil) for (i in 1:length(depth)) { #gehe Anteil nach 1ern durch if (Anteil[i]==1) { #wenn Anteil=1, dann vergrößere Fehler um 10% und setze allgemeine Prüfvariable auf 1 error[i]<-error[i]*1.1 test<-0 } } errbar(depth, age, age+error, age-error, add=TRUE) #Plotten der Daten } x11() errbar(depth, age, age+error, age-error) #Plotten der Daten title(main="Age data screened for minor outliers") Daten<-data.frame(depth=depth, age=age, error=error) detach(Daten) return(Daten) }