#A function to obtain the data field from ncdfs and to get the data in the right order, adjusting for missingness #INPUT: DataDir a string with the directory that contains the ncdf data #NOTE: It is assumed we are working in the directory that contains the parameter data GetDataAndDesign <- function(DataDir="~/Documents/CanadaData/MSLP/", prefix="psl", variable="psl"){ param.names <- c("FACAUT", "UICEFAC", "CT", "CBMF", "WEIGHT", "DRNGAT", "RKXMIN", "XINGLE", "ALMC", "ALF", "TAUS1", "CSIGMA", "CVSG") param.lows <- c(0.5, 600, 0.75e-03, 0.01, 0.1, 0, 0.01, 10, 10, 1e06, 1800, 0.05, 5e-04) param.highs <- c(5, 7500, 1.3e-03, 0.06, 1, 0.1, 0.5, 50, 1000, 1e09, 21600, 0.5, 1e-02) which.logs <- c(9, 10, 13) param.defaults <- c(2.5, 4800, 1e-03, 0.03, 0.75, 0.005, 0.1, 10, 600, 5e08, 6*3600, 0.2, 3e-03) plows <- param.lows plows[which.logs] <- log10(plows[which.logs]) phighs <- param.highs phighs[which.logs] <- log10(phighs[which.logs]) StandardParams_U <- param.defaults StandardParams_U[which.logs] <- log10(StandardParams_U[which.logs]) StandardParams_U <- ((StandardParams_U-plows)/(phighs-plows))*2 - 1 tid0 <- "dma_1-000" Stands <- data.frame(tid0,t(StandardParams_U)) names(Stands) <- c("t_IDs",param.names) load("tMasterWave1_US.RData") tID1 <- "dma" labels <- c("0","1","2","3","4","5","6","7","8","9") counter <- 1 first <- 2 second <- 1 third <- 1 t_IDs <- rep(tID1,65) twave <- "1" while(counter<66){ tnew <- paste(labels[third],labels[second],labels[first],sep="") t_IDs[counter] <- paste(t_IDs[counter],twave,sep="_") t_IDs[counter] <- paste(t_IDs[counter],tnew,sep="-") first <- first + 1 if(first>10){ second <- second+1 first <- 1 if(second > 10){ third <- third+1 second <- 1 } } counter <- counter + 1 } tMasterWave1_US$t_IDs <- t_IDs tMasterWave1_US <- rbind(tMasterWave1_US, Stands) nc000 <- nc_open(file=paste(DataDir, prefix, "_Amon_DevAM4-4_dma_1-000_r1i1p1_200301-200812.nc", sep="")) psl000 <- ncvar_get(nc000,variable) PSLwave1all <- array(NA, dim = c(dim(psl000),66)) PSLwave1all[,,,1] <- psl000 numbers <- 1:66 numbers <- sapply(numbers, function(e) paste("0",numbers[e],sep="")) numbers[1:9] <- sapply(1:9, function(e) paste("0",numbers[e],sep="")) numbers Missing <- c() k <- 2 while(k <= 66){ filename <- paste(DataDir, prefix, "_Amon_DevAM4-4_dma_1-", numbers[k-1], "_r1i1p1_200301-200812.nc", sep="") newNC <- try(nc_open(file=filename),silent=TRUE) if(inherits(newNC,"try-error")){ Missing <- c(Missing,numbers[k-1]) k <- k+1 } else{ PSLwave1all[,,,k] <- ncvar_get(newNC,variable) k <- k+1 } } MissingMembers <- which(numbers %in% Missing) wave1Design <- tMasterWave1_US[-MissingMembers,] N1 <- length(wave1Design[,1]) wave1Design <- wave1Design[c(N1,1:(N1-1)),] PSLwave1all <- PSLwave1all[,,,-(MissingMembers+1)] dim(PSLwave1all) <- c(prod(dim(PSLwave1all)[1:2]),dim(PSLwave1all)[3:4]) OriginalField <- aperm(PSLwave1all,c(1,3,2)) return(list(Design=wave1Design[,-1], FieldData = OriginalField)) } #EXAMPLE CALL - Tested 27/07/16 #ourData <- GetDataAndDesign() #Get 3D data using pressure and lat (zonally integrating over longitude) GetDataAndDesignZonalPressure <- function(DataDir="~/Documents/CanadaData/MSLP/", prefix="psl", variable="psl"){ param.names <- c("FACAUT", "UICEFAC", "CT", "CBMF", "WEIGHT", "DRNGAT", "RKXMIN", "XINGLE", "ALMC", "ALF", "TAUS1", "CSIGMA", "CVSG") param.lows <- c(0.5, 600, 0.75e-03, 0.01, 0.1, 0, 0.01, 10, 10, 1e06, 1800, 0.05, 5e-04) param.highs <- c(5, 7500, 1.3e-03, 0.06, 1, 0.1, 0.5, 50, 1000, 1e09, 21600, 0.5, 1e-02) which.logs <- c(9, 10, 13) param.defaults <- c(2.5, 4800, 1e-03, 0.03, 0.75, 0.005, 0.1, 10, 600, 5e08, 6*3600, 0.2, 3e-03) plows <- param.lows plows[which.logs] <- log10(plows[which.logs]) phighs <- param.highs phighs[which.logs] <- log10(phighs[which.logs]) StandardParams_U <- param.defaults StandardParams_U[which.logs] <- log10(StandardParams_U[which.logs]) StandardParams_U <- ((StandardParams_U-plows)/(phighs-plows))*2 - 1 tid0 <- "dma_1-000" Stands <- data.frame(tid0,t(StandardParams_U)) names(Stands) <- c("t_IDs",param.names) load("tMasterWave1_US.RData") tID1 <- "dma" labels <- c("0","1","2","3","4","5","6","7","8","9") counter <- 1 first <- 2 second <- 1 third <- 1 t_IDs <- rep(tID1,65) twave <- "1" while(counter<66){ tnew <- paste(labels[third],labels[second],labels[first],sep="") t_IDs[counter] <- paste(t_IDs[counter],twave,sep="_") t_IDs[counter] <- paste(t_IDs[counter],tnew,sep="-") first <- first + 1 if(first>10){ second <- second+1 first <- 1 if(second > 10){ third <- third+1 second <- 1 } } counter <- counter + 1 } tMasterWave1_US$t_IDs <- t_IDs tMasterWave1_US <- rbind(tMasterWave1_US, Stands) nc000 <- nc_open(file=paste(DataDir, prefix, "_Amon_DevAM4-4_dma_1-000_r1i1p1_200301-200812.nc", sep="")) initArray <- ncvar_get(nc000,variable) Pressure <- ncvar_get(nc000, "plev") lat <- ncvar_get(nc000, "lat") zonalArray <- apply(initArray, MARGIN = 2:4, mean) Arraywave1all <- array(NA, dim = c(dim(zonalArray),66)) Arraywave1all[,,,1] <- zonalArray numbers <- 1:66 numbers <- sapply(numbers, function(e) paste("0",numbers[e],sep="")) numbers[1:9] <- sapply(1:9, function(e) paste("0",numbers[e],sep="")) numbers Missing <- c() k <- 2 while(k <= 66){ filename <- paste(DataDir, prefix, "_Amon_DevAM4-4_dma_1-", numbers[k-1], "_r1i1p1_200301-200812.nc", sep="") newNC <- try(nc_open(file=filename),silent=TRUE) if(inherits(newNC,"try-error")){ Missing <- c(Missing,numbers[k-1]) k <- k+1 } else{ Arraywave1all[,,,k] <- apply(ncvar_get(newNC,variable), MARGIN=2:4, mean) k <- k+1 } } MissingMembers <- which(numbers %in% Missing) wave1Design <- tMasterWave1_US[-MissingMembers,] N1 <- length(wave1Design[,1]) wave1Design <- wave1Design[c(N1,1:(N1-1)),] Arraywave1all <- Arraywave1all[,,,-(MissingMembers+1)] dim(Arraywave1all) <- c(prod(dim(Arraywave1all)[1:2]),dim(Arraywave1all)[3:4]) OriginalField <- aperm(Arraywave1all,c(1,3,2)) return(list(Design=wave1Design[,-1], FieldData = OriginalField)) } #Example call: Tested 11/8/16 #ourDataTA <- GetDataAndDesignZonalPressure(DataDir="~/Documents/CanadaData/ta/", prefix="ta", variable="ta") #Convert the 3D spatio-temporal data into spatial data, by extracting the required monthly average and get the svd basis #INPUTS: #OriginalField is a data array with the first dimension the length of the field (so a strung out map), the second the ensemble size and the third in months from the start of the simulation. #which.months Jan = 1, Dec = 12. DJF is then c(12,1,2) but consecutive months will be taken (e.g. c(12, 13, 14)), #num.years: how many of the last n years of the simulation to keep #scaling: A scaling to apply for numerical tractability #OUTPUTS: List containing: #tBasis: the required svd basis #CentredField the correctly averaged field with the ensemble mean removed from each ensemble member and then scaled by the scaling #EnsembleMean The mean field of the correctly averaged ensemble. (So e.g. the ensemble mean for DJF) #scaling: The used scaling from the input to the function. ExtractCentredScaledDataAndBasis <- function(OriginalField, which.months, num.years, scaling=1){ tmonths <- seq(from=which.months[1],by=1,length.out = length(which.months)) allYears <- dim(OriginalField)[3] while(tmonths[length(tmonths)] + 12 <= allYears){ l1 <- length(tmonths) tmonths <- c(tmonths, c(tmonths[c(l1-2,l1-1,l1)])+12) } needed.months <- num.years*length(which.months) if(needed.months < length(tmonths)) tmonths <- tmonths[-c(1:(length(tmonths) - needed.months))] NewArray <- OriginalField[,,tmonths] MeanField <- apply(NewArray, MARGIN=c(1,2), mean) #MeanField is now the uncentered, unscaled field we want to emulate. The last step is to centre, scale and extract the basis EnsMean <- apply(MeanField, MARGIN=1, mean) CentredField <- MeanField for(i in 1:dim(MeanField)[2]){ CentredField[,i] <- CentredField[,i] - EnsMean } CentredField <- CentredField/scaling Basis <- svd(t(CentredField))$v return(list(tBasis=Basis, CentredField = CentredField, EnsembleMean = EnsMean, scaling=scaling, Months=tmonths)) } #Example call: Tested 27/7/16 #DJFdata <- ExtractCentredScaledDataAndBasis(OriginalField = ourData$FieldData, which.months=c(12,1,2), num.years=5, scaling=10^4) #MAMdata <- ExtractCentredScaledDataAndBasis(OriginalField = ourData$FieldData, which.months=c(3,4,5), num.years=5, scaling=10^4) #JJAdata <- ExtractCentredScaledDataAndBasis(OriginalField = ourData$FieldData, which.months=c(6,7,8), num.years=5, scaling=10^4) #SONdata <- ExtractCentredScaledDataAndBasis(OriginalField = ourData$FieldData, which.months=c(9,10,11), num.years=5, scaling=10^4) #Change to separate temporal reduction and basis calculation (data cleaning vs every-application calculations.) ExtractData <- function(OriginalField, which.months, num.years){ tmonths <- seq(from=which.months[1],by=1,length.out = length(which.months)) allYears <- dim(OriginalField)[3] while(tmonths[length(tmonths)] + 12 <= allYears){ l1 <- length(tmonths) tmonths <- c(tmonths, c(tmonths[c(l1-2,l1-1,l1)])+12) } needed.months <- num.years*length(which.months) if(needed.months < length(tmonths)) tmonths <- tmonths[-c(1:(length(tmonths) - needed.months))] NewArray <- OriginalField[,,tmonths] MeanField <- apply(NewArray, MARGIN=c(1,2), mean) #MeanField is now the uncentered, unscaled field we want to emulate. The last step is to centre, scale and extract the basis return(list(Data = MeanField)) } CentreAndBasis <- function(MeanField, scaling=1, weightinv = NULL){ EnsMean <- apply(MeanField, MARGIN=1, mean) CentredField <- MeanField for(i in 1:dim(MeanField)[2]){ CentredField[,i] <- CentredField[,i] - EnsMean } CentredField <- CentredField/scaling Basis <- wsvd(t(CentredField), weightinv = weightinv)$v return(list(tBasis=Basis, CentredField = CentredField, EnsembleMean = EnsMean, scaling=scaling)) } #Code for plotting a basis #INPUTS: #Basis: The basis whose columns you want to plot #num.vectors: The number of basis vectors you want to plot (currently an integer) #breakVec: An optional vector containing the breaks for the plot image. #col.fun: A colour function defaulting to tim.colors from fields. #lat, lon ordered latitude and longitude as output from the relevant ncdf (see example). plotBasis <- function(Basis, num.vectors, ylat, xlon, breakVec=NULL, col.fun=tim.colors, latlon=TRUE){ tRange <- range(Basis) if(is.null(breakVec)) breakVec <- pretty(tRange,65) cols <- col.fun(length(breakVec)-1) mar <- par("mar") tmar <- mar tmar[4] <- tmar[2] tmar[2] <- 1 tmar <- tmar/4 tmar[4] <- 3 tmar[1] <- 0.3 tmar[3] <- tmar[1] if(num.vectors<5){ N <- 2 M <- 2 } else if(num.vectors < 10){ N <- 3 M <- 3 } else if(num.vectors < 13){ N <- 3 M <- 4 } else if(num.vectors < 17){ N <- 4 M <- 4 } else if(num.vectors < 21){ N <- 5 M <- 4 } else if(num.vectors < 26){ N <- 5 M <- 5 } else{ stop("Choose 25 basis vectors or less, or change code") } key <- rep(1, M) numMatrix <- t(matrix(2:(N*M+1),nrow=N,ncol=M)) layout(cbind(numMatrix, key), widths=c(rep(0.3,N), lcm(1.6))) par(mar=tmar,las=1) plot.new() plot.window(c(0,1), range(breakVec), xaxs="i", yaxs="i") rect(0, breakVec[-length(breakVec)],1,breakVec[-1],col=cols) axis(4) par(mar=rep(0.1,4),usr=c(0,1,0,1)) for(k in 2:(num.vectors+1)){ basisVec <- Basis[,(k-1)] dim(basisVec) <- c(length(xlon),length(ylat)) plot.new() if(latlon) plot.window(c(-180,180),c(-90,90)) else plot.window(range(xlon)[c(2,1)], range(ylat)[c(2,1)]) .filled.contour(xlon[order(xlon)],ylat[order(ylat)],basisVec[order(xlon),order(ylat)],breakVec,cols) rect(range(xlon)[1], range(ylat)[1],range(xlon)[2], range(ylat)[2]) if(latlon) map("world",add=T,wrap=FALSE,interior=FALSE) } } #Example Call: Tested 27/7/16 #nc000 <- nc_open(file="~/Documents/CanadaData/MSLP/psl_Amon_DevAM4-4_dma_1-000_r1i1p1_200301-200812.nc") #lat <- ncvar_get(nc000,"lat") #lon <- ncvar_get(nc000,"lon") #lon[lon>180] <- lon[lon>180] - 360 #plotBasis(Basis=DJFdata$tBasis, 9, lat, lon, pretty(range(DJFdata$tBasis[,1:9]),65)) #Function to compute the coefficients of an ensemble by projecting it onto a given basis. #INPUTS: #SpatialFieldsEnsemble: The ensemble consisting of an l x n matrix where l is the number of gridboxes in the field and n is the number of ensemble members. #basis: The l x nprime matrix of basis vectors where nprime <= n #orthogonal: Boolean to indicate whether the basis vectors are orthogonal. #When time is not in the ensemble due to pre-averaging #OUTPUT: nprime x n matrix of coefficients for the given ensemble StandardCoefficients <- function(SpatialFieldsEnsemble, basis, orthogonal=TRUE){ EnsDims <- dim(SpatialFieldsEnsemble) n <- EnsDims[2] l <- EnsDims[1] nprime <- dim(basis)[2] if(is.null(nprime)) nprime <- 1 OrthogCoeffs <- tensor(basis,SpatialFieldsEnsemble,1,1) if(orthogonal){ return(OrthogCoeffs) } else{ Qbasis <- chol(crossprod(basis)) t1 <- backsolve(Qbasis, OrthogCoeffs, transpose =TRUE) #n' x n t2 <- backsolve(Qbasis, diag(nprime), transpose=TRUE) #n' x n' return(tensor(t2,t1,2,1)) } } #Example call: (first 10 coefficients) Tested 29/07/16 #DJFcoefs <- StandardCoefficients(DJFdata$CentredField, DJFdata$tBasis[,1:10], orthogonal=FALSE) #Reconstruct a spatial field from a set of basis vectors and relevant coefficients #INPUTS: #coefficients: nprime x n matrix, #basis: l x nprime matrix Reconstruct <- function(coefficients, basis){ tensor(basis, coefficients, 2, 1) } #Example call: Tested 29/07/16 #Reconstructed <- Reconstruct(DJFcoefs, DJFdata$tBasis[,1:10]) #INPUTS: #Coefficients: Coefficients of basis computed using StandardCoefficients #EnsembleData: List generated by ExtractCentredScaledDataAndBasis #which.plot. Which ensemble member to plot #OriginalScale: Boolean. Do you want to compute the basis back on the original scale including the ensemble mean? plot.EnsembleMemberReconstruction <- function(coefficients, EnsembleData, which.plot=1, OriginalScale=TRUE){ nprime <- dim(coefficients)[1] trecon <- Reconstruct(coefficients=coefficients, basis=EnsembleData$tBasis[,1:nprime]) VarianceExplained <- crossprod(c(trecon))/crossprod(c(EnsembleData$CentredField)) VarianceExplained.String <- paste("Ensemble variance explained = ", 100*VarianceExplained, "%", sep="" ) print(VarianceExplained.String) EnsembleField <- EnsembleData$CentredField[,which.plot]*EnsembleData$scaling + EnsembleData$EnsembleMean ReconField <- trecon[,which.plot]*EnsembleData$scaling + EnsembleData$EnsembleMean par(mfrow=c(3,1)) tdims <- c(length(lon), length(lat)) tanom <- EnsembleField - ReconField image.plot(lon[order(lon)],lat, matrix(EnsembleField,nrow=tdims[1],ncol=tdims[2])[order(lon),],main=paste("Ensemble member",which.plot,sep=" ")) map("world",add=T) image.plot(lon[order(lon)],lat, matrix(ReconField,nrow=tdims[1],ncol=tdims[2])[order(lon),], main="Reconstruction") map("world",add=T) image.plot(lon[order(lon)],lat, matrix(tanom,nrow=tdims[1],ncol=tdims[2])[order(lon),], main = "Anomaly") map("world",add=T) } #Example call: Tested 29/07/16 #plot.EnsembleMemberReconstruction(DJFcoefs, DJFdata, 1) #Function to extract multiple observation data sets centred using the mean of an ensemble and scaled using the same scaling as our ensemble data #INPUTS: #DataFiles: A string vector of file locations for data fields #which.obs: String declaring the field name in the ncdf #EnsembleData: Post-processed ensemble data in list form as output by ExtractCentredScaledDataAndBasis #orignalLat: The value of lat extracted for the ensemble (we need lat and lon to match) #orignalLon: The value of lon extracted for the ensemble (we need lat and lon to match) #OUTPUT: #A list of observation vectors each centred with the mean of the ensemble as the EnsembleData was and then scaled in the same way. GetObservations <- function(DataFiles, which.obs="psl", EnsembleData, originalLat=lat, originalLon=lon, permanent.scaling=1){ numFiles <- length(DataFiles) ObsList <- list() for(i in 1:numFiles){ ncdatatemp <- nc_open(file=DataFiles[i]) psltemp <- ncvar_get(ncdatatemp, which.obs)/permanent.scaling datlon <- ncvar_get(ncdatatemp, "lon") datlon[datlon>180] <- datlon[datlon>180] - 360 ldl <- length(datlon) if((ldl>length(originalLon))&(datlon[1]==datlon[ldl])){ warning("Repeated Longitude, removing last row of data") psltemp <- psltemp[-ldl,,] } datlat <- ncvar_get(ncdatatemp, "lat") latlen <- length(datlat) if((latlen>length(originalLat))&(datlat[1]==datlat[latlen])){ warning("Repeated Latitude, removing last column of data") psltemp <- psltemp[,-latlen,] } dim(psltemp) <- c(prod(dim(psltemp)[c(1,2)]),dim(psltemp)[3]) ttimes <- ncvar_get(ncdatatemp, "time") mytimes <- (which(ttimes>=200309)[1]):(which(ttimes<=200808)[length(which(ttimes<=200808))]) psltemp <- psltemp[,mytimes] psltemp <- psltemp[,EnsembleData$Months-8] psltempMean <- apply(psltemp,MARGIN = 1, mean) ObsList <- c(ObsList, list((psltempMean - EnsembleData$EnsembleMean)/EnsembleData$scaling)) } return(ObsList) } #Example Call: Tested 29/07/16 #tDataFiles <- c("~/Documents/CanadaData/MSLP/psl_Amon_ERA-Interim_reanalysis_r1i1p1_197901-201510.nc", "~/Documents/CanadaData/MSLP/psl_Amon_MERRA_reanalysis_r1i1p1_197901-201511.nc", "~/Documents/CanadaData/MSLP/psl_Amon_NCEP2_reanalysis_r1i1p1_197901-201512.nc") #tObs <- GetObservations(DataFiles=tDataFiles, which.obs="psl", EnsembleData = DJFdata) #tObsJJA <- GetObservations(DataFiles=tDataFiles, which.obs="psl", EnsembleData = JJAdata) GetObservationsZonalPressures <- function(DataFiles, which.obs="psl", EnsembleData, originalLat=lat, originalLon=lon, originalPressure=Pressure, permanent.scaling=1){ numFiles <- length(DataFiles) ObsList <- list() for(i in 1:numFiles){ ncdatatemp <- nc_open(file=DataFiles[i]) psltemp <- ncvar_get(ncdatatemp, which.obs)/permanent.scaling datlon <- ncvar_get(ncdatatemp, "lon") datlon[datlon>180] <- datlon[datlon>180] - 360 ldl <- length(datlon) if((ldl>length(originalLon))&(datlon[1]==datlon[ldl])){ warning("Repeated Longitude, removing last row of data") psltemp <- psltemp[-ldl,,,] } datlat <- ncvar_get(ncdatatemp, "lat") latlen <- length(datlat) if((latlen>length(originalLat))&(datlat[1]==datlat[latlen])){ warning("Repeated Latitude, removing last column of data") psltemp <- psltemp[,-latlen,,] } datpressure <- ncvar_get(ncdatatemp, "Z") prelen <- length(datpressure) if((prelen>length(originalPressure))&(datpressure[1]==datpressure[prelen])){ warning("Repeated Pressure, removing last columnBar of data") psltemp <- psltemp[,,-prelen,] } tzonal <- apply(psltemp, MARGIN=2:4, mean) dim(tzonal) <- c(prod(dim(tzonal)[c(1,2)]),dim(tzonal)[3]) ttimes <- ncvar_get(ncdatatemp, "time") mytimes <- (which(ttimes>=200309)[1]):(which(ttimes<=200808)[length(which(ttimes<=200808))]) tzonal <- tzonal[,mytimes] tzonal <- tzonal[,EnsembleData$Months-8] psltempMean <- apply(tzonal,MARGIN = 1, mean) ObsList <- c(ObsList, list((psltempMean - EnsembleData$EnsembleMean)/EnsembleData$scaling)) } return(ObsList) } #Plot an ensemble member and an observation field and their anomaly. #INPUTS: #ObsField: List of Observation fields as output by GetObservations #EnsembleData: Post-processed ensemble data in list form as output by ExtractCentredScaledDataAndBasis #which.obs: Integer: which member of the observations list #which.plot: Integer: which ensemble member #OriginalScale: Not yet coded #AnomBreaks: Vector of breaks for plotting (see ?image) #AnomCol: Vector of colours for plotting (1 lower than breaks, see ?image) plot.DataEnsembleMember <- function(ObsField, EnsembleData, which.obs = 1, which.plot=1, OriginalScale = TRUE, AnomCols=NULL, AnomBreaks=NULL,add.contours=FALSE,Anomaly.Only=FALSE,tcontours=seq(from=-40,by=2,to=40), contour.zero=FALSE, ...){ EnsembleField <- EnsembleData$CentredField[,which.plot]*EnsembleData$scaling + EnsembleData$EnsembleMean ObsToScale <- ObsField[[which.obs]]*EnsembleData$scaling + EnsembleData$EnsembleMean tanom <- EnsembleField - ObsToScale print(range(tanom)) par(mar=c(4,4,2,1),mfrow=c(1,1)) tdims <- c(length(lon), length(lat)) if(!Anomaly.Only){ par(mfrow=c(3,1)) image.plot(lon[order(lon)],lat, matrix(EnsembleField,nrow=tdims[1],ncol=tdims[2])[order(lon),],main=paste("Ensemble member",which.plot,sep=" ")) map("world",add=T) image.plot(lon[order(lon)],lat, matrix(ObsToScale,nrow=tdims[1],ncol=tdims[2])[order(lon),], main="Observations") map("world",add=T) } tanom1 <- tanom tanom1[tanom1>AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] # tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] # tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom0[tanom0AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom1[tanom1AnomBreaks[length(AnomBreaks)]] <- AnomBreaks[length(AnomBreaks)] tanom0[tanom0