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))
}
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
Like the title says, I want to download multiple jpegs into an array from their url in a dataframe. The code I now have is as follows:
# for loop for train set
for (i in 1:274) {
theurl <- paste(train[i,c("Icon.URL")], sep = "")
z <- tempfile()
download.file(theurl,z,mode = "wb") #Download to the directory
train_image <- readJPEG(z)
writeJPEG(train_image, paste("imageTrain", i, ".jpg", sep = ""))
file.remove(z)
}
The 'train_image' is now a large array, with 786432 elements. This means that ultimately, only one of the jpegs is downloaded into that file, as each jpeg's dimensions are 512 x 512 x 3 = 786432. What is going wrong in the code that it seems to overwrite itself each time the for loop runs?
Additional information:
'train' is the data frame containing the urls
I got this code from here:
https://community.rstudio.com/t/access-and-download-images-from-urls-which-are-values-of-a-variable/66534 and
https://community.rstudio.com/t/access-and-download-images-from-urls/94422
I have also tried to use append() in the following way:
for (i in 1:10) {
theurl <- paste(train[i,c("Icon.URL")], sep = "")
z <- tempfile()
download.file(theurl,z,mode = "wb") #Download to the directory
train_img <- readJPEG(z)
train_image <- append(train_image, train_img)
writeJPEG(train_img, paste("imageTrain", i, ".jpg", sep = ""))
file.remove(z)
}
In this way, the images are added to 'train_image', but the results is a large numeric vector instead of an array
We can create an array with the desired dimensions and use an additional dimension for the picture number.
#Example list of urls
urllist <- rep("http://upload.wikimedia.org/wikipedia/commons/9/95/Apollonian_spheres.jpg", 10)
#create array with desired dimensions (pics here are 492x492x3). Include length of urllist as dimension
#create array with desired dimension
arrays <- array(dim = c(492, 492, 3, length(urllist)))
#loop through urllist and assign to array
for(i in 1:length(urllist)){
#download
z <- tempfile()
download.file(myurl,z,mode="wb")
#read
pic <- readJPEG(z)
#add to array.list
arrays[,,,i] <- pic
}
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)
}
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()
}
I'm new to R and trying to generate a lot of graphs from one file, with headers between different data sets.
I have a tab-delimited plaintext file, formatted like this:
Header: Boston city data
Month Data1 Data2 Data3
1 1.5 9.1342 8.1231
2 12.3 12.31 1.129
3 (etc...)
Header: Chicago city data
Month Data1 Data2 Data3
1 1.5 9.1342 8.1231
2 12.3 12.31 1.129
...
I would like to create a graph of month vs Data1, month vs Data2, and month vs Data2, for each city.
I know in python, I could iterate through each line, do something different if the line starts with 'Header', and then somehow process the numbers. I would like to simply do this:
for (data block starting with header) in inf:
data = read.delim()
barplot(data, main=header, ylab="Data1", xlab="Month")
# repeat for Data2, Data3
but I'm not sure how to actually iterate through the file, or if I should just split up my file by city into lots of small files, then run through a list of small files to read.
You could use a combination of gsub, grep and strsplit:
## get city name
nameSet <- function(x) {
return(gsub(pattern="Header: (.*) city data", replacement="\\1", x=x))
}
## extract monthly numbers
singleSet <- function(x) {
l <- lapply(x, function(y) {
## split single line by spaces
s <- strsplit(y, "[[:space:]]+")
## turn characters into doubles
return(as.double(s[[1]]))
})
## turn list into a matrix
m <- do.call(rbind, l)
return(m)
}
## read file
con <- file("data.txt", "r")
lines <- readLines(con)
close(con)
## determine header lines and calculate begin/end lines for each dataset
headerLines <- grep(pattern="^Header", x=lines)
beginLines <- headerLines+2
endLines <- c(headerLines[-1]-1, length(lines))
## layout plotting region
par(mfrow=c(length(beginLines), 3))
## loop through all datasets
for (i in seq(along=headerLines)) {
city <- nameSet(lines[headerLines[i]])
data <- singleSet(lines[beginLines[i]:endLines[i]])
for (j in 2:ncol(data)) {
barplot(data[,j], main=city, xlab="Month", ylab=paste("Data", j-1))
}
}
par(mfrow=c(1, 1))
Here is a slightly modified version of the function referred to in my comment.
read.funkyfile = function(funkyfile, expression, ...) {
temp = readLines(funkyfile)
temp.loc = grep(expression, temp)
temp.loc = c(temp.loc, length(temp)+1)
temp.nam = gsub("[[:punct:]][[:space:]]", "",
grep(expression, temp, value=TRUE))
temp.nam = gsub(expression, "", temp.nam)
temp.out = vector("list")
for (i in 1:length(temp.nam)) {
temp.out[[i]] = read.table(textConnection(
temp[seq(from = temp.loc[i]+1,
to = temp.loc[i+1]-1)]),
...)
names(temp.out)[i] = temp.nam[i]
}
temp.out
}
Assuming your file is named "File.txt", load the function and read in the data like this. You can add any of the arguments to read.table that you need to:
temp = read.funkyfile("File.txt", "Header", header=TRUE, sep="\t")
Now, plot:
# to plot everything on one page (used for this example), uncomment the next line
# par(mfcol = c(length(temp), 1))
lapply(names(temp), function(x) barplot(as.matrix(temp[[x]][-1]),
beside=TRUE, main=x,
legend=TRUE))
# dev.off() or par(mfcol = c(1, 1)) if par was modified
Here's what your small sample data look like with par(mfcol = c(length(temp), 1)):