NCO: can we remove dimension without modifying coordinates attribute? - netcdf

I have a netcdf file :
dimensions:
y = 453 ;
x = 453 ;
plev = 1 ;
time = UNLIMITED ; // (1460 currently)
variables:
double plev(plev) ;
plev:name = "plev" ;
plev:standard_name = "air_pressure" ;
plev:long_name = "pressure" ;
plev:units = "Pa" ;
plev:axis = "Z" ;
plev:positive = "down" ;
float va925(time, plev, y, x) ;
va925:_FillValue = 1.e+20f ;
va925:missing_value = 1.e+20f ;
va925:coordinates = "lon lat plev" ;
va925:grid_mapping = "Lambert_Conformal" ;
I would like to remove the plev dimension, but keep plev variable and do not modify va925 coordinates attribute.
So I would like :
dimensions:
y = 453 ;
x = 453 ;
time = UNLIMITED ; // (1460 currently)
variables:
double plev;
plev:name = "plev" ;
plev:standard_name = "air_pressure" ;
plev:long_name = "pressure" ;
plev:units = "Pa" ;
plev:axis = "Z" ;
plev:positive = "down" ;
float va925(time, y, x) ;
va925:_FillValue = 1.e+20f ;
va925:missing_value = 1.e+20f ;
va925:coordinates = "lon lat plev" ;
va925:grid_mapping = "Lambert_Conformal" ;
I have tried with :
ncwa -a plev in.nc out.nc
But it modifies va925 coordinates such as :
va925:coordinates = "lon lat ";
I can change it again with :
ncatted -h -O -a coordinates,va925,m,c,"lon lat plev" out.nc
But it means that I have to loop on the variable name, which is too long!
Thank you in advance,
Lola

As you have discovered, ncwa automatically removes the averaged dimensions from the coordinates attribute. There is no switch to turn this off. It took a lot of work to include this feature so it is ironic that some users want to disable it :) You have already discovered and rejected the obvious workaround with ncatted. A lengthier workaround would be to rename all the coordinates attributes before using ncwa, then rename back afterwards, e.g.,
ncrename -a .coordinates,impeachment in.nc
ncwa -a lon in.nc out.nc
ncrename -a .impeachment,coordinates out.nc

Related

`coordinates` attribute of a netcdf variable is missing in xarray

I have a netcdf variable, namely mesh2d_sa1 which contains an attribute coordinates. But when I tried to call this attribute by ds.mesh2d_sa1.attrs["coordinates"], it is not found. The following is an extract of the output of ncdump -h xxxxxxx.nc, which confirms the existence of the attribute of coordinates.
double mesh2d_sa1(time, mesh2d_nFaces, mesh2d_nLayers) ;
mesh2d_sa1:mesh = "mesh2d" ;
mesh2d_sa1:location = "face" ;
mesh2d_sa1:coordinates = "mesh2d_face_x mesh2d_face_y" ;
mesh2d_sa1:cell_methods = "mesh2d_nFaces: mean" ;
mesh2d_sa1:standard_name = "sea_water_salinity" ;
mesh2d_sa1:long_name = "Salinity in flow element" ;
mesh2d_sa1:units = "1e-3" ;
mesh2d_sa1:grid_mapping = "wgs84" ;
mesh2d_sa1:_FillValue = -999. ;
The coordinate attribute can be accessed via ds.mesh2d_sa1.encoding['coordinates']

95% significance plot with NCL

