Полное руководство: чтение файлов голов MODFLOW в Python
Узнайте, как читать и анализировать двоичные файлы голов MODFLOW на Fortran с помощью Python с использованием FloPy или прямых методов чтения двоичных файлов. Полное руководство с примерами и советами по устранению неполадок.
Как читать и парсить двоичный файл голов MODFLOW Fortran с помощью Python
Чтение и разбор двоичных файлов голов MODFLOW Fortran в Python
Чтение и разбор двоичных файлов голов MODFLOW Fortran в Python можно осуществить с помощью специализированных библиотек, таких как FloPy, которая предоставляет специализированные классы для обработки двоичных выходных файлов MODFLOW, или через прямые методы чтения двоичных файлов для более индивидуальных подходов.
Содержание
- Использование FloPy для двоичных файлов MODFLOW
- Прямые методы чтения двоичных файлов
- Понимание структуры двоичных файлов MODFLOW
- Практические примеры
- Распространенные проблемы и решения
Использование FloPy для двоичных файлов MODFLOW
FloPy является наиболее полным и рекомендуемым подходом для чтения двоичных файлов MODFLOW, включая файлы голов. Библиотека предоставляет специализированные классы, которые понимают формат двоичных файлов MODFLOW.
Класс HeadFile
Класс HeadFile из flopy.utils.binaryfile специально разработан для чтения стандартных двоичных файлов голов MODFLOW:
import flopy.utils.binaryfile as bf
# Создание объекта headfile
hdobj = bf.HeadFile('model.hds', precision='single')
# Список доступных временных записей
times = hdobj.get_times()
print(times)
# Получение данных для конкретного времени
head_data = hdobj.get_data(totim=1.0)
Класс HeadUFile
Для моделей MODFLOW-USG используйте класс HeadUFile:
headobj = bf.HeadFile(modelname+'.hds', text='headu')
head = headobj.get_data()
Согласно документации flopy, класс BinaryLayerFile “создан… для целых чисел, которые являются указателями на первые байты данных для соответствующего массива данных.”
Основные методы FloPy
get_times(): Возвращает список доступных временных шаговget_data(): Извлекает данные голов для указанного времениlist_records(): Показывает доступные записи в файлеget_kstpkper(): Получает комбинации периодов напряженности/временных шагов
Как показано в учебнике flopy на GitHub, вы можете легко извлекать и строить графики данных голов MODFLOW с помощью этих методов.
Прямые методы чтения двоичных файлов
Когда вам нужен больший контроль или вы хотите реализовать собственный разбор, вы можете читать двоичные файлы Fortran напрямую с помощью Python.
Использование NumPy
Функция numpy.fromfile может читать неформатированные двоичные файлы Fortran:
import numpy as np
# Прямое чтение двоичного файла
data = np.fromfile('model.hds', dtype='float32')
# Изменение формы в соответствии с размерами модели
heads = data.reshape((nlay, nrow, ncol))
Использование библиотеки FortranFile
Библиотека fortio предоставляет специализированные инструменты для чтения неформатированных двоичных файлов Fortran:
from fortio import FortranFile
# Открытие файла с правильной обработкой заголовка
f = FortranFile('model.hds', header_dtype='uint32')
# Чтение записей
while True:
try:
record = f.read_record()
# Обработка данных записи
except:
break
Как описано в репозитории GitHub fortio, эта библиотека обрабатывает “неформатированные двоичные файлы Fortran с записями переменной длины.”
Ручное чтение двоичных файлов
Для полного контроля вы можете реализовать ручное чтение двоичных файлов:
import struct
def read_modflow_heads(filename):
with open(filename, 'rb') as f:
# Чтение информации заголовка
header = f.read(4) # Первые 4 байта
# Чтение записей данных
# Реализация зависит от конкретного формата MODFLOW
Понимание структуры двоичных файлов MODFLOW
Двоичные файлы MODFLOW используют специфические структуры неформатированных записей Fortran:
Структура файла
[Запись 1] - Информация заголовка
[Запись 2] - Данные временного шага 1
[Запись 3] - Данные временного шага 2
...
Каждая запись обычно содержит:
- Заголовок: Информация о записи (время, слой и т.д.)
- Данные: Фактические значения голов
- Подвал: Маркеры завершения записи
Размеры данных
Структура данных обычно имеет размеры [output_times, nlay, nrow, ncol], где:
output_times: Количество временных шагов с выходными даннымиnlay: Количество слоевnrow: Количество строкncol: Количество столбцов
Как отмечено в обсуждении flopy, “данные имеют размеры [output_times, nlay, nrow, ncol], где output_times - это количество раз, когда у вас есть выходные двоичные данные голов.”
Обработка точности
Файлы MODFLOW могут использовать различную точность:
- Одинарная точность (4 байта на число с плавающей точкой)
- Двойная точность (8 байт на число с плавающей точкой)
FloPy автоматически определяет точность, но вы можете указать ее вручную:
hdobj = bf.HeadFile('model.hds', precision='single') # или 'double'
Практические примеры
Пример 1: Базовое чтение файла голов
import flopy.utils.binaryfile as bf
# Загрузка файла голов MODFLOW
hdobj = bf.HeadFile('model.hds')
# Получение доступных времен
times = hdobj.get_times()
print(f"Доступные временные шаги: {times}")
# Получение данных для последнего временного шага
final_heads = hdobj.get_data(totim=times[-1])
# Сохранение в текстовый файл
np.savetxt('final_heads.txt', final_heads[0])
Пример 2: Извлечение временного ряда
import numpy as np
import matplotlib.pyplot as plt
# Чтение файла голов
hdobj = bf.HeadFile('model.hds')
# Получение временного ряда для конкретной ячейки
cell_i, cell_j = 10, 20 # Индексы ячейки
time_series = []
for time in hdobj.get_times():
heads = hdobj.get_data(totim=time)
time_series.append(heads[0, cell_i, cell_j]) # Первый слой, конкретная ячейка
# Построение графика временного ряда
plt.plot(hdobj.get_times(), time_series)
plt.xlabel('Время')
plt.ylabel('Голова')
plt.title('Временной ряд голов в ячейке (10, 20)')
plt.show()
Пример 3: Преобразование данных оседания
Как показано в примере Stack Overflow, вы можете читать другие выходные двоичные файлы MODFLOW:
import flopy.utils.binaryfile as bf
# Чтение данных оседания
sobj = bf.HeadFile('model.zdisplacement.bin', text='Z DISPLACEMENT')
times = sobj.get_times()
zd = sobj.get_data(totim=times[-1])
# Сохранение смещения первого слоя
np.savetxt('layer0.zdisplacement.txt', zd[0])
Распространенные проблемы и решения
Проблема 1: Ошибки определения точности
Если FloPy не может автоматически определить точность:
# Указание точности вручную
hdobj = bf.HeadFile('model.hds', precision='single')
Проблема 2: Значения “HNOFLO” или отсутствующие данные
MODFLOW часто использует специальные значения, такие как -999, для представления неактивных ячеек:
import numpy as np
heads = hdobj.get_data(totim=1.0)
heads[heads == -999] = np.nan # Замена отсутствующих значений на NaN
Проблема 3: Чтение нестандартных файлов
Для нестандартных двоичных файлов используйте прямой подход:
# Проверка структуры файла
with open('model.hds', 'rb') as f:
header = f.read(100) # Просмотр первых 100 байт
Проблема 4: Обработка больших файлов
Для очень больших моделей MODFLOW обрабатывайте данные порциями:
import flopy.utils.binaryfile as bf
hdobj = bf.HeadFile('large_model.hds')
for time in hdobj.get_times():
# Обработка одного временного шага за раз
heads = hdobj.get_data(totim=time)
# Сохранение или обработка данных
np.save(f'heads_time_{time}.npy', heads)
Заключение
Чтение и разбор двоичных файлов голов MODFLOW Fortran в Python можно эффективно осуществить с помощью нескольких подходов:
- Используйте FloPy как основной метод для большинства приложений - он предоставляет надежные, хорошо протестированные классы, специально разработанные для двоичных файлов MODFLOW
- Прямое чтение двоичных файлов предлагает гибкость для пользовательских реализаций, когда FloPy не подходит
- Понимайте структуру файла, включая заголовки, организацию данных и обработку точности
- Правильно обрабатывайте распространенные проблемы, такие как определение точности, специальные значения и управление большими файлами
Для большинства приложений моделирования грунтовых вод FloPy предоставляет наиболее надежное и комплексное решение для чтения двоичных файлов голов MODFLOW, в то время как методы прямого чтения двоичных файлов предлагают ценные альтернативы для специализированных случаев использования.
Источники
- flopy.utils.binaryfile module — flopy Documentation 3.3.2
- Python Read Fortran Binary File - Stack Overflow
- Extract heads from MODFLOW-USG binary output using flopy - Stack Overflow
- GitHub - syrte/fortio: A Python IO for Fortran Unformatted Binary File with Variable-Length Records
- Reading MODFLOW binary files with flopy – viewing with VisIt
- Extracting heads from Modflow binary files using flopy · modflowpy/flopy · Discussion
- flopy/.docs/Notebooks/mf_tutorial01.py at develop · modflowpy/flopy
- Extract subsidence data from MODFLOW-2000 binary output using FloPy - Stack Overflow