Source code for snowex_db.upload.raster_mapping

from copy import deepcopy
from enum import Enum
from pathlib import Path
from typing import Dict, List, Tuple

from snowex_db.interpretation import get_InSar_flight_comment
from snowex_db.metadata import read_InSar_annotation


[docs] class RasterType(Enum): """ Enum for different types of raster files. value, description, abbreviation """ DEM = "DEM" DEPTH = "depth" SWE = "swe" CANOPY_HEIGHT = "canopy_height" # SAR raster types INT = "int", "interferogram", "interferogram" AMP1 = "amp1", "amplitude of pass 1", "amplitude", 1 AMP2 = "amp2", "amplitude of pass 2", "amplitude", 2 COR = "corr", "correlation", "correlation" def __new__(cls, *args, **kwds): obj = object.__new__(cls) obj._value_ = args[0] return obj # ignore the first param since it's already set by __new__ def __init__( self, _: str, description: str = None, abbreviation: str = None, pass_num: int = None ): """ Args: _: original args for the enum description: a description of the raster type abbreviation: the abbreviation for the raster type """ self._description_ = description self._abbrv_ = abbreviation self._pass_num_ = pass_num def __str__(self): return self.value @property def description(self): return self._description_ @property def abbreviation(self): return self._abbrv_ @property def pass_num(self): return self._pass_num_
[docs] def rasters_from_annotation( annotation_file: Path, tif_dir: Path, **kwargs ) -> List[Tuple[Dict[str, str], Path]]: """ Given an annotation file, return the insar raster files associated with the file. Also return the metadata Args: annotation_file: uavsar annotation file tif_dir: Path to the directory where the tif files are stored **kwargs: Additional keyword arguments for metadata Returns: List of tuples containing metadata and the path to the raster file. """ result = [] # form the pattern to look for and grab the tifs pattern = annotation_file.name.removesuffix('.ann') + '*.tif' # Grab information from the filename tif_files = list(tif_dir.glob(pattern)) for tif_path in tif_files: # Split the file into parts f_pieces = tif_path.name.split('.') component = f_pieces[-2] # Real or imaginary component data_abbr = f_pieces[-3] # Key to the data name raster_type = RasterType[data_abbr.upper()] metadata = meta_from_annotation_file( annotation_file, raster_type, component, **kwargs ) result.append((metadata, tif_path)) return result
[docs] def meta_from_annotation_file( annotation_file: Path, raster_type: RasterType, component: str, **kwargs ) -> dict: """ Given an annotation file, return the metadata associated with this Args: annotation_file: Path to the annotation file raster_type: The type of raster file (e.g., interferogram, amplitude, etc.) component: The component of the raster file (e.g., real, imaginary) **kwargs: Additional keyword arguments for metadata Returns: A dictionary containing metadata for the raster file. keys are: - measurement_type: Type of the raster file - date: Date of the acquisition - units: Units of the raster file - comments: Comments about the raster file """ meta = deepcopy(kwargs) desc = read_InSar_annotation(annotation_file) # Populate the metadata meta['measurement_type'] = 'insar ' + raster_type.abbreviation if raster_type == RasterType.INT: meta['measurement_type'] += (' ' + component) # Assign the date for the respective flights if raster_type in [RasterType.AMP1, RasterType.AMP2]: meta['date'] = desc[ f'start time of acquisition for pass {raster_type.pass_num}' ]['value'] # Derived products always receive the date of the last overpass else: meta['date'] = desc['start time of acquisition for pass 2']['value'] # Assign only the date not the date and time meta['date'] = meta['date'].date() # Assign units meta['units'] = desc[f'{raster_type.abbreviation} units']['value'] # Flexibly form a comment for each of the products for dates comment = get_InSar_flight_comment(raster_type.description, desc) # add which dem was used which dictates the file name convert e.g. # ...VV_01.int.grd comment += ', DEM used = {}'.format( desc['dem used in processing']['value']) # Add the polarization to the comments comment += ', Polarization = {}'.format( desc['polarization']['value']) meta['comments'] = comment return meta
[docs] def metadata_from_single_file( raster_file: Path, raster_type: RasterType, **kwargs ): """ Create the metadata dictionary from a single raster file and its type. Examples would be depth, dem, etc. Args: raster_file: Path to the raster file raster_type: RasterType enum indicating the type of raster **kwargs: Additional keyword arguments for metadata Returns: A dictionary containing metadata for the raster file. keys are: - type: Type of the raster file - date: Date of the acquisition - units: Units of the raster file - comments: Comments about the raster file """ meta = deepcopy(kwargs) # Assign the type meta['measurement_type'] = raster_type.value # TODO: figure the rest of this out # Assign the date from the filename if 'date' not in meta: raise ValueError( "Date must be provided in metadata or extracted from filename." ) # Assign units based on raster type if raster_type == RasterType.DEPTH: meta['units'] = 'meters' elif raster_type == RasterType.DEM: meta['units'] = 'meters' elif raster_type == RasterType.SWE: meta['units'] = 'meters' elif raster_type == RasterType.CANOPY_HEIGHT: meta['units'] = 'meters' else: meta['units'] = 'unknown' return meta