Создать Iris Cube из файлового объекта или набора данных netCDF4 - PullRequest
10 голосов
/ 08 мая 2019

Есть ли способ создать (открыть / загрузить) Iris Cube, используя файловый объект (двоичный поток) или, альтернативно, из объекта набора данных netCDF4?

В частности, у меня есть файл, обслуживаемый по 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 голосов
/ 15 мая 2019

Для чтения .nc файлов Iris внутренне использует ту же самую netcdf4-python библиотеку, которую вы упомянули.

Это означает, что теоретически вы можете:

  1. Подкласс CFReader , переопределяющий его __init__ метод с единственным изменением в строке self._dataset = netCDF4.Dataset(self._filename, mode='r')

  2. Либо напишите свою собственную функцию load_cube ( на основе этого кода ), которая будет использовать ваш пользовательский CFReader, либо вы можете сделать monkeypatch iris с вашим настроенным CFReader.

Общая идея для исправления обезьян:

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')

ВНИМАНИЕ! В зависимости от того, как выполняется импорт в вашем проекте, исправление обезьян может не всегда работает, как вы сначала думаете. Так что, возможно, вам лучше использовать библиотеку специально разработанный для мартышек, например Горилла:

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)
...