NetCDF.jl icon indicating copy to clipboard operation
NetCDF.jl copied to clipboard

Writing values into unlimited dimension variable

Open milankl opened this issue 7 years ago • 4 comments

If I create dimensions like

xdim = NcDim("x",nx,values=x)
ydim = NcDim("y",ny,values=y)
tdim = NcDim("t",0,unlimited=true)

and the variables as

uvar = NcVar("u",[xdim,ydim,tdim],t=Float32)
tvar = NcVar("t",tdim,t=Int64)

I can write the u variable for a given timestep i with

ncu = NetCDF.create("u.nc",[uvar,tvar],mode=NC_NETCDF4)
NetCDF.putvar(ncu,"u",Float32.(u),start=[1,1,i],count=[-1,-1,1])

However, no matter how I try to write the values into the unlimited dimension variable "t" (either all at once

NetCDF.putvar(ncu,"t",t)

where t is an integer array, or consequitively everytime I also write "u")

NetCDF.putvar(ncu,"t",[i],start=[i],count=[1])

the values do not get written into the nc file (but also no error is thrown)

milankl avatar Jul 20 '18 17:07 milankl

Thanks for the report. I can not seem to reproduce the issue. The following works as expected, it writes the time variable as well as the actual data:

using NetCDF
x=[0.1*i for i=1:100];nx=length(x)
y=[0.1*i for i=1:200];ny=length(y)

xdim = NcDim("x",nx,values=x)
ydim = NcDim("y",ny,values=y)
tdim = NcDim("t",0,unlimited=true)

uvar = NcVar("u",[xdim,ydim,tdim],t=Float32)
tvar = NcVar("t",tdim,t=Int64)

fn=tempname()
ncu = NetCDF.create(fn,[uvar,tvar],mode=NC_NETCDF4)

for i=1:10
  u=rand(nx,ny)
  NetCDF.putvar(ncu,"u",Float32.(u),start=[1,1,i],count=[-1,-1,1])
  NetCDF.putvar(ncu,"t",Int64[i*5],start=[i]) #Write the time
end
NetCDF.close(ncu)

ncread(fn,"t")

which I think reflects your workflow. In case you read the NetCDF file from an external resource, make sure to call NetCDF.sync(ncu) after every write operation. Otherwise the write might be cached by the NetCDF library so you do not see it on disc yet.

meggart avatar Jul 27 '18 11:07 meggart

Thanks for your input, indeed your example also works for me.

In my slightly more extensive version of that code (see output.jl) the variable t gets correctly written in some cases (that means if I write the variable η), but in others (for writing u and v) a fill value of -9223372036854775806 appears. Any idea whether this is actually me misusing the package?

milankl avatar Aug 06 '18 17:08 milankl

Okay, I think I found the issue. Let's extend your code so that two variables u,v with same dimensions get written to two different files, both with the same dimensions.

using NetCDF
x = [0.1*i for i=1:100];nx=length(x)
y = [0.1*i for i=1:200];ny=length(y)

xdim = NcDim("x",nx,values=x)
ydim = NcDim("y",ny,values=y)
tdim = NcDim("t",0,unlimited=true)

uvar = NcVar("u",[xdim,ydim,tdim],t=Float32)
vvar = NcVar("v",[xdim,ydim,tdim],t=Float32)
tvar = NcVar("t",tdim,t=Int64)

fn1=tempname()
fn2=tempname()
ncu = NetCDF.create(fn1,[uvar,tvar],mode=NC_NETCDF4)
ncv = NetCDF.create(fn2,[vvar,tvar],mode=NC_NETCDF4)

for i=1:10
    u = rand(nx,ny)
    v = rand(nx,ny)
    NetCDF.putvar(ncu,"u",Float32.(u),start=[1,1,i],count=[-1,-1,1])
    NetCDF.putvar(ncv,"v",Float32.(v),start=[1,1,i],count=[-1,-1,1])

    NetCDF.putvar(ncu,"t",Int64[i*5],start=[i]) #Write the time
    NetCDF.putvar(ncv,"t",Int64[i*5],start=[i]) #Write the time
end
NetCDF.close(ncu)
NetCDF.close(ncv)

t1 = ncread(fn1,"t")
t2 = ncread(fn2,"t")

now t1 contains only the fill value -9223372036854775806 and t2 contains the correct values 5,10,15, etc. It always seems to be the last ncfile where NetCDF.putvar works as intended. Maybe it's me misunderstanding what's happening under the hood, but I find this behaviour confusing. An obvious work-around would be to define tvar1,tvar2,... but definitely not an elegant solution.

milankl avatar Aug 07 '18 09:08 milankl

Ah thanks, this is definitely a bug. Will fix as soon as possible.

meggart avatar Aug 08 '18 10:08 meggart