Source code for spatialist.envi

##############################################################
# ENVI header management
# John Truckenbrodt 2015-2019
##############################################################
"""
This module offers functionality for editing ENVI header files
"""
import re
from .ancillary import parse_literal


[docs]def hdr(data, filename): """ write ENVI header files Parameters ---------- data: str or dict the file or dictionary to get the info from filename: str the HDR file to write Returns ------- """ hdrobj = data if isinstance(data, HDRobject) else HDRobject(data) hdrobj.write(filename)
[docs]class HDRobject(object): """ ENVI HDR info handler Parameters ---------- data: str, dict or None the file or dictionary to get the info from; If None (default), an object with default values for an empty raster file is returned Examples -------- >>> from spatialist.envi import HDRobject >>> with HDRobject('E:/test.hdr') as hdr: >>> hdr.band_names = ['one', 'two'] >>> print(hdr) >>> hdr.write() """ def __init__(self, data=None): self.filename = data if isinstance(data, str) else None if isinstance(data, str): if re.search('.hdr$', data): args = self.__hdr2dict() else: raise RuntimeError('the data does not seem to be a ENVI HDR file') elif data is None: args = {'bands': 1, 'header_offset': 0, 'file_type': 'ENVI Standard', 'interleave': 'bsq', 'sensor_type': 'Unknown', 'byte_order': 0, 'wavelength_units': 'Unknown', 'samples': 0, 'lines': 0} elif isinstance(data, dict): args = data else: raise RuntimeError('parameter data must be of type str, dict or None') for arg in args: setattr(self, arg, args[arg]) def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): return def __str__(self): lines = ['ENVI'] for item in ['description', 'acquisition_time', 'samples', 'lines', 'bands', 'header_offset', 'file_type', 'data_type', 'data_ignore_value', 'interleave', 'sensor_type', 'byte_order', 'map_info', 'coordinate_system_string', 'wavelength_units', 'band_names']: if hasattr(self, item): value = getattr(self, item) if isinstance(value, (list, map)): lines.append(item.replace('_', ' ') + ' = {' + ', '.join([str(x) for x in value]) + '}') elif item in ['description', 'band_names', 'coordinate_system_string']: lines.append(item.replace('_', ' ') + ' = {' + str(value) + '}') else: lines.append(item.replace('_', ' ') + ' = ' + str(value) + '') return '\n'.join(lines) def __hdr2dict(self): """ read a HDR file into a dictionary http://gis.stackexchange.com/questions/48618/how-to-read-write-envi-metadata-using-gdal Returns ------- dict the hdr file metadata attributes """ with open(self.filename, 'r') as infile: lines = infile.readlines() i = 0 out = dict() while i < len(lines): line = lines[i].strip('\r\n') if '=' in line: if '{' in line and '}' not in line: while '}' not in line: i += 1 line += lines[i].strip('\n').lstrip() line = list(filter(None, re.split(r'\s+=\s+', line))) line[1] = re.split(',[ ]*', line[1].strip('{}')) key = line[0].replace(' ', '_') val = line[1] if len(line[1]) > 1 else line[1][0] out[key] = parse_literal(val) i += 1 if 'band_names' in out.keys() and not isinstance(out['band_names'], list): out['band_names'] = [out['band_names']] return out
[docs] def write(self, filename='same'): """ write object to an ENVI header file """ if filename == 'same': filename = self.filename if not filename.endswith('.hdr'): filename += '.hdr' with open(filename, 'w') as out: out.write(self.__str__())