pysiral.retracker.samosa_wfm

This is the SAMOSA+ retracker variant that uses samosa-waveform-model, a re-implementation of the SAMPy package. The objective of the re-implementation is better performance (code optimization and multiprocessing) and a greater flexibility for retracking settings (sub-waveform retracking, limiting parameters of the fit)

NOTES:

List of fit modes:

  • single fit - all parameters

  • double fit - all parameters

  • single fit - fixed mean square slope

All variants with options for single core and multi-processing

TODO: Implement sigma0/windspeed computation (per switch in config file) TODO: Computation of residuals should be configurable method

Workflow

  1. Colocate all input variables in dedicated list of input data classes

  2. Initialize specified fit method (one class per fit method?)

  3. Process waveforms with/without multiprocessing

  4. Organize output

Attributes

__author__

VALID_METHOD_LITERAL

VALID_METHODS

DEFAULT_FIT_KWARGS

SAMOSA_WFM_COLLECT_FIT_PARAMS

NU_OCOG_COEFS

Classes

WaveformModelParametersFit

NormedWaveform

Data container for the input waveform

WaveformFitData

Dataclass that contains all data from l1b and l2 data objects

SAMOSAWaveformFitResult

Dataclass for all output parameters of the waveform fitting process

SAMOSAWaveformFit

Class for fitting the SAMOSA waveform model to a single waveform.

SAMOSAWaveformCollectionFit

Handles the SAMOSA waveform model fitting of a waveform

SAMOSAModelParameterPrediction

Class to get initial guess and bounds of SAMOSA waveform fit parameter

SAMOSAPlusRetracker

Main Retracker Class (all retrackers must be of instance BaseRetracker)

Functions

samosa_fit_samosap_single(→ SAMOSAWaveformFitResult)

Fits the SAMOSA waveform model with all free parameters (epoch, swh, mss, amplitude) using

samosa_fit_samosap_standard(→ SAMOSAWaveformFitResult)

Fits the SAMOSA waveform model with all free parameters (epoch, swh, mss, amplitude) using

samosa_fit_samosap_specular(→ SAMOSAWaveformFitResult)

Fits the SAMOSA waveform model with (epoch, mss, [amplitude]) and a fixed swh

samosa_fit_samosap_single_step2(...)

Performs fit step 2 of the SAMOSAPlus retracker (as implemented in SAMPY)

samosa_fit_samosap_standard_step1(...)

Performs fit step 1 of the SAMOSAPlus retracker (as implemented in SAMPY)

samosa_fit_samosap_standard_step2(...)

Performs fit step 2 of the SAMOSAPlus retracker (as implemented in SAMPY)

get_model_from_args(...)

Compute waveform model with final fit parameters. This function

total_velocity_from_vector(→ float)

Compute total velocity from vector

get_valid_epoch_range(→ Tuple[float, float])

Get bounds for epoch based on the valid fraction range in the range window.

get_epoch_bounds(→ Tuple[float, float])

Compute the fit bounds for the epoch. The lower epoch bound is defined by

sampy_misfit(→ float)

Computes the SAMOSA waveform model misfit parameter according to SAMPy with optional

compute_thermal_noise(→ float)

Compute thermal noise for waveform collection (from SAMPy). The strategy is

epoch2range(→ float)

Computes the retracker range, defined as range of spacecraft center or mass

get_look_angles(→ numpy.ndarray)

Compute the lookangles based on l1b stack information

get_least_squares_parameter_sdev(→ numpy.ndarray)

Compute standard deviation of parameter from Jacobian.

get_sub_waveform_mask(→ numpy.ndarray)

Estimates a sub-waveform mask by flagging off-nadir backscatter elements

get_trailing_edge_lower_envelope_mask(→ numpy.ndarray)

Compute the indices of the waveforms trailing edge lower envelope.

get_samosa_leading_edge_error(→ float)

Compute the SAMOSA+ leading edge error value from the RMSE of the

rmse(→ float)

Compute root-mean-square-error (rmse) of 2 non-Nan arrays

get_nu_from_ocog_width(→ float)

Compute the inverse mean square slope (nu) from an empirical parametrization

Module Contents

