Source code for flopy.utils.mfreadnam

"""
mfreadnam module.  Contains the NamData class. Note that the user can access
the NamData class as `flopy.modflow.NamData`.

Additional information about the MODFLOW name file can be found at the `Online
MODFLOW Guide
<http://water.usgs.gov/ogw/modflow/MODFLOW-2005-Guide/name_file.htm>`_.

"""
import os
import sys

if sys.version_info < (3, 6):
    from collections import OrderedDict

    dict = OrderedDict


[docs]class NamData: """ MODFLOW Namefile Class. Parameters ---------- pkgtype : string String identifying the type of MODFLOW package. See the mfnam_packages dictionary keys in the model object for a list of supported packages. This dictionary is also passed in as packages. name : string Filename of the package file identified in the name file handle : file handle File handle referring to the file identified by `name` packages : dictionary Dictionary of package objects as defined in the `mfnam_packages` attribute of :class:`flopy.modflow.mf.Modflow`. Attributes ---------- filehandle : file handle File handle to the package file. Read from `handle`. filename : string Filename of the package file identified in the name file. Read from `name`. filetype : string String identifying the type of MODFLOW package. Read from `pkgtype`. package : string Package type. Only assigned if `pkgtype` is found in the keys of `packages` Methods ------- See Also -------- Notes ----- Examples -------- """ def __init__(self, pkgtype, name, handle, packages): self.filehandle = handle self.filename = name self.filetype = pkgtype self.package = None if self.filetype.lower() in packages: self.package = packages[self.filetype.lower()] def __repr__(self): return "filename:{0}, filetype:{1}".format( self.filename, self.filetype )
[docs]def getfiletypeunit(nf, filetype): """ Method to return unit number of a package from a NamData instance Parameters ---------- nf : NamData instance filetype : string, name of package seeking information for Returns ------- cunit : int, unit number corresponding to the package type """ for cunit, cvals in nf.items(): if cvals.filetype.lower() == filetype.lower(): return cunit print('Name file does not contain file of type "{0}"'.format(filetype)) return None
[docs]def parsenamefile(namfilename, packages, verbose=True): """ Returns dict from the nam file with NamData keyed by unit number Parameters ---------- namefilename : str Name of the MODFLOW namefile to parse. packages : dict Dictionary of package objects as defined in the `mfnam_packages` attribute of :class:`flopy.modflow.mf.Modflow`. verbose : bool Print messages to screen. Default is True. Returns ------- dict or OrderedDict For each file listed in the name file, a :class:`flopy.utils.mfreadnam.NamData` instance is stored in the returned dict keyed by unit number. Prior to Python version 3.6 the return object is an OrderedDict to retain the order of items in the nam file. Raises ------ IOError: If namfilename does not exist in the directory. ValueError: For lines that cannot be parsed. """ # initiate the ext_unit_dict ordered dictionary ext_unit_dict = dict() if verbose: print("Parsing the namefile --> {0:s}".format(namfilename)) if not os.path.isfile(namfilename): # help diagnose the namfile and directory e = "Could not find {} ".format( namfilename ) + "in directory {}".format(os.path.dirname(namfilename)) raise IOError(e) with open(namfilename, "r") as fp: lines = fp.readlines() for ln, line in enumerate(lines, 1): line = line.strip() if len(line) == 0 or line.startswith("#"): # skip blank lines or comments continue items = line.split() # ensure we have at least three items if len(items) < 3: e = "line number {} has fewer than 3 items: {}".format(ln, line) raise ValueError(e) ftype, key, fpath = items[0:3] ftype = ftype.upper() # remove quotes in file path if '"' in fpath: fpath = fpath.replace('"', "") if "'" in fpath: fpath = fpath.replace("'", "") # need make filenames with paths system agnostic if "/" in fpath: raw = fpath.split("/") elif "\\" in fpath: raw = fpath.split("\\") else: raw = [fpath] fpath = os.path.join(*raw) fname = os.path.join(os.path.dirname(namfilename), fpath) if not os.path.isfile(fname) or not os.path.exists(fname): # change to lower and make comparison (required for linux) dn = os.path.dirname(fname) fls = os.listdir(dn) lownams = [f.lower() for f in fls] bname = os.path.basename(fname) if bname.lower() in lownams: idx = lownams.index(bname.lower()) fname = os.path.join(dn, fls[idx]) # open the file kwargs = {} if ftype == "DATA(BINARY)": openmode = "rb" else: openmode = "r" kwargs["errors"] = "replace" try: filehandle = open(fname, openmode, **kwargs) except IOError: if verbose: print("could not set filehandle to {0:s}".format(fpath)) filehandle = None # be sure the second value is an integer try: key = int(key) except ValueError: raise ValueError( "line number {}: the unit number (second item) " "is not an integer: {}".format(ln, line) ) # Trap for the case where unit numbers are specified as zero # In this case, the package must have a variable called # unit number attached to it. If not, then the key is set # to fname if key == 0: ftype_lower = ftype.lower() if ftype_lower in packages: key = packages[ftype_lower]._reservedunit() else: key = ftype ext_unit_dict[key] = NamData(ftype, fname, filehandle, packages) return ext_unit_dict
[docs]def attribs_from_namfile_header(namefile): # check for reference info in the nam file header defaults = { "xll": None, "yll": None, "xul": None, "yul": None, "rotation": 0.0, "proj4_str": None, } if namefile is None: return defaults header = [] with open(namefile, "r") as f: for line in f: if not line.startswith("#"): break header.extend(line.strip().replace("#", "").split(";")) for item in header: if "xll" in item.lower(): try: xll = float(item.split(":")[1]) defaults["xll"] = xll except: print(" could not parse xll in {}".format(namefile)) elif "yll" in item.lower(): try: yll = float(item.split(":")[1]) defaults["yll"] = yll except: print(" could not parse yll in {}".format(namefile)) elif "xul" in item.lower(): try: xul = float(item.split(":")[1]) defaults["xul"] = xul except: print(" could not parse xul in {}".format(namefile)) elif "yul" in item.lower(): try: yul = float(item.split(":")[1]) defaults["yul"] = yul except: print(" could not parse yul in {}".format(namefile)) elif "rotation" in item.lower(): try: angrot = float(item.split(":")[1]) defaults["rotation"] = angrot except: print(" could not parse rotation in {}".format(namefile)) elif "proj4_str" in item.lower(): try: proj4 = ":".join(item.split(":")[1:]).strip() if proj4.lower() == "none": proj4 = None defaults["proj4_str"] = proj4 except: print(" could not parse proj4_str in {}".format(namefile)) elif "start" in item.lower(): try: start_datetime = item.split(":")[1].strip() defaults["start_datetime"] = start_datetime except: print(" could not parse start in {}".format(namefile)) return defaults