python, netcdf4: требуется введение в создание неограниченного измерения времени для netcdf

Может ли кто-нибудь дать представление о том, как создать неограниченное измерение времени для файла NetCDF? Я пытался использовать data.createDimension('t', None), но когда я смотрю на t, это массив Numpy. Если возможно, дайте также представление о присвоении ему значений. Я использую питон 2.7.

отредактированный вопрос

У меня есть несколько файлов NetCDF (3 измерения), и для каждого мне нужно вычислить массив (3 измерения). Временной шаг между файлами составляет 3 часа. Теперь мне нужно создать новый NetCDF с вычисляемым массивом для каждого временного шага. Моя проблема в том, что я не знаю, как получить доступ к оси времени, чтобы я мог назначить вычисляемый массив другому временному шагу.

отредактированный вопрос

Я хочу назначить дату оси времени. Для создания даты я использовал datetime следующим образом:

t_start = dt.datetime(1900,1,1)
t_delta = dt.timedelta(hours=3)

Время между двумя временными шагами составляет 3 часа. При циклическом просмотре файлов дата для временного шага рассчитывается следующим образом:

t_mom = t_start + i*t_delta
t_mom_str = t_mom.strftime("%d %B %Y %H  %M  %S")
t_mom_var = netCDF4.stringtochar(np.array([t_mom_str]))

Я создал переменную следующим образом:

time = data.createVariable('time', np.float32, ('time'))

Теперь я хочу присвоить дату переменной времени:

time[i] = t_mom_var[:]

Но это не работает таким образом. Спасибо за помощь.


person Jan    schedule 10.05.2017    source источник
comment
Думали ли вы об использовании пакета Python xarray? (например, пример в ответе, связанном здесь)   -  person tsherwen    schedule 26.11.2017


Ответы (3)


Использование createDimension с None должно работать:

import netCDF4 as nc4
import numpy as np

f = nc4.Dataset('test.nc', 'w')

# Create the unlimited time dimension:
dim_t = f.createDimension('time', None)
# Create a variable `time` using the unlimited dimension:
var_t = f.createVariable('time', 'int', ('time'))
# Add some values to the variable:
var_t[:] = np.arange(10)
f.close()

Это приводит к (ncdump -h test.nc):

netcdf test {
dimensions:
    time = UNLIMITED ; // (10 currently)
variables:
    int64 time(time) ;
}

Для обновленного вопроса минимальный рабочий пример того, как объединить несколько файлов в один, добавив новое неограниченное измерение:

import netCDF4 as nc4
import numpy as np

# Lets quickly create 3 NetCDF files with 3 dimensions
for i in range(3):
    f = nc4.Dataset('test_{0:1d}.nc'.format(i), 'w')

    # Create the 3 dimensions
    dim_x = f.createDimension('x', 2)
    dim_y = f.createDimension('y', 3)
    dim_z = f.createDimension('z', 4)
    var_t = f.createVariable('temperature', 'double', ('x','y','z'))

    # Add some dummy data
    var_t[:,:,:] = np.random.random(2*3*4).reshape(2,3,4)

    f.close()

# Now the actual merging:
# Get the dimensions (sizes) from the first file:
f_in = nc4.Dataset('test_0.nc', 'r')
dim_size_x = f_in.dimensions['x'].size
dim_size_y = f_in.dimensions['y'].size
dim_size_z = f_in.dimensions['z'].size
dim_size_t = 3
f_in.close()

# Create new NetCDF file:
f_out = nc4.Dataset('test_merged.nc', 'w')

# Add the dimensions, including an unlimited time dimension:
dim_x = f_out.createDimension('x', dim_size_x)
dim_y = f_out.createDimension('y', dim_size_y)
dim_z = f_out.createDimension('z', dim_size_z)
dim_t = f_out.createDimension('time', None)

# Create new variable with 4 dimensions
var_t = f_out.createVariable('temperature', 'double', ('time','x','y','z'))

# Add the data
for i in range(3):
    f_in = nc4.Dataset('test_{0:1d}.nc'.format(i), 'r')
    var_t[i,:,:,:] = f_in.variables['temperature'][:,:,:]
    f_in.close()

f_out.close()
person Bart    schedule 10.05.2017
comment
Я отредактировал свой вопрос, было бы здорово, если бы вы могли помочь. - person Jan; 13.05.2017
comment
То есть вы имеете в виду переход от нескольких файлов NetCDF с 3 измерениями (каждый из которых содержит один временной шаг) к одному файлу NetCDF с исходными 3 измерениями плюс измерение времени из разных файлов? - person Bart; 14.05.2017
comment
Да, это именно то, что я имею в виду. - person Jan; 15.05.2017
comment
Хорошо, я добавил простой рабочий пример, надеюсь, это поможет - person Bart; 15.05.2017
comment
Спасибо, жис очень помог. Но у меня проблема с назначением даты оси времени. Я отредактировал свой вопрос. Спасибо за помощь. - person Jan; 19.05.2017
comment
У меня есть это сейчас. Помощь больше не нужна. - person Jan; 19.05.2017
comment
Отлично, если бы он ответил на ваш вопрос, вы могли бы принять его, что попало в список открытых вопросов. - person Bart; 19.05.2017

@Bart прав, но не ответил на вторую часть вашего вопроса. Вам нужно создать переменную времени, размер которой соответствует вашему измерению времени.

  import numpy as np
  import dateutil.parser

  # create a time variable, using the time dimension.
  var_t = nc4.createVariable('time', 'int32', ('time'))
  var_t.setncattr('units', 'seconds since 1970-01-01 00:00:00 UTC')
  # create a start time
  dt = dateutil.parser.parse("2017-05-01T00:00)
  ntime = nc4.date2num(dt, var_t.units)
  # add some hours
  times = [ntime, ntime + 3600, ntime + 7200]
  # Not sure but you may need a numpy array
  times = np.array([times])
  var_t[:] = times
person Eric Bridger    schedule 10.05.2017
comment
Вы правы, пропустил эту часть. Я обновил свой ответ. - person Bart; 11.05.2017
comment
Я отредактировал свой вопрос, было бы здорово, если бы вы могли помочь. - person Jan; 13.05.2017

Вы можете читать файлы NetCDF через xarray xr.open_dataset():

# Get all the files as a list and open them as Datasets
import glob
folder = '<folder directory with files>'
ncfiles = glob.glob(folder+'*.nc')
ds_l = [ xr.open_dataset(i) for i in ncfiles]

# To make this a stand alone example, i'll just create a list of Datasets too
ds = xr.Dataset( data_vars={'data': ( [ 'lon', 'lat',], arr)}, 
    coords={'lat': np.arange(30), 'lon': np.arange(50)}, ) 
ds_l = [ds]*5

Теперь вы можете добавить даты в качестве новой координаты:
(здесь я создаю список дат с помощью pandas ' метод pd.data_range())

# List of dates
start = datetime.datetime(1900,1,1)
end = datetime.datetime(1900,1,5)
import pandas as pd
dates = pd.date_range( start, end, freq='3H')
# Now add these dates to the datasets
for n, ds in enumerate( ds_l ):
   ds.coords['time'] = dates[n]

Затем вы можете объединить по оси времени с помощью метода xr.concat(). и сохраните как netCDF через xr.to_netdf() метод (Обратите внимание, что для измерения времени задано неограниченное значение)

# Then concatenate them:
ds = xr.concat( ds_l, dim='time' )
ds.to_netcdf('mynewfile.nc', unlimited_dims={'time':True})
person tsherwen    schedule 26.11.2017