简体   繁体   中英

How to ofsetting cartopy coast line to match with actual lat and lon

I am using Arch Linux with cartopy version 0.17.0 installed on the system through packagemanager. I am trying to plot a simple satellite image from hdf5 file with cartopy as plotting tool. Following is the sample code I am trying to do to produce image:-

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import h5py
import numpy as np
import cartopy
import matplotlib.pyplot as plt
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER

input_file = "../input/satellite/3RIMG_27MAR2020_0545_L1C_ASIA_MER.h5"

fh=h5py.File(input_file, 'r')
X = fh["X"][()]
Y = fh["Y"][()]
IMG_TIR1 = fh["IMG_TIR1"][()][0, ::-1, :]

lower_latitude, left_longitude = fh['Projection_Information'].attrs["lower_left_lat_lon(degrees)"]
upper_latitude, right_longitude = fh['Projection_Information'].attrs["upper_right_lat_lon(degrees)"]
lons_values = np.linspace(left_longitude, right_longitude, X.shape[0])
lats_values = np.linspace(lower_latitude, upper_latitude, Y.shape[0])
print(lons_values)
print(lats_values)
lons, lats = np.meshgrid(lons_values, lats_values)

fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(projection=cartopy.crs.Mercator()))

ax.pcolormesh(lons, lats, IMG_TIR1, cmap=plt.cm.gist_gray, transform=cartopy.crs.PlateCarree())
ax.coastlines('50m', linewidth=0.8, color='black')
gl = ax.gridlines(draw_labels=True)
gl.xformatter = LONGITUDE_FORMATTER
plt.title('IMG_TIR1')

# plt.savefig('INSAT3D_IMG_TIR1_cartopy.png', bbox_inches='tight', dpi=100)

plt.show()

The result is shown below:-

在此处输入图片说明

All looks fine. But if you look at the image closely, you will find that there is a huge mismatch or offset between the actual dataset and cartopy coast line.

Can some some one help me why the coastline is hugely offset and how to correct it. Any help is appreciated.

Update 1 Uploading metadata of the hdf file using ncdump.

dimensions:
        GreyCount = 1024 ;
        X = 1737 ;
        Y = 1616 ;
        proj_dim = 1 ;
        time = 1 ;