i want to plot a contour of PBLH difference between 2 wrf-chem simulations. I have the netcdf means (attached files), and i want to draw contour of 95% significance levels, but the script did not work, can you give your suggestions please?
"Error: scalar_field: If the input data is 1-dimensional, you must set sfXArray and sfYArray to 1-dimensional arrays of the same length.
warning:create: Bad HLU id passed to create, ignoring it"
i'm explecting a contour plot with Grey shaded areas indicate regions with less than 95 % significance.
here is the code. You can test it with any two WRF netcdf files:
`;----------------------------------------------------------------------
; contoursym_1.ncl
;
; Concepts illustrated:
; - Using a symmetric color map
; - Using a blue-red color map
; - Explicitly setting contour levels
;----------------------------------------------------------------------
;
; These files are loaded by default in NCL V6.2.0 and newer
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_csm.ncl"
load "$NCARG_ROOT/lib/ncarg/nclscripts/wrf/WRF_contributed.ncl"
; This file still has to be loaded manually
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/shea_util.ncl"
begin
;*****************
;-- load data
;*****************
;specify file names (input&output, netCDF)
pathin = "./" ; directory
fin1 = "15-25-omet.nc" ; input file name #1
fin2 = "15-25-wrfda.nc" ; input file name #2
fout = "signif_pblh_omet-wrfda" ; output file name
foutnc = fout+".nc"
f = addfile ("15-25-omet.nc", "r")
; open input files
in1 = addfile(pathin+fin1,"r")
in2 = addfile(pathin+fin2,"r")
; read data
tmp1 = in1->PBLH
tmp2 = in2->PBLH
x = f->PBLH(0,:,:)
diff=tmp1-tmp2
printVarSummary(tmp1)
printVarSummary(tmp2)
;****************************************************
; calculate probabiliites
;****************************************************
;t-test
res1=True
xtmp=tmp1(XTIME|:,south_north|:, west_east|:)
ytmp = tmp2(XTIME|:,south_north|:, west_east|:)
aveX = dim_avg_Wrap(xtmp)
aveY = dim_avg_Wrap(ytmp)
varX = dim_variance(xtmp)
varY = dim_variance(ytmp)
sX = dimsizes(xtmp&XTIME)
sY = dimsizes(ytmp&XTIME)
print(sX)
print(sY)
alphat = 100.*(1. - ttest(aveX,varX,sX, aveY,varY,sY, True, False))
;aveX = where(alphat.lt.95.,aveX#FillValue, aveX)
;print(alphat)
;*********************
;---Start the graphics
;**********************
wks = gsn_open_wks("ps" ,"Bias_gray_F") ; ps,pdf,x11,ncgm,eps
res = True
res#gsnMaximize = True ; uncomment to maximize size
res#gsnSpreadColors = True ; use full range of colormap
res#cnFillOn = True ; color plot desired
res#cnLinesOn = False ; turn off contour lines
res#cnLineLabelsOn = True ; turn off contour labels
res#cnLineLabelsOn = True ; turn on line labels
res#lbOrientation = "Vertical"
res#lbLabelPosition = "Right" ; label position
res#tiMainFontHeightF = 0.025
res#lbBoxEndCapStyle = "TriangleBothEnds" ; triangle label bar
;************************************************
; Use WRF_contributed procedure to set map resources
;************************************************
res = True
WRF_map_c(f, res, 0) ; reads info from file
;************************************************
; if appropriate, set True for native mapping (faster)
; set False otherwise
;************************************************
res#tfDoNDCOverlay = True
;************************************************
; associate the 2-dimensional coordinates to the variable for plotting
; only if non-native plot
;************************************************
if (.not.res#tfDoNDCOverlay) then
x#lat2d = f->XLAT(0,:,:) ; direct assignment
x#lon2d = f->XLONG(0,:,:)
end if
;************************************************
; Turn on lat / lon labeling
;************************************************
res#pmTickMarkDisplayMode = "Always" ; turn on tickmarks
;res#tmXTOn = False ; turn off top labels
;res#tmYROn = False ; turn off right labels
;************************************************
; Loop over all times and levels ( uncomment )
; Demo: one arbitrarily closen time and level
;************************************************
dimx = dimsizes(x) ; dimensions of x
ntim = dimx(0) ; number of time steps
klev = dimx(1) ; number of "bottom_top" levels
nt = 0 ; arbitrary time
kl = 6 ; " level
opt=True
opts=True
res1=True
res = opts ; Use basic options for this field
opts#MainTitle = "OMET-FBDA"
opts#InitTime = False ; Do not plot time or footers
opts#Footer = False
plot0 = gsn_csm_contour_map(wks,diff(0,:,:),res ) ; define plot 0
pval = gsn_csm_contour(wks,alphat(0,:),res1) ;-- this adds a contour line around the stippling
opt#gsnShadeMid="gray62"
pval = gsn_contour_shade(pval,0.05,1.00,opt) ;-- this adds the stippling for all pvalues <= 0.05
overlay(plot0,pval)
draw(plot0)
frame(wks)
end`

zsh loses precision when miltiplying two floats of significantly different magnitude

