Source code for ran.phy.numpy.pusch.noisevar_rsrp_sinr

# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
#
# 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.

"""
Noise variance, RSRP and SINR calculators (NumPy translations of MATLAB detPusch.m).

Implements helpers corresponding to the measurement block in detPusch.m:
- noise_variance_db: compute noise variance per DMRS position (dB) from tmp_noiseVar
- rsrp_db: compute RSRP per DMRS position and UE (dB) from h_est and layer2ue
- sinr_db: compute SINR per DMRS position and UE (dB) as rsrp_db - noise_variance_db
"""

import numpy as np

from ran.types import ComplexArrayNP, FloatArrayNP, FloatNP, IntArrayNP
from ran.utils import db


[docs] def noise_variance_db( mean_noise_var: FloatArrayNP, ) -> FloatArrayNP: """ Compute noise variance per DMRS position (dB) following detPusch.m. Args: mean_noise_var: (n_prb, n_pos) linear noise variances Returns ------- noise variance in dB, shape (n_pos,) """ # Full-slot: scalar mean over all entries, then repeat per position return db(np.maximum(np.mean(mean_noise_var, axis=0), np.finfo(float).tiny)) + 0.5
[docs] def rsrp_db( h_est: ComplexArrayNP, layer2ue: IntArrayNP, n_ue: int, ) -> FloatArrayNP: """ Compute RSRP per DMRS position and UE (dB) following detPusch.m. Args: h_est: (n_f, nl, n_ant, n_pos) complex channel estimates, with nf: number of subcarriers in frequency (12*n_prb) layer2ue: (nl,) int mapping from layer index to UE index (0-based) n_ue: number of UEs Returns ------- rsrp in dB, shape (n_pos, n_ue) """ nf, nl, n_ant, n_pos = h_est.shape # Sum |H|^2 across frequency and antennas -> (nl, n_pos) per_layer_pos = np.abs(h_est) ** 2 per_layer_pos = per_layer_pos.sum(axis=(0, 2)).astype(FloatNP) # (nl, n_pos) # Aggregate layers -> UEs: (n_ue, n_pos) then transpose to (n_pos, n_ue) rsrp_lin = np.zeros((n_ue, n_pos), dtype=FloatNP) if n_ue > 0 and nl > 0: np.add.at(rsrp_lin, layer2ue, per_layer_pos) rsrp_lin = rsrp_lin.T # Normalize by (nf*nAnt) rsrp_lin /= nf * max(n_ant, 1) # Always full-slot average (subslot_proc_option assumed 0) mean_over_pos = rsrp_lin.mean(axis=0, keepdims=True) rsrp_lin = np.repeat(mean_over_pos, repeats=n_pos, axis=0) # Convert to dB return db(np.maximum(rsrp_lin, np.finfo(float).tiny))
[docs] def sinr_db( rsrp_db: FloatArrayNP, noise_var_db: FloatArrayNP, ) -> FloatArrayNP: """ Compute SINR per DMRS position and UE (dB) as rsrp_db - noise_var_db. Args: rsrp_db: (n_pos, n_ue) RSRP in dB noise_var_db: (n_pos,) noise variance in dB Returns ------- SINR in dB, shape (n_pos, n_ue) """ return rsrp_db - noise_var_db
[docs] def noise_rsrp_sinr_db( mean_noise_var: FloatArrayNP, h_est: ComplexArrayNP, layer2ue: IntArrayNP, n_ue: int, ) -> tuple[FloatArrayNP, FloatArrayNP, FloatArrayNP]: """ Compute noise variance, RSRP, and SINR per DMRS position and UE (all in dB). This function sequentially calls noise_variance_db, rsrp_db, and sinr_db to compute all three metrics in one call. Args: mean_noise_var: Noise variance estimate per DMRS position, shape (n_prb, n_pos) h_est: Channel estimates, shape (n_f, nl, n_ant, n_pos) layer2ue: Maps layers to UEs (0-indexed), shape (nl,) n_ue: Number of UEs Returns ------- tuple containing: - noise_var_db: Noise variance in dB, shape (n_pos,) - rsrp_db_val: RSRP in dB, shape (n_pos, n_ue) - sinr_db_val: SINR in dB, shape (n_pos, n_ue) """ # Compute noise variance in dB noise_var_db = noise_variance_db(mean_noise_var) # Compute RSRP in dB rsrp_db_val = rsrp_db(h_est, layer2ue, n_ue) # Compute SINR in dB sinr_db_val = sinr_db(rsrp_db_val, noise_var_db) return noise_var_db, rsrp_db_val, sinr_db_val
__all__ = [ "noise_rsrp_sinr_db", "noise_variance_db", "rsrp_db", "sinr_db", ]