###############################################################################
# interface for translating GAMMA errors messages into Python error types
# Copyright (c) 2015-2026, the pyroSAR Developers.
# This file is part of the pyroSAR Project. It is subject to the
# license terms in the LICENSE.txt file found in the top-level
# directory of this distribution and at
# https://github.com/johntruckenbrodt/pyroSAR/blob/master/LICENSE.txt.
# No part of the pyroSAR project, including this file, may be
# copied, modified, propagated, or distributed except according
# to the terms contained in the LICENSE.txt file.
###############################################################################
import re
import signal
[docs]
def gammaErrorHandler(returncode: int, out: str, err: str) -> None:
"""
Function to raise errors in Python. This function is not intended
for direct use but as part of function :func:`pyroSAR.gamma.auxil.process`.
Parameters
----------
returncode:
the subprocess return code
out:
the stdout message returned by a subprocess call of a gamma command
err:
the stderr message returned by a subprocess call of a gamma command
Raises: IOError | ValueError | RuntimeError
"""
# scan stdout and stdin messages for lines starting with 'ERROR'
messages = out.split('\n') if out else []
messages.extend(err.strip().split('\n'))
errormessages = [x for x in messages if x.startswith('ERROR')]
# registry of known gamma error messages and corresponding Python error types
# do not change the Python error types of specific messages! This will change the behavior of several functions
# in case no error is to be thrown define None as error type
knownErrors = {'image data formats differ': IOError,
'cannot open': IOError,
r'no coverage of SAR image by DEM(?: \(in (?:latitude/northing|longitude/easting)\)|)': RuntimeError,
'libgdal.so.1: no version information available': None,
'line outside of image': ValueError,
'no offsets found above SNR threshold': ValueError,
'window size < 4': ValueError,
'MLI oversampling factor must be 1, 2, 4, 8': ValueError,
'no points available for determining average intensity': ValueError,
'p_interp(): time outside of range': RuntimeError,
'no overlap with lookup table': RuntimeError,
'insufficient offset points to determine offset model parameters': RuntimeError,
'insufficient offset points left after culling to determine offset model parameters': RuntimeError,
'calloc_1d: number of elements <= 0': ValueError,
'multi-look output line:': RuntimeError,
'no OPOD state vector found with the required start time!': RuntimeError,
'gc_map operates only with slant range geometry, image geometry in SLC_par: GROUND_RANGE': RuntimeError,
'OPOD state vector data ends before start of the state vector time window': RuntimeError,
'non-zero exit status': RuntimeError,
'unsupported DEM projection': RuntimeError,
'tiffWriteProc:No space left on device': RuntimeError,
'in subroutine julday: there is no year zero!': RuntimeError,
'cannot create ISP image parameter file': OSError}
# check if the error message is known and throw the mapped error from knownErrors accordingly.
# Otherwise raise a RuntimeError if killed by a signal and a GammaUnknownError in all other cases.
# The actual message is passed to the error and thus visible for backtracing.
if returncode != 0:
if len(errormessages) > 0:
errormessage = errormessages[-1]
err_out = '\n\n'.join([re.sub('ERROR[: ]*', '', x) for x in errormessages])
for error in knownErrors:
if re.search(error, errormessage):
errortype = knownErrors[error]
if errortype:
raise errortype(err_out)
else:
return
else:
err_out = f'failed with return code {returncode}'
if returncode < 0:
# handle signal kills like SIGSEGV (segmentation fault)
sig = signal.Signals(-returncode)
raise RuntimeError(err_out + f' ({sig.name})')
raise GammaUnknownError(err_out)
[docs]
class GammaUnknownError(Exception):
"""
This is a general error, which is raised if the error message is not yet integrated
into the known errors of function :func:`gammaErrorHandler`.
If this error occurs, the message should be included in this function.
"""
def __init__(self, errormessage):
Exception.__init__(self, errormessage)