I'm reading multiple .tif files in R and am converting raster value less than 6000 as NA, and then plotting the raster and saving it in folder as .png. Everything works fine except that output png raster plots are empty. Here is my code which I'm using -
library(raster)
#get the path
path <- "C:/lab/fire/photo_2/gif_images/gif_images_2"
#list all files
files <- list.files(path, pattern = "tif$", full.names = TRUE)
files
for (i in 1:length(files)){
# load one raster
r <- raster(files[i])
values(r)[values(r) < 6000] = NA
png(paste("plot_", i, ".png", sep = ""), width=600, height=500, res=120)
plot(r)
dev.off()
}
I can do this on single rasters quite easily but need to run the loop to account for 300 .tifs.
You have to print your plot to make it visible in png:
An example with fake data:
library(raster)
r <- s <- t <- u <- v <- z <- raster()
r[] <- s[] <- t[] <- u[] <- v[] <- z[] <- 1:ncell(r)
rast.list <- list(r,s,t,u,v,z)
for (i in 1:length(rast.list)){
r <- rast.list[[i]]
r <- clamp(r, -Inf, 6000)
png(paste("plot_", i, ".png", sep = ""), width=600, height=500, res=120)
print(plot(r))
dev.off()
}
Related
I'm trying to run pvclust as a test Im running it in small subset of files. The issue is it works but instead of list which i would have used downstream to print it to individual files it gets printed.
My code
list_of_files <- list.files('Model_pvclust/',pattern = '\\.txt$', full.names = TRUE)
cmplx_ht<-function(file_list){
start_time <- Sys.time()
df_list<-list()
#heat_list<-list()
pv_list<-list()
require(pvclust)
for(f in file_list){
message(paste0("Making pvclust for: ",f))
#fname <- gsub("Model_hmap\/\/|\.txt","",f)
df <- read.csv(f, header = TRUE, sep = "\t", check.names = FALSE)
mat <- t(scale(t(as.matrix(df[,grepl("TCGA-",colnames(df))]))))
rownames(mat)<-df$Symbol
df_list[[f]]<-mat
#print(head(mat))
hm <- pvclust(as.data.frame(t(mat)), method.hclust="complete",
method.dist="euclidian",nboot = 10, parallel=T)
#heat_list[[f]]<-hm
plot(hm)
b <-pvrect(hm, alpha=.95)
pv_list[[f]] <-b
#dev.off()
# dev.off()
message("Done")
}
end_time <- Sys.time()
time_taken<- end_time-start_time
message(paste0(time_taken,"s"))
return(pv_list)
}
hm_lst<-cmplx_ht(list_of_files)
To print it to individual files this is what Im doing
for (i in 1:length(hm_lst)) {
file_name = paste(names(hm_lst)[[i]],".pdf", sep="")
#file_name = paste(names(hm_lst),".pdf", sep="")
pdf(file_name,width = 15,height = 10)
draw(hm_lst[[i]])
dev.off()
}
But my hm_list is coming empty the output is getting printed which i don't want.
I want to store the output as lists the want to print it to files
Im not sure what exactly I'm doing wrong. Any suggestion or help would be really appreciated
You can use recordPlot to store a base plot in a object.
x = 1:10
plot(x)
# record the plot
g <- recordPlot()
# clean the device
plot.new()
# plot is saved to g
g
I have some code in R which does the following:
Uses lapply to bring in files in a set folder e.g. 1997 data
Makes file list into a brick - they are NetCDF files, so I've used brick function
Stacks the bricks into one raster stack of months for each year.
Calculate the mean from the stack
Crops the new mean raster to the Area of Interest (AOI).
I've got a working code, see below, but it is clunky and I feel could be better in one loop to then run through each year's folder (I have data from 1997 to 2018). Could anyone aid in streamlining this into a simple looped code I could run by changing the filepath? I've used loops a bit before but not from scratch.
# Packages:
library(raster)
library(parallel) # Check cores in PC
library(lubridate) # needed for lapply
library(dplyr) # ""
library(sf) # For clipping data
library(rgdal)
# ChlA
# Set file paths for input and outputs:
usingfp <- "/filepath/GIS/ChlA/1997/"
the_dir_ex <- "Data/CHL/1997"
# List all NETCDF files in folder:
CHL_1997 <- list.files(path = usingfp, pattern = "\\.nc$", full.names = TRUE,
recursive = FALSE)
# Make file list into brick
CHL_1997_brick <- lapply(CHL_1997,
FUN = brick,
the_dir = the_dir_ex)
# Stack bricks
s <- stack(CHL_1997_brick)
# Calculate mean from stack
mean <- calc(s, fun = mean, na.rm = T)
plot(mean)
# Load vector boundary to "crop" to
AOI <- readOGR("/filepath/AOI/AOI.shp")
plot(AOI,
main = "Shapefile imported into R - crop extent",
axes = TRUE,
border = "blue",
add = T)
# crop the raster using the vector extent
CHL_1997_mean <- crop(mean, AOI)
plot(CHL_1997_mean, main = "Cropped mean CHL - 1997")
# add shapefile on top of the existing raster
plot(AOI, add = TRUE)
Thanks very much.
Something like this should work
library(raster)
AOI <- shapefile("/filepath/AOI/AOI.shp")
path <- "/filepath/GIS/ChlA/"
years <- 1997:2018
for (yr in years) {
fp <- file.path(path, yr)
fout <- file.path(fp, paste0(year, ".tif"))
print(fout); flush.console()
# if (file.exists(fout)) next
files <- list.files(path=fp, pattern="\\.nc$", full.names=TRUE)
b <- lapply(files, brick)
s <- stack(b)
s <- mean(s)
s <- crop(s, AOI, filename=fout) #, overwrite=TRUE)
}
Notes:
mean(s) is more efficient than calc(s, mean)
If the AOI is relatively small, it can be more efficient to first
use crop, then mean (and then use writeRaster)
You can also use terra like this:
library(terra)
AOI <- vect("/filepath/AOI/AOI.shp")
path <- "/filepath/GIS/ChlA/"
years <- 1997:2018
for (yr in years) {
fp <- file.path(path, year)
fout <- file.path(fp, paste0(year, ".tif"))
print(fout); flush.console()
# if (file.exists(fout)) next
files <- list.files(path=fp, pattern="\\.nc$", full.names=TRUE)
r <- rast(files)
s <- mean(r)
s <- crop(s, AOI, filename=fout) #, overwrite=TRUE)
}
R Programming Language (New to this)
I am attempting to loop through a number of tiled rasters that have been output by splitRaster. During the loop I want to carry out some processes on each raster.
But the following code throws an error.
library(ForestTools)
library(raster)
library(sp)
library(rgdal)
library(SpaDES)
rm(list = ls())
tmpdir <- file.path(tempdir(), "splitRaster")
lin <- function(x){x * 0.1 + 0.6}
inCHM <- raster("input raster path and name.tif")
split <- splitRaster(inCHM, 5, 5, c(0.05, 0.05), tmpdir)
files <- list.files(path=tmpdir, pattern="*.grd", full.names=FALSE, recursive=FALSE)
file.names <- dir(tmpdir, pattern ="*.grd")
for(file.names in files ){
name <- file.names
ttops <- vwf(name, winFun = lin, minHeight = 5)
writeOGR(ttops, "output folder", name, driver = "ESRI Shapefile")
}
and this is the error
[1] "Xrastername_tile1.grd"
Error in CRS(x) :
PROJ4 argument-value pairs must begin with +: Xrastername_tile1.grd
More to the problem (24/7/2020),
I have removed the loop for trouble shooting instead just choosing one of the splitRasters outputs that would be used in the loop ie files[[3]]
When I run the following code the error is the same;
library(ForestTools)
library(raster)
library(sp)
library(rgdal)
library(SpaDES)
rm(list = ls())
# set temp directory
tmpdir <- "C:\\R-Test\\Temp_Output"
# get raster
r <- raster("C:\\Lidar\\grid_treeheight_max_1m_nofill.tif")
# define projection
projection(r) <- "+proj=utm +zone=50 +south +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs"
# split raster brick
y <- splitRaster(r, 8, 8, c(0.05, 0.05), tmpdir)
# Get the complete file locations with full.names = T
files <- list.files(path=tmpdir, pattern="*.grd", full.names=FALSE, recursive=FALSE)
tmpfile <- paste(tmpdir, "\\", files[[3]], sep="")
lin <- function(x){x * 0.06 + 0.6}
ttops <- vwf(tmpfile, winFun = lin, minHeight = 5)
This is the error
Error in CRS(x) :
PROJ4 argument-value pairs must begin with +: D:\R-Test\Temp_Output\Xgrid_treeheight_max_1m_nofill_tile11.grd
When I run the following code using one of the splitRaster outputs (files[[3]]) from the above code it runs error free and I am able to plot ttops.
rm(list = ls())
# set temp directory
tmpdir <- "D:\\R-Test\\Temp_Output"
# get raster
r <- raster("D:\\R-Test\\Temp_Output\\Xgrid_treeheight_max_1m_nofill_tile11.grd")
lin <- function(x){x * 0.06 + 0.6}
ttops <- vwf(r, winFun = lin, minHeight = 5)
Why is the PROJ4 error occurring?
This seems to be the error that is causing the loop to fail?
I think the problem is that you are trying to feed the vwf function with the file name instead of a raster object. I would also recommend using lapply instead of for for the loop. Here is a code that should work
library(raster)
library(ForestTools)
library(rgdal)
# Get the complete file locations with full.names = T
files <- list.files(path=tmpdir, pattern="*.grd", full.names=T, recursive=FALSE)
# Loop over each item of the list, i.e., each raster
lapply(files, function(x){
# Load the image as raster
image <- raster(x)
# Calculate vwf (I added a dummy function for winFun)
ttops <- vwf(image, winFun = function(x){x * 0.06 + 0.5}, minHeight = 5)
# Write the file with the name of each raster
writeOGR(ttops, "output_dir", names(x), driver = "ESRI Shapefile")
})
I have a main directory, and each folder within this has the same format of data. I'd like to go into each folder individually and preform the same function. Each folder has a slightly different name, but the files all follow the same naming protocol (ie. YYYYMMDD_XX_raster1.tif; YYYYMMDD_XX_raster2.geo.tif).
I've tried modifying a code that I already had, but in that instance the .tifs were all in the same folder.
library(raster)
library(sp)
library(rgdal)
#create sample rasters
r <- raster(nrow=10, ncol=10)
x <- setValues(r, sample(-180:180,ncell(r), replace(T))
y <- setValues(r, sample(-90:90,ncell(r), replace(T))
dq2<- function(in_dir_path, add_file_name, silent=F){
#inputs
#in_dir_path: path to directory
#add_file_name: ie. finished
list_files <- sort(list.files(path= in_dir_path, pattern =""))
print(list_files)
if(silent == F){
message(paste"Nb files in in_dir", length(list_files))
}
for(i in 1: length(list_files)){
if(silent == F){
message(paste("Processing", i, "out of", length(list_files)))
}
#get rasters (this would normally grab from within the subfolder, but here refers to the rasters created above)
x <- raster(paste(in_dir_path, "/$raster1.geo.tif", list_files[i], sep = ""))
y <- raster(paste(in_dir_path, "/$raster2.geo.tif", list_files[i], sep = ""))
#Create filename to save
split<- strsplit(list_files[i], split=".tif")[[1]][1]
sprint (split)
nameFile <- paster(in_dir_path, "/", split, "_", add_file_name, ".tif", sep = "")
# calculation here
tf <- function(x,y) {
return(100 * x / y)
}
answer <- overlay(x,y, fun=tf)
WriteRaster(answer, filename=nameFile, format="GTiff", overwrite=TRUE, options=c('TFW=YES'))
if(silent == F){
message(paste("process complete", nameFile))
}
}
message("finished")
dq2("C:/Users", "fin", silent=F)
When I try to run this, it looks like the code is waiting for more input.
I'm working with a .tif image captured from a Sequoia Parrot sensor. I want to do radiometric calibration and export the resulting image in the same format (.tif).
I import the image as a raster, then process with some algorithms and finally try to export as a .tif file but it is impossible to open. The resulting file is 7 MB but the image cannot be viewed.
Here is my script:
setwd("/where the images are/")
rlist=list.files(getwd(), pattern="TIF$", full.names=F)
options(digits=20)
for(i in rlist){
data <- raster(i)
meta <- exifr(i, recursive = FALSE, quiet = TRUE, exiftoolargs = NULL)
SM <- meta$SensorModel
SM <- strsplit(SM, ",")[[1]]
A <- as.numeric(SM[1])
B <- as.numeric(SM[2])
C <- as.numeric(gsub("[^0-9\\.]", "", SM[3]) )
Ep <- meta$ExposureTime ## Epsilon
f <- meta$FNumber ## Focus Number
ys <- meta$ISO ##ISO
I <- f^2*(data-B)/(A*Ep*ys+C)
I <- flip(I,"x")
I <- flip(I,"y")
Is original script well indented? With your example image, everything works right.
I made small changes for better understanding:
library(raster)
library(exifr)
setwd("/where the images are/")
rlist=list.files(getwd(), pattern="TIF$", full.names=F)
options(digits=20)
for(i in seq_along(rlist)){ # small change
data <- raster(rlist[i]) # small change
meta <- exifr(rlist[i], recursive = FALSE, quiet = TRUE, exiftoolargs = NULL) # small change
SM <- meta$SensorModel
SM <- strsplit(SM, ",")[[1]]
A <- as.numeric(SM[1])
B <- as.numeric(SM[2])
C <- as.numeric(gsub("[^0-9\\.]", "", SM[3]) )
Ep <- meta$ExposureTime ## Epsilon
f <- meta$FNumber ## Focus Number
ys <- meta$ISO ##ISO
I <- calc(data,fun = function(x){f^2*(x-B)/(A*Ep*ys+C)}) # small change
I <- flip(I,"x")
I <- flip(I,"y")
print(plot(I))
}