variables:
        int GreyCount(GreyCount) ;
        ushort IMG_MIR(time, Y, X) ;
                IMG_MIR:long_name = "Middle Infrared Count" ;
                IMG_MIR:invert = "true" ;
                IMG_MIR:central_wavelength = 3.907f ;
                IMG_MIR:bandwidth = 0.2f ;
                IMG_MIR:wavelength_unit = "micron" ;
                IMG_MIR:bits_per_pixel = 10 ;
                IMG_MIR:resolution = 4.f ;
                IMG_MIR:resolution_unit = "km" ;
                IMG_MIR:_FillValue = 1023US ;
                IMG_MIR:lab_radiance_scale_factor = 0.000294963f ;
                IMG_MIR:lab_radiance_add_offset = -0.00477786f ;
                IMG_MIR:lab_radiance_quad = -2.00028e-12 ;
                IMG_MIR:lab_radiance_scale_factor_gsics = 0.000326854f ;
                IMG_MIR:lab_radiance_add_offset_gsics = -0.0131381f ;
                IMG_MIR:lab_radiance_quad_gsics = -2.21654e-12 ;
                IMG_MIR:radiance_units = "mW.cm-2.sr-1.micron-1" ;
                IMG_MIR:grid_mapping = "Projection_Information" ;
        float IMG_MIR_RADIANCE(GreyCount) ;
                IMG_MIR_RADIANCE:long_name = "Middle Infrared Radiance" ;
                IMG_MIR_RADIANCE:invert = "true" ;
                IMG_MIR_RADIANCE:units = "mW.cm-2.sr-1.micron-1" ;
                IMG_MIR_RADIANCE:_FillValue = 999.f ;
        float IMG_MIR_TEMP(GreyCount) ;
                IMG_MIR_TEMP:long_name = "Middle Infrared Brightness Temperature" ;
                IMG_MIR_TEMP:invert = "true" ;
                IMG_MIR_TEMP:units = "K" ;
                IMG_MIR_TEMP:_FillValue = 999.f ;
        ushort IMG_SWIR(time, Y, X) ;
                IMG_SWIR:long_name = "Shortwave Infrared Count" ;
                IMG_SWIR:invert = "false" ;
                IMG_SWIR:central_wavelength = 1.625f ;
                IMG_SWIR:bandwidth = 0.15f ;
                IMG_SWIR:wavelength_unit = "micron" ;
                IMG_SWIR:bits_per_pixel = 10 ;
                IMG_SWIR:resolution = 4.f ;
                IMG_SWIR:resolution_unit = "km" ;
                IMG_SWIR:_FillValue = 0US ;
                IMG_SWIR:lab_radiance_scale_factor = 0.00689f ;
                IMG_SWIR:lab_radiance_add_offset = -0.1674f ;
                IMG_SWIR:lab_radiance_quad = 0. ;
                IMG_SWIR:lab_radiance_scale_factor_gsics = 0.00689f ;
                IMG_SWIR:lab_radiance_add_offset_gsics = -0.1674f ;
                IMG_SWIR:lab_radiance_quad_gsics = 0. ;
                IMG_SWIR:radiance_units = "mW.cm-2.sr-1.micron-1" ;
                IMG_SWIR:grid_mapping = "Projection_Information" ;
        float IMG_SWIR_RADIANCE(GreyCount) ;
                IMG_SWIR_RADIANCE:long_name = "Shortwave Infrared Radiance" ;
                IMG_SWIR_RADIANCE:invert = "false" ;
                IMG_SWIR_RADIANCE:units = "mW.cm-2.sr-1.micron-1" ;
                IMG_SWIR_RADIANCE:_FillValue = 999.f ;
        ushort IMG_TIR1(time, Y, X) ;
                IMG_TIR1:long_name = "Thermal Infrared1 Count" ;
                IMG_TIR1:invert = "true" ;
                IMG_TIR1:central_wavelength = 10.785f ;
                IMG_TIR1:bandwidth = 1.f ;
                IMG_TIR1:wavelength_unit = "micron" ;
                IMG_TIR1:bits_per_pixel = 10 ;
                IMG_TIR1:resolution = 4.f ;
                IMG_TIR1:resolution_unit = "km" ;
                IMG_TIR1:_FillValue = 1023US ;
                IMG_TIR1:lab_radiance_scale_factor = 0.001708f ;
                IMG_TIR1:lab_radiance_add_offset = -0.0145189f ;
                IMG_TIR1:lab_radiance_quad = -4.23297e-07 ;
                IMG_TIR1:lab_radiance_scale_factor_gsics = 0.00250456f ;
                IMG_TIR1:lab_radiance_add_offset_gsics = -0.209975f ;
                IMG_TIR1:lab_radiance_quad_gsics = -6.20708e-07 ;
                IMG_TIR1:radiance_units = "mW.cm-2.sr-1.micron-1" ;
                IMG_TIR1:grid_mapping = "Projection_Information" ;
        float IMG_TIR1_RADIANCE(GreyCount) ;
                IMG_TIR1_RADIANCE:long_name = "Thermal Infrared1 Radiance" ;
                IMG_TIR1_RADIANCE:invert = "true" ;
                IMG_TIR1_RADIANCE:units = "mW.cm-2.sr-1.micron-1" ;
                IMG_TIR1_RADIANCE:_FillValue = 999.f ;
        float IMG_TIR1_TEMP(GreyCount) ;
                IMG_TIR1_TEMP:_FillValue = 999.f ;
                IMG_TIR1_TEMP:long_name = "Thermal Infrared1 Brightness Temperature" ;
                IMG_TIR1_TEMP:invert = "true" ;
                IMG_TIR1_TEMP:units = "K" ;
        ushort IMG_TIR2(time, Y, X) ;
                IMG_TIR2:long_name = "Thermal Infrared2 Count" ;
                IMG_TIR2:invert = "true" ;
                IMG_TIR2:central_wavelength = 11.966f ;
                IMG_TIR2:bandwidth = 1.f ;
                IMG_TIR2:wavelength_unit = "micron" ;
                IMG_TIR2:bits_per_pixel = 10 ;
                IMG_TIR2:resolution = 4.f ;
                IMG_TIR2:resolution_unit = "km" ;
                IMG_TIR2:_FillValue = 1023US ;
                IMG_TIR2:lab_radiance_scale_factor = 0.001549f ;
                IMG_TIR2:lab_radiance_add_offset = -0.0113878f ;
                IMG_TIR2:lab_radiance_quad = -4.33804e-07 ;
                IMG_TIR2:lab_radiance_scale_factor_gsics = 0.00242858f ;
                IMG_TIR2:lab_radiance_add_offset_gsics = -0.195822f ;
                IMG_TIR2:lab_radiance_quad_gsics = -6.80131e-07 ;
                IMG_TIR2:radiance_units = "mW.cm-2.sr-1.micron-1" ;
                IMG_TIR2:grid_mapping = "Projection_Information" ;
        float IMG_TIR2_RADIANCE(GreyCount) ;
                IMG_TIR2_RADIANCE:units = "mW.cm-2.sr-1.micron-1" ;
                IMG_TIR2_RADIANCE:_FillValue = 999.f ;
                IMG_TIR2_RADIANCE:long_name = "Thermal Infrared2 Radiance" ;
                IMG_TIR2_RADIANCE:invert = "true" ;
        float IMG_TIR2_TEMP(GreyCount) ;
                IMG_TIR2_TEMP:long_name = "Thermal Infrared2 Brightness Temperature" ;
                IMG_TIR2_TEMP:invert = "true" ;
                IMG_TIR2_TEMP:units = "K" ;
                IMG_TIR2_TEMP:_FillValue = 999.f ;
        ushort IMG_VIS(time, Y, X) ;
                IMG_VIS:long_name = "Visible Count" ;
                IMG_VIS:invert = "false" ;
                IMG_VIS:central_wavelength = 0.65f ;
                IMG_VIS:wavelength_unit = "micron" ;
                IMG_VIS:bandwidth = 0.25f ;
                IMG_VIS:bits_per_pixel = 10 ;
                IMG_VIS:resolution = 4.f ;
                IMG_VIS:resolution_unit = "km" ;
                IMG_VIS:_FillValue = 0US ;
                IMG_VIS:lab_radiance_scale_factor = 0.06131f ;
                IMG_VIS:lab_radiance_add_offset = -2.643f ;
                IMG_VIS:lab_radiance_quad = 0. ;
                IMG_VIS:lab_radiance_scale_factor_gsics = 0.06131f ;
                IMG_VIS:lab_radiance_add_offset_gsics = -2.643f ;
                IMG_VIS:lab_radiance_quad_gsics = 0. ;
                IMG_VIS:radiance_units = "mW.cm-2.sr-1.micron-1" ;
                IMG_VIS:grid_mapping = "Projection_Information" ;
        float IMG_VIS_ALBEDO(GreyCount) ;
                IMG_VIS_ALBEDO:long_name = "Visible Albedo" ;
                IMG_VIS_ALBEDO:invert = "false" ;
                IMG_VIS_ALBEDO:units = "%" ;
        float IMG_VIS_RADIANCE(GreyCount) ;
                IMG_VIS_RADIANCE:long_name = "Visible Radiance" ;
                IMG_VIS_RADIANCE:invert = "false" ;
                IMG_VIS_RADIANCE:units = "mW.cm-2.sr-1.micron-1" ;
                IMG_VIS_RADIANCE:_FillValue = 999.f ;
        ushort IMG_WV(time, Y, X) ;
                IMG_WV:long_name = "Water Vapor Count" ;
                IMG_WV:invert = "true" ;
                IMG_WV:wavelength_unit = "micron" ;
                IMG_WV:central_wavelength = 6.866f ;
                IMG_WV:bandwidth = 0.6f ;
                IMG_WV:bits_per_pixel = 10 ;
                IMG_WV:resolution = 4.f ;
                IMG_WV:resolution_unit = "km" ;
                IMG_WV:_FillValue = 1023US ;
                IMG_WV:lab_radiance_scale_factor = 0.00114622f ;
                IMG_WV:lab_radiance_add_offset = -0.010913f ;
                IMG_WV:lab_radiance_quad = -2.06407e-07 ;
                IMG_WV:lab_radiance_scale_factor_gsics = 0.00145709f ;
                IMG_WV:lab_radiance_add_offset_gsics = -0.0332341f ;
                IMG_WV:lab_radiance_quad_gsics = -2.62387e-07 ;
                IMG_WV:radiance_units = "mW.cm-2.sr-1.micron-1" ;
                IMG_WV:grid_mapping = "Projection_Information" ;
        float IMG_WV_RADIANCE(GreyCount) ;
                IMG_WV_RADIANCE:long_name = "Water Vapor Radiance" ;
                IMG_WV_RADIANCE:invert = "true" ;
                IMG_WV_RADIANCE:units = "mW.cm-2.sr-1.micron-1" ;
                IMG_WV_RADIANCE:_FillValue = 999.f ;
        float IMG_WV_TEMP(GreyCount) ;
                IMG_WV_TEMP:long_name = "Water Vapor Brightness Temperature" ;
                IMG_WV_TEMP:invert = "true" ;
                IMG_WV_TEMP:units = "K" ;
                IMG_WV_TEMP:_FillValue = 999.f ;
        int Projection_Information(proj_dim) ;
                Projection_Information:upper_left_lat_lon\(degrees\) = 45.5, 44.5 ;
                Projection_Information:upper_right_lat_lon\(degrees\) = 45.5, 110. ;
                Projection_Information:lower_left_lat_lon\(degrees\) = -10., 44.5 ;
                Projection_Information:lower_right_lat_lon\(degrees\) = -10., 110. ;
                Projection_Information:upper_left_xy\(meters\) = -3473242.733735, 5401854.420193 ;
                Projection_Information:grid_mapping_name = "mercator" ;
                Projection_Information:false_easting = 0. ;
                Projection_Information:false_northing = 0. ;
                Projection_Information:longitude_of_projection_origin = 77.25 ;
                Projection_Information:semi_major_axis = 6378137. ;
                Projection_Information:semi_minor_axis = 6356752.3142 ;
                Projection_Information:standard_parallel = 17.75 ;
        ushort Sat_Azimuth(time, Y, X) ;
                Sat_Azimuth:scale_factor = 0.01f ;
                Sat_Azimuth:_FillValue = 65535US ;
                Sat_Azimuth:long_name = "Satellite Azimuth" ;
                Sat_Azimuth:add_offset = 0.f ;
                Sat_Azimuth:units = "degree" ;
                Sat_Azimuth:grid_mapping = "Projection_Information" ;
        short Sat_Elevation(time, Y, X) ;
                Sat_Elevation:long_name = "Satellite Elevation" ;
                Sat_Elevation:units = "degree" ;
                Sat_Elevation:add_offset = 0.f ;
                Sat_Elevation:scale_factor = 0.01f ;
                Sat_Elevation:grid_mapping = "Projection_Information" ;
                Sat_Elevation:_FillValue = 32767s ;
        ushort Sun_Azimuth(time, Y, X) ;
                Sun_Azimuth:add_offset = 0.f ;
                Sun_Azimuth:scale_factor = 0.01f ;
                Sun_Azimuth:units = "degree" ;
                Sun_Azimuth:long_name = "Sun Azimuth" ;
                Sun_Azimuth:_FillValue = 65535US ;
                Sun_Azimuth:grid_mapping = "Projection_Information" ;
        short Sun_Elevation(time, Y, X) ;
                Sun_Elevation:long_name = "Sun Elevation" ;
                Sun_Elevation:add_offset = 0.f ;
                Sun_Elevation:scale_factor = 0.01f ;
                Sun_Elevation:units = "degree" ;
                Sun_Elevation:_FillValue = 32767s ;
                Sun_Elevation:grid_mapping = "Projection_Information" ;
        double X(X) ;
                X:long_name = "x coordinate of projection" ;
                X:standard_name = "projection_x_coordinate" ;
                X:units = "m" ;
        double Y(Y) ;
                Y:long_name = "y coordinate of projection" ;
                Y:standard_name = "projection_y_coordinate" ;
                Y:units = "m" ;
        int proj_dim(proj_dim) ;
        double time(time) ;
                time:units = "minutes since 2000-01-01 00:00:00" ;