pysiral.retracker.samosa_wfm.__author__ = 'Stefan Hendricks <stefan.hendricks@awi.de>'
pysiral.retracker.samosa_wfm.VALID_METHOD_LITERAL
pysiral.retracker.samosa_wfm.VALID_METHODS
pysiral.retracker.samosa_wfm.DEFAULT_FIT_KWARGS
pysiral.retracker.samosa_wfm.SAMOSA_WFM_COLLECT_FIT_PARAMS = False
pysiral.retracker.samosa_wfm.NU_OCOG_COEFS = (11111080.7, 2.50396017)
class pysiral.retracker.samosa_wfm.WaveformModelParametersFit

Bases: samosa_waveform_model.WaveformModelParameters

samosa_step: Literal['step1', 'step2'] = None
num_ddm_evaluations: int = -1
class pysiral.retracker.samosa_wfm.NormedWaveform

Data container for the input waveform

power: numpy.ndarray
range_bins: numpy.ndarray
tau: numpy.ndarray
ocog_width: float
scaling_factor: float
radar_mode_flag: int
window_delay: float
transmit_power: float
look_angles: numpy.ndarray
surface_type: str
surface_class: str
thermal_noise: float = 0.0
first_maximum_index: int = None
idx: int = None
absolute_maximum: float
__post_init__()
class pysiral.retracker.samosa_wfm.WaveformFitData

Dataclass that contains all data from l1b and l2 data objects required for the SAMOSA waveform model fit

idx: int
waveform_data: NormedWaveform
scenario_data: samosa_waveform_model.ScenarioData
class pysiral.retracker.samosa_wfm.SAMOSAWaveformFitResult

Dataclass for all output parameters of the waveform fitting process

epoch: float
retracker_range: float
retracker_range_standard_error: float
significant_wave_height: float
significant_wave_height_standard_error: float
mean_square_slope: float
mean_square_slope_standard_error: float
thermal_noise: float
misfit: float
fit_mode: str = 'n/a'
waveform: numpy.ndarray = None
waveform_model: numpy.ndarray = None
sub_waveform_mask: numpy.ndarray = None
misfit_sub_waveform: float = None
number_of_model_evaluations_step1: int = -1
number_of_model_evaluations_step2: int = -1
fit_return_status_step1: int = -2
fit_return_status_step2: int = -2
sigma0: float = 0.0
property is_sub_waveform_fit: bool
property samosa_leading_edge_error: float
class pysiral.retracker.samosa_wfm.SAMOSAWaveformFit(scenario_data: samosa_waveform_model.ScenarioData, normed_waveform: NormedWaveform, waveform_model: samosa_waveform_model.SAMOSAWaveformModel | None = None, sub_waveform_mask: numpy.ndarray | None = None, waveform_model_kwargs: Dict | None = None, step1_fixed_nu_value: float = 0.0, step2_fixed_swh_value: float = 0.0, amplitude_is_free_param: bool = True, method: str = None)

Bases: object

Class for fitting the SAMOSA waveform model to a single waveform. The purpose of this class is to minimize the CPU load for the fitting procedure.

This class will therefore initiliaze the waveform model with all static parameters and then only re-compute the variables that directly depend on the fit parameters.

Usage:

fit_cls = SAMOSAWaveformFit(scenario_data, normed_waveform, …) fit_result = scipy.optimize.least_squares(fit_cls.fit_func, …)

samosa_waveform_model = None
normed_waveform
step1_fixed_nu_value = 0.0
step2_fixed_swh_value = 0.0
amplitude_is_free_param = True
nu_ocog_coefs = (11111080.7, 2.50396017)
sub_waveform_mask = None
method = None
fit_func(fit_args: List[float], *_) numpy.ndarray

Fit function for the least square algorithm. Computes and returns the residual between waveform and SAMOSA+ waveform model.

Also stores the last waveform model in class instance, which then can be accessed later after the optimization is complete.

Parameters:

fit_args – Waveform model parameter

Returns:

Difference between waveform and waveform model. be minimized by least square process.

fit_func_samosap_standard_step1(fit_args: List[float], *_) numpy.ndarray

Fit of the first step in the SAMOSA+ fitting process.

Parameters:
  • fit_args

  • _

Returns:

(Masked) residual vector

fit_func_samosap_standard_step2(fit_args: List[float], *_) numpy.ndarray

Fit of the second step in the SAMOSA+ fitting process.

Parameters:
  • fit_args

  • _

Returns:

Masked residual vector

compute_residuals(waveform_model: samosa_waveform_model.dataclasses.WaveformModelOutput) numpy.ndarray

