Reading and displaying SARAL/AltiKa Brightness Temperature data using Python
On 25 February 2013, India and France jointly launched an oceanographic satellite mission called ‘Satellite with Advanced Research and Global Observation Satellite (Argos) and Ka-band Altimeter (ALtiKa)(SARAL/AltiKa). SARAL (SRL)carries a Radar Altimeter operating at Ka-band (35.75 GHz) for measuring the dynamic ocean surface topography. Besides an altimeter, SARAL carries onboard a dual frequency (23.8 and 37 GHz) nadir-looking Passive Microwave Radiometer (PMR), and an ‘Advanced Research and Global Observation Satellite-3’ (ARGOS-3) data collection system. This article will get you started with reading PMR data in Network common data form (NetCDF) file using Python.
Data
The PMR provides brightness temperature (Tb) and operates at two frequencies of 23.80 GHz (Tb_K)and 37.00 GHz (Tb_Ka), from an altitude of 800 km, with an orbit repeat cycle of 35 days or 501 revolutions. AltiKa points to nadir, while providing observations along the sub-satellite tracks, with about 8 km footprint that are traced at 75 km apart at the equator. The observations are provided along the track at two different temporal resolutions of 1 Hz and 40 Hz, with corresponding spatial resolution of about 6 km and 175 m, respectively. The Level-2 SRL data are provided in nine different types of Geophysical Data Records (GDR), which depending on latency and accuracy, are classified into three families of GDRs. For the present study, we utilize GDR-F data (source: www.mosdac.gov.in) for the period January 2020.
Data pre-processing
Daily SRL Tb data are available and can be processed to monthly data using Basic Radar Altimetry Toolbox (BRAT). All the ascending and the descending orbits of the Tb data are gridded using an operation which computes the mean of the daily along-track Tb for the given month by sub-sampling at each latitude and longitude. BRAT provides the possibility for extrapolating the Tb data to fill in the gaps between tracks. All extrapolated data of the Tb are output in the form of a single NetCDF file format.
Installing necessary libraries in Python
NetCDF files can be read with a few different Python modules. The most popular are netCDF4
and gdal
. We will use netCDF4
for this article. Using the anaconda Python distribution, we will install by simply typing pip install netCDF4
or conda install netCDF4
at your virtual environment.
Although we are not going to use gdal
, it is a tricky library to install. In order to avoid conflicts with other libraries, I will show you a simple trick how to install gdal
in a way that won’t interfere with other libraries. We will accomplish this by installing geopandas
library because gdal
is one of the dependencies and installing this will save you from all the hustles. Just type conda install geopandas
at your virtual environment and voilà!!! Doing this will install all the necessary dependencies like numpy
, pandas
, matplotlib
, etc. including gdal
.
To make sure your netCDF4
module is properly installed, start an interactive session in the terminal (type python
and press ‘Enter’). Then import netCDF4 as nc
and from osgeo import gdal
. And that’s it!
Reading a NetCDF Dataset
Loading a dataset is simple, just pass a NetCDF file path to netCDF4.Dataset()
. For this article, I’m using a file name “January_2020_tb_ka.nc” containing Tb data from Data.
from netCDF4 import Datasetdata = Dataset(r'\path\to\file.nc')
A NetCDF file consists of three basic parts: metadata, dimensions and variables. Variables contain both metadata and data. netCDF4
allows us to access the metadata and data associated with a NetCDF file. More details about NetCDF file is available here.
Access Metadata
Printing the dataset, data
, gives us information about the variables contained in the file and their dimensions.
print(data)
And the output is shown below:
<class 'netCDF4._netCDF4.Dataset'>
root group (NETCDF4 data model, file format HDF5):
FileType: Z=F(X,Y)
Conventions: CF-1.0
lat_min: -90.0
lat_max: 90.0
lon_min: -180.0
lon_max: 179.83333333333331
dimensions(sizes): lat(1081), lon(2160)
variables(dimensions): float64 lat(lat), float64 lon(lon), float64 tb_ka(lon, lat)
groups:
We can see from the above output the information for the file format, data source, data version, citation, dimensions, and variables. The variables we are interested in are lat
, lon
, and tb_ka
(brightness temperature, Tb_Ka). Using these variables, we can find the Tb for January 2020.
Accessing Dimensions
Each dimension is stored as a dimension class which contains relevant information. We can access the metadata for all dimensions by looping through all available dimensions:
for dim in data.dimensions.values():
print(dim)<class 'netCDF4._netCDF4.Dimension'>: name = 'lat', size = 541
<class 'netCDF4._netCDF4.Dimension'>: name = 'lon', size = 1080
Individual dimensions can be accessed by data.dimensions['lat']
.
Accessing Variables
To access information for a specific variable, we simply type data.variables[‘lat’]
(latitude) or data.variables[‘lon’]
(longitude).
And the output for latitude is shown below:
<class 'netCDF4._netCDF4.Variable'>
float64 lat(lat)
_FillValue: 1.8446744073709552e+19
axis: Y
long_name: lat
standard_name: latitude
units: degrees_north
valid_max: 90.0
valid_min: -90.0
unlimited dimensions:
current shape = (541,)
filling on
For longitude:
<class 'netCDF4._netCDF4.Variable'>
float64 lon(lon)
_FillValue: 1.8446744073709552e+19
axis: X
long_name: lon
standard_name: longitude
units: degrees_east
valid_max: 179.66666666666663
valid_min: -180.0
unlimited dimensions:
current shape = (1080,)
filling on
Accessing Data Values
The Tb data values are accessed by array indexing, and a numpy
masked array is returned. For more information about masked array, see masked_array. The variable tb_ka
data can be access as follows:
print (data.variables['tb_ka'][:])
And the output:
masked_array(
data=[[--, --, --, ..., --, --, --],
[--, --, --, ..., --, --, --],
[--, --, --, ..., --, --, --],
...,
[--, --, --, ..., --, --, --],
[--, --, --, ..., --, --, --],
[--, --, --, ..., --, --, --]],
mask=[[ True, True, True, ..., True, True, True],
[ True, True, True, ..., True, True, True],
[ True, True, True, ..., True, True, True],
...,
[ True, True, True, ..., True, True, True],
[ True, True, True, ..., True, True, True],
[ True, True, True, ..., True, True, True]],
fill_value=1.8446744073709552e+19)
Displaying Tb_Ka data
Now, let’s try to plot the Tb_Ka data using python. The code is simple. We have to just use matplotlib
library and that’s pretty much it. The full code is as follows:
import matplotlib.pyplot as plt
from netCDF4 import Datasetdata = Dataset(r'\path\to\file.nc')#Reading the viariables
lats = data.variables['lat'][:]
lons = data.variables['lon'][:]
tbka = data.variables['tb_ka'][:]#PLotting Tb_Ka
fig, (ax) = plt.subplots()#Creating colourbar for the plot
cmmap = plt.cm.jet
cmmap.set_bad('dimgrey',1.)
#Positioning the colourbarcbar_ax = fig.add_axes([0.92, 0.15, 0.03, 0.7])im = ax.imshow(tbka, cmap='jet')fig.colorbar(im, cax=cbar_ax, orientation='vertical', label='Brightness Temperature (K)')ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.gcf().set_size_inches(15, 15)
ax.set_title('SARAL Tb_Ka', fontsize=20)
fig.set_dpi(100.0)
plt.show()
Output:
Notice that the image is vertical. Don’t worry, we can fix this! We just have to rotate the tb_ka
array in counter-clockwise direction by 90 degrees. The most efficient way of doing this is by using the numpy.rot90()
module. You can read the details of the module here. The full code is as follows:
import matplotlib.pyplot as plt
from netCDF4 import Dataset
import numpy as npdata = Dataset(r'\path\to\file.nc')#Reading the viariables
lats = data.variables['lat'][:]
lons = data.variables['lon'][:]
tbka = data.variables['tb_ka'][:]#Rotating the matric by 90 degrees counter-clockwise
Ka = np.rot90(tbka, k=1, axes=(0, 1))#PLotting Tb_Ka
fig, (ax) = plt.subplots()
cmmap = plt.cm.jet
cmmap.set_bad('dimgrey',1.)cbar_ax = fig.add_axes([0.92, 0.15, 0.03, 0.7])im = ax.imshow(Ka, cmap='jet')fig.colorbar(im, cax=cbar_ax, orientation='vertical', label='Brightness Temperature (K)')ax.axes.xaxis.set_visible(False)
ax.axes.yaxis.set_visible(False)
plt.gcf().set_size_inches(15, 15)
ax.set_title('SARAL Tb_Ka', fontsize=20)
fig.set_dpi(100.0)
plt.show()
Output:
Conclusion
We have learnt how to read a NetCDF file and plot the Tb of SRL using Python. In this way, we can exploit the power of Python using libraries. Why Python? Python is an open-source and the Python community is large. So, the solution to any problem is readily available. Not to forget the plethora of libraries freely available.