Geotiff Image upside down in python - python

I have converted a NetCDF file to Geotiff. However when I display the Geotiff file it appears flipped or upside down. Here is my code:
import xarray as xr
import rioxarray as rio
import rasterio
nc_file = xr.open_dataset('Africa_salinity.nc')
nc_file
sss = nc_file['sss']
sss
sss = sss.rio.set_spatial_dims(x_dim='lon', y_dim='lat')
sss.rio.crs
sss.rio.write_crs("epsg:4326", inplace=True)
sss.rio.to_raster(r"Africa_19.tiff")
ax = show((sss))
How can I rotate the file and save it as tiff to use for further analysis?

You should be able to fix this using CDO on the command line. The following will likely work:
cdo invertlat infile outfile
This will invert the latitudes as the name suggests

Related

Python convert KML to image file

Looking for some guidance on how to convert a KML file to an image file showing simple polygons of the GPS data held in the file? I've been looking at ways to do this via python using mapnik and simplekml but I'm unsure if this is the correct usage of the tools.
Ideally, I just want a simple way to produce polygons from a KML file
Any advice very welcome
Manage to get a crud script working using geopandas
import geopandas as gpd
import matplotlib.pyplot as plt
gpd.io.file.fiona.drvsupport.supported_drivers['KML'] = 'rw'
# Filepath to KML file
fp = "history.kml"
polys = gpd.read_file(fp, driver='KML')
print(polys)
polys.plot()
plt.savefig('test.jpg')

How do I reproject a raster image in geoTiff format in python?

I want to reproject a raster image that is given as a geoTiff file into another coordinate system. The map is in WGS84-Pseudo-Mercator.
But when I run the following code I only get a white image as my output raster. How can I fix this?
import rioxarray
rds = rioxarray.open_rasterio("path_to_raster.tif")
crs = "EPSG:4978" # this depends on the exact projection you want to use
projected = rds.rio.reproject(crs)
projected.rio.to_raster("path_to_enu_raster.tif")
Well I found a solution by trial and error. This code works for germany:
from osgeo import gdal
filename = "berlin.tif"
input_raster = gdal.Open(filename)
for epsg in ["EPSG:4839", "EPSG:3068", "EPSG:25833"]:
gdal.Warp('output_raster' + epsg + '.tif', input_raster, dstSRS=epsg)

Export matplotlib basemap to SVG

How can I save a basemap created by the code below in Python as a SVG image (a *.pdf file would also do the job as it can easily be converted)?
from mpl_toolkits.basemap import Basemap
import numpy as np
import matplotlib.pyplot as plt
# lon_0 is central longitude of projection.
# resolution = 'c' means use crude resolution coastlines.
m = Basemap(projection='robin',lon_0=0,resolution='c')
m.drawcoastlines()
m.fillcontinents(color='coral',lake_color='aqua')
# draw parallels and meridians.
m.drawparallels(np.arange(-90.,120.,30.))
m.drawmeridians(np.arange(0.,360.,60.))
m.drawmapboundary(fill_color='aqua')
plt.title("Robinson Projection")
plt.show()
Source: https://matplotlib.org/basemap/users/robin.html
Applying plt.savefig("filename.pdf") only yields a white/emtpy file.
Is there a reason that plt.savefig(filename) wouldn't work?
By specifying the file format in the filename, you can make it any format you want. For example, if you want a .pdf you would type plt.savefig("filename.pdf").

How to correctly combine PNG and FITS data into one Matplotlib figure in Python?

I have a FITS file of 4545x4545 pixels with a header containing its coordinate system. Since DS9 (another software to view and handle FITS images) handles the color map scaling better, I had the idea of:
open the FITS file using DS9 to tweak the color map of the image,
save this image in a PNG file,
load this PNG file in matplotlib and add the header from the original FITS file, so I can add the coordinate system to the PNG file.
But the coordinates are not showing correctly, because the pixelization changes to different values in every step. How can I do this correctly?
This the relevant part of my code:
from astropy.io import fits
import matplotlib.pyplot as plt
import aplpy
from wcsaxes import WCSAxes
from astropy import wcs
import sys
import matplotlib.image as mpimg
image_fits = 'image_in.fits'
image_png = 'image_in.png' # this came from the one before, has different pixelization
image_data_png = mpimg.imread(image_png)
image_head_fits = fits.getheader(image_fits)
hdu_list = fits.open(image_fits)
F = aplpy.FITSFigure(hdu_list, figure=plt.figure(1))
fig = plt.figure()
mywcs = wcs.WCS(image_head_fits)
ax = WCSAxes(fig,[0.1, 0.1, 0.8, 0.8],wcs=mywcs)
fig.add_axes(ax)
ax.imshow(image_data_png)
plt.savefig('image_out.png')

