R: How is it possible to export from R an image from a raster layer while maintaining image resolution? - r

I have been attempting to export a geographic raster layer which is projected in terms of the Lambert Conformal Conic projection (with a resolution of 1000 m by 1000 m) as an image file (e.g. as an *.eps) after having plotted it with some overlaid points (which is straightforward enough), but upon opening the image after export, it is clear that it has a resolution of a lesser quality than the aforementioned.
I've been using the 24 Bioclimate layers downloadable from: https://sites.ualberta.ca/~ahamann/data/climatewna.html. Here is an example of one of those layers (which was saved as a *.tif), and its resolution:
Below is the section of the script I have been running which is of relevance:
> projection <- raster("prediction.grd")
> projection
class : RasterLayer
dimensions : 3132, 2359, 7388388 (nrow, ncol, ncell)
resolution : 1000, 1000 (x, y)
extent : -3594000, -1235000, 4703000, 7835000 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=lcc +lat_1=49 +lat_2=77 +lat_0=0 +lon_0=-95 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : C:\Users\User\Documents\Project\prediction.grd
names : layer
values : 7.006775e-12, 0.001495079 (min, max)
> plot(projection, col = colorPalette(14, "jc"), colNA = 'black', axes = FALSE);
> points(train_locality_points, col='white', pch=15, cex=0.2)
Following the running of this code, I've gone about exporting the plot generated via the 'export' dropdown menu of R Studio to save it as an image with an extension that can be viewed outside of R instead of as a file with its original extension or something similar. I can open the image which is saved, but it evidently is not of the same quality as what the resolution of the layer is stated as above.
The image below is one I've saved in the way just described. To illustrate the trouble I've been having, Vancouver Island ( i.e. the large one with many white dots clustered at its southern end) is about 500 kilometres in length, which should correspond to about 500 pixels in the image if the resolution were 1 km by 1 km as the raster layer is. In this image the length of the island is represented by about a fifth of that number (...yes, I counted).
Any help as to how this issue could be remedied I would greatly appreciate. Thank-you for taking the time to read through and consider this question.

To get an image with same resolution as RasterLayer r, you can do
png('file.png', height=nrow(r), width=ncol(r))
plot(r, maxpixels=ncell(r))
dev.off()

Related

Convert HDF4 to raster; with longitude/latitude grids are available in another HDF file

I am trying to convent HDF4 files (representing daily Sea Ice Concentration) to raster object in R. However, the HDF files themselves do not contain the longitude/latitude grids or projection information, and such information should be extracted from another hdf file.
The website on data format says:
Data Format
Sea ice concentration maps with two different color scales are available as PNG image. The NIC color scale uses the same colors as the National Ice Center, the "visual" color scale uses white and shades of grey.
There is one file per day per region per color scale.
Sea ice concentration data are available as HDF4 files: There is one file per day per region. Each file contains one two-dimensional array of the sea ice concentration in a polar stereographic grid.
The longitude and latitude coordinates of each pixel in a the HDF4 file are saved in extra files, one file per region for each available resolution.
They are found here: https://seaice.uni-bremen.de/data/grid_coordinates/, sorted by hemisphere and grid resolution (see also the README file https://seaice.uni-bremen.de/data/grid_coordinates/README).
GEOTIFF files use the NIC color scale and were tested to work with QGIS. Ice concentrations are scaled between 0 and 100, land and missing values are set to 120 (older files: SIC: 0-200, land/NaN: 255).
I tried to use R to load this map using this code:
> require(raster)
> CurrTemp <- tempfile()
> download.file(url = "https://seaice.uni-bremen.de/data/amsre/asi_daygrid_swath/s6250/2003/feb/Antarctic/asi-s6250-20030214-v5.hdf", destfile = CurrTemp, mode = "wb", quiet = T)
> Map1 <- readAll(raster(CurrTemp))
> plot(Map1)
> Map1
class : RasterLayer
dimensions : 1328, 1264, 1678592 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0, 1264, 0, 1328 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : in memory
names : file43fc5b4e68de
values : 0, 100 (min, max)
The map is loaded into R as raster object but with wrong coordinates and with no projection. According to this page, coordinates should be extracted from another hdf file.
Could you please let me know how to convert these hdf files into raster obejcts with correct coordinates and projection.
Thanks.
I used one of the geotiff files that they also make available to find the extent and crs.
library(raster)
raster('asi-AMSR2-s6250-20180922-v5.tif')
#class : RasterLayer
#dimensions : 1328, 1264, 1678592 (nrow, ncol, ncell)
#resolution : 6250, 6250 (x, y)
#extent : -3950000, 3950000, -3950000, 4350000 (xmin, xmax, ymin, ymax)
#coord. ref. : +proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m +no_defs
#data source : asi-AMSR2-s6250-20180922-v5.tif
#names : asi.AMSR2.s6250.20180922.v5
#values : 0, 255 (min, max)
Now I know I can do
library(raster)
CurrTemp <- tempfile()
download.file(url = "https://seaice.uni-bremen.de/data/amsre/asi_daygrid_swath/s6250/2003/feb/Antarctic/asi-s6250-20030214-v5.hdf", destfile = CurrTemp, mode = "wb", quiet = T)
r <- raster(CurrTemp)
extent(r) <- c(-3950000, 3950000, -3950000, 4350000)
crs(r) <- "+proj=stere +lat_0=-90 +lat_ts=-70 +lon_0=0 +k=1 +x_0=0 +y_0=0 +a=6378273 +b=6356889.449 +units=m +no_defs "
# writeRaster(r, 'my_asi-s6250-20030214-v5.tif')
The "other hdf" file has longitude / latitude values for the cells, but that is not what you are after as the data do not have a lon/lat coordinate reference system.

