Source code for snowex_db.conversions
"""
Module contains all conversions used for manipulating data. This includes:
filetypes, datatypes, etc. Many tools here will be useful for most end users
of the database.
"""
from os.path import basename, dirname, join
import numpy as np
import rasterio
from rasterio.crs import CRS
from rasterio.transform import Affine
from .utilities import get_logger
[docs]
def INSAR_to_rasterio(grd_file, desc, out_file):
"""
Reads in the UAVSAR interferometry file and saves the real and complex
value and writes them to GeoTiffs. Requires a .ann file in the same
directory to describe the data.
Args:
grd_file: File containing the UAVsAR data
desc: dictionary of the annotation file.
out_file: Directory to output the converted files
"""
log = get_logger('insar_2_raster')
data_map = {'int': 'interferogram',
'amp1': 'amplitude of pass 1',
'amp2': 'amplitude of pass 2',
'cor': 'correlation'}
# Grab just the filename and make a list splitting it on periods
fparts = basename(grd_file).split('.')
fkey = fparts[0]
ftype = fparts[-2]
dname = data_map[ftype]
log.info('Processing {} file...'.format(dname))
# Grab the metadata for building our georeference
nrow = desc['ground range data latitude lines']['value']
ncol = desc['ground range data longitude samples']['value']
# Find starting latitude, longitude already at the center
lat1 = desc['ground range data starting latitude']['value']
lon1 = desc['ground range data starting longitude']['value']
# Delta latitude and longitude
dlat = desc['ground range data latitude spacing']['value']
dlon = desc['ground range data longitude spacing']['value']
log.debug('Expecting data to be shaped {} x {}'.format(nrow, ncol))
log.info('Using Deltas for lat/long = {} / {} degrees'.format(dlat, dlon))
# Read in the data as a tuple representing the real and imaginary
# components
log.info(
'Reading {} and converting it from binary...'.format(
basename(grd_file)))
bytes = desc['{} bytes per pixel'.format(dname.split(' ')[0])]['value']
log.info('{} bytes per pixel = {}'.format(dname, bytes))
# Form the datatypes
if dname in 'interferogram':
# Little Endian (<) + real values (float) + 4 bytes (32 bits) = <f4
dtype = np.dtype([('real', '<f4'), ('imaginary', '<f4')])
else:
dtype = np.dtype([('real', '<f{}'.format(bytes))])
# Read in the data according to the annotation file and bytes
z = np.fromfile(grd_file, dtype=dtype)
# Reshape it to match what the text file says the image is
z = z.reshape(nrow, ncol)
# Build the transform and CRS
crs = CRS.from_user_input("EPSG:4326")
# Lat1/lon1 are already the center so for geotiff were good to go.
t = Affine.translation(lon1, lat1) * Affine.scale(dlon, dlat)
ext = out_file.split('.')[-1]
fbase = join(
dirname(out_file), '.'.join(
basename(out_file).split('.')[
0:-1]) + '.{}.{}')
for i, comp in enumerate(['real', 'imaginary']):
if comp in z.dtype.names:
d = z[comp]
out = fbase.format(comp, ext)
log.info('Writing to {}...'.format(out))
dataset = rasterio.open(
out,
'w+',
driver='GTiff',
height=d.shape[0],
width=d.shape[1],
count=1,
dtype=d.dtype,
crs=crs,
transform=t,
)
# Write out the data
dataset.write(d, 1)
# show(new_dataset.read(1), vmax=0.1, vmin=-0.1)
# for stat in ['min','max','mean','std']:
# log.info('{} {} = {}'.format(comp, stat, getattr(d, stat)()))
dataset.close()