// global attributes:
                :conventions = "CF-1.6" ;
                :title = "3RIMG_27MAR2020_0545_ASIA_MER_L1C" ;
                :institute = "BES,SAC/ISRO,Ahmedabad,INDIA." ;
                :source = "BES,SAC/ISRO,Ahmedabad,INDIA." ;
                :Unique_Id = "3RIMG_27MAR2020_0545_ASIA_MER" ;
                :Satellite_Name = "INSAT-3DR" ;
                :Sensor_Id = "IMG" ;
                :Sensor_Name = "IMAGER" ;
                :HDF_Product_File_Name = "3RIMG_27MAR2020_0545_L1C_ASIA_MER.h5" ;
                :Output_Format = "hdf5-1.8.8" ;
                :Station_Id = "BES" ;
                :Ground_Station = "BES,SAC/ISRO,Ahmedabad,INDIA." ;
                :Product_Type = "SECTOR" ;
                :Processing_Level = "L1C" ;
                :Acquisition_Date = "27MAR2020" ;
                :Acquisition_Time_in_GMT = "0545" ;
                :Acquisition_Start_Time = "27-MAR-2020T05:45:15" ;
                :Acquisition_End_Time = "27-MAR-2020T06:12:09" ;
                :Product_Creation_Time = "2020-03-27T11:49:58" ;
                :Nominal_Altitude\(km\) = 36000.f ;
                :Nominal_Central_Point_Coordinates\(degrees\)_Latitude_Longitude = 0., 74. ;
                :Software_Version = "1.0" ;
                :left_longitude = 44.5f ;
                :right_longitude = 110.f ;
                :upper_latitude = 45.5f ;
                :lower_latitude = -10.f ;
                :Datum = "WGS84" ;
                :Ellipsoid = "WGS84" ;
}

