从文件对象或netCDF4数据集创建Iris Cube

13
有没有办法使用文件对象(二进制流)或从netCDF4数据集对象创建(打开/加载)一个Iris Cube?具体而言,我有一个通过URL提供的文件,但不是由OpenDAP服务器提供的;iris.load_cube()等函数在此文件上失败。我意识到Iris更喜欢惰性加载,因此使用URI而不是内存数据,但这并非总是可行的。对于一个普通的netCDF4 Dataset对象,我可以执行以下操作:
from urllib.request import urlopen
import netCDF4 as nc

url = 'https://crudata.uea.ac.uk/cru/data/temperature/HadCRUT.4.6.0.0.median.nc'
with urlopen(url) as stream:
    ds = nc.Dataset('HadCRUT', memory=stream.read())

所以我希望对Iris Cube 做类似的事情,或者将netCDF4数据集读入到一个立方体中,而不需要通过磁盘上的临时文件。我原本希望在Iris的功能中会存在这样的东西,但是我还没有在参考文档中找到它。

1个回答

0

为了读取 .nc 文件,Iris 内部使用了你提到的 相同的 netcdf4-python 库。

这意味着理论上你可以:

  1. 子类化 CFReader,覆盖它的 __init__ 方法,并将唯一的更改行改为 self._dataset = netCDF4.Dataset(self._filename, mode='r')

  2. 编写自己的 load_cube 函数(基于此代码),该函数将使用您自定义的 CFReader,或者您可以使用自定义的 CFReader 对 iris 进行 monkeypatch。

monkey-patching 的一般思路:

from urllib.request import urlopen

import iris.fileformats.cf
import netCDF4 as nc


def __patch_CFReader():
    if getattr(iris.fileformats.cf.CFReader, '_HACKY_PATCHED'):
        return

    from iris.fileformats.cf import CFReader

    class CustomCFReader(CFReader):
        _HACKY_PATCHED = True

        def __init__(self, uri, *args, **kwargs):
            # ... other code copied
            with urlopen(url) as stream:
                self._dataset = nc.Dataset('HadCRUT', memory=stream.read())
            # ... other code copied

    iris.fileformats.cf.CFReader = CustomCFReader


__patch_CFReader()

import iris
cube = iris.load_cube('https://crudata.uea.ac.uk/cru/data/temperature/HadCRUT.4.6.0.0.median.nc')

警告!根据您的项目中如何导入模块,猴子补丁可能不会像您最初想象的那样总是有效。因此,您可能应该使用一些专门设计用于猴子补丁的库,例如gorilla:

https://gorilla.readthedocs.io/en/latest/tutorial.html

# my_patches.py:
from urllib.request import urlopen

import gorilla
import iris.fileformats.cf
import netCDF4 as nc

settings = gorilla.Settings(allow_hit=True)

@gorilla.patch(iris.fileformats.cf.CFReader, settings=settings)
def __init__(self, uri, *args, **kwargs):
    # ... other code copied
    with urlopen(url) as stream:
        self._dataset = nc.Dataset('HadCRUT', memory=stream.read())
    # ... other code copied

# earliest_imported_module.py:
import gorilla
import my_patches

for patch in gorilla.find_patches([my_patches]):
    gorilla.apply(patch)

我认为你可以直接调用 iris.fileformats.netcdf.load_cubes。文档可能不鼓励直接使用这些方法,但如果你要使用 monkeypatching,那么这只是你问题中最小的一部分。 - imposeren
很遗憾,经过更详细的查看,我认为这也不是正确的方法:load_cubes 调用 _load_cube,后者还需要一个文件名,以将 netCDF 变量读入可能的单独立方体中。对于内存中的 netCDF 数据集,乍一看需要覆盖 netcdf.py 中的各种(私有)函数。在这种情况下,覆盖 load_cubes 实际上变成了实现自己的文件格式模块。 - 9769953

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接