Source code for in2Trans.ascUtils

"""
    ASCII file reader and handler

"""

import logging

import numpy as np

# create local logger
log = logging.getLogger(__name__)


[docs]def readASCheader(fname): """return a class with information from an ascii file header Parameters ----------- fname: str or pathlib object path to ascii file Returns -------- headerInfo: class information that is stored in header (ncols, nrows, xllcenter, yllcenter, nodata_value) """ # read header headerRows = 6 # six rows for header information headerInfo = ( {} ) # store header information including ncols, nrows, xllcorner, yllcorner, cellsize, nodata_value rowCount = 1 with open(str(fname), "rt") as fileH: for line in fileH: if rowCount <= headerRows: line = line.split() headerInfo[line[0].lower()] = float(line[1]) else: break rowCount = rowCount + 1 if ("xllcenter" not in headerInfo and "xllcorner" in headerInfo) and ( "yllcenter" not in headerInfo and "yllcorner" in headerInfo ): headerInfo["xllcenter"] = headerInfo["xllcorner"] + headerInfo["cellsize"] / 2 headerInfo["yllcenter"] = headerInfo["yllcorner"] + headerInfo["cellsize"] / 2 # remove xllcorner, yllcorner headerInfo.pop("xllcorner") headerInfo.pop("yllcorner") # convert ncols and nrows to int headerInfo["ncols"] = int(headerInfo["ncols"]) headerInfo["nrows"] = int(headerInfo["nrows"]) headerItems = [item.lower() for item in list(headerInfo.keys())] if sorted(headerItems) != sorted( ["cellsize", "nrows", "ncols", "xllcenter", "yllcenter", "nodata_value"] ): message = "DEM header is not in correct format - needs to contain values for: cellsize, nrows, ncols, xllcenter(-corner), yllcenter(-corner), nodata_value" log.error(message) raise ValueError(message) fileH.close() return headerInfo
[docs]def isEqualASCheader(headerA, headerB): """Test if two headers (A,B) are the same (except for noData Values) Parameters ----------- headerA: class headerB: class Returns -------- boolean: True if header A and B are equal (disregrad the noData field) """ a = headerA b = headerB return ( (a["ncols"] == b["ncols"]) and (a["nrows"] == b["nrows"]) and (a["xllcenter"] == b["xllcenter"]) and (a["yllcenter"] == b["yllcenter"]) and (a["cellsize"] == b["cellsize"]) )
[docs]def readASCdata2numpyArray(fName): """Read ascii matrix as numpy array Parameters ----------- fname: str or pathlib object path to ascii file Returns -------- -rasterdata : 2D numpy array 2D numpy array of ascii matrix """ infile = open(fName, "r") rasterdata = np.loadtxt(fName, skiprows=6) infile.close() return rasterdata
[docs]def readRaster(fname, noDataToNan=True): """Read raster file (.asc) Parameters ----------- fname: str or pathlib object path to ascii file noDataToNan: bool if True convert nodata_values to nan and set nodata_value to nan Returns -------- data: dict -headerInfo: class information that is stored in header (ncols, nrows, xllcenter, yllcenter, nodata_value) -rasterdata : 2D numpy array 2D numpy array of ascii matrix """ log.debug("Reading dem : %s", fname) header = readASCheader(fname) rasterdata = readASCdata2numpyArray(fname) data = {} data["header"] = header if noDataToNan: rasterdata[rasterdata == header["nodata_value"]] = np.NaN data["header"]["nodata_value"] = np.nan data["rasterData"] = np.flipud(rasterdata) return data
[docs]def writeResultToAsc(header, resultArray, outFileName, flip=False): """Write 2D array to an ascii file with header and save to location of outFileName Parameters ---------- header : class class with methods that give cellsize, nrows, ncols, xllcenter yllcenter, nodata_value resultArray : 2D numpy array 2D numpy array of values that shall be written to file outFileName : str path incl. name of file to be written flip: boolean if True, flip the rows of the resultArray when writing """ # Open outfile with open(outFileName, "w") as outFile: # write the header and array values to file outFile.write("ncols %d\n" % header["ncols"]) outFile.write("nrows %d\n" % header["nrows"]) outFile.write("xllcenter %.2f\n" % header["xllcenter"]) outFile.write("yllcenter %.2f\n" % header["yllcenter"]) outFile.write("cellsize %.2f\n" % header["cellsize"]) outFile.write("nodata_value %.2f\n" % header["nodata_value"]) M = resultArray.shape[0] for m in range(M): if flip: line = np.array([resultArray[M - m - 1, :]]) else: line = np.array([resultArray[m, :]]) np.savetxt(outFile, line, fmt="%.16g") outFile.close()