Compute the residuals between the waveform model and the waveform data depending on the sub-waveform mask.

Note: The peak power is scaled to 1 in both the waveform and the model

Therefore amplitude scaling is not applied and only thermal noise is added.

Parameters:

waveform_model – SAMOSA+ waveform model output

Returns:

residual vector

class pysiral.retracker.samosa_wfm.SAMOSAWaveformCollectionFit(fit_method: VALID_METHOD_LITERAL, predictor_method: str, use_multiprocessing: bool = False, num_processes: int | None = None, samosap_fit_kwargs: Dict | None = None, predictor_kwargs: Dict | None = None, least_squares_kwargs: Dict | None = None)

Bases: object

Handles the SAMOSA waveform model fitting of a waveform collection. Can be configured to use several fitting strategies with or without multiprocessing.

The notation convention for class methods is _fit_{fit_method}{_mp: use_multiprocessing: True}. Therefore, each fit method needs to class methods: One for single process and one for parallel processes.

Parameters:
  • fit_method – Name of the fitting method (choices: “mss_swh”, “mss_preset”, “mss_seperate”)

  • predictor_method

  • use_multiprocessing – Flag if to use multiprocessing (default: False)

  • num_processes – Number of multiprocessing workers

  • predictor_kwargs – Keyword arguments for the parameter predictor class

  • least_squares_kwargs – Keyword arguments for scipy.optimize.least_squares

fit_method
predictor_method
samosap_fit_kwargs
least_squares_kwargs
predictor_kwargs
use_multiprocessing = False
num_processes = None
fit(waveform_collection: List[WaveformFitData]) List[SAMOSAWaveformFitResult]

Main entry method for the waveform collection fitting.

Parameters:

waveform_collection – Waveform collection data

Returns:

List of waveform fit results

_select_fit_method() Callable

Selects to appropiate fit method based on class configuration.

Raises:

AttributeError" – Invalid configuration

Returns:

callable fit method

_fit_samosap_single(waveform_collection: List[WaveformFitData]) List[SAMOSAWaveformFitResult]

Computes Samosa waveform model fit in the main process (no multiprocessing)

Parameters:

waveform_collection – List of fit input

Returns:

List of fit outputs

_fit_samosap_single_mp(waveform_collection: List[WaveformFitData]) List[SAMOSAWaveformFitResult]

Computes Samosa waveform model fit with multiprocessing

Parameters:

waveform_collection – List of fit input

Returns:

List of fit outputs

_fit_samosap_standard(waveform_collection: List[WaveformFitData]) List[SAMOSAWaveformFitResult]

Computes Samosa waveform model fit in the main process (no multiprocessing)

Parameters:

waveform_collection – List of fit input

Returns:

List of fit outputs

_fit_samosap_standard_mp(waveform_collection: List[WaveformFitData]) List[SAMOSAWaveformFitResult]

Computes Samosa waveform model fit with multiprocessing

Parameters:

waveform_collection – List of fit input

Returns:

List of fit outputs

_fit_samosap_specular(waveform_collection: List[WaveformFitData]) List[SAMOSAWaveformFitResult]

Computes Samosa waveform model fit in the main process (no multiprocessing)

Parameters:

waveform_collection – List of fit input

Returns:

List of fit outputs

_fit_samosap_specular_mp(waveform_collection: List[WaveformFitData]) List[SAMOSAWaveformFitResult]

Computes Samosa waveform model fit with multiprocessing

Parameters:

waveform_collection – List of fit input

Returns:

List of fit outputs

_mp_fit(func, waveform_collection)
class pysiral.retracker.samosa_wfm.SAMOSAModelParameterPrediction(method: VALID_METHOD_LITERAL, surface_type: str, initial_guess: Dict[str, Tuple[float, float]], bounds: Dict[str, Tuple[float, float]], amplitude_is_free_parameter: Tuple[bool, bool] = (True, True))

Bases: object

Class to get initial guess and bounds of SAMOSA waveform fit parameter

TODO: Class Docstr

surface_type
amplitude_is_free_parameter = (True, True)
method
bounds
initial_guess
first_guess_method
bounds_method
get(waveform: NormedWaveform, **kwargs) Tuple[Tuple, Tuple, Tuple]

Get first guess and fit bounds for fit parameters from input waveform. The specific parameters and their order in the return tuples is defined by the property method of this class.

Parameters:
  • waveform – Waveform data

  • kwargs – Potential keyword arguments, e.g. fit mode

Returns:

Tuples of first guess, lower bounds and upper bounds for the fit parametes.

_get_first_guess_samosap_specular(waveform: NormedWaveform, **_) Tuple

Estimate the first guess for the SAMOSA+ specular waveform fitting mode (fixed swh, only nu). Equivalent to SAMOSA+ standard fit method with mode 2.

Parameters:

waveform – Waveform data

Returns:

Parameter first guess (epoch, nu, amplitude)

_get_first_guess_samosap_single(waveform: NormedWaveform, **_) Tuple

Estimate the first guess for the SAMOSA+ specular waveform fitting mode (fixed swh, only nu). Equivalent to SAMOSA+ standard fit method with mode 2.

Parameters:

waveform – Waveform data

Returns:

Parameter first guess (epoch, nu, amplitude)

_get_bounds_samosap_single(tau, first_guess) Tuple[Tuple, Tuple]
Returns:

Parameter fit bounds: (lower bounds, upperbounds) [mode 1: epoch, swh, amplitude; mode 2: epoch, nu]

_get_bounds_samosap_specular(tau, first_guess, **_) Tuple[Tuple, Tuple]

Estimate the fit bounds for the SAMOSA+ specular waveform fitting mode (fixed swh, only nu). Equivalent to SAMOSA+ standard fit method with mode 2.

Parameters:
  • tau – range gates in seconds

  • first_guess – first guess triplet

Returns:

Parameter first guess (epoch, nu, amplitude)

_get_first_guess_samosap_standard(waveform: NormedWaveform, mode: int = -1) Tuple

Estimate the first guess for the two-step SAMOSA+ waveform fitting approch. The fit parameter depend on the specific mode/step.

First fit step (mode=1): [epoch, significant_waveheight, amplitude scale] Seconds fit step (mode=2): [epoch, mean square slope]

Parameters:
  • waveform – Waveform data

  • mode – The SAMOSA+ waveform model mode (conf.STEP in SAMPy)

Raises:

ValueError – mode not 1 or 2

Returns:

Parameter first guess [mode 1: epoch, swh, amplitude; mode 2: epoch, nu]

_get_bounds_samosap_standard(tau, first_guess, mode: int = -1) Tuple[Any, Any]

Estimate the parameter bounds for the two-step SAMOSA+ waveform fitting approch. The bounds depend on the specific mode/step.

First fit step (mode=1): [epoch, significant_waveheight, amplitude scale] Seconds fit step (mode=2): [epoch, mean square slope, amplitude scale]

The bounds for the epoch are set to end behind the first maximum. For the other parameter bounds need to be provided during the initialization of this class.

Parameters:
  • tau – range gates in seconds

  • first_guess – first guess triplet

  • mode – The SAMOSA+ waveform model mode (conf.STEP in SAMPy)

Raises:

ValueError – mode not 1 or 2

Returns:

Parameter fit bounds: (lower bounds, upperbounds) [mode 1: epoch, swh, amplitude; mode 2: epoch, nu]

_compile_bounds(epoch_bnds, param_bnds, amp_bnds, mode) Tuple[Any, Any]
class pysiral.retracker.samosa_wfm.SAMOSAPlusRetracker

Bases: pysiral.retracker.BaseRetracker

Main Retracker Class (all retrackers must be of instance BaseRetracker) # TODO: API clean-up is sorely needed.

_retracker_params
l2_retrack(rng: numpy.ndarray, wfm: numpy.ndarray, indices: numpy.ndarray, radar_mode: numpy.ndarray, is_valid: numpy.ndarray) None

API method for the retracker interface in the Level-2 processor.

Parameters:
  • rng – The range per waveform samples for all waveforms in the Level-1 data object

  • wfm – All waveforms in the Level-1 data object

  • indices – List of waveforms for the retracker

  • radar_mode – Flag indicating the radar mode for all waveforms

  • is_valid – Error flag for all waveforms

Returns:

None (Output is added to the instance)

create_retracker_properties(n_records: int) None

Initialize retracker properties with correct arrays shapes (shape = (n_records, )). The list of parameters depends on whether the SAMOSA_DEBUG_MODE flag is set.

NOTE: The properties are set to an array, but can be accessed as self.{property_name} via the __getattr__ method.

Parameters:

n_records – Number of Level-2 data points

