...
 
Commits (2)
#!/usr/bin/env python
import sys
import owi
import argparse
import sys
import netCDF4
import datetime
import logging
logging.basicConfig()
logger = logging.getLogger(__name__)
if sys.gettrace():
logger.setLevel(logging.DEBUG)
else:
logger.setLevel(logging.INFO)
if __name__ == "__main__":
description = """Converts owi nc file to lightweight nc format"""
......@@ -17,11 +27,5 @@ if __name__ == "__main__":
startdate = datetime.datetime.strptime(owi.getAttribute(args.infile,'firstMeasurementTime'),"%Y-%m-%dT%H:%M:%SZ")
stopdate = datetime.datetime.strptime(owi.getAttribute(args.infile,'lastMeasurementTime'),"%Y-%m-%dT%H:%M:%SZ")
owi.writeLight(args.outfile,data,startdate + (stopdate - startdate) / 2,meta=meta)
logger.info("wrote %s" % args.outfile)
# check
#import xarray
#import cyclone_formatter
#dslight = xarray.open_dataset(args.outfile,drop_variables=['incidence','wind_to_direction','elevation']).transpose().squeeze().rename_dims({'X':'x','Y':'y'})
#dscycl = cyclone_formatter.readSar(args.infile)
......@@ -71,6 +71,7 @@ def readFile(fname):
def readMeta(fname):
data={}
#list_var=('owiLon','owiLat','owiHeading','owiEcmwfWindSpeed','owiWindSpeed_IPF', 'owiPreProcessing/estimWindDir200', 'owiPreProcessing/MixWindDir200', 'owiPreProcessing/CoefMixWindDir200', 'owiEcmwfWindDirection','owiWindDirection_mod1','owiWindSpeed_mod1','owiWindDirection_mod2','owiWindSpeed_mod2','owiWindDirection_mod3','owiWindSpeed_mod3','owiPreProcessing/FilterBinary200','owiLandFlag','owiIncidenceAngle')
attrs = ['long_name','units','valid_range','flag_values','flag_meanings']
try:
nc=netCDF4.Dataset(fname)
except Exception as e:
......@@ -80,7 +81,6 @@ def readMeta(fname):
# read globals attr
for attr in nc.ncattrs():
data[attr]=nc.getncattr(attr)
#logger.warn("got attr : %s = %s" % (attr,nc.getncattr(attr)))
refDims=nc.variables['owiLon'].dimensions
......@@ -97,70 +97,76 @@ def readMeta(fname):
for varName in group.variables:
var=group[varName]
data["%s%s" % (groupNamePref,varName)]={}
try:
data["%s%s" % (groupNamePref,varName)]['description']=var.long_name
except:
data["%s%s" % (groupNamePref,varName)]['description']=None
#print "XXXX %s" % (varName)
try:
data["%s%s" % (groupNamePref,varName)]['units']=var.units
except:
data["%s%s" % (groupNamePref,varName)]['units']=None
for _attr in attrs:
try:
data["%s%s" % (groupNamePref,varName)][_attr]=getattr(var,_attr)
except:
data["%s%s" % (groupNamePref,varName)][_attr]=None
# compatibility old version
data["%s%s" % (groupNamePref,varName)]['description'] = data["%s%s" % (groupNamePref,varName)]['long_name']
dims=var.dimensions
if dims != refDims:
# some vars are 3D:
# pdb.set_trace()
try:
if dims[1:] == refDims:
#values3D=var[::]
for islice in range(var.shape[0]):
#value=values3D[islice,:,:]
try:
# try to find sliceName from varName and ncattrs
sliceName=group.getncattr([ groupAttr for groupAttr in groupAttrs if groupAttr in varName ][0]).split(', ')[islice]
#print "got meta slice : %s" %sliceName
except:
sliceName="%d" % islice
#pdb.set_trace()
data["%s%s/%s" % (groupNamePref,varName, sliceName)]={}
try:
data["%s%s/%s" % (groupNamePref,varName, sliceName)]['description']=var.long_name
except:
data["%s%s/%s" % (groupNamePref,varName, sliceName)]['description']=None
try:
data["%s%s/%s" % (groupNamePref,varName, sliceName)]['units']=var.units
except:
data["%s%s/%s" % (groupNamePref,varName, sliceName)]['units']=None
#pdb.set_trace()
for _attr in attrs:
try:
data["%s%s" % (groupNamePref,varName)][_attr]=getattr(var,_attr)
except:
data["%s%s" % (groupNamePref,varName)][_attr]=None
# compatibility old version
data["%s%s" % (groupNamePref,varName)]['description'] = data["%s%s" % (groupNamePref,varName)]['long_name']
except:
pass
nc.close
return data
def writeLight(fname,data,date,meta=None):
"""lightweigth file format writer
specs from https://github.com/Unidata/EC-netCDF-CF/blob/master/swath/swath.adoc#image-swath
xarray reader exemple:
xarray.open_dataset(fname,drop_variables=['incidence','wind_to_direction','elevation','heterogeneity_copol_h','heterogeneity_copol_m','heterogeneity_copol_l','heterogeneity_cross_h','heterogeneity_cross_m','heterogeneity_cross_l]).transpose().squeeze().rename_dims({'X':'x','Y':'y'})
* only root group:
xarray.open_dataset(fname).transpose().squeeze().rename_dims({'X':'x','Y':'y'})
* all groups:
xarray.merge([xarray.open_dataset(args.outfile),xarray.open_dataset(args.outfile,group='preprocessing')])
"""
names_mapping = OrderedDict([
('owiLon' , 'lon'),
('owiLat' , 'lat'),
('owiWindSpeed' , 'wind_speed'),
('owiWindDirection' , 'wind_to_direction'),
('owiElevationAngle' , 'elevation'),
('owiIncidenceAngle' , 'incidence'),
('owiPreProcessing/FilterBinary_1' , 'heterogeneity_copol_h'),
('owiPreProcessing/FilterBinary_2' , 'heterogeneity_copol_m'),
('owiPreProcessing/FilterBinary_3' , 'heterogeneity_copol_l'),
('owiPreProcessing/FilterBinary_1_cross' , 'heterogeneity_cross_h'),
('owiPreProcessing/FilterBinary_2_cross' , 'heterogeneity_cross_m'),
('owiPreProcessing/FilterBinary_3_cross' , 'heterogeneity_cross_l'),
('owiInversionQuality' , 'quality_flag'),
('owiLandFlag' , 'land_flag'),
('owiPreProcessing/ND_2','radar_image_co'),
('owiPreProcessing/ND_2_cross' , 'radar_image_cr'),
('owiPreProcessing/FilterBinary_1' , 'heterogeneity_co_h'),
('owiPreProcessing/FilterBinary_2' , 'heterogeneity_co_m'),
('owiPreProcessing/FilterBinary_3' , 'heterogeneity_co_l'),
('owiPreProcessing/FilterBinary_1_cross' , 'heterogeneity_cr_h'),
('owiPreProcessing/FilterBinary_2_cross' , 'heterogeneity_cr_m'),
('owiPreProcessing/FilterBinary_3_cross' , 'heterogeneity_cr_l'),
('owiNrcs' , 'nrcs_co'),
('owiNrcs_cross' , 'nrcs_cr'),
('owiElevationAngle' , 'elevation_angle'),
('owiIncidenceAngle' , 'incidence_angle'),
])
# global attrs
global_attrs = [ 'sourceProduct' , 'missionName', 'polarisation', 'footprint','l2ProcessingUtcTime']
attrs = ['long_name','units','valid_range','flag_values','flag_meaning']
# overwrite meta
meta_over = {
'wind_speed' : {
......@@ -173,7 +179,11 @@ def writeLight(fname,data,date,meta=None):
'lat' : {
'standard_name' : 'latitude',
'units' : 'degrees_north'
}
},
'wind_to_direction': {
'long_name' : 'Wind to direction (oceanographic convention)',
'units' : 'degrees'
}
}
X,Y = data['owiLon'].shape
dims = (X,Y)
......@@ -182,9 +192,15 @@ def writeLight(fname,data,date,meta=None):
nc.createDimension('Y',Y)
nc.createDimension('X',X)
nc.Conventions = 'CF-1.6'
nc.title = 'SAR wind speed'
nc.title = 'SAR ocean surface wind field'
nc.institution = 'IFREMER LOPS/SIAM'
nc.reference = 'Mouche Alexis, Chapron Bertrand, Knaff John, Zhao Yuan, Zhang Biao, Combot Clement (2019). Copolarized and Cross‐Polarized SAR Measurements for High‐Resolution Description of Major Hurricane Wind Structures: Application to Irma Category 5 Hurricane. Journal Of Geophysical Research-oceans, 124(6), 3905-3922. https://doi.org/10.1029/2019JC015056'
nc.measurementDate = date.strftime("%Y-%m-%dT%H:%M:%SZ")
for global_attr in global_attrs:
try:
setattr(nc, global_attr, meta[global_attr])
except:
logger.warning('skipping missing attr %s' % global_attr)
time = nc.createVariable('time',np.int64,dimensions=('time'))
time.standard_name = 'time'
epoch = datetime.datetime(1970, 1, 1)
......@@ -203,20 +219,25 @@ def writeLight(fname,data,date,meta=None):
# transpose dims for correct netcdf ordering
ncvar = nc.createVariable(out_name,value.dtype,dimensions=('time','Y','X'),fill_value=fill_value)
try:
for _attr in attrs:
try:
ncvar.long_name = meta_over[in_name]['description']
try:
setattr(ncvar,_attr,meta_over[in_name][_attr])
except:
if meta[in_name][_attr] is not None:
setattr(ncvar,_attr, meta[in_name][_attr])
except:
ncvar.long_name = meta[in_name]['description']
except:
pass
pass
else:
logger.warning('skipping missing var %s' % in_name)
if in_name not in ['owiLon','owiLat']:
ncvar.coordinates="time lat lon"
ncvar[::]=value.T
if in_name not in ['owiInversionQuality']:
ncvar[::]=value.T
else:
# known bad vars are set to _FillValue
ncvar[::]=ncvar._FillValue
#ncvar.grid_mapping = "crs"
if out_name in meta_over:
......