In R, I can prefix functions with the name of the package they belong to (e.g., dplyr::select). Nevertheless, I am having problems when doing this with c from the terra package. I can do it fine with base::c (should I want to):
base::c(1, 2, 3)
# [1] 1 2 3
However, I run into problems when running similar code for terra:
# Dummy SpatRaster
foo <- terra::rast(matrix(1:9, ncol=3))
# Works fine
c(foo, foo)
# Not so much
terra::c(foo, foo)
# Error: 'c' is not an exported object from 'namespace:terra'
I am confused how c is not an exported function of terra and yet I can access and use it just fine... so long as I don't use a prefix.
Q: Can someone explain why this is the case and how I can explicitly refer to c from terra?
PS ?terra::c gives a help page explaining how c combines SpatRasterobjects into a new SpatRaster object, which suggests to me that this function must've been implemented in the terra package.
This is because c is a "primitive" function --- these follow their own rules. A package cannot / need not import and export them
c
#function (...) .Primitive("c")
This is not the case, for, for example, nrow
nrow
#function (x)
#dim(x)[1L]
#<bytecode: 0x000000001662d228>
#<environment: namespace:base>
And terra creates a generic function from it, and exports it so that you can do terra::nrow().
Your question triggered me to look a bit more at this, and I noted that in the current version of terra many primitive functions do not work if you do not load the package with library(terra). For example, you get
foo <- terra::rast(matrix(1:9, ncol=3))
x <- c(foo, foo)
max(x)
#Error in x#ptr$summary(fun, na.rm, .terra_environment$options#ptr) :
# trying to get slot "ptr" from an object of a basic class ("NULL") with no slots
I just fixed that in the development version; and with that version the above returns
#class : SpatRaster
#dimensions : 3, 3, 1 (nrow, ncol, nlyr)
#resolution : 1, 1 (x, y)
#extent : 0, 3, 0, 3 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=longlat +datum=WGS84 +no_defs
#source : memory
#names : max
#min values : 1
#max values : 9
Related
I would like to write a RasterStack object and preserve names and metadata of the individual layers. How to preserve names is explained here. Is there a way to preserve metadata of individual layers when writing a RasterStack object?
Here is replicable code:
# load library
library(raster)
# create example rasters
ras_1 <- raster(nrows=180, ncols=360, xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=, vals=1)
ras_2 <- raster(nrows=180, ncols=360, xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=, vals=2)
ras_3 <- raster(nrows=180, ncols=360, xmn=-180, xmx=180, ymn=-90, ymx=90, resolution=, vals=3)
# assign names
names(ras_1) <- "raster_A"
names(ras_2) <- "raster_B"
names(ras_3) <- "raster_C"
# assign metadata
metadata(ras_1) <- list("metadata_raster_A")
metadata(ras_2) <- list("metadata_raster_B")
metadata(ras_3) <- list("metadata_raster_C")
# check
ras_1
ras_2
ras_3
metadata(ras_1)
metadata(ras_2)
metadata(ras_3)
# create and check stack
raster_stack <- stack(ras_1,
ras_2,
ras_3)
raster_stack
raster_stack[[1]]
metadata(raster_stack[[1]])
# write raster stack to disk
setwd("~")
# load library
library(terra)
# create rast object
raster_stack_terr <- rast(raster_stack)
# write raster stack
terra::writeRaster(raster_stack_terr, "raster_stack_terr_test.tif")
# load and check raster stack
raster_stack_check <- stack("raster_stack_terr_test.tif")
raster_stack_check
raster_stack_check[[1]]
names(raster_stack_check[[1]])
metadata(raster_stack_check[[1]])
Use terra to preseve names according to the 3rd answer from here.
When opening the RasterStack from disk, the metadata is not preserved. See console output:
> metadata(raster_stack_check[[1]])
list()
How to preserve metadata of individual layers when writing and re-loading a RasterStack object? Thanks!
It does not seem like {terra} offers an equivalent to raster::metadata(). However, from my perspective, the use cases would be limited here, because you would only be able to store structured information in corresponding format-specific tags (at least, this is my understanding) when writing to disk.
TIFF files (c.f. here) seem to offer the following tags:
TIFFTAG_DOCUMENTNAME
TIFFTAG_IMAGEDESCRIPTION
TIFFTAG_SOFTWARE
TIFFTAG_DATETIME
TIFFTAG_ARTIST
TIFFTAG_HOSTCOMPUTER
TIFFTAG_COPYRIGHT
TIFFTAG_XRESOLUTION
TIFFTAG_YRESOLUTION
TIFFTAG_RESOLUTIONUNIT
ESRI-Grids, on the other hand, do not offer any possibilities to store metadata except for the known header and maybe the filename as far as I know.
If you only wanted to store certain metadata with your raster object, you might as well make use of attr(r, "meta") <- "foobar". However, I don't see how this (random) information can be stored in specific formats and restored afterwards.
You already noticed names() when using {terra}, but there is also time() to be mentioned. Maybe this already suits your needs, since you did not specify what exactly you intend to store.
# set up a raster stack with three layers
library(terra)
#> terra 1.6.17
# create raster
r <- rast(nrows = 10, ncols = 10)
values(r) <- rnorm(100)
# set metadata
names(r) <- "foo"
time(r) <- as.Date("2000-01-01")
attr(r, "meta") <- "bar"
# inspect
r
#> class : SpatRaster
#> dimensions : 10, 10, 1 (nrow, ncol, nlyr)
#> resolution : 36, 18 (x, y)
#> extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84
#> source : memory
#> name : foo
#> min value : -2.503790
#> max value : 1.998731
#> time (days) : 2000-01-01
# write to disk
writeRaster(r, "sample.tif", overwrite = TRUE)
# read from disk
r2 <- rast("sample.tif")
r2
#> class : SpatRaster
#> dimensions : 10, 10, 1 (nrow, ncol, nlyr)
#> resolution : 36, 18 (x, y)
#> extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : lon/lat WGS 84 (EPSG:4326)
#> source : sample.tif
#> name : foo
#> min value : -2.503790
#> max value : 1.998731
#> time (days) : 2000-01-01
# try to access attributes
attr(r2, "meta")
#> NULL
As expected, data stored as attribute has been lost whereas information provided via names() and time() was sustained.
I have these 3 files here. Trying to stack them and extract a variable called "OzoneTropColumn". I am able to extract data for single file but unable to extract for multiple files.
library(raster)
library(ncdf4)
list_col1 <- list.files("E:/TES", pattern = "*.hdf", full.names = TRUE)
ncin1 <- raster::stack(list_col1, varname = "Data Fields/OzoneTropColumn", ncdf=TRUE)
Any help would be much appreciated.
Thank you
I don't know if this really works since I am no expert in raster or importing hdf files. But this code did load the three files in R for me but still gave some warnings:-
library(raster)
library(ncdf4)
list_col1 <- as.list(list.files("E:/TES", pattern = "*.hdf",
full.names = TRUE))
ncin1 <- raster::stack(list_col1,
varname = "Data Fields/OzoneTropColumn",
ncdf=TRUE)
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_1 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_0 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_1 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_0 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_1 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_0 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_1 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
[1] "vobjtovarid4: **** WARNING **** I was asked to get a varid for dimension named Data Fields/phony_dim_0 BUT this dimension HAS NO DIMVAR! Code will probably fail at this point"
But does shows me that it has read the 3 files
ncin1[[1]]
class : RasterLayer
dimensions : 83, 90, 7470 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0.5, 90.5, 0.5, 83.5 (xmin, xmax, ymin, ymax)
crs : NA
source : /home/shawn/Downloads/TES/TES-Aura_L3-O3-M2004m09_F01_12.hdf
names : Data.Fields.OzoneTropColumn.1
zvar : Data Fields/OzoneTropColumn
ncin1[[2]]
class : RasterLayer
dimensions : 83, 90, 7470 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0.5, 90.5, 0.5, 83.5 (xmin, xmax, ymin, ymax)
crs : NA
source : /home/shawn/Downloads/TES/TES-Aura_L3-O3-M2004m10_F01_12.hdf
names : Data.Fields.OzoneTropColumn.2
zvar : Data Fields/OzoneTropColumn
ncin1[[3]]
class : RasterLayer
dimensions : 83, 90, 7470 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0.5, 90.5, 0.5, 83.5 (xmin, xmax, ymin, ymax)
crs : NA
source : /home/shawn/Downloads/TES/TES-Aura_L3-O3-M2004m11_F01_12.hdf
names : Data.Fields.OzoneTropColumn.3
zvar : Data Fields/OzoneTropColumn
The script posted by Robert works well the only difference there was using as.list and without using as.list]1]1. I tried before using without as.list. The extracted data loses its georeference for reason unknown. So had to give extent and projection after raster stack. Thanks Robert.
Good day everyone..
I have 13 bioclimatic variables (in .tiff format) that I will used to perform sdm by using dismo package.
I followed the tutorial written by Robert J. Hijmans and Jane Elith.
However, when I tried to stack all of the variables, I got the following error
Error in .local(.Object, ...) :
Error in .rasterObjectFromFile(x, band = band, objecttype = "RasterLayer", :
Cannot create a RasterLayer object from this file.
All of my file's coordinate system, extent, and cell size have been adjusted so they are all the same..
when I tried to used the alternative brick function, I got the following error :
Error in .rasterObjectFromFile(x, objecttype = "RasterBrick", ...) :
Cannot create a RasterLayer object from this file.
In addition: There were 12 warnings (use warnings() to see them)
I used the warning() message but it was empty..
do any of you have any hints regarding what may be the cause of such errors?
i've tried to google it, but unfortunately, no answer can solve it.
Thank you in advance..
Here presented is the fraction of the transcript
#setting the workspace
setwd("D:/Riset/MaxentSelaginella/newpaperproject_part2/MakalahVI/Workspace_R")
#Loading Libraries
library("sp")
library("raster")
library("maptools")
library("rgdal")
library("dismo")
library("rJava")
#open the csv file
obs.data <- read.csv(file = "data3/Selaginella_plana.csv", sep = ",")
#open Environmental Data
files <- list.files(path = "data3/tif/", pattern = ".tif", full.names=TRUE)
#stacking all the files
predictors <- brick(files)
I guess you need to use stack instead of brick. As per brick help, in fact:
A RasterBrick is a multi-layer raster object. They are typically created from
a multi-layer (band) file; but they can also exist entirely in memory.
They are similar to a RasterStack (that can be created with stack), but processing
time should be shorter when using a RasterBrick. Yet they are less flexible as they can only point to a single file.
So, if we try to “stack” multiple files:
library(raster)
r <- raster(ncols = 100, nrows = 100, vals = 1:10000)
rfile1 <- tempfile(fileext = ".tif")
writeRaster(r, filename = rfile1)
rfile2 <- tempfile(fileext = ".tif")
writeRaster(r, filename = rfile2)
files_to_stack <- c(rfile1, rfile2)
This fails:
brick(files_to_stack)
#> Warning in if (x == "" | x == ".") {: the condition has length > 1 and only
#> the first element will be used
#> Warning in if (!start %in% c("htt", "ftp")) {: the condition has length > 1
#> and only the first element will be used
#> Warning in if (fileext %in% c(".GRD", ".GRI")) {: the condition has length
#> > 1 and only the first element will be used
#> Warning in if (!file.exists(x)) {: the condition has length > 1 and only
#> the first element will be used
.....
#> Error in .rasterObjectFromFile(x, objecttype = "RasterBrick", ...): Cannot create a RasterLayer object from this file.
While this works:
stack(files_to_stack)
#> class : RasterStack
#> dimensions : 100, 100, 10000, 2 (nrow, ncol, ncell, nlayers)
#> resolution : 3.6, 1.8 (x, y)
#> extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
#> names : file46e41bcd78e3, file46e43ea75bad
#> min values : 1, 1
#> max values : 10000, 10000
If you want to have a brick to get some gain in “efficiency” in further
processing, you can save the different "layers" as a multiband tiff, and then open using brick:
rfile_multi <- tempfile(fileext = ".tif")
writeRaster(stack(files_to_stack), filename = rfile_multi)
brick(rfile_multi)
#> class : RasterBrick
#> dimensions : 100, 100, 10000, 2 (nrow, ncol, ncell, nlayers)
#> resolution : 3.6, 1.8 (x, y)
#> extent : -180, 180, -90, 90 (xmin, xmax, ymin, ymax)
#> coord. ref. : +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0
#> data source : D:\RTemp\RtmpacXztJ\file4808784f268c.tif
#> names : file4808784f268c.1, file4808784f268c.2
#> min values : 1, 1
#> max values : 10000, 10000
Created on 2018-11-10 by the reprex package (v0.2.1)
I have been trying to use the gdal_grid in R and while running the example data set I recieve a raster which has only zero values. I have tried experimenting with this with my own data, and have searched the forums with no luck. Can others get the example to work?
I have tried to explicitly call my path to my GDAL library, and have updated the version of GDAL. I am running R studio with version 3.3.1.
library(raster)
library(rgeos)
library(gdalUtils)
# We'll pre-check to make sure there is a valid GDAL install
# and that raster and rgdal are also installed.
# Note this isn't strictly neccessary, as executing the function will
# force a search for a valid GDAL install.
gdal_setInstallation()
valid_install <- !is.null(getOption("gdalUtils_gdalPath"))
if(require(raster) && valid_install)
{
# Create a properly formatted CSV:
temporary_dir <- tempdir()
tempfname_base <- file.path(temporary_dir,"dem")
tempfname_csv <- paste(tempfname_base,".csv",sep="")
pts <- data.frame(
Easting=c(86943.4,87124.3,86962.4,87077.6),
Northing=c(891957,892075,892321,891995),
Elevation=c(139.13,135.01,182.04,135.01)
)
write.csv(pts,file=tempfname_csv,row.names=FALSE)
# Now make a matching VRT file
tempfname_vrt <- paste(tempfname_base,".vrt",sep="")
vrt_header <- c(
'<OGRVRTDataSource>',
'\t<OGRVRTLayer name="dem">',
'\t<SrcDataSource>dem.csv</SrcDataSource>',
'\t<GeometryType>wkbPoint</GeometryType>',
'\t<GeometryField encoding="PointFromColumns" x="Easting" y="Northing" z="Elevation"/>',
'\t</OGRVRTLayer>',
'\t</OGRVRTDataSource>'
)
vrt_filecon <- file(tempfname_vrt,"w")
writeLines(vrt_header,con=vrt_filecon)
close(vrt_filecon)
tempfname_tif <- paste(tempfname_base,".tiff",sep="")
# Now run gdal_grid:
setMinMax(gdal_grid(src_datasource=tempfname_vrt,
dst_filename=tempfname_tif,a="invdist:power=2.0:smoothing=1.0",
txe=c(85000,89000),tye=c(894000,890000),outsize=c(400,400),
of="GTiff",ot="Float64",l="dem",output_Raster=TRUE))
}
r<-raster(tempfname_tif)
r
#class : RasterLayer
#dimensions : 400, 400, 160000 (nrow, ncol, ncell)
#resolution : 10, 10 (x, y)
#extent : 85000, 89000, 890000, 894000 (xmin, xmax, ymin, ymax)
#coord. ref. : NA
#data source : C:\Users\m.modeler\AppData\Local\Temp\RtmpW6HvOc\dem.tiff
#names : dem
#min values : 0
#max values : 0
plot(r)
Raster results plot with zero values:
Thanks much,
I have got the code to run by changing the path from the temp directory to a folder on my hard drive. Example below.
# change to a path on your computer
setwd("C:\\Users\\m.modeler\\Documents\\R\\gdal_Examples")
#######################################################
#create XYZ csv
pts <- data.frame(
Easting=c(86943.4,87124.3,86962.4,87077.6),
Northing=c(891957,892075,892321,891995),
Elevation=c(139.13,135.01,182.04,135.01))
write.csv(pts,file="dem.csv",row.names=FALSE)
#######################################################
#create VRT
fn_vrt<-"dem.vrt"
# Now make a matching VRT file
vrt_header <- c(
'<OGRVRTDataSource>',
'\t<OGRVRTLayer name="dem">',
'\t<SrcDataSource>dem.csv</SrcDataSource>',
'\t<GeometryType>wkbPoint</GeometryType>',
'\t<GeometryField encoding="PointFromColumns" x="Easting" y="Northing" z="Elevation"/>',
'\t</OGRVRTLayer>',
'\t</OGRVRTDataSource>')
vrt_filecon <- file(fn_vrt,"w")
writeLines(vrt_header,con=vrt_filecon)
close(vrt_filecon)
#######################################################
#create interpolated DEM
fn_tif <- "dem.tif"
# Now run gdal_grid:
r.dem <- setMinMax(gdal_grid(src_datasource=fn_vrt,
dst_filename=fn_tif,a="invdist:power=2.0:smoothing=1.0",
txe=c(85000,89000),tye=c(894000,890000),outsize=c(400,400),
of="GTiff",ot="Float64",l="dem",output_Raster=TRUE,verbose=TRUE))
plot(r.dem)
I am working from the post here: How can I create raster mosaic using list of rasters? to create a raster mosaic using a list of rasters. The example in the answer given by fmark works perfectly but I get an error when I follow the steps using my own data. Not sure where I am going wrong, any help would be very much appreciated!
R version 2.15.3 (2013-03-01)
Platform: x86_64-unknown-linux-gnu (64-bit)
locale:
[1] C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] raster_2.2-12 rgdal_0.8-10 sp_1.0-14
loaded via a namespace (and not attached):
[1] grid_2.15.3 lattice_0.20-15 tools_2.15.3
I used the function from How to iterate over a list preserving the format of the results? to generate my raster list.
ListRasters <- function(list_names) {
raster_list <- list() # initialise the list of rasters
for (i in 1:(length(list_names))){
grd_name <- list_names[i] # list_names contains all the names of the images in .grd format
raster_file <- raster(grd_name)
}
raster_list <- append(raster_list, raster_file) # update raster_list at each iteration
}
Then I generate my list names and create my raster list from them.
wgs84.tif.list <- list.files(path=mod.dir, pattern=glob2rx("*_wgs84.tif"), full.names=T,recursive=F)
list_names <- NULL
for (i in 1:length(wgs84.tif.list)) {
list_names <- c(list_names, wgs84.tif.list[i])
}
raster.list <-sapply(list_names, FUN = ListRasters)
raster.list$fun <- mean
mos <- do.call(mosaic, raster.list)
This is the error I get:
Error in function (classes, fdef, mtable) : unable to find an
inherited method for function 'mosaic' for signature '"missing",
"missing"'
My raster.list starts off like this (it contains 11 rasters):
$`/import/c/w/kbennett/MODSCAG/snow-dav.jpl.nasa.gov/modscag-historic/2002/091/MOD09GA.A2002091.h08v03.005.2007124035032snow_fraction_wgs84.tif`
class : RasterLayer
dimensions : 2400, 2400, 5760000 (nrow, ncol, ncell)
resolution : 463.3127, 463.3127 (x, y)
extent : -11119737, -10007786, 5559984, 6671935 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=sinu +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : /import/c/w/kbennett/MODSCAG/snow-dav.jpl.nasa.gov/modscag-historic/2002/091/MOD09GA.A2002091.h08v03.005.2007124035032snow_fraction_wgs84.tif
names : MOD09GA.A2002091.h08v03.005.2007124035032snow_fraction_wgs84
values : 0, 255 (min, max)
My rasters were not named correctly. To rectify this ran, before calling fun on it:
names(rasters.list) <- NULL
Then:
raster.list$fun <- mean
mos <- do.call(mosaic, raster.list)
To expand a bit on foo's answer. You can use sapply to create a list of RasterLayer objects.
rlist <- sapply(list_names)
Then add the names of the other arguments. The first ones are 'x' and 'y' (see ?mosaic). However it will also work if they are NULL (as their position will be used).
names(rlist)[1:2] <- c('x', 'y')
rlist$fun <- mean
rlist$na.rm <- TRUE
And now call do.call
x <- do.call(mosaic, rlist)
how about that? Im noob in R.
lista = list of rasters
mosaicar = function(lista){
raster = lista[[1]]
for (i in 2:length(lista)){
raster1 = mosaic(raster, lista[[i]], fun = max)
raster = raster1
}
return(raster)
}
As mentioned by #Bappa Das above, the provided solution does not work on terra. #moho wu did not mention the na.rm issue. It remains unclear how to pass the na.rm to terra::mosaic. If anywone has a working answer...