Skip to main content
  • Home
  • Development
  • Documentation
  • Donate
  • Operational login
  • Browse the archive

swh logo
SoftwareHeritage
Software
Heritage
Archive
Features
  • Search

  • Downloads

  • Save code now

  • Add forge now

  • Help

https://github.com/GeoscienceAustralia/PyRate
09 August 2023, 08:52:18 UTC
  • Code
  • Branches (23)
  • Releases (1)
  • Visits
    • Branches
    • Releases
    • HEAD
    • refs/heads/CI-patch
    • refs/heads/data
    • refs/heads/dependabot/pip/joblib-1.2.0
    • refs/heads/dependabot/pip/numpy-1.22.0
    • refs/heads/dependabot/pip/scipy-1.10.0
    • refs/heads/develop
    • refs/heads/gh-pages
    • refs/heads/master
    • refs/heads/mg/actions
    • refs/heads/sb/largetifs-enhancements
    • refs/heads/sb/orbfit-independent-method
    • refs/heads/sb/orbital-correction-experiements
    • refs/heads/sb/phase-closure-correction
    • refs/heads/sb/upgrade-ci-ubuntu
    • refs/heads/sb/use-mpi-shared
    • refs/tags/0.3.0
    • refs/tags/0.4.0
    • refs/tags/0.4.1
    • refs/tags/0.4.2
    • refs/tags/0.4.3
    • refs/tags/0.5.0
    • refs/tags/0.6.0
    • refs/tags/0.6.1
    • 0.2.0
  • 0d3ff26
  • /
  • pyrate
  • /
  • gamma.py
Raw File Download Save again
Take a new snapshot of a software origin

If the archived software origin currently browsed is not synchronized with its upstream version (for instance when new commits have been issued), you can explicitly request Software Heritage to take a new snapshot of it.

Use the form below to proceed. Once a request has been submitted and accepted, it will be processed as soon as possible. You can then check its processing state by visiting this dedicated page.
swh spinner

Processing "take a new snapshot" request ...

To reference or cite the objects present in the Software Heritage archive, permalinks based on SoftWare Hash IDentifiers (SWHIDs) must be used.
Select below a type of object currently browsed in order to display its associated SWHID and permalink.

  • content
  • directory
  • revision
  • snapshot
  • release
origin badgecontent badge
swh:1:cnt:516a26b1c16c00a4daa3bcd4d9d180ac01fdb408
origin badgedirectory badge
swh:1:dir:9fe4569968d540ed47abf6a3d37372f784c1ca22
origin badgerevision badge
swh:1:rev:d0a634bff0ab79420b9e28abd21f1f48146f642c
origin badgesnapshot badge
swh:1:snp:e85aafb5fc900c1df2eebb773a8b8e11798084c1
origin badgerelease badge
swh:1:rel:a9b832cf9205fbc5139f38ae7f3c59eff218095a

This interface enables to generate software citations, provided that the root directory of browsed objects contains a citation.cff or codemeta.json file.
Select below a type of object currently browsed in order to generate citations for them.

  • content
  • directory
  • revision
  • snapshot
  • release
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Generate software citation in BibTex format (requires biblatex-software package)
Generating citation ...
Tip revision: d0a634bff0ab79420b9e28abd21f1f48146f642c authored by Matt Garthwaite on 22 May 2017, 05:42:23 UTC
update version to 0.2.0
Tip revision: d0a634b
gamma.py
#   This Python module is part of the PyRate software package.
#
#   Copyright 2017 Geoscience Australia
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.
"""
This Python module contains tools for reading GAMMA format input data.
"""
# coding: utf-8

#import os
import datetime
import numpy as np
import pyrate.ifgconstants as ifc

# constants
GAMMA_DATE = 'date'
GAMMA_WIDTH = 'width'
GAMMA_NROWS = 'nlines'
GAMMA_CORNER_LAT = 'corner_lat'
GAMMA_CORNER_LONG = 'corner_lon'
GAMMA_Y_STEP = 'post_lat'
GAMMA_X_STEP = 'post_lon'
GAMMA_DATUM = 'ellipsoid_name'
GAMMA_FREQUENCY = 'radar_frequency'
GAMMA_INCIDENCE = 'incidence_angle'
RADIANS = 'RADIANS'
GAMMA = 'GAMMA'


