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']
Related
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`
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
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).
The question
Given a MiniZinc array of strings:
int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;
... with data loaded from a MiniZinc data file:
numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];
How can one look up the index of a specific string in the array? For example, that ARMOR is located at position 2.
The context
I need to find an optimal selection of items with regard to some constraints on their stats. This information is stored in a 2D array declared as follows:
int: numItems;
set of int: Items = 1..numItems;
array[Items, Stats] of float: itemStats;
So in order to write a constraint on, say, the minimum amount of ARMOR obtained through the selected items, I need to know that ARMOR has index 2 in the inner array.
Since the data file is generated by an external program, and the number and order of stats are dynamic, I cannot hardcode the indices in the constraints.
One solution (that won't work in my case)
The MiniZinc tutorial uses an interesting trick to achieve something similar:
set of int: Colors = 1..3;
int: red = 1;
int: yellow = 2;
int: blue = 3;
array[Colors] of string: name = ["red", "yellow", "blue"];
var Colors: x;
constraint x != red;
output [ name[fix(x)] ];
Unfortunately, as variable declarations are not allowed in MiniZinc data files, this trick won't work in my case.
You can write your own custom function to get the index of a string within a string array:
function int: getIndexOfString(string: str,
array[int] of string: string_array) =
sum( [ if str = string_array[i]
then i
else 0 endif
| i in index_set(string_array) ]
);
In this function I create an array of integers where the integer at position i either equals the index of str if string_array[i]=str and 0 otherwise. For instance, for your sample string array ["HEALTH", "ARMOR", "MANA"] and str ARMOR the resulting int array will be [0,2,0].
This is why I can simply sum over the int array to get the index of the string. If the string does not occur, the return value is 0, which is fine since indices in MiniZinc start with 1 by default.
Here is how you can call the function above for your first example:
int: numStats;
set of int: Stats = 1..numStats;
array[Stats] of string: statNames;
numStats = 3;
statNames = ["HEALTH", "ARMOR", "MANA"];
var int: indexOfArmor;
constraint
indexOfArmor = getIndexOfString("ARMOR",statNames);
solve satisfy;
Note however that the function above is limited and has some flaws. First, if you have multiple occurrences of the string in the array, then you will receive an invalid index (the sum of all indices where str occurred). Also, if you have your own index set for your string array (say (2..6)), then you will need to adapt the function.
Another, cleaner option is to write a function that uses a recursive helper function:
% main function
function int: index_of(string: elem, array[int] of string: elements) =
let {
int: index = length(elements);
} in % calls the helper function with the last index
get_index(elem, elements, index)
;
% recursive helper function
function int: get_index(string: elem, array[int] of string: elements, int: index) =
if index == 0
then -1 % the element was not found (base case of recursion)
elseif elements[index] == elem
then index % the element was found
else
get_index(elem, elements, index - 1) % continue searching
endif
;
The helper function iterates recursively over the array, starting from the last element, and when it finds the element, it returns the index. If the element was not found in the array, then -1 is returned. Alternatively, you can also throw an assertion following the suggestion of Patrick Trentin by replacing then -1 with then assert(false, "unknown element: " + elem).
An example of calling this function:
set of int: Customers = 1..5;
array[Customers] of string: ids = ["a-1", "a-2", "a-3", "a-4", "a-5"];
var int: index = index_of("a-3", ids);
var int: unknown_index = index_of("x-3", ids);
where index will be assigned 3 and unknown_index will be -1.
An alternative approach to that presented by Andrea Rendl-Pitrey, is the following one:
array[int] of string: statNames = array1d(10..12, ["HEALTH", "ARMOR", "MANA"]);
var int: indexOfArmor =
sum([i | i in index_set(statNames) where statNames[i] = "ARMOR"]);
solve satisfy;
output [
"indexOfArmor=", show(indexOfArmor), "\n",
];
which outputs:
~$ mzn2fzn example.mzn ; flatzinc example.fzn
indexOfArmor = 11;
----------
note: that var can be dropped from the declaration of indexOfArmor, since the index can be statically computed. I kept it here only for output purposes.
A better solution is to declare a new predicate:
predicate index_of_str_in_array(var int: idx,
string: str,
array[int] of string: arr) =
assert(
not exists(i in index_set(arr), j in index_set(arr))
(i != j /\ arr[i] = str /\ arr[j] = str),
"input string occurs at multiple locations",
assert(
exists(i in index_set(arr))
(arr[i] = str),
"input string does not occur in the input array",
exists(i in index_set(arr))
(arr[i] = str /\ i = idx)
));
which enforces both of the following conditions:
str occurs at least once in arr
str does not occur multiple times in arr
e.g
predicate index_of_str_in_array(var int: idx,
string: str,
array[int] of string: arr) =
...
array[10..13] of string: statNames =
array1d(10..13, ["HEALTH", "ARMOR", "MANA", "ATTACK"]);
var int: indexOfArmor;
constraint index_of_str_in_array(indexOfArmor, "ARMOR", statNames);
solve satisfy;
output [
"indexOfArmor=", show(indexOfArmor), "\n",
];
outputs
~$ mzn2fzn example.mzn ; flatzinc example.fzn
indexOfArmor = 11;
----------
If one changes statNames in the following way
array[10..13] of string: statNames =
array1d(10..13, ["HEALTH", "ARMOR", "MANA", "ARMOR"]);
then mzn2fzn detects an assertion violation:
~$ mzn2fzn example.mzn ; flatzinc example.fzn
MiniZinc: evaluation error:
example.mzn:24:
in call 'index_of_str_in_array'
example.mzn:4:
in call 'assert'
Assertion failed: input string occurs at multiple locations
flatzinc:
example.fzn: cannot open input file: No such file
A similar result would be obtained by searching for the index of a string that does not occur in the array. This condition can of course be removed if not necessary.
DISCLAIMER: older versions of mzn2fzn don't seem to check that the declared index-set of an array of strings variable matches the index-set of an array of strings literal that is being assigned to it. This rule is enforced on newer versions, as it is also valid for other data types.
According to this other post on Stackoverflow there is no way of converting strings to integers in MiniZinc, only the other way around. You need to first pre process your data in some other language and turn it into integers. You can however turn those integers into string once you are done in MiniZinc.
You can however load MiniZinc files instead of data files if you would like. Use the include syntax to include any .mzn file.
I am having trouble figuring out how to get the length of a matrix within a matrix within a matrix (nested depth of 3). So what the code is doing in short is... looks to see if the publisher is already in the array, then it either adds a new column in the array with a new publisher and the corresponding system, or adds the new system to the existing array publisher
output[k][1] is the publisher array
output[k][2][l] is the system
where the first [] is the amount of different publishers
and the second [] is the amount of different systems within the same publisher
So how would I find out what the length of the third deep array is?
function reviewPubCount()
local output = {}
local k = 0
for i = 1, #keys do
if string.find(tostring(keys[i]), '_') then
key = Split(tostring(keys[i]), '_')
for j = 1, #reviewer_code do
if key[1] == reviewer_code[j] and key[1] ~= '' then
k = k + 1
output[k] = {}
-- output[k] = reviewer_code[j]
for l = 1, k do
if output[l][1] == reviewer_code[j] then
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
else
output[k][1] = reviewer_code[j]
output[k][2][1] = key[2]
end
end
end
end
end
end
return output
end
The code has been fixed here for future reference: http://codepad.org/3di3BOD2#output
You should be able to replace table.getn(t) with #t (it's deprecated in Lua 5.1 and removed in Lua 5.2); instead of this:
ltable = output[l][2]
temp = table.getn(ltable)
output[l][2][temp+1] = key[2]
try this:
output[l][2][#output[l][2]+1] = key[2]
or this:
table.insert(output[l][2], key[2])