pysiral.waveform ================ .. py:module:: pysiral.waveform .. autoapi-nested-parse:: Created on Fri Jul 01 13:07:10 2016 @author: shendric Classes ------- .. autoapisummary:: pysiral.waveform.TFMRALeadingEdgeWidth pysiral.waveform.L1POCOG pysiral.waveform.L1PLeadingEdgeWidth pysiral.waveform.L1PSigma0 pysiral.waveform.L1PWaveformPeakiness pysiral.waveform.L1PLeadingEdgeQuality pysiral.waveform.L1PLateTail2PeakPower pysiral.waveform.WFMTrailingEdgeData pysiral.waveform.L1PTrailingEdgeProperties pysiral.waveform.WaveFormTrailingEdgeParameterData pysiral.waveform.WaveFormTrailingEdgeDecayFit pysiral.waveform.WaveFormTrailingEdgeParameter pysiral.waveform.L1PLeadingEdgePeakiness pysiral.waveform.WFMTrailingEdgeSlopeData pysiral.waveform.L1PTrailingEdgeSlope pysiral.waveform.OCOGParameter pysiral.waveform.CS2PulsePeakiness pysiral.waveform.S3LTPP pysiral.waveform.CS2LTPP pysiral.waveform.EnvisatWaveformParameter Functions --------- .. autoapisummary:: pysiral.waveform.get_waveforms_peak_power pysiral.waveform.get_footprint_pulse_limited pysiral.waveform.get_footprint_sar pysiral.waveform.get_sigma0_sar pysiral.waveform.get_sigma0 pysiral.waveform.trailing_edge_slope pysiral.waveform.coeficient_of_determination pysiral.waveform.get_trailing_edge_lower_envelope_mask Module Contents --------------- .. py:function:: get_waveforms_peak_power(wfm: numpy.typing.NDArray, use_db: bool = False) -> numpy.typing.NDArray Return the peak power (in input coordinates) of an array of waveforms Arguments --------- wfm (float array) echo waveforms, order = (n_records, n_range_bins) Returns ------- float array with maximum for each echo .. py:function:: get_footprint_pulse_limited(r: float, band_width: float) -> float Compute the CryoSat-2 LRM footprint for variable range to the surface. Applicable Documents: Michele Scagliola, CryoSat Footprints ESA/Aresys, v1.2 ESA document ref: XCRY-GSEG-EOPG-TN-13-0013 :param r: range from satellite center of mass to surface reflection point :param band_width: pulse bandwidth in Hz :return area_pl: Radar backscatter coefficient .. py:function:: get_footprint_sar(r: float, v_s: float, ptr_width: float, tau_b: float, lambda_0: float, wf: float = 1.0, r_mean: float = 6371000.0) -> float Compute the radar footprint of SAR altimeters for variable range to the surface. Applicable Documents: Michele Scagliola, CryoSat Footprints ESA/Aresys, v1.2 ESA document ref: XCRY-GSEG-EOPG-TN-13-0013 :param r: range from satellite center of mass to surface reflection point :param v_s: satellite along track velocity in meter/sec :param ptr_width: 3dB range point target response temporal width in seconds :param tau_b: burst length in seconds :param lambda_0: radar wavelength in meter :param wf: footprint widening factor :param r_mean: mean earth radius in meter :return area_sar: The SAR footprint in square meters .. py:function:: get_sigma0_sar(rx_pwr: float, tx_pwr: float, r: float, a: float, lambda_0: float, g_0: float, l_atm: float = 1.0, l_rx: float = 1.0, bias_sigma0: float = 0.0) -> float Compute the sigma0 backscatter coefficient according the radar equation, e.g. equation 20 in Guidelines for reverting Waveform Power to Sigma Nought for CryoSat-2 in SAR mode (v2.2), Salvatore Dinardo, 23/06/2016 XCRY-GSEG-EOPS-TN-14-0012 :param rx_pwr: received power (waveform maximumn) :param tx_pwr: transmitted power :param r: range to surface in ms :param a: area illuminated by the altimeter :param lambda_0: radar wavelength in meter :param g_0: antenna gain factor :param l_atm: atmospheric loss factor (1.0 -> no loss) :param l_rx: receiving chain losses :param bias_sigma0: sigma0 bias in dB :return: sigma0 in dB .. py:function:: get_sigma0(wf_peak_power_watt: float, tx_pwr: float, r: float, wf_thermal_noise_watt: float = 0.0, lambda_0: float = 0.022084, band_width: float = 320000000.0, g_0: float = 19054.607179632483, bias_sigma0: float = 0.0, l_atm: float = 1.0, l_rx: float = 1.0, c_0: float = 299792458.0) -> float Compute the radar backscatter coefficient sigma nought (sigma0) for lrm waveforms. Uses the radar equation and the computation of the pulse limited footprint Applicable Documents: Guidelines for reverting Waveform Power to Sigma Nought for CryoSat-2 in SAR mode (v2.2), Salvatore Dinardo, 23/06/2016 XCRY-GSEG-EOPS-TN-14-0012 :param wf_peak_power_watt: waveform peak power in watt :param tx_pwr: transmitted peak power in watt :param r: range from satellite center of mass to surface reflection point (to be appoximated by satellite altitude if no retracker range available) :param wf_thermal_noise_watt: estimate of thermal noise power in watt (default: 0.0) will be used to estimate waveform amplitude (Pu) :param band_width: CryoSat-2 pulse bandwidth in Hz :param lambda_0: radar wavelength in meter (default: 0.022084 m for CryoSat-2 Ku Band altimeter) :param g_0: antenna gain at boresight (default: 10^(4.28) from document) :param bias_sigma0: sigma nought bias (default: 0.0) :param l_atm: two ways atmosphere losses (to be modelled) (default: 1.0 (no loss)) :param l_rx: receiving chain (RX) waveguide losses (to be characterized) (default: 1.0 (no loss)) :param c_0: vacuum light speed in meter/sec :return sigma_0: Radar backscatter coefficient .. py:class:: TFMRALeadingEdgeWidth(rng, wfm, radar_mode, retrack_flag, tfmra_options=None) Bases: :py:obj:`object` Container for computation of leading edge width by taking differences between first maximum power thresholds .. py:attribute:: tfmra .. py:method:: get_width_from_thresholds(thres0, thres1, **kwargs) Returns the range difference in range bin units between two thresholds, by subtracting the range value of thresh0 from thresh1. This is done for all waveforms passed to this class during initialization. Intended to compute the width of the leading edge. :param thres0: (float) The minimum threshold :param thres1: (float) The minimum threshold :return: .. py:class:: L1POCOG(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` Computes OCOG (Offset Centre of Gravity) width and amplitude as a Level-1 pre-processor item .. py:method:: apply(l1: pysiral.l1data.Level1bData) -> None Compute OCOG Width and Amplitude for each waveform and add to classifier data group :param l1: Level-1 data object .. py:property:: required_options :type: List[str] .. py:class:: L1PLeadingEdgeWidth(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` A L1P pre-processor item class for computing leading edge width of a waveform using the TFMRA retracker as the difference between two thresholds. The unit for leading edge width are range bins .. py:attribute:: tfmra_leading_edge_start :value: None .. py:attribute:: tfmra_leading_edge_end :value: None .. py:attribute:: tfmra_options :value: None .. py:method:: apply(l1: pysiral.l1data.Level1bData) -> None API class for the Level-1 pre-processor. Functionality is compute leading edge width (full, first half & second half) and adding the result to the classifier data group :param l1: A Level-1 data instance :return: None, Level-1 object is change in place .. py:property:: required_options .. py:class:: L1PSigma0(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` A L1P pre-processor item class for computing the backscatter coefficient (sigma0) from waveform data .. py:method:: apply(l1) API class for the Level-1 pre-processor. Functionality is to compute leading edge width (full, first half & second half) and adding the result to the classifier data group :param l1: A Level-1 data instance :return: None, Level-1 object is change in place .. py:method:: get_sigma0(rx_power: numpy.ndarray, tx_power: numpy.ndarray, altitude: numpy.ndarray, velocity: numpy.ndarray, radar_mode: numpy.ndarray) -> numpy.ndarray :param rx_power: :param tx_power: :param altitude: :param velocity: :param radar_mode: :return: .. py:property:: required_options .. py:class:: L1PWaveformPeakiness(skip_first_range_bins: int = 0, norm_is_range_bin: bool = True) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` A L1P pre-processor item class for computing pulse peakiness .. py:method:: apply(l1: pysiral.l1data.Level1bData) -> None Computes pulse peakiness and adds parameter to classifier data group. NOTE: The classifier parameter name depends on the `norm_is_range_bin keyword: norm_is_range_bin = True -> parameter name: 'peakiness' norm_is_range_bin = False -> parameter name: 'peakiness_normed' :param l1: l1bdata.Level1bData instance :raises None: :return: None .. py:method:: compute_for_waveforms(waveforms: numpy.typing.NDArray) -> numpy.typing.NDArray Compute pulse peakiness for a waveform array :param waveforms: :return: pulse peakiness array .. py:method:: compute_for_waveform(waveform: numpy.typing.NDArray) -> float Compute pulse peakiness for a single waveform :param waveform: :return: pulse peakiness .. py:method:: _compute(waveform: numpy.typing.NDArray, norm: Union[int, float]) -> float :staticmethod: Compute pulse peakiness for a single waveform :param waveform: The waveform :param norm :return: pulse peakiness .. py:property:: required_options .. py:class:: L1PLeadingEdgeQuality(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` Class to compute a leading edge width quality indicator Requires `first_maximum_index` classifier parameter .. py:method:: apply(l1) Adds a quality indicator for the leading edge :param l1: l1bdata.Level1bData instance :return: None .. py:property:: required_options .. py:class:: L1PLateTail2PeakPower(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` .. py:method:: apply(l1: pysiral.l1data.Level1bData) -> None Compute late tail to peakiness and add to l1 data object :param l1: :return: .. py:method:: late_tail_to_peak_power(wfm: numpy.typing.NDArray, late_tail_window_idxs: List[int]) -> float :staticmethod: :param wfm: :param late_tail_window_idxs: :return: .. py:class:: WFMTrailingEdgeData Data Class for L1PTrailingEdgeProperties .. py:attribute:: waveform_full :type: numpy.ndarray .. py:attribute:: trailing_edge_start_idx :type: int .. py:attribute:: waveform_trailing_edge_idx :type: numpy.ndarray .. py:attribute:: trailing_edge_lower_envelope_idx :type: numpy.ndarray .. py:attribute:: trailing_edge_fit :type: numpy.ndarray :value: None .. py:attribute:: trailing_edge_decay :type: float .. py:attribute:: trailing_edge_decay_fit_quality :type: float .. py:attribute:: trailing_edge_decay_mean_absolute_difference :type: float .. py:method:: decay_debug_plot(title='') -> None .. py:property:: trailing_edge_size :type: int .. py:property:: waveform_trailing_edge_subset :type: numpy.ndarray .. py:property:: waveform_trailing_edge_subset_lower_envelope :type: numpy.ndarray .. py:property:: first_maximum_power :type: float .. py:property:: decay_parameters :type: Tuple[float, float, float] .. py:class:: L1PTrailingEdgeProperties(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` .. py:method:: apply(l1: pysiral.l1data.Level1bData) -> None Compute late tail to peakiness and add to l1 data object :param l1: The Level-1 data container :return: .. py:method:: _compute_single_processing(*args) -> WaveFormTrailingEdgeParameterData :staticmethod: Compute waveform trailing edge parameter on a single thread :param args: Arguments to WaveFormTrailingEdgeParameter :return: Waveform trailing edge parameter object .. py:property:: config_validation_schema :type: schema.Schema .. py:class:: WaveFormTrailingEdgeParameterData(n_records: int) Bases: :py:obj:`object` .. py:attribute:: tew .. py:attribute:: teq .. py:attribute:: ted .. py:attribute:: tedfq .. py:attribute:: tepr .. py:attribute:: temad .. py:attribute:: decay_fit_has_failed .. py:attribute:: te_exp_popt0 .. py:attribute:: te_exp_popt1 .. py:attribute:: te_exp_popt2 .. py:method:: add(other_params: WaveFormTrailingEdgeParameterData) -> None .. py:class:: WaveFormTrailingEdgeDecayFit(fit_kwargs=None) Bases: :py:obj:`object` .. py:attribute:: default_fit_kwargs .. py:attribute:: fit_kwargs .. py:attribute:: default_bounds .. py:attribute:: p0 :value: None .. py:method:: fit(data) .. py:class:: WaveFormTrailingEdgeParameter(waveforms: numpy.typing.NDArray, first_maximum_index: numpy.typing.NDArray, valid_first_maximum_index_range: List, trailing_edge_width_kwargs: Dict) Bases: :py:obj:`object` .. py:attribute:: waveforms .. py:attribute:: first_maximum_index .. py:attribute:: valid_first_maximum_index_range .. py:attribute:: trailing_edge_width_kwargs .. py:attribute:: last_fit_popt :value: None .. py:attribute:: params .. py:method:: _compute() -> None Loop over all waveforms and compute the parameters # TODO: Need documentation and potentially move to sub-modules .. py:method:: get_waveform_trailing_edge_data(waveform_full: numpy.ndarray, first_maximum_index: int = None) -> WFMTrailingEdgeData :staticmethod: Aggregate all necesary trailing edge properties in a data class. :param waveform_full: The full waveform in original units :param first_maximum_index: Index of first maximum (definition of trailing edge start) :return: Data class .. py:method:: get_trailing_edge_decay(data: WFMTrailingEdgeData, popt: List) -> WFMTrailingEdgeData :staticmethod: Fit inverse power law to the lower envelope of the trailing edge and compute decay factor, fit quality and residual to trailing edge power. Result will be added to data class. :param data: Pre-compiled trailing edge data :param popt: Fit coefficient (function inverse power low) :raises None: :return: Data class with updated results .. py:method:: trailing_edge_power_ratio(data: WFMTrailingEdgeData, noise_level_normed: float = 0.005) -> float :staticmethod: Compute the trailing edge power ratio defined as the fraction of the trailing edge power above a noise level of the exponentation fit. in relation to the integrated power of the full waveform. Valaues higher than 0.5 indicate that more than half of the waveform power is contained in the trailing edge above the noise level. :param data: Waveform Trailing Edge data object :param noise_level_normed: The noise level in relation to the first maximum power :return: .. py:method:: get_trailing_edge_width(data: WFMTrailingEdgeData, oversample_factor: int, trailing_edge_end_power_treshold_normed: float) -> float :staticmethod: Compute the width of the trailing edge based on the decay fit. :param data: :param oversample_factor: :param trailing_edge_end_power_treshold_normed: :raises None: :return: The trailing edge width in range gate units .. py:method:: get_trailing_edge_quality(data: WFMTrailingEdgeData) -> float :staticmethod: :param data: :return: .. py:method:: get_trailing_edge_lower_envelope(wfm_trailing_edge: numpy.typing.NDArray) -> numpy.typing.NDArray :staticmethod: :param wfm_trailing_edge: :return: .. py:class:: L1PLeadingEdgePeakiness(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` .. py:method:: apply(l1: pysiral.l1data.Level1bData) Mandatory class of a L1 preproceessor item. Computes the leading edge peakiness :param l1: :return: .. py:method:: leading_edge_peakiness(wfm: numpy.ndarray, fmi: int, window: int) -> float :staticmethod: Compute the leading edge peakiness :param wfm: Waveform power :param fmi: first maximum index :param window: the number or leading range bins to the first maximum for the peakiness computation :return: .. py:property:: required_options .. py:class:: WFMTrailingEdgeSlopeData .. py:attribute:: waveform_normed :type: numpy.ndarray .. py:attribute:: trailing_edge_start_idx :type: int .. py:attribute:: trailing_edge_idx :type: numpy.ndarray .. py:attribute:: noise_floor_power_threshold :type: float .. py:attribute:: linregress_result :type: LinregressResult .. py:property:: range_gate_idx :type: numpy.ndarray .. py:property:: trailing_edge_slope :type: float .. py:property:: trailing_edge_slope_quality :type: float .. py:method:: debug_plot() .. py:class:: L1PTrailingEdgeSlope(**cfg) Bases: :py:obj:`pysiral.l1preproc.procitems.L1PProcItem` .. py:method:: apply(l1: pysiral.l1data.Level1bData) :param l1: :return: .. py:method:: _get_trailing_edge_slope(waveforms: numpy.ndarray, first_maximum_indices: numpy.ndarray) -> Tuple[numpy.ndarray, numpy.ndarray] :param waveforms: :param first_maximum_indices: :param use_multiprocessing: :return: .. py:function:: trailing_edge_slope(waveform: numpy.ndarray, trailing_edge_start_index: int, noise_floor_power_threshold: float = 0.15) -> WFMTrailingEdgeSlopeData Compute trailing edge slope as linear fit to the trailing edge plus the quality (Pearson correlation factor) of the fit :param waveform: Waveform :param trailing_edge_start_index: Prior information of the start of the trailing edge :param noise_floor_power_threshold: Trailing edge power below this threshold will be ignored for the fit :return: .. py:class:: OCOGParameter(wfm_counts) Bases: :py:obj:`object` Calculate OCOG Parameters (Amplitude, Width) for CryoSat-2 waveform counts. Algorithm Source: retrack_ocog.pro from CS2AWI lib .. py:attribute:: _n .. py:attribute:: _amplitude .. py:attribute:: _width .. py:method:: _calc_parameters(wfm_counts) .. py:property:: amplitude .. py:property:: width .. py:class:: CS2PulsePeakiness(wfm_counts, pad=2) Bases: :py:obj:`object` Calculates Pulse Peakiness (full, left & right) for CryoSat-2 waveform counts XXX: This is a 1 to 1 legacy implementation of the IDL CS2AWI method, consistent method of L1bData or L2Data is required .. py:attribute:: _n .. py:attribute:: _n_range_bins .. py:attribute:: _pad :value: 2 .. py:attribute:: _peakiness .. py:attribute:: _peakiness_r .. py:attribute:: _peakiness_l .. py:attribute:: _noise_floor .. py:attribute:: _peakiness_normed .. py:method:: _calc_parameters(wfm_counts) .. py:property:: peakiness .. py:property:: peakiness_normed .. py:property:: noise_floor .. py:property:: peakiness_r .. py:property:: peakiness_l .. py:class:: S3LTPP(wfm_counts, pad=1) Bases: :py:obj:`object` Calculates Late-Tail-to-Peak-Power ratio. source: Rinne 2016 .. py:attribute:: _n .. py:attribute:: _n_range_bins .. py:attribute:: _pad :value: 1 .. py:attribute:: _ltpp .. py:method:: _calc_parameters(wfm_counts) .. py:property:: ltpp .. py:class:: CS2LTPP(wfm_counts, pad=2) Bases: :py:obj:`object` Calculates Late-Tail-to-Peak-Power ratio. .. py:attribute:: _n .. py:attribute:: _n_range_bins .. py:attribute:: _pad :value: 2 .. py:attribute:: _ltpp .. py:method:: _calc_parameters(wfm_counts) .. py:property:: ltpp .. py:class:: EnvisatWaveformParameter(wfm, skip=5, bins_after_nominal_tracking_bin=83) Bases: :py:obj:`object` Currently only computes pulse peakiness for Envisat waveforms from SICCI processor. Parameter for Envisat from SICCI Processor skip = 5 bins_after_nominal_tracking_bin = 83 .. py:attribute:: t_n :value: 83 .. py:attribute:: skip :value: 5 .. py:attribute:: _n .. py:attribute:: _n_range_bins .. py:method:: _init_parameter() .. py:method:: _calc_parameter(wfm) .. py:function:: coeficient_of_determination(y: numpy.ndarray, y_fit: numpy.ndarray) -> float Compute coeficient of determination :param y: :param y_fit: :return: .. py:function:: 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', mask_fill_value: bool = True) -> 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. :param waveform_power: Waveform power values (any unit) :param first_maximum_index: Range gate index of the first maximum. :param 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. :param 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. :param return_type: Options are a boolean array with the same dimensions as the waveform (default), or an index array. :param mask_fill_value: Default flag value before trailing edge (Default: True) :return: