Project

General

Profile

RE: Converting CERRA (lambert conformal) to rotated latlo... ยป lcc2silamgrid.py

Rostislav Kouznetsov, 2025-09-11 09:31

 
#!/usr/bin/env python3
# Copyleft Rostislav Kouznetsov 11.2023-

descr="""
Approximates lcc grid from a given file wth SILAM rll grid
optionally, calculates grid indices of given lon,lat pair
and indices of areea of interest
"""


import netCDF4 as nc
import numpy as np
from pyproj import CRS, Transformer
import argparse
import sys

infname="grid_template_2500.nc"
infname="grid_template_0750.nc"


parser = argparse.ArgumentParser(
prog=sys.argv[0],
description=descr,
epilog='')
parser.add_argument('filename')
parser.add_argument('-l', '--location', default=None, help="lon,lat of the point of interest")
parser.add_argument('-s', '--size', default=None, help="nx,ny around the point of interest")


args = parser.parse_args(sys.argv[1:])
infname = args.filename




#infname = "grid_template_shmu_2000.nc"

with nc.Dataset(infname) as inf:
projvar=inf.variables["Lambert_Conformal"]
xvals = inf.variables["x"][:]
yvals = inf.variables["y"][:]
nx = len(xvals)
ny = len(yvals)

try:
proj4strIn = projvar.proj4
except AttributeError:
proj4strIn = "+proj=lcc +a=%(a)f +b=%(b)f +lat_1=%(lat_1)f +lat_2=%(lat_2)f +lon_0=%(lon_0)f +lat_0=%(lat_0)f +k_0=1 +x_0=%(x_0)f +y_0=%(y_0)f +datum=WGS84 +units=m "%dict(
a = projvar.earth_radius,
b = projvar.earth_radius,
lat_1 = projvar.latitude_of_projection_origin,
lat_2 = projvar.latitude_of_projection_origin,
lon_0 = projvar.longitude_of_central_meridian,
lat_0 = projvar.latitude_of_projection_origin,
x_0 = projvar.false_easting,
y_0 = projvar.false_northing,
)
#proj4strIn = "+proj=lcc +a=6371229 +b=6371229 +lat_1=51.970001 +lat_2=51.970001 +lon_0=0.0 +lat_0=51.97 +k_0=1 +x_0=-324328.303458971 +y_0=17464.56278250541 +datum=WGS84 +units=m " ;

crsIn=CRS.from_proj4(proj4strIn)

spolelon = projvar.longitude_of_central_meridian
spolelat = projvar.standard_parallel - 90.
proj4rll = "+proj=ob_tran +o_proj=longlat +o_lat_p=%10f +o_lon_p=%10f +lon_0=%10f"%(-spolelat, spolelon,spolelon)
crsRll = CRS.from_proj4(proj4rll)

transformer = Transformer.from_crs(crsIn, crsRll)

xx,yy = np.meshgrid(xvals,yvals)

lons2d,lats2d = transformer.transform(xx,yy)
lons = np.mean(lons2d, axis=0)
lats = np.mean(lats2d, axis=1)

xstep = (lons[-1] - lons[0]) / (len(lons) - 1)
ystep = (lats[-1] - lats[0]) / (len(lats) - 1)
## Restore
lo2d,la2d = np.meshgrid(lons,lats)

dist = np.sqrt((lons2d -lo2d)**2 + (lats2d -la2d)**2)
maxdist = np.amax(dist)

lons -= spolelon

grid ="""
grid_method = CUSTOM_GRID # METEO_GRID / EMISSION_GRID / OUTPUT_GRID / CUSTOM_GRID
grid_type = lon_lat
grid_title = %(name) s
# proj string="%(proj)s"
# maxdist/xstep = %(relerrx)f, maxdist/ystep = %(relerry)f
resol_flag = 128
ifReduced = 0
earth_flag = 0
wind_component = 0
reduced_nbr_str = 0
lon_start = %(x0)f
lat_start = %(y0)f
dx = %(dx)f
dy = %(dy)f
nx = %(nx)d
ny = %(ny)d
# lon_end = %(x1)f
# lat_end = %(y1)f

#lon0 to 0th meridian
#lat0 to equator
lat_s_pole = %(splat)f
lon_s_pole = %(splon)f
lat_pole_stretch = 0.
lon_pole_stretch = 0.
"""%dict(name=infname, x0=lons[0], y0=lats[0], dx=xstep, dy=ystep, nx=nx, ny=ny,
x1 = lons[-1], y1 = lats[-1], proj=proj4rll,
splat=spolelat, splon=spolelon, relerrx = maxdist/xstep, relerry = maxdist/ystep)
print(grid)

proj4wgs84 = "+proj=longlat +datum=WGS84 +no_defs +type=crs"
crsll = CRS.from_proj4(proj4wgs84)
transformer = Transformer.from_crs(crsIn, crsll)
lons2d,lats2d = transformer.transform(xx,yy)


transformer_to = Transformer.from_crs(crsll,crsIn)

if args.location is None:
ix = len(xvals)//2
iy = len(yvals)//2

else:
lonc,latc = [ float(v) for v in args.location.split(',') ]
xc,yc = transformer_to.transform(lonc,latc)
ix = np.argmin((xvals-xc)**2)
iy = np.argmin((yvals-yc)**2)

if args.size is None:
xrang="0,%d"%(len(xvals)-1)
yrang="0,%d"%(len(yvals)-1)
else:
if args.location is None:
raise ValueError("size specified but not location. Too bad...")
nxo,nyo = [ int(v) for v in args.size.split(',') ]
xrang="%d,%d"%(ix - nxo//2, ix + nxo//2 ) ## nco indexing _includes_ last element
yrang="%d,%d"%(iy - nyo//2, iy + nyo//2 )

print("#minloc for location(%s), ix=%d, iy=%d: lon=%f, lat=%f\n"%(args.location,ix,iy, lons2d[iy,ix],lats2d[iy,ix]))
print("#DEODExrange = "+xrang)
print("#DEODEyrange = "+yrang)
# print(lons[ix-2:])






WGS84lonrange="#WGS84lonrange = %.1f,%.1f"%(np.amin(lons2d), np.amax(lons2d))
WGS84latrange="#WGS84latrange = %.1f,%.1f"%(np.amin(lats2d), np.amax(lats2d))
print(WGS84lonrange)
print(WGS84latrange)









    (1-1/1)