Update 2

It appears that it is the problem with conversion from X, Y coordinates to lats and lons. The X and Y data is in meters. I have converted this 1D data to 2D using X& Y dimesion along with meshgrid command. Here is the sample X and Y data for review:-

X = -3473242.733735, -3469241.30201411, -3465239.87029321, 
    -3461238.43857232, -3457237.00685143, -3453235.57513054, 
    -3449234.14340964, -3445232.71168875, -3441231.27996786, 
    -3437229.84824696, -3433228.41652607, -3429226.98480518, 
    -3425225.55308429, -3421224.12136339, -3417222.6896425, 
    -3413221.25792161, -3409219.82620071, -3405218.39447982, 
    -3401216.96275893, -3397215.53103804, -3393214.09931714, 

Y = 5401854.420193, 5397853.95696842, 5393853.49374385, 5389853.03051927, 
    5385852.5672947, 5381852.10407012, 5377851.64084554, 5373851.17762097, 
    5369850.71439639, 5365850.25117182, 5361849.78794724, 5357849.32472267, 
    5353848.86149809, 5349848.39827351, 5345847.93504894, 5341847.47182436, 
    5337847.00859979, 5333846.54537521, 5329846.08215063, 5325845.61892606, 
    5321845.15570148, 5317844.69247691, 5313844.22925233, 5309843.76602776, 
    5305843.30280318, 5301842.8395786, 5297842.37635403, 5293841.91312945, 