_samosa_plus_retracker(rng: numpy.ndarray, wfm: numpy.ndarray, indices: numpy.ndarray, radar_mode: numpy.ndarray) List[SAMOSAWaveformFitResult]

Performs the retracking via SAMOSA waveform model fits for all target waveforms.

Parameters:
  • rng – Range window arrays

  • wfm – Waveform arrays

  • indices – Target waveform indices

  • radar_mode – Radar modes

Returns:

List of SAMOSA plus waveform fit results

_get_waveform_fit_data(rng: numpy.ndarray, wfm: numpy.ndarray, indices: numpy.ndarray, radar_mode: numpy.ndarray) List[WaveformFitData]

Collects all the data required for the waveform model fits. Whenever possible,

Parameters:
  • rng

  • wfm

  • indices

  • radar_mode

Returns:

_get_scenario_data(l1: pysiral.l1data.Level1bData, l2: pysiral.l2data.Level2Data, idx: int, look_angles) samosa_waveform_model.ScenarioData

Creates the scenario data for the SAMOSA waveform model. This dataclass is needed for the initialization of the SAMOSA waveform model class and contains information on the radar mode and radar processing settings as well as the geometry (location, altitude & altitude rate, attitude and velocity of the altimeter platform).

The specific radar parameters are expected to be included in the samosa_waveform_model and are retrieved by specifying platform and radar mode.

Geometry parameters are available in the Level-1 and Level-2 data containers.

Parameters:
  • l1 – Level-1 data container

  • l2 – Level-2 data container

  • idx – Target Waveform index

  • look_angles

Returns:

SAMOSA waveform model scenario data for specific waveform

_get_normed_waveform(rng: numpy.ndarray, wfm: numpy.ndarray, tau: numpy.ndarray, radar_mode: int, window_delay: float, transmit_power: float, look_angles: numpy.ndarray, first_maximum_index: int, ocog_width: float, idx: int = None) NormedWaveform

Return a normed representation of the input waveform

Parameters:
  • rng

  • wfm

  • radar_mode

Returns:

_get_waveform_model_fit_configuration() Tuple[List, Dict]

Constructs the arguments and keywords for the SAMOSAWaveformCollectionFit class, defining the fit method and its configration

Returns:

arguments and keyword arguments for the waveform model

_set_range_uncertainty(fit_results: List[SAMOSAWaveformFitResult], indices: numpy.ndarray) None

The retracker range uncertainty is computed directly from the epoch standard error (from the least squares cost function) in the waveform model fitting process.

Parameters:
  • fit_results – A list of waveform model fit results

  • indices – List of waveform indices

_apply_filter() None

Apply a filter to the retracker results. E.g., range values exceeding a certain misfit value or leading edge error are masked.

Returns:

