|
def | calCond (userCSI) |
|
def | calDemmel (userCSI) |
|
def | calCapacity (userCSI, noise, beamweights, downlink=False) |
|
def | calContCapacity (csi, conj=True, downlink=False, offset=1) |
|
def | calExpectedCapacity (csi, user=0, max_delay=100, conj=True, downlink=False) |
|
def | find_bad_nodes (csi, corr_thresh=0.32, user=0) |
|
def | calCorr (userCSI, corr_vec) |
|
def | demult (csi, data, method='zf') |
|
channel_analysis.py
CSI analysis API file
Author(s): Clay Shepard: cws@rice.edu
Rahman Doost-Mohamamdy: doost@rice.edu
Oscar Bejarano: obejarano@rice.edu
---------------------------------------------------------------------
Copyright © 2018-2019. Rice University.
RENEW OPEN SOURCE LICENSE: http://renew-wireless.org/license
---------------------------------------------------------------------
def channel_analysis.calCapacity |
( |
|
userCSI, |
|
|
|
noise, |
|
|
|
beamweights, |
|
|
|
downlink = False |
|
) |
| |
Calculate the capacity of a trace with static beamweights.
Apply a set of beamweights to a set of wideband user channels and calculate the shannon capacity of the resulting channel for every Frame.
Note that if the beamweights are calculated with a frame from the trace, that frame will have unrealistic capacity since it will correlate noise as signal.
Args:
userCSI: Complex numpy array with [Frame, User, BS Ant, Subcarrier]
noise: Complex numpy array with [Frame, BS Ant, Subcarrier]
beamweights: Set of beamweights to apply to userCSI [BS Ant, User, Subcarrier]
downlink: (Boolean) Compute downlink capacity if True, else Uplink
Returns:
cap_total: Total capacity across all users averaged over subarriers in bps/hz [Frame]
cap_u: Capacity per user across averaged over subcarriers in bps/hz [Frame, User]
cap_sc: Capacity per user and subcarrier in bps/hz [Frame, User, Subcarrier]
SINR: Signtal to interference and noise ratio for each frame user and subcarrier [Frame, User, Subcarrier]
cap_su_sc: Single user (no interference) capacity per subcarrier in bps/hz [Frame, User, Subcarrier]
cap_su_u: Single user (no interference) capacity averaged over subcarriers in bps/hz [Frame, User]
SNR: Signtal to noise ratio for each frame user and subcarrier [Frame, User, Subcarrier]
def channel_analysis.calContCapacity |
( |
|
csi, |
|
|
|
conj = True , |
|
|
|
downlink = False , |
|
|
|
offset = 1 |
|
) |
| |
Calculate the capacity of a trace with continuous beamforming.
For every frame in a trace, calculate beamweights (either conjugate or ZF),
apply them to a set of wideband user channels either from the same frame or some constant offset (delay),
then calculate the shannon capacity of the resulting channel.
The main difference in uplink/downlink is the source of interference (and power allocation).
In uplink the intended user's interference is a result of every other user's signal passed through that user's beamweights.
In downlink the inteded user's interference is a result of every other user's signal passed through their beamweights (applied to the intended user's channel).
Note that every user has a full 802.11 LTS, which is a repitition of the same symbol.
This method uses the first half of the LTS to make beamweights, then applies them to the second half.
Otherwise, noise is correlated, resulting in inaccurate results.
Args:
csi: Full complex numpy array with separate LTSs and noise [Frame, User, BS Ant, Subcarrier] (noise is last user)
conj: (Boolean) If True use conjugate beamforming, else use zeroforcing beamforming.
downlink: (Boolean) Compute downlink capacity if True, else Uplink
offset: Number of frames to delay beamweight application.
Returns:
cap_total: Total capacity across all users averaged over subarriers in bps/hz [Frame]
cap_u: Capacity per user across averaged over subcarriers in bps/hz [Frame, User]
cap_sc: Capacity per user and subcarrier in bps/hz [Frame, User, Subcarrier]
SINR: Signtal to interference and noise ratio for each frame user and subcarrier [Frame, User, Subcarrier]
cap_su_sc: Single user (no interference) capacity per subcarrier in bps/hz [Frame, User, Subcarrier]
cap_su_u: Single user (no interference) capacity averaged over subcarriers in bps/hz [Frame, User]
SNR: Signtal to noise ratio for each frame user and subcarrier [Frame, User, Subcarrier]
def channel_analysis.calCorr |
( |
|
userCSI, |
|
|
|
corr_vec |
|
) |
| |
Calculate instantaneous correlation with a correlation vector.
Sub-samples userCSI in the time/user/subcarrier slice before
passing it. If slicing just one user, dimensionality has to be
maintained, i.e. slice like userCSI[:,[2],:,:].
Args:
userCSI: Complex numpy array [Frame, User, BS Ant, Subcarrier].
corr_vec: Vector to correlate with [BS Ant, User, Subcarrier].
Returns:
corr_total: Average correlation across subcarriers [Frame,User].
sig_sc: Correlation on every [Frame, User, Subcarrier].
Typical usage example:
corr_total,sig_sc = calCorr(userCSI,
np.transpose(np.conj(userCSI[frame,:,:,:]),(1,0,2)))
def channel_analysis.calExpectedCapacity |
( |
|
csi, |
|
|
|
user = 0 , |
|
|
|
max_delay = 100 , |
|
|
|
conj = True , |
|
|
|
downlink = False |
|
) |
| |
Calculate the expected capacity for beamweights calculated with delayed stale CSI.
Args:
csi: Full complex numpy array with separate LTSs and noise [Frame, User, BS Ant, Subcarrier] (noise is last user)
user: Index of user to compute for (note that other users still affect capacity due to their interference)
max_delay: Maximum delay (in frames) to delay the beamweight computation.
conj: (Boolean) If True use conjugate beamforming, else use zeroforcing beamforming.
downlink: (Boolean) Compute downlink capacity if True, else Uplink
Returns:
cap: Average capacity across all frames for a given delay (in frames) in bps/hz [Delay]
def channel_analysis.demult |
( |
|
csi, |
|
|
|
data, |
|
|
|
method = 'zf' |
|
) |
| |
csi: Frame, User, Antenna, Subcarrier
data: Frame, Uplink Syms, Antenna, Subcarrier
def channel_analysis.find_bad_nodes |
( |
|
csi, |
|
|
|
corr_thresh = 0.32 , |
|
|
|
user = 0 |
|
) |
| |
Find bad Iris nodes.
Find bad nodes based on the correlation between a reference node
and every other node. If all nodes are 'bad' then the reference
node is assumed to be bad, and a new reference node is chosen. The
reference node is picked sequentially from the list of BS antennas.
Note:
csi should be a channel trace taken in a stable environment.
If AGC is used, csi should be taken after AGC has settled.
Note:
By only correlating one node with another, the decorrelation
is maximized when there is a sync issue. (If you use more
antennas for reference, the impact of the time sync is less.
If you use fewer, the bad antennas, which have all of the same
phase shift, dominate correlation.)
An important trick is to normalize amplitudes of the CSI so
that the phase shift always has the same impact, regardless of
channel gains (i.e. if the reference node has low or high
signal strength relative to the bad node it would decrease the
impact of a time sync issue).
This also allows a fixed threshold to work well as a single
sample shift of 4 antennas out of 8 relatively consistently
causes a decorrelation of .25. If half the samples (worst
case), this is a .125 deviation from the mean.
Args:
csi: Complex array [Frame, User, Pilot Rep, BS Ant, Subcarrier]
thresh: Lower threshold means more sensitivity to deviation in
correlation. Higher shall give more false negatives, lower
shall give more false positives.
user: The index of the user to use for correlation.
Returns:
bad_nodes: A list of indices of nodes determined to be bad.