Converting HDF to georeferenced file (geotiff, shapefile)

I am dealing with 28 HDF4 files on ocean primary productivity (annual .tar files can be found here: http://orca.science.oregonstate.edu/1080.by.2160.monthly.hdf.cbpm2.v.php)
My goal is to do some calculations (I need to calculate concentrations per area and obtain the mean over several years, i.e. combine all files spatially) and then convert them to a georeferenced file I can work with in ArcGIS (preferably shapefile, or geotiff).
I have tried several ways to convert to ASCII or raster files and then add a projection using gdalUtils tools such as gdal_translate and get_subdatasets. However, as the HDF4 files are not named after the standards (unlike the MODIS files), the latter doesn't work and I cannot access the subsets.
Here's the code I used to convert to raster:
library(raster)
library(gdalUtils)
setwd("...path_to_files...")
gdalinfo("cbpm.2015060.hdf")
hdf_file <- "cbpm.2015060.hdf"
outfile="testout"
gdal_translate(hdf_file,outfile,sds=TRUE,verbose=TRUE)
file.rename(outfile,paste("CBPM_test",".tif",sep=""))
rast <- raster("CBPM_test.tif")
wgs1984 <- CRS("+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0")
projection(rast) <- wgs1984
#crs(rast) <- "+proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0"
plot(rast)
writeRaster(rast, file="CBPM_geo.tif", format='GTiff', overwrite=TRUE)
The resulting projection is completely off. I'd appreciate help how to do this (converting through any format that works), preferably as batch process.
You've not set the extent of your raster, so its assumed to be 1:ncols, 1:nrows, and that's not right for a lat-long data set...
The gdalinfo implies its meant to be a full sphere, so if I do:
extent(rast)=c(xmn=-180, xmx=180, ymn=-90, ymx=90)
plot(rast)
writeRaster(rast, "output.tif")
I see a raster with full global lat-long extent and when I load the raster into QGIS it overlays nicely with an OpenStreetMap.
There doesn't seem to be enough metadata in the file to do a precise projection (what's the Earth radius and eccentricity?) so don't try and do anything small-scale with this data...
Here's how it looks:
Also you've jumped through a few unnecessary hoops to read this. You can read the HDF directly and set its extent and projection:
> r = raster("./cbpm.2017001.hdf")
What do we get:
> r
class : RasterLayer
dimensions : 1080, 2160, 2332800 (nrow, ncol, ncell)
resolution : 1, 1 (x, y)
extent : 0, 2160, 0, 1080 (xmin, xmax, ymin, ymax)
coord. ref. : NA
data source : /home/rowlings/Downloads/HDF/cbpm.2017001.hdf
names : cbpm.2017001
Set extent:
> extent(r)=c(xmn=-180, xmx=180, ymn=-90, ymx=90)
And projection:
> projection(r)="+init=epsg:4326"
And land values to NA:
> r[r==-9999]=NA
Write it, plot it:
> writeRaster(r,"r.tif")
> plot(r)

Why the box is so broad when plotting raster in R?

