Python NetCDF IOError: netcdf: 无效的维度ID或名称
我正在用Python写一个处理NetCDF文件的脚本,但在创建变量时遇到了一些问题,这里是代码的一部分:
stepnumber_var = ofl.createVariable("step_number", "i",("step_number",))
stepnumber_var.standard_name = "step_number"
atomNumber_var = ofl.createVariable("atom_number", "i", ("atom_number",))
atomNumber_var.standard_name = "atom__number"
但是出现了这个错误:
Traceback (most recent call last):
File "sub_avg.py", line 141, in <module>
atomNumber_var = ofl.createVariable("atom_number", "i", ("atom_number",))
IOError: netcdf: NetCDF: Invalid dimension ID or name
我的问题是,为什么第一个变量可以正常创建,而第二个变量却不行呢?
谢谢
这是完整的代码:
from array import array
import os
import sys
import math
import string as st
import numpy as N
from Scientific.IO.NetCDF import NetCDFFile as S
if len(sys.argv) < 2:
sys.exit( "No input file found. \nPlease privide NetCDF trajectory input file" )
#######################
## Open NetCDF file ###
#######################
infl = S(sys.argv[1], 'r')
file = sys.argv[1]
title,ext = file.split(".")
#for v in infl.variables: # Lists the variables in file
# print(v)
#################################################################################
# Variable "configurations" has the structure [step_number, atom_number, x y z] #
#################################################################################
varShape = infl.variables['configuration'].shape # This gets the shape of the variable, i.e. the dimension in terms of elements
nSteps = varShape[0]
nAtoms = varShape[1]
coordX_atom = N.zeros((nSteps,nAtoms))
coordY_atom = N.zeros((nSteps,nAtoms))
coordZ_atom = N.zeros((nSteps,nAtoms))
sumX = [0] * nAtoms
sumY = [0] * nAtoms
sumZ = [0] * nAtoms
######################################################
# 1) Calculate the average structure fron trajectory #
######################################################
for i in range(0, 3):
for j in range(0, 3):
coordX_atom[i][j] = infl.variables["configuration"][i,j,0]
coordY_atom[i][j] = infl.variables["configuration"][i,j,1]
coordZ_atom[i][j] = infl.variables["configuration"][i,j,2]
sumX[j] = sumX[j] + coordX_atom[i][j]
sumY[j] = sumY[j] + coordY_atom[i][j]
sumZ[j] = sumZ[j] + coordZ_atom[i][j]
avgX = [0] * nAtoms
avgY = [0] * nAtoms
avgZ = [0] * nAtoms
for j in range(0, 3):
avgX[j] = sumX[j]/nSteps
avgY[j] = sumY[j]/nSteps
avgZ[j] = sumZ[j]/nSteps
##############################################################
# 2) Subtract average structure to each atom and for each frame #
##############################################################
for i in range(0, 3):
for j in range(0, 3):
coordX_atom[i][j] = infl.variables["configuration"][i,j,0] - avgX[j]
coordY_atom[i][j] = infl.variables["configuration"][i,j,1] - avgY[j]
coordZ_atom[i][j] = infl.variables["configuration"][i,j,2] - avgZ[j]
#######################################
# 3) Write new NetCDF trajectory file #
#######################################
ofl = S(title + "_subAVG.nc", "a")
############################################################
# Get information of variables contained in the NetCDF input file
#############################################################
i = 0
for v in infl.variables:
varNames = [v for v in infl.variables]
i += 1
#############################################
# Respectively get, elements names in variable, dimension of elements and lenght of the array variableNames
##############################################
for v in infl.variables["box_size"].dimensions:
boxSizeNames = [v for v in infl.variables["box_size"].dimensions]
for v in infl.variables["box_size"].shape:
boxSizeShape = [v for v in infl.variables["box_size"].shape]
boxSizeLenght = boxSizeNames.__len__()
print boxSizeLenght
for v in infl.variables["step"].dimensions:
stepNames = [v for v in infl.variables["step"].dimensions]
for v in infl.variables["step"].shape:
stepShape = [v for v in infl.variables["box_size"].shape]
stepLenght = stepNames.__len__()
print stepLenght
for v in infl.variables["configuration"].dimensions:
configurationNames = [v for v in infl.variables["configuration"].dimensions]
for v in infl.variables["configuration"].shape:
configurationShape = [v for v in infl.variables["configuration"].shape]
configurationLenght = configurationNames.__len__()
print configurationLenght
for v in infl.variables["description"].dimensions:
descriptionNames = [v for v in infl.variables["description"].dimensions]
for v in infl.variables["description"].shape:
descriptionShape = [v for v in infl.variables["description"].shape]
descriptionLenght = descriptionNames.__len__()
print descriptionLenght
for v in infl.variables["time"].dimensions:
timeNames = [v for v in infl.variables["time"].dimensions]
for v in infl.variables["time"].shape:
timeShape = [v for v in infl.variables["time"].shape]
timeLenght = timeNames.__len__()
print timeLenght
#Get Box size
xBox = infl.variables["box_size"][0,0]
yBox = infl.variables["box_size"][0,1]
zBox = infl.variables["box_size"][0,2]
# Get description lenght
description_lenghtLenght = infl.variables["description"][:]
############################################################
# Create Dimensions
############################################################
stepnumber_var = ofl.createVariable("step_number", "i",("step_number",))
stepnumber_var.standard_name = "step_number"
atomNumber_var = ofl.createVariable("atom_number", "i", ("atom_number",))
atomNumber_var.standard_name = "atom__number"
#
#xyz_var = ofl.createVariable("xyz", "f",("xyz",))
#xyz_var.units = "nanometers"
#xyz_var.standard_name = "xyz"
#
#configuration_var = ofl.createVariable("configuration", "f", ("step_number", "atom_number", "xyz"))
#configuration_var.units = "nanometers"
#configuration_var.standard_name = "configuration"
#
#print configuration_var.shape
#step_var = ofl.createVariable("box_size_lenght", 3)
#configuration_var = ofl.createVariable("atom_number", nAtoms)
#description_var = ofl.createVariable("xyz", 3)
#time_var = ofl.createVariable(description_lenght, description_lenghtLenght)
#
#a = infl.variables["step_number"].dimensions.keys()
#print a
谢谢!
2 个回答
atomNumber_var.standard_name = "atom__number"
这里的atom__number用了两个"__",而不是一个"_"。我不确定这是不是你的问题,但可以考虑看看。
我还建议你把netcdf文件的步骤写得更清楚。我喜欢把它分成三步。我用的是一个关于海洋表面温度的科学数据的例子。你有一个创建维度的部分,但实际上并没有做到。这部分更准确来说应该是创建变量的部分。
创建维度
创建变量
填充变量
from netCDF4 import Dataset ncfile = Dataset('temp.nc','w') lonsdim = latdata.shape #Set dimension lengths latsdim = londata.shape ############### #Create Dimensions ############### latdim = ncfile.createDimension('latitude', latsdim) londim = ncfile.createDimension('longitude', lonsdim) ############### #Create Variables ################# The variables contain the dimensions previously set latitude = ncfile.createVariable('latitude','f8',('latitude')) longitude = ncfile.createVariable('longitude','f8',('longitude')) oceantemp = ncfile.createVariable('SST','f4' ('latitude','longitude'),fill_value=-99999.0) ############### Fill Variables ################ latitude[:] = latdata #lat data to fill in longitude[:] = londata #lon data to fill in oceantemp[:,:] = sst[:,:] #some variable previous calculated
希望这些对你有帮助。
这可能是一个库在试图“帮忙”的情况(具体情况我在帖子最后会详细说明,但我不能确认)。要解决这个问题,你需要明确为 atom_number 和 step_number 创建维度,可以在创建变量之前使用以下代码(假设我对 nSteps 和 nAtoms 的理解是正确的):
ofl.createDimension("step_number", nSteps)
ofl.createDimension("atom_number", nAtoms)
如果你对 netCDF 还不太熟悉,我建议你看看 netcdf4-python 这个包,
http://unidata.github.io/netcdf4-python/
或者在 scipy 中找到的 netCDF 包:
http://docs.scipy.org/doc/scipy/reference/io.html
可能发生的情况是:当你创建变量 step_number 时,库试图帮忙,创建了一个无限长度的 step_number 维度。然而,在 netcdf-3 文件中,你只能有一个无限维度,所以这个“帮忙”的做法并不奏效。