Read .nc (netcdf) files using python

I am trying to learn how to read .nc (netcdf) files using Python in the most easiest/fastest way. I heard that it can be done with 3 lines of code but I really don't know how.
I am running the MITgcm numerical model. I'm trying to get an easy way to visualize the output data in the same way as programs like NCview does but with Python, so I can customise the parameters to read and everything.
I found this:
from matplotlib import pyplot as plt
import pandas as pd
import netCDF4
fp='uwstemp.nc'
nc = netCDF4.Dataset(fp)
plt.imshow(nc['Temp'][1,:,0,:])
plt.show()
It worked roughly like I want it, but I would like to understand word by word what is it doing. I guess 'Temp' is one of my variables, but I don't know how to figure out what all my variables are.
Specially, I don't understand plt.imshow(nc['Temp'][1,:,0,:]) thhat [1,:,0,:] I tried to change it and does not compile; but I don't understand what is it doing and why this numbers.
I use the MITgcm too. Say you have your state.nc output.
First of all make sure you import all you need:
from scipy.io import netcdf
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
The easiest way to read the data is:
file2read = netcdf.NetCDFFile(path+'state.nc','r')
temp = file2read.variables[var] # var can be 'Theta', 'S', 'V', 'U' etc..
data = temp[:]*1
file2read.close()
Then a quick way to plot say layer z at time t is:
plt.contourf(data[t,z,:,:])
To answer your question I commented the code:
from matplotlib import pyplot as plt # import libraries
import pandas as pd # import libraries
import netCDF4 # import libraries
fp='uwstemp.nc' # your file name with the eventual path
nc = netCDF4.Dataset(fp) # reading the nc file and creating Dataset
""" in this dataset each component will be
in the form nt,nz,ny,nx i.e. all the variables will be flipped. """
plt.imshow(nc['Temp'][1,:,0,:])
""" imshow is a 2D plot function
according to what I have said before this will plot the second
iteration of the vertical slize with y = 0, one of the vertical
boundaries of your model. """
plt.show() # this shows the plot
If you want to check the various dimensions of your data so you know what you can plot simply do print(nc['Temp'].shape)
For netCDF4 files (with python 3), use:
import netCDF4
file2read = netCDF4.Dataset(cwd+'\filename.nc','r')
var1 = file2read.variables['var1'] # access a variable in the file
where cwd is my current working directory for getting the file path for the .nc file in order to read it:
import os
cwd = os.getcwd()
I am using Windows, so file directory will be different than for Mac or Linux.
To look at all of the variable keys:
print(file2read.variables.keys())
Which will give an output like this:
dict_keys(['ap', 'ap_bnds', 'b', 'b_bnds', 'bnds', 'ch4', 'lat', 'lat_bnds', 'lev', 'lev_bnds', 'lon', 'lon_bnds', 'time', 'time_bnds'])
Or to look at all of the variables in your netcfd4 file, you can just print 'file2read':
print(file2read)
And the output will include something like this (look at the end specifically):
source_id: GFDL-ESM4
source_type: AOGCM AER CHEM BGC
sub_experiment: none
sub_experiment_id: none
title: NOAA GFDL GFDL-ESM4 model output prepared for CMIP6 update of RCP8.5 based on SSP5
variable_id: ch4
variant_info: N/A
references: see further_info_url attribute
variant_label: r1i1p1f1
dimensions(sizes): lev(49), bnds(2), time(1032), lat(180), lon(288)
variables(dimensions): float64 ap(lev), float64 ap_bnds(lev, bnds), float64 b(lev), float64 b_bnds(lev, bnds), float64 bnds(bnds), float32 ch4(time, lev, lat, lon), float64 lat(lat), float64 lat_bnds(lat, bnds), float64 lev(lev), float64 lev_bnds(lev, bnds), float64 lon(lon), float64 lon_bnds(lon, bnds), float64 time(time), float64 time_bnds(time, bnds)
You can notice that the last part includes the dimensions of the variables along with the type and name of the variables.
Check out this website for more info and examples:
https://www.earthinversion.com/utilities/reading-NetCDF4-data-in-python/
If you are working in Linux, my package nctoolkit (toolkit.readthedocs.io/en/latest/) offers similar functionality to ncview, but within Python. It can autoplot the contents of NetCDF files either within a Jupyter notebook or a web browser. The following should work for the data given:
import nctoolkit as nc
fp='uwstemp.nc'
data = nc.open_data(fp)
data.plot()

Categories