I want to plot the raster ,using code as follows:
library(raster)
tmp <- scan(what='')
'D:\temp\m2001EOS.tif'
ra<-raster(tmp)
plot(ra)
ra attribution as follows:
class : RasterLayer
dimensions : 1941, 1832, 3555912 (nrow, ncol, ncell)
resolution : 981.8572, 981.8572 (x, y)
extent : 4723620, 6522382, 4203136, 6108921 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=aea +lat_1=25 +lat_2=47 +lat_0=0 +lon_0=105 +x_0=4000000 +y_0=0 +datum=WGS84 +units=m +no_defs +ellps=WGS84 +towgs84=0,0,0
data source : D:\temp\m2001EOS.tif
names : m2001EOS
values : -32768, 32767 (min, max)
The plot is so wide that is not match xmin and xmax, but the range of height seem reasonable to ymin and ymax. Which parameter causes different patterns?
And how to adjust the box outline?
The example file is m2001EOS.tif
Using the volcano data set, we can get a simple reproducible example which does not require downloading data from a remote link:
library(raster)
plot(raster(volcano))
When plotting rasters (using raster::plot):
The shape of the bounding box is determined by the aspect ratio (shape) of the device window in which it is plotted.
The scale size is forced to be the same in x and y directions, as this is standard practice for spatial data (because we don't want to distort the shape of spatial data by stretchng it out to fit the box). We can see this in the example plot above by the fact that the raster is exactly square.
Given these two constraints, the need to fill the bounding box with blank areas follows as a direct consequence.
So how to avoid this? One way is to simply change the height to width ratio of the plot window or output file.
pdf(height = 4, width = 4)
plot(raster(volcano))
dev.off()
Even better is to use rasterVis::levelplot for nicer plotting:
library(rasterVis)
levelplot(raster(volcano), margin = F)

Raster stack incorrecting plotting latitude and longitude coordinates

I've downloaded precipitation data from the TRMM (rainfall across the tropics) satellite as a netCDF file and have been trying to plot the data in R as a rasterstack. However, R insists on plotting the latitude and longitude axes incorrectly, such that longitude is plotted on the x-axis (as it should be) but uses the latitude coordinates, while latitude is on the y-axis, but uses the longitude coordinates. I've tried using both the plot() and levelplot() functions but neither seems to work. Can anyone help me correct this?
These are the characteristic of the stack:
class : RasterStack
dimensions : 1440, 186, 267840, 12 (nrow, ncol, ncell, nlayers)
resolution : 0.25, 0.25 (x, y)
extent : -23.25, 23.25, -180, 180 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=longlat +datum=WGS84 +ellps=WGS84 +towgs84=0,0,0
names : X2016.01.16, X2016.02.15, X2016.03.16, X2016.04.15, X2016.05.16, X2016.06.15, X2016.07.16, X2016.08.16, X2016.09.15, X2016.10.16, X2016.11.15, X2016.12.16
Date : 2016-01-16, 2016-02-15, 2016-03-16, 2016-04-15, 2016-05-16, 2016-06-15, 2016-07-16, 2016-08-16, 2016-09-15, 2016-10-16, 2016-11-15, 2016-12-16
In the following image you can see the current output. It should show rainfall over the tropics from -23 to 23 degrees latitude, and -180 to 180 degrees longitude.
It's odd if the coordinates are switched prior to any processing. Maybe you want to asses the source you downloaded the data from and if there's maybe a better one.
Anyways, (in the meantime) the raster package can be of help for you .. specifically the transpose t() function. Here's an example:
# data before transpose
x <- getData('worldclim',var='tmean',res=10)
plot(x)
# data after transpose
y <- t(x)
plot(y)
There are also a couple of other functions in raster which could be of interest for you: flip and rotate
HTH
thanks for your response. It does seem strange that the coordinates are messed up right out of the box, and I did try downloading a fresh set of data and the same problem occurred. However, thanks to your input, I was able to rectify the problem through using the transpose() and flip() functions. I had to transpose the data, then flip it along both the x and y dimensions as the image was 'mirrored'. Here's the code I used in case anyone else encounters this problem with the TRMM data sets:
a.t = t(test.rasterstack)
a.flipy = flip(a.t, direction = 2)
a.t.flipxy = flip(a.t.flipy, direction = 1)
levelplot(a.t.flipxy)

Importing projected GeoTIFF and transforming to latitude and longitude coordinates in R

While I am not new to R, I am new to visualizing spatial data in it rather than ArcGIS.
I am attempting to import a GeoTIFF image from a public-access GIS website that is already projected in Mercator (image can be found here). Using the raster package in R, I can successfully import the GeoTIFF into R and plot it (see below).
> library(raster)
> mb <- raster("/Maps/mb_srelief10m/mb_srelief10m.tif")
> mb
class : RasterLayer
dimensions : 8060, 7220, 58193200 (nrow, ncol, ncell)
resolution : 10, 10 (x, y)
extent : -48598.54, 23601.46, 3850014, 3930614 (xmin, xmax, ymin, ymax)
coord. ref. : +proj=merc +lon_0=-70.31666666666668 +lat_ts=41.65 +x_0=0 +y_0=0 +datum=NAD83 +units=m +no_defs +ellps=GRS80 +towgs84=0,0,0
data source : C:\Users\Connor\Documents\ArcGIS\Maps\mb_srelief10m\mb_srelief10m.tif
names : mb_srelief10m
values : 0, 255 (min, max)
attributes :
ID COUNT BinValues Value
from: 0 1460797 0 0
to : 51 14795988 255 255
As you can see, the x- and y-axis labels represent the NAD83 values from the raster file (red boxes in image). Yet, when I attempt to use the crop function to use only a portion of this raster file, I cannot select the appropriate area because my user-defined extent object is in latitude and longitude coordinates. I understand I can use the drawExtent function to manually select the area but I want to automate this process.
My question is:
How do I transform the raster file so that my axes are in latitude and longitude and I can crop the file using latitude and longitude coordinates?
If this post would be more appropriate elsewhere, please let me know and I will remove the file. Thank you!

Resources