def _parse_header(path):
    """Parses all GAMMA header file fields into a dictionary"""
    with open(path) as f:
        text = f.read().splitlines()
        raw_segs = [line.split() for line in text if ':' in line]

    # convert the content into a giant dict of all key, values
    return dict((i[0][:-1], i[1:]) for i in raw_segs)


def parse_epoch_header(path):
    """
    Returns dictionary of epoch metadata required for PyRate

    :param str path: `Full path to Gamma *slc.par file`

    :return: subset: subset of full metadata
    :rtype: dict
    """
    lookup = _parse_header(path)
    subset = _parse_date_time(lookup)

    # handle conversion of radar frequency to wavelength
    freq, unit = lookup[GAMMA_FREQUENCY]
    if unit != "Hz":  # pragma: no cover
        msg = 'Unrecognised unit field for radar_frequency: %s'
        raise GammaException(msg % unit)
    subset[ifc.PYRATE_WAVELENGTH_METRES] = _frequency_to_wavelength(float(freq))

    incidence, unit = lookup[GAMMA_INCIDENCE]
    if unit != "degrees":  # pragma: no cover
        msg = 'Unrecognised unit field for incidence_angle: %s'
        raise GammaException(msg % unit)
    subset[ifc.PYRATE_INCIDENCE_DEGREES] = float(incidence)

    return subset


def _parse_date_time(lookup):
    """Grab date and time metadata and convert to datetime objects"""
    subset = {}
    if len(lookup[GAMMA_DATE]) == 3:  # pragma: no cover
        year, month, day, = [int(float(i)) for i in lookup[GAMMA_DATE][:3]]
        # Occasionally GAMMA header has no time information - default to midnight
        hour, mins, sec = 0, 0, 0
    elif len(lookup[GAMMA_DATE]) == 6:
        year, month, day, hour, mins, sec = [int(float(i))
                                             for i in lookup[GAMMA_DATE][:6]]
    else:  # pragma: no cover
        msg = "Date and time information not complete in GAMMA headers"
        raise GammaException(msg)

    subset[ifc.MASTER_DATE] = datetime.date(year, month, day)
    subset[ifc.MASTER_TIME] = datetime.time(hour, mins, sec)

    return subset


def parse_dem_header(path):
    """
    Returns dictionary of DEM metadata required for PyRate

    :param str path: `Full path to Gamma *dem.par file`

    :return: subset: subset of full metadata
    :rtype: dict
    """
    lookup = _parse_header(path)

    # NB: many lookup fields have multiple elements, eg ['1000', 'Hz']
    subset = {ifc.PYRATE_NCOLS: int(lookup[GAMMA_WIDTH][0]),
              ifc.PYRATE_NROWS: int(lookup[GAMMA_NROWS][0])}

    expected = ['decimal', 'degrees']
    for k in [GAMMA_CORNER_LAT, GAMMA_CORNER_LONG, GAMMA_X_STEP, GAMMA_Y_STEP]:
        units = lookup[GAMMA_CORNER_LAT][1:]
        if units != expected:  # pragma: no cover
            msg = "Unrecognised units for GAMMA %s field\n. Got %s, expected %s"
            raise GammaException(msg % (k, units, expected))

    subset[ifc.PYRATE_LAT] = float(lookup[GAMMA_CORNER_LAT][0])
    subset[ifc.PYRATE_LONG] = float(lookup[GAMMA_CORNER_LONG][0])
    subset[ifc.PYRATE_Y_STEP] = float(lookup[GAMMA_Y_STEP][0])
    subset[ifc.PYRATE_X_STEP] = float(lookup[GAMMA_X_STEP][0])
    subset[ifc.PYRATE_DATUM] = "".join(lookup[GAMMA_DATUM])
    subset[ifc.PYRATE_INSAR_PROCESSOR] = GAMMA
    return subset


