def test_dpa_gain(self): hor_dirs = [0, 1.49, 360 - 1.49, 1.51, 360 - 1.51, 90, 320] gains = antenna.GetRadarNormalizedAntennaGains(hor_dirs, 0) self.assertEqual( np.max(np.abs(gains - np.array([0, 0, 0, -25, -25, -25, -25]))), 0) for k, hor in enumerate(hor_dirs): gain = antenna.GetRadarNormalizedAntennaGains(hor, 0) self.assertEqual(gain, gains[k]) gains = antenna.GetRadarNormalizedAntennaGains([5, 8.6, 11.4, 20], 10) self.assertEqual(np.max(np.abs(gains - np.array([-25, 0, 0, -25]))), 0) gains = antenna.GetRadarNormalizedAntennaGains( [5, 8.99, 9.01, 10, 10.99, 11.01], 10, radar_beamwidth=2) self.assertEqual( np.max(np.abs(gains - np.array([-25, -25, 0, 0, 0, -25]))), 0)
def calcAggregatedInterference(protection_point, low_freq, high_freq, grants, inc_ant_height, num_iter, beamwidth, neighbor_distances, min_azimuth=0, max_azimuth=360, do_max=False): """Computes the 95% aggregated interference quantile on a protected point. Inputs: protection_point: A protection point location, having attributes 'latitude' and 'longitude'. low_freq: The low frequency of protection constraint (Hz). high_freq: The high frequency of protection constraint (Hz). grants: A list of CBSD |data.CbsdGrantInfo| active grants. inc_ant_height: The reference incumbent antenna height (meters). num_iter: The number of Monte Carlo iterations. beamwidth: The protection antenna beamwidth (degree). min_azimuth: The minimum azimuth (degrees) for incumbent transmission. max_azimuth: The maximum azimuth (degrees) for incumbent transmission. neighbor_distances: The neighborhood distances (km) as a sequence: [cata_dist, catb_dist, cata_oob_dist, catb_oob_dist] do_max: If True, returns the maximum interference over all radar azimuth. Returns: The 95% aggregated interference (dB) either: - as a vector (ndarray) of length N, where the element k corresponds to azimuth k * (beamwith/2). The length N is thus equal to 2 * 360 / beamwith, (or 2 * azimuth_range / beamwidth if using a smaller azimuth range than 360 degrees, as specified by min_azimuth/max_azimuth). - or the maximum over all radar azimuth, if `do_max` is set to True. """ dpa_type = findDpaType(low_freq, high_freq) if not beamwidth: beamwidth = 360 # Assign values to the protection constraint constraint = data.ProtectionConstraint( latitude=protection_point.latitude, longitude=protection_point.longitude, low_frequency=low_freq, high_frequency=high_freq, entity_type=data.ProtectedEntityType.DPA) # DPA Purge algorithm for OOB if dpa_type is DpaType.OUT_OF_BAND: cbsds_grants_map = defaultdict(list) for grant in grants: key = grant.uniqueCbsdKey() _addMinFreqGrantToFront(cbsds_grants_map[key], grant) # Reset the grants to the minimum frequency grant for each CBSDs. grants = [cbsd_grants[0] for cbsd_grants in cbsds_grants_map.values()] # Identify CBSD grants in the neighborhood of the protection constraint neighbor_grants, _ = findGrantsInsideNeighborhood(grants, constraint, dpa_type, neighbor_distances) if not neighbor_grants: return np.asarray(-1000) interf_matrix = np.zeros((num_iter, len(neighbor_grants))) bearings = np.zeros(len(neighbor_grants)) for k, grant in enumerate(neighbor_grants): interf, _ = computeInterference(grant, constraint, inc_ant_height, num_iter, dpa_type) interf_matrix[:, k] = interf.randomInterference bearings[k] = interf.bearing_c_cbsd interf_matrix = 10**(interf_matrix / 10.) azimuths = findAzimuthRange(min_azimuth, max_azimuth, beamwidth) agg_interf = np.zeros(len(azimuths)) for k, azi in enumerate(azimuths): dpa_gains = antenna.GetRadarNormalizedAntennaGains( bearings, azi, beamwidth) dpa_interf = interf_matrix * 10**(dpa_gains / 10.0) agg_interf[k] = np.percentile(np.sum(dpa_interf, axis=1), PROTECTION_PERCENTILE, interpolation='lower') agg_interf = 10 * np.log10(agg_interf) return np.max(agg_interf) if do_max else agg_interf
def find_nc(I, bearings, t, beamwidth, min_azimuth, max_azimuth): """Returns the index (nc) of the grant in the ordered list of grants such that the protection percentile of the interference from the first nc grants is below the threshold for all azimuths of the receiver antenna. Inputs: I: 2D array of interference contributions (dBm/10 MHz); columns correspond to grants, and rows correspond to Monte Carlo iterations. bearings: a list of bearings from protection point to CBSDs. t: protection percentile threshold (dBm/10 MHz) beamwidth: protection antenna beamwidth (degree). min_azimuth: minimim protection azimuth (degree). max_azimuth: maximum protection azimuth (degree). Returns: nc: index nc that defines the move list to be {G_nc+1, G_nc+2, ..., G_Nc} """ # Create array of incumbent antenna azimuth angles (degrees). azimuths = findAzimuthRange(min_azimuth, max_azimuth, beamwidth) # Initialize nc to Nc. Nc = I.shape[1] nc = Nc # Convert protection threshold and interference matrix to linear units. t_mW = np.power(10.0, t / 10.0) I_mW = np.power(10.0, I / 10.0) # Loop through every azimuth angle. for azi in azimuths: # Calculate interference contributions at output of receiver antenna. dpa_gains = antenna.GetRadarNormalizedAntennaGains( bearings, azi, beamwidth) IG = I_mW * 10**(dpa_gains / 10.0) # Compute the protection percentile of the aggregate interference, and remove # grants until the protection threshold is met or all grants are moved. agg_interf = np.percentile(np.sum(IG[:, 0:nc], axis=1), PROTECTION_PERCENTILE, interpolation='lower') if agg_interf <= t_mW: continue # Conduct binary search for nc. hi = nc lo = 0 while (hi - lo) > 1: mid = (hi + lo) / 2 agg_interf = np.percentile(np.sum(IG[:, 0:mid], axis=1), PROTECTION_PERCENTILE, interpolation='lower') if agg_interf > t_mW: hi = mid else: lo = mid nc = lo if nc == 0: return 0 return nc