None (Variables are changed in place

_store_retracker_properties(fit_results: List[SAMOSAWaveformFitResult], indices: numpy.ndarray) None

Store the output of the SAMOSA+ retracker in the class and maps the fit result to the corresponding indices in the Level-2 data.

Parameters:
  • fit_results

  • indices

Returns:

None

_l2_register_retracker_parameters() None

Add retracker variables to the L2 data object. The specific variables depend on surface type.

__getattr__(item: str) Any

Direct attribute access to the retracker properties dictionary

Parameters:

item – parameter name

Raises:

AttributeError – item not in self._retracker_params (see self.create_retracker_properties)

Returns:

pysiral.retracker.samosa_wfm.samosa_fit_samosap_single(fit_data: WaveformFitData, samosap_fit_kwargs: Dict = None, predictor_kwargs: Dict = None, least_squares_kwargs: Dict = None, filter_trailing_edge_kwargs: Dict = None) SAMOSAWaveformFitResult

Fits the SAMOSA waveform model with all free parameters (epoch, swh, mss, amplitude) using the two-step standard fitting approach used for open ocean waveforms with SAMOSA+.

This fit is intended for waveforms classified as sea ice.

Parameters:
  • fit_data – Input parameters for waveform fitting process. Mainly contains waveform model scenario data and waveform data.

  • samosap_fit_kwargs

  • predictor_kwargs – Input parameter for parameter first guess and fit bounds

  • least_squares_kwargs – Keyword arguments to scipy.optimize.least_squares

  • filter_trailing_edge_kwargs – Keyword arguments to

Returns:

SAMOSA+ waveform model fit result

pysiral.retracker.samosa_wfm.samosa_fit_samosap_standard(fit_data: WaveformFitData, samosap_fit_kwargs: Dict = None, predictor_kwargs: Dict = None, least_squares_kwargs: Dict = None, filter_trailing_edge_kwargs: Dict = None) SAMOSAWaveformFitResult

Fits the SAMOSA waveform model with all free parameters (epoch, swh, mss, amplitude) using the two-step standard fitting approach used for open ocean waveforms with SAMOSA+.

This fit is intended for waveforms classified as sea ice.

Parameters:
  • fit_data – Input parameters for waveform fitting process. Mainly contains waveform model scenario data and waveform data.

  • samosap_fit_kwargs – Input parameters for SAMOSA+ fitting process

  • predictor_kwargs – Input parameter for parameter first guess and fit bounds

  • least_squares_kwargs – Keyword arguments to scipy.optimize.least_squares

  • filter_trailing_edge_kwargs – Keyword arguments to

Returns:

SAMOSA+ waveform model fit result

pysiral.retracker.samosa_wfm.samosa_fit_samosap_specular(fit_data: WaveformFitData, samosap_fit_kwargs: Dict = None, predictor_kwargs: Dict = None, least_squares_kwargs: Dict = None) SAMOSAWaveformFitResult

Fits the SAMOSA waveform model with (epoch, mss, [amplitude]) and a fixed swh in a single step that is equivalent of the fit step 2 in the default fit procedure

This fit is intended for waveforms classified as lead waveforms.

Parameters:
  • fit_data – Input parameters for waveform fitting process. Mainly contains waveform model scenario data and waveform data.

  • samosap_fit_kwargs – Input parameters for SAMOSA+ fitting process

  • predictor_kwargs – Input parameter for parameter first guess and fit bounds

  • least_squares_kwargs – Keyword arguments to scipy.optimize.least_squares

Returns:

SAMOSA+ waveform model fit result

pysiral.retracker.samosa_wfm.samosa_fit_samosap_single_step2(waveform_data: NormedWaveform, scenario_data: samosa_waveform_model.ScenarioData, predictor: SAMOSAModelParameterPrediction, least_squares_kwargs: Dict | None = None, sub_waveform_mask: numpy.ndarray | None = None, amplitude_is_free_param: bool = True) Tuple[WaveformModelParametersFit, samosa_waveform_model.dataclasses.WaveformModelOutput, scipy.optimize.OptimizeResult]

Performs fit step 2 of the SAMOSAPlus retracker (as implemented in SAMPY)

Parameters:
  • waveform_data

  • scenario_data

  • predictor

  • least_squares_kwargs

  • sub_waveform_mask

  • amplitude_is_free_param

Returns:

Fit result waveform mode

pysiral.retracker.samosa_wfm.samosa_fit_samosap_standard_step1(waveform_data: NormedWaveform, scenario_data: samosa_waveform_model.ScenarioData, predictor: SAMOSAModelParameterPrediction, step1_fixed_nu_value: float = 0.0, amplitude_is_free_param: bool = True, least_squares_kwargs: Dict | None = None, sub_waveform_mask: numpy.ndarray | None = None) Tuple[WaveformModelParametersFit, samosa_waveform_model.dataclasses.WaveformModelOutput, scipy.optimize.OptimizeResult]

Performs fit step 1 of the SAMOSAPlus retracker (as implemented in SAMPY)

Parameters:
  • waveform_data

  • scenario_data

  • predictor

  • amplitude_is_free_param

  • step1_fixed_nu_value

  • least_squares_kwargs

  • sub_waveform_mask

Returns:

Waveform model parameters,

pysiral.retracker.samosa_wfm.samosa_fit_samosap_standard_step2(waveform_data: NormedWaveform, scenario_data: samosa_waveform_model.ScenarioData, predictor: SAMOSAModelParameterPrediction, amplitude_is_free_param: bool = True, step2_fixed_swh_value: float = 0.0, least_squares_kwargs: Dict | None = None, sub_waveform_mask: numpy.ndarray | None = None) Tuple[WaveformModelParametersFit, samosa_waveform_model.dataclasses.WaveformModelOutput, scipy.optimize.OptimizeResult]

Performs fit step 2 of the SAMOSAPlus retracker (as implemented in SAMPY)

Parameters:
  • waveform_data

  • scenario_data

  • predictor

  • amplitude_is_free_param

  • step2_fixed_swh_value

  • least_squares_kwargs

  • sub_waveform_mask

Returns:

Fit result waveform mode

pysiral.retracker.samosa_wfm.get_model_from_args(samosa_waveform_model, args, amplitude_scale: float = 1.0, thermal_noise: float = 0.0) samosa_waveform_model.dataclasses.WaveformModelOutput

Compute waveform model with final fit parameters. This function allows to compute the waveform model from fit parameter triplets.

Parameters:
  • samosa_waveform_model – Initialized and configured SAMOSA+ Waveform model instance.

  • args – list of [epoch, swh, mss]

  • amplitude_scale – Optional scaling factor

  • thermal_noise – Optional thermal noise

Returns:

Waveform model

pysiral.retracker.samosa_wfm.total_velocity_from_vector(velocity_x: float, velocity_y: float, velocity_z: float) float

Compute total velocity from vector

Parameters:
  • velocity_x – velocity x-component

  • velocity_y – velocity y-component

  • velocity_z – velocity z-component

Returns:

Total velocity

pysiral.retracker.samosa_wfm.get_valid_epoch_range(epoch: numpy.ndarray, earliest_fraction: float = 0.0, latest_fraction: float = 1.0) Tuple[float, float]

Get bounds for epoch based on the valid fraction range in the range window.

Parameters:
  • epoch – epoch array

  • earliest_fraction – first valid epoch as fraction of the range window

  • latest_fraction – last valid epoch as fraction of the range window

Raises:

ValueError – fraction not in interval [0-1] or earliest > latest

Returns:

(epoch lower bound, epoch upper bound)

pysiral.retracker.samosa_wfm.get_epoch_bounds(tau: numpy.ndarray, epoch_first_guess_ns: float, tau_earliest_fraction: float = 0.02, tau_latest_fraction: float = 0.8, range_gates_after_fmi: int = 20) Tuple[float, float]

Compute the fit bounds for the epoch. The lower epoch bound is defined by a fraction of the range window, while the upper epoch bound is defined as a certain number of range gates after the first guess (first maximum index).

Parameters:
  • tau – range gates in nanoseconds

  • epoch_first_guess_ns – First guess for the epoch (ususally location of first maximum)

  • tau_earliest_fraction – Fraction of the range window for the earliest epoch bound

  • tau_latest_fraction – Fraction of the range window for the latest epoch bound (not used)

  • range_gates_after_fmi – Number of trailing range gates after the epoch first guess (defines the upper epoch bound)

pysiral.retracker.samosa_wfm.sampy_misfit(residuals: numpy.ndarray, waveform_mask: numpy.ndarray | None = None, waveform_scale: float = None) float

Computes the SAMOSA waveform model misfit parameter according to SAMPy with optional misfit computation on sub-waveform.

One deviation from the SAMPy approach is the optional misfit reduction due to waveform maximum power > 1. This may happen when the first maximum power is less than the maximum power. In this case the misfit value is artificially increased compared to the SAMPy approach and scenarious where the first maximum is also the absolute maximum power. This cannot be derived from the residuals alone and therefore need to be provided as apriori information.

Parameters:
  • residuals – difference between waveform and waveform model

  • waveform_mask – numpy index array of sub-waveform mask

  • waveform_scale – Maximum power the waveform. (Only needed if maximum power > 1).

Returns:

SAMOSA waveform model misfit

pysiral.retracker.samosa_wfm.compute_thermal_noise(waveform: numpy.ndarray, start_index: int = 4, end_index: int = 12) float

Compute thermal noise for waveform collection (from SAMPy). The strategy is to compute the media in a slice of the lowest values of the first half of the waveform (apparently the end of the waveform contains zeros).

Parameters:
  • waveform – The waveform array

  • start_index – start of the slice of sorted waveform power values (forced to valid range)

  • end_index – end of the slice of sorted waveform power values (forced to valid range)

Returns:

thermal noise in waveform power units

pysiral.retracker.samosa_wfm.epoch2range(epoch: float, range_array: numpy.ndarray) float

Computes the retracker range, defined as range of spacecraft center or mass to retracked elevation.

Parameters:
  • epoch – retracker epoch in seconds

  • range_array

Returns:

retracker range in meter.

pysiral.retracker.samosa_wfm.get_look_angles(l1, index: int) numpy.ndarray

Compute the lookangles based on l1b stack information # TODO: This functions raises a ValueError for NaN values in the classifiers (LRM?)

Parameters:
  • l1 – The level 1 data object

  • index – Waveform index

Returns:

pysiral.retracker.samosa_wfm.get_least_squares_parameter_sdev(optimize_result: scipy.optimize.OptimizeResult) numpy.ndarray

Compute standard deviation of parameter from Jacobian.

Solution from Stack Overflow: https://stackoverflow.com/questions/42388139

Parameters:

optimize_result – Return object from scipy.optimize.least_squares

Returns:

List of fit parameter standard deviations

pysiral.retracker.samosa_wfm.get_sub_waveform_mask(waveform_data: NormedWaveform, filter_trailing_edge_kwargs: Dict) numpy.ndarray

Estimates a sub-waveform mask by flagging off-nadir backscatter elements that manifests as peaks on the trailing edge. This is done by estimating the lower envelope of the trailing edge and exclude all waveform power values that

Parameters:
  • waveform_data – Waveform data

  • filter_trailing_edge_kwargs – Configuration keyword arguments for the trailing edge filter.

Returns:

sub-waveform mask (True: masked)

pysiral.retracker.samosa_wfm.get_trailing_edge_lower_envelope_mask(waveform_power: numpy.ndarray, first_maximum_index: int, max_minimum_cleaning_passes: int = 5, noise_level_normed: float = 0.02, return_type: Literal['bool', 'indices'] = 'bool') numpy.ndarray

Compute the indices of the waveforms trailing edge lower envelope. This method relies on the computation of relative minima via scipy. with added filtering.

Parameters:
  • waveform_power – Waveform power values (any unit)

  • first_maximum_index – Range gate index of the first maximum.

  • max_minimum_cleaning_passes – Local minima on the trailing edge may not be in strictly decreasing in power depending on the off-nadir backscatter contanimation of the trailing edge. Local minima are iteratively removed that are not decreasing in power.

  • noise_level_normed – Points within the noise level of the linear fit between successive local minima are added to the trailing edge mask. Noise level unit is the first maximum power.

  • return_type – Options are a boolean array with the same dimensions as the waveform (default), or an index array.

Returns:

pysiral.retracker.samosa_wfm.get_samosa_leading_edge_error(waveform_model: numpy.ndarray, waveform: numpy.ndarray, leading_edge_start_power_threshold: float = 0.005) float

Compute the SAMOSA+ leading edge error value from the RMSE of the leading edge of the waveform and the fitted SAMOSA+ waveform model.

This error is an additional quality control measure for the SAMOSA+ range e.g., in cases where the overall fit seems to be nominal, but the leading edge (and its tracking point) are not well represented.

The leading edge will be estmated from the SAMOSA+ waveform model (because this is a lot easier than from the actual waveform).

Parameters:
  • waveform_model – The SAMOSA+ waveform model.

  • waveform – The actual waveform

  • leading_edge_start_power_threshold – Power threshold in units of the maximum power of the SAMOSA+ waveform model to determine the start of the leading edge.

Returns:

SAMOSA+ leading edge error value (RMSE between waveform and waveform model for leading edge only).

pysiral.retracker.samosa_wfm.rmse(predictions: numpy.ndarray, targets: numpy.ndarray) float

Compute root-mean-square-error (rmse) of 2 non-Nan arrays

Parameters:
  • predictions – predicted values (non-NaN)

  • targets – target values (non-NaN)

Returns:

rmse value

pysiral.retracker.samosa_wfm.get_nu_from_ocog_width(ocog_width: float, nu_ocog_coefs: Tuple[float, float], ocog_width_max: float = 50, nu_min: float = 0, nu_max: float = 1000000.0, default_nu: float = 0.0) float

Compute the inverse mean square slope (nu) from an empirical parametrization based on ocog width. For stability reasons, the nu value is clipped to a minimum and maximum value.

Parameters:
  • ocog_width – OCOG width (in range gates)

  • nu_ocog_coefs – coeficients for the OCOG width to nu relation (c[0] * ocog_width ** (-c[1]))

  • ocog_width_max – The maximum OCOG value for which this relation is valid

  • nu_min – Minimum value for nu

  • nu_max – Maximum value for nu

  • default_nu – Default value for nu if the OCOG width is above the maximum value

Returns:

Inverse mean square slope (nu)