I'm trying to do some floating-point math in a zsh script. I'm seeing the following behavior:
$ (( a = 1.23456789 * 0.00000001 )); printf "a = %g\n" $a
a = 1.23e-08
$ (( a = 1.23456789 * 0.00000001 )); printf "a = %e\n" $a
a = 1.230000e-08
$ (( a = 1.23456789 * 0.0000001 )); printf "a = %e\n" $a
a = 1.235000e-07
I expect not to loose the 1st number's mantissa precision when I merely multiply it by a number whose mantissa is 1 (or at least very close to 1, if the true binary representation is considered). In other words, I'd expect to get a = 1.23456789e-08 or maybe some truncated mantissa, but not zeros after 1.23 / 1.235.
I'm running the following version:
$ zsh --version
zsh 5.8 (x86_64-apple-darwin20.0)
Am I missing something? Or is it an issue in zsh? I'm new to zsh, and I don't have a lot of experience in shell programming in general, so any help is appreciated. Thanks!
It appears that (( x = 1.0 )), when x is not defined, will cause Zsh to declare the variable as -F: a double precision floating point which is formatted to fixed-point with 10 decimal digits on output:
% unset x; (( x = 0.12345678901234567 )); declare -p x
typeset -F x=0.1234567890
% unset x; x=$((0.12345678901234567)); declare -p x
typeset x=0.12345678901234566
I don't know why it works this way, but if you manually declare your variable as a string first, this won't happen, and you'll get the full value:
% unset a; typeset a; (( a = 1.23456789 * 0.00000001 )); printf "a = %g\n" $a
a = 1.23457e-08
The difference comes from the way of how you pass the value of a to printf. If you write it as
(( a = 1.23456789 * 0.00000001 )); printf "a = %e\n" $((a))
$ (( a = 1.23456789 * 0.0000001 )); printf "a = %e\n" $((a))
the problem does not occur. This is described here, where it says:
floating point numbers can be declared with the float builtin; there are two types, differing only in their output format, as described for the typeset builtin. The output format can be bypassed by using arithmetic substitution instead of the parameter substitution, i.e. ‘${float}’ uses the defined format, but ‘$((float))’ uses a generic floating point format

Mask/CLIP Raster images with different resolution in IDL