Does your data file have information about the original projection? This looks like it could be an issue with a globe mismatch (CartoPy defaults to WGS84) or missing some kind of projection parameter, like latitude at origin.

Edited based on other answer

So now with the proper projection information, this is how I would plot your data:

import h5py
import numpy as np
import cartopy
import matplotlib.pyplot as plt
from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER

input_file = "../input/satellite/3RIMG_27MAR2020_0545_L1C_ASIA_MER.h5"

fh = h5py.File(input_file, 'r')
X = fh["X"][()]
Y = fh["Y"][()]
IMG_TIR1 = fh["IMG_TIR1"][()][0, ::-1, :]

globe = ccrs.Globe(semimajor_axis=6378137, semiminor_axis=6356752.3142)
proj = ccrs.Mercator(central_longitude=77.25,
                     latitude_true_scale=17.75, globe=globe)

fig, ax = plt.subplots(figsize=(8, 8), subplot_kw=dict(projection=proj))

ax.pcolormesh(X, Y, IMG_TIR1, cmap=plt.cm.gist_gray)
ax.coastlines('50m', linewidth=0.8, color='black')
gl = ax.gridlines(draw_labels=True)
gl.xformatter = LONGITUDE_FORMATTER
plt.title('IMG_TIR1')

plt.show()

Got it solved by myself after hours of finding information about the projection systems. The issue was that X and Y are projection coordinates and not lons and lats. Therefore, it need to be projected to mercator first before proceeding for plotting. Got all the clues about projection information from metadata of hdf file (see update 1) and then used following code to convert to lons and lats grid:-

import pyproj

fh=h5py.File(input_file, 'r')

X = fh["X"][()]
Y = fh["Y"][()]

p = pyproj.Proj("+proj=merc +lon_0=77.25 +k=1 +x_0=0 +y_0=0 +a=6378137 +b=6356752.3142 +lat_ts=17.75 "
                    "+ellps=WGS84 +datum=WGS84 +towgs84=0,0,0 +units=m +no_defs")
xv, yv = np.meshgrid(X, Y)
lon_grid, lat_grid = p(xv, yv, inverse=True)
.
.
.

Thereafter, processed the data as usual and the result is shown below: 在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM