【问题标题】:lat,lon information from hdf file python来自hdf文件python的纬度,经度信息
【发布时间】:2019-01-04 13:23:54
【问题描述】:

我有一个 hdf 文件,想从中提取数据。由于某种原因,我无法提取纬度和经度值:

我尝试的代码是:

from pyhdf import SD
hdf = SD.SD('MOD10C2.A2001033.006.2016092173057.hdf')
data = hdf.select('Eight_Day_CMG_Snow_Cover')
lat = (hdf.select('Latitude'))[:]

它给了我一个错误:

HDF4Error: select: non-existent dataset

我试过了:

lat = (hdf.select('Lat'))[:]

还是没用!

数据可以在这个link找到

我们将不胜感激任何帮助!

数据格式如下:

我得到的错误是:

---------------------------------------------------------------------------
HDF4Error                                 Traceback (most recent call last)
~/anaconda3/lib/python3.6/site-packages/pyhdf/SD.py in select(self, name_or_index)
   1635             try:
-> 1636                 idx = self.nametoindex(name_or_index)
   1637             except HDF4Error:

~/anaconda3/lib/python3.6/site-packages/pyhdf/SD.py in nametoindex(self, sds_name)
   1528         sds_idx = _C.SDnametoindex(self._id, sds_name)
-> 1529         _checkErr('nametoindex', sds_idx, 'non existent SDS')
   1530         return sds_idx

~/anaconda3/lib/python3.6/site-packages/pyhdf/error.py in _checkErr(procName, val, msg)
     22             err = "%s : %s" % (procName, msg)
---> 23         raise HDF4Error(err)

HDF4Error: nametoindex : non existent SDS

During handling of the above exception, another exception occurred:

HDF4Error                                 Traceback (most recent call last)
<ipython-input-11-21e6a4fdf8eb> in <module>()
----> 1 hdf.select('Lat')

~/anaconda3/lib/python3.6/site-packages/pyhdf/SD.py in select(self, name_or_index)
   1636                 idx = self.nametoindex(name_or_index)
   1637             except HDF4Error:
-> 1638                 raise HDF4Error("select: non-existent dataset")
   1639         id = _C.SDselect(self._id, idx)
   1640         _checkErr('select', id, "cannot execute")

HDF4Error: select: non-existent dataset

【问题讨论】:

  • 您可以在这里发布您的数据格式吗?
  • 您不应该提供数据集的完整路径吗?它不在文件根目录中...
  • 另外,你有一个 hdf5 标签。据我所知,pyhdf 是一个 HDF 4 库。解决方案是什么?文件版本是 4 还是 5?
  • 查看此评论并关注以下内容:stackoverflow.com/questions/49670685/…。看起来 panoply 在这里做一些课外活动:)
  • Panoply 使用 netCDF-Java 库打开数据文件并指定“增强模式”,以便更好地获取坐标系信息。借助 HDFEOS 文件,该库显然构建了一些“虚拟”地理定位数组,例如 Lat 和 Lon。对于更新版本的 Panoply,您应该会看到语句“显示增强模式描述。变量似乎是‘虚拟’,基于数据集元数据构建。”在此类变量的信息面板中。

标签: python hdf pyhdf


【解决方案1】:

您使用的数据文件是 MODIS 3 级产品。所有 3 级产品都插入到一些规则网格上。在 MOD10C2 的情况下,网格是所谓的气候建模网格 (CMG)。该网格以 0.05 度的间隔规则地间隔开。 Panoply 知道这一点。

CMG 是圆柱投影中的规则矩形网格。我们可以使用这些信息来定位数据。请考虑以下示例。

from pyhdf import SD
import numpy as np
from matplotlib import pyplot as plt
from mpl_toolkits.basemap import Basemap
from matplotlib.colors import LinearSegmentedColormap
hdf = SD.SD('MOD10C2.A2001033.006.2016092173057.hdf')
data = hdf.select('Eight_Day_CMG_Snow_Cover')
snowcover=np.array(data[:,:],np.float)
snowcover[np.where(snowcover==255)]=np.nan
m = Basemap(projection='cyl', resolution = 'l',
    llcrnrlat=-90, urcrnrlat=90,llcrnrlon=-180,urcrnrlon=180)
cdict = {'red' : [(0,0.,0.), (100./255.,1.,1.),(1.,0.,0.)],
         'green' : [(0,0.,0.),(1.,0.,0.)] , 
         'blue' : [(0,0.,0.),(100./255.,0.,0.),(1.,1.,1.)] }
blue_red = LinearSegmentedColormap('BlueRed',cdict)

m.drawcoastlines(linewidth=0.5)
m.drawparallels(np.arange(-90,120,30), labels=[1,0,0,0])
m.drawmeridians(np.arange(-180,181,45),labels=[0,0,0,1])
m.imshow(np.flipud(snowcover),cmap=blue_red)
plt.title('MOD10C2: Eight Day Global Snow Cover')
plt.show()

这段代码应该显示一张雪覆盖的图片。

如果您需要处理不同投影中的数据,您可以使用 python GDAL 接口将 snowcover 数组转换为地理定位数据集。

将数据作为不规则网格处理也是可能的,但效率非常低。

lon,lat = np.meshgrid(np.arange(-180,180,0.05),np.arange(-90,90,0.05))

将是相应的经度和纬度网格。

【讨论】:

  • 非常感谢您的回答并提供有关数据集的详细信息:)
【解决方案2】:

通常经纬度信息不在 hdf 文件的科学模式下,这主要是因为lat = (hdf.select('Lat'))[:] 不像其他变量那样工作。使用以下函数,您可以在 hdf 文件中提取任何类型的变量存储

from pyhdf.HDF import *
from pyhdf.V   import *
from pyhdf.VS  import *
from pyhdf.SD  import *

def HDFread(filename, variable, Class=None):
    """
    Extract the data for non scientific data in V mode of hdf file
    """
    hdf = HDF(filename, HC.READ)

    # Initialize the SD, V and VS interfaces on the file.
    sd = SD(filename)
    vs = hdf.vstart()
    v  = hdf.vgstart()

    # Encontrar el puto id de las Geolocation Fields
    if Class == None:
        ref = v.findclass('SWATH Vgroup')
    else:
        ref = v.findclass(Class)

    # Open all data of the class
    vg = v.attach(ref)
    # All fields in the class
    members = vg.tagrefs()

    nrecs = []
    names = []
    for tag, ref in members:
        # Vdata tag
        vd = vs.attach(ref)
        # nrecs, intmode, fields, size, name = vd.inquire()
        nrecs.append(vd.inquire()[0]) # number of records of the Vdata
        names.append(vd.inquire()[-1])# name of the Vdata
        vd.detach()

    idx = names.index(variable)
    var = vs.attach(members[idx][1])
    V   = var.read(nrecs[idx])
    var.detach()
    # Terminate V, VS and SD interfaces.
    v.end()
    vs.end()
    sd.end()
    # Close HDF file.
    hdf.close()

    return np.array(V).ravel()

如果您不知道确切的变量名称,您可以尝试使用下面的程序pyhdf.V,它显示了其中包含的 vgroup 的内容 任何 HDF 文件。

from pyhdf.HDF import *
from pyhdf.V   import *
from pyhdf.VS  import *
from pyhdf.SD  import *

def describevg(refnum):
    # Describe the vgroup with the given refnum.
    # Open vgroup in read mode.
    vg = v.attach(refnum)
    print "----------------"
    print "name:", vg._name, "class:",vg._class, "tag,ref:",
    print vg._tag, vg._refnum

    # Show the number of members of each main object type.
    print "members: ", vg._nmembers,
    print "datasets:", vg.nrefs(HC.DFTAG_NDG),
    print "vdatas:  ", vg.nrefs(HC.DFTAG_VH),
    print "vgroups: ", vg.nrefs(HC.DFTAG_VG)

    # Read the contents of the vgroup.
    members = vg.tagrefs()

    # Display info about each member.
    index = -1
    for tag, ref in members:
        index += 1
        print "member index", index
        # Vdata tag
        if tag == HC.DFTAG_VH:
            vd = vs.attach(ref)
            nrecs, intmode, fields, size, name = vd.inquire()
            print "  vdata:",name, "tag,ref:",tag, ref
            print "    fields:",fields
            print "    nrecs:",nrecs
            vd.detach()

        # SDS tag
        elif tag == HC.DFTAG_NDG:
            sds = sd.select(sd.reftoindex(ref))
            name, rank, dims, type, nattrs = sds.info()
            print "  dataset:",name, "tag,ref:", tag, ref
            print "    dims:",dims
            print "    type:",type
            sds.endaccess()

        # VS tag
        elif tag == HC.DFTAG_VG:
            vg0 = v.attach(ref)
            print "  vgroup:", vg0._name, "tag,ref:", tag, ref
            vg0.detach()

        # Unhandled tag
        else:
            print "unhandled tag,ref",tag,ref

    # Close vgroup
    vg.detach()

# Open HDF file in readonly mode.
filename = 'yourfile.hdf'
hdf = HDF(filename)

# Initialize the SD, V and VS interfaces on the file.
sd = SD(filename)
vs = hdf.vstart()
v  = hdf.vgstart()

# Scan all vgroups in the file.
ref = -1
while 1:
    try:
        ref = v.getid(ref)
        print ref
    except HDF4Error,msg:    # no more vgroup
        break
    describevg(ref)

【讨论】:

    【解决方案3】:

    我认为问题在于该文件没有传统的纬度和经度数据(就像许多 .nc 文件一样)。 当我想处理 MYD14 数据时遇到类似的问题(这是一个关于防火罩的 MODIS 文件)。我搜索了很长时间以找到解决方案。以下是我的发现: ①如果 MODIS 文件使用 SIN-Grid(Sinusoidal Projection) 定义数据,该文件不会给你传统的 lon,lat 数据。 ②更多Sinusoidal Projection的详细内容,可以阅读本站:https://code.env.duke.edu/projects/mget/wiki/SinusoidalMODIS

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-03-17
      • 2017-03-06
      • 1970-01-01
      • 2012-05-28
      • 2011-01-25
      • 2013-11-02
      • 1970-01-01
      • 2011-02-09
      相关资源
      最近更新 更多