I want to clip/mask raster image (500meters resolution) by another raster images (10 km resolution) using IDL Programming after the clip/mask process image should be in 500 meters resolution. I have 365 images pair and I want to a process by IDL programming. Can anybody write this code in IDL?
Thanks in advance.
#MrFuppes
Initially, I write one code in IDL which able to mask/clip the same resolution images because those are in same dimension.
But I cannot write the mask function for different resolution where is the problem in dimension and resolution.
In my code:
Band 1(500 meters) is my base images and I want to mask this image by cloud mask image(500 meters)(It works well) and then I want to do another mask by AOD_MASK images(10 km) resolution.
But how to write MASK function for different dimension images I have no idea.
If you have any suggestion regarding this issue then, please suggested me.
Here I attached my test DATA please check it.
Below is my IDL code:
`Pro MASK
COMPILE_OPT idl2
ENVI, /RESTORE_BASE_SAVE_FILES
ENVI_BATCH_INIT, /NO_STATUS_WINDOW
print, ' ' + 'Batch Processing Start'
print, ' ' + systime()
;********************************************************************************
;Input location of different file
InputAOD = 'F:\DB_test_data\VAR2\TEST_DATA\Clip\'
Input_cloud = 'F:\DB_test_data\VAR2\TEST_DATA\Clip\'
Input_TOA_B1 = 'F:\DB_test_data\VAR2\TEST_DATA\Clip\'
;Output location
Output = 'F:\DB_test_data\OUT_PUT\'
; Search for inpiut data
FileCloud = File_search(Input_cloud + "*Aerosol_Cldmask_Land_Ocean-
Aerosol_Cldmask_Land_Ocean.tif",COUNT=Count_in1)
FileAOD = File_Search(InputAOD + '*Corrected_Optical_Depth_Land_2-
Corrected_Optical_Depth_Land.tif',COUNT=count_in)
FileBAND1 = File_Search(Input_TOA_B1 + '*pssgrp_000501330352.EV_500_RefSB_1-
EV_500_RefSB.tif',COUNT=COUNT)
nfiles = n_elements(count_in1)
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$ $$$$$$$$$$$$$$$$$
FOR k=0, nfiles-1 DO BEGIN
Print, 'Processing File =', k +1
Print, 'Total Files=', count_in1
string_count = strtrim(nfiles,2)
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;cloud(500_METER)
ENVI_OPEN_FILE, FileCloud[k], r_FiD=FiD_cld
IF (FiD_cld EQ -1) then return
ENVI_FILE_QUERY, FiD_cld, dims=dims, nb=nb, ns=cld_ncols, nl=cld_nrows
pos = [0]
map_info = envi_get_map_info(FiD=FiD_cld)
Cloud = Double(ENVI_GET_DATA(FiD=FiD_cld, dims=dims, pos=[0]))
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;BAND_1(500_METER)
envi_open_file,FileBAND1[k],r_fid=fid_T_B1
if (fid_T_B1 eq -1)then return
envi_file_query,fid_T_B1,dims=dims,nb=nb, ns=toa_B1_ncols, nl=toa_B1_nrows
pos=[0]
map_info1=envi_get_map_info(fid=fid_T_B1)
layer1 = fltarr(toa_B1_ncols,toa_B1_nrows,nb)
FOR i=0,nb-1 DO BEGIN
layer1[*,*,i]=ENVI_GET_DATA(fid=fid_T_B1,dims=dims,pos=pos[i])
ENDFOR
;To replace 65535 with NAN
i=WHERE(layer1 eq 65535,count)
if (count gt 0)then layer1[i]=!VALUES.F_NAN
TOA_B1=layer1*0.000053811826d
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;AOD(10KM_RESOLUTION)
ENVI_OPEN_FILE, FileAOD[k], r_FiD=FiD_AOD
IF (FiD_AOD EQ -1) then return
ENVI_FILE_QUERY, FiD_AOD, dims=dims, nb=nb, ns=aod_ncols, nl=aod_nrows
pos = [0]
map_info = envi_get_map_info(FiD=FiD_AOD)
layer2 = fltarr(aod_ncols,aod_nrows,nb)
FOR i=0,nb-1 DO BEGIN
layer2[*,*,i]=ENVI_GET_DATA(fid=FiD_AOD,dims=dims,pos=pos[i])
ENDFOR
;To replace -9999 with NAN
i=WHERE(layer2 eq -9999,count)
if (count gt 0)then layer2[i]=!VALUES.F_NAN
AOD=layer2*0.0010000000474974513d
;set the specific range for mask
AOD_MASK = 1.0*(AOD GE 0.0 and AOD LE 0.1) + (AOD GT 0.1)*0.0
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; to get same dimensions for B1TOA and CLD data
if (cld_ncols le toa_B1_ncols) then begin
xsize = cld_ncols
endif else begin
xsize = toa_B1_ncols
endelse
if (cld_nrows le toa_B1_nrows) then begin
ysize = cld_nrows
endif else begin
ysize = toa_B1_nrows
endelse
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; to call parameters again with same dims
Cloud = FSC_Resize_Image(Cloud,xsize, ysize)
Band1 = FSC_Resize_Image(TOA_B1,xsize, ysize)
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
;First masking processes with cloud mask images(500 meters)
Cloud_masked = Cloud * Band1
;To replace 0 with NAN
i=WHERE(Cloud_masked eq 0,count)
if (count gt 0)then Cloud_masked[i]=!VALUES.F_NAN
Cloud_masked_Band1=Cloud_masked
;Second masking processes with AOD_MASK images(10KM)
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
; Define output FileName
FileName = STRJOIN(STRSPLIT(STRMID(FILE_BASENAME(FileBAND1[k], '.tif'), 0, 75), '.', /EXTRACT), '_')
print, FileName
; write output File
out_name_out = Output + FileName +'_masked_image.tif'
map_info = envi_get_map_info(FiD=fid_T_B1)
ENVI_WRITE_ENVI_FILE, Cloud_masked, out_name=out_name_out, map_info=map_info
;FileName = STRJOIN(STRSPLIT(STRMID(FILE_BASENAME(FileAOD[k], '.tif'), 0, 75), '.', /EXTRACT), '_')
;print, FileName
; write output File
;out_name_out = Output + FileName +'_AOD.tif'
;map_info = envi_get_map_info(FiD=FiD_AOD)
;ENVI_WRITE_ENVI_FILE, AOD,out_name=out_name_out, map_info=map_info
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
Print, FileName + ' ' + strtrim(k+1,2) + ' of ' + string_count + ' Processed'
Endfor
Print, ' ' + systime()
Print, ' ' + 'Batch Processing End'
End
;$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$
FUNCTION FSC_Resize_Image, image, cols, rows, $
INTERPOLATE=interp, $
MINUS_ONE=minus_one
Compile_Opt idl2
; Check parameters.
IF N_Params() EQ 0 THEN BEGIN
Print, 'USE SYNTAX: FSC_Resize_Image, image, cols, rows'
RETURN, "FSC_Resize_Image Syntax Error"
ENDIF
; Return to the caller on an error.
On_Error, 2
; Check image parameter for size. Only 2D and 3D images allowed.
ndim = SIZE(image, /N_DIMENSIONS)
dims = SIZE(image, /DIMENSIONS)
IF ((ndim LT 2) OR (ndim GT 3)) THEN $
Message, 'Input image must have two or three dimensions.'
; Check for keywords. Default for minus_one is 0.
interp = Keyword_Set(interp)
IF N_Elements(minus_one) EQ 0 THEN minus_one = 0
m1 = Keyword_Set(minus_one)
; 2D images are immediately passed to IDL's Congrid command, with
; the CENTER keyword set.
IF ndim EQ 2 THEN BEGIN
RETURN, Congrid(image, cols, rows, CENTER=1, MINUS_ONE=minus_one, $
INTERP=interp)
ENDIF
; 24-bit images are handled differently. The "3" dimension of a 24-bit
; image should not be interpolated.
offset = 0.5 ; To center the pixel location (i.e., CENTER=1 for Congrid)
index3 = Where(dims EQ 3)
CASE index3 OF
0: BEGIN
srx = [0,1,2]
sry = Float(dims[1] - m1) / (cols - m1) *(Findgen(cols) + offset) - offset
srz = Float(dims[2] - m1) / (rows - m1) *(Findgen(rows) + offset) - offset
END
1: BEGIN
srx = Float(dims[0] - m1) / (cols - m1) *(Findgen(cols) + offset) - offset
sry = [0,1,2]
srz = Float(dims[2] - m1) / (rows - m1) *(Findgen(rows) + offset) - offset
END
2: BEGIN
srx = Float(dims[0] - m1) / (cols - m1) *(Findgen(cols) + offset) - offset
sry = Float(dims[1] - m1) / (rows - m1) *(Findgen(rows) + offset) - offset
srz = [0,1,2]
END
ENDCASE
; Do the interpolation. Preserve nearest neighbor sampling, if required.
IF interp THEN BEGIN
RETURN, Interpolate(image, srx, sry, srz, /GRID)
ENDIF ELSE BEGIN
RETURN, Interpolate(image, Round(srx), Round(sry), Round(srz), /GRID)
ENDELSE
END`

How can I swap the dimensions of a netCDF file?

I have a
dimensions:
time = 1000 ;
xr = 100 ;
variables:
int time(time) ;
time:long_name = "time since time reference (instant)" ;
time:units = "hours since 2010-05-01" ;
double v1(xr, time) ;
v1:long_name = "V1" ;
averageInstantRunoff:units = "m s-1" ;
double v1(time, xr) ;
v1:long_name = "V1" ;
averageInstantRunoff:units = "m s-1" ;
int xr(xr) ;
xr:long_name = "xr index" ;
xr:units = "-" ;
Here, I want to make variable v1 to have dimensions of (time, xr) instead of (xr,time).
I do this using:
ncpdq -v v1 -a time,xr test.nc test2.nc
But ofcourse, it doesn't copy v2. I do it over large files with large number of variables and I only want to do it for a single variable.
How can I do this?
You can also the use ncap2 permute() method:
ncap2 -s 'v1_prm=v1.permute($time,$xr)' in.nc out.nc
but then your output will have a v1 and a v1_prm. Either way it's a two line process with NCO because you need a second step to append (ncpdq method) or remove the extra variable (ncap2 method).

Resources