def _frequency_to_wavelength(freq):
    """
    Convert radar frequency to wavelength
    """
    return ifc.SPEED_OF_LIGHT_METRES_PER_SECOND / freq


def combine_headers(hdr0, hdr1, dem_hdr):
    """
    Combines metadata for master and slave epochs and DEM into a single
    dictionary for an interferogram.

    :param dict hdr0: Metadata for the master image
    :param dict hdr1: Metadata for the slave image
    :param dict dem_hdr: Metadata for the DEM

    :return: chdr: combined metadata
    :rtype: dict
    """
    if not all([isinstance(a, dict) for a in [hdr0, hdr1, dem_hdr]]):
        raise GammaException('Header args need to be dicts')

    date0, date1 = hdr0[ifc.MASTER_DATE], hdr1[ifc.MASTER_DATE]
    if date0 == date1:
        raise GammaException("Can't combine headers for the same day")
    elif date1 < date0:
        raise GammaException("Wrong date order")

    chdr = {ifc.PYRATE_TIME_SPAN: (date1 - date0).days / ifc.DAYS_PER_YEAR,
            ifc.MASTER_DATE: date0,
            ifc.MASTER_TIME: hdr0[ifc.MASTER_TIME],
            ifc.SLAVE_DATE: date1,
            ifc.SLAVE_TIME: hdr1[ifc.MASTER_TIME],
            ifc.DATA_UNITS: RADIANS,
            ifc.PYRATE_INSAR_PROCESSOR: GAMMA}

    # set incidence angle to mean of master and slave
    inc_ang = hdr0[ifc.PYRATE_INCIDENCE_DEGREES]
    if np.isclose(inc_ang, hdr1[ifc.PYRATE_INCIDENCE_DEGREES], atol=1e-1):
        chdr[ifc.PYRATE_INCIDENCE_DEGREES] = \
            (hdr0[ifc.PYRATE_INCIDENCE_DEGREES] +
             hdr1[ifc.PYRATE_INCIDENCE_DEGREES]) / 2
    else:
        msg = "Incidence angles differ by more than 1e-1"
        raise GammaException(msg)

    wavelen = hdr0[ifc.PYRATE_WAVELENGTH_METRES]
    if np.isclose(wavelen, hdr1[ifc.PYRATE_WAVELENGTH_METRES], atol=1e-6):
        chdr[ifc.PYRATE_WAVELENGTH_METRES] = wavelen
    else:
        args = (chdr[ifc.MASTER_DATE], chdr[ifc.SLAVE_DATE])
        msg = "Wavelength mismatch, check both header files for %s & %s"
        raise GammaException(msg % args)
    # non-cropped, non-multilooked geotif process step information added
    chdr[ifc.DATA_TYPE] = ifc.ORIG

    chdr.update(dem_hdr)  # add geographic data
    return chdr


def manage_headers(dem_header_file, header_paths):
    """
    Manage and combine  header files for GAMMA interferograms, DEM and
    incidence files

    :param str dem_header_file: DEM header path
    :param list header_paths: List of master/slave header paths

    :return: combined_header: Combined metadata dictionary
    :rtype: dict
    """
    dem_header = parse_dem_header(dem_header_file)
    # find param files containing filename dates
    if len(header_paths) == 2:
        headers = [parse_epoch_header(hp) for hp in header_paths]
        combined_header = combine_headers(headers[0], headers[1], dem_header)
    else:
        # probably have DEM or incidence file
        combined_header = dem_header
        combined_header[ifc.DATA_TYPE] = ifc.DEM

    return combined_header


class GammaException(Exception):
    """
    Gamma generic exception class
    """

back to top

Software Heritage — Copyright (C) 2015–2026, The Software Heritage developers. License: GNU AGPLv3+.
The source code of Software Heritage itself is available on our development forge.
The source code files archived by Software Heritage are available under their own copyright and licenses.
Terms of use: Archive access, API— Content policy— Contact— JavaScript license information— Web API