Skip to content

Commit 89530a5

Browse files
Merge pull request #914 from Wireless-Innovation-Forum/dpa-median-pathloss
Use median for DPA interference calc
2 parents fc279b0 + 51075ad commit 89530a5

4 files changed

Lines changed: 165 additions & 61 deletions

File tree

src/harness/reference_models/dpa/dpa_mgr.py

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2018 SAS Project Authors. All Rights Reserved.
1+
# Copyright 2024 SAS Project Authors. All Rights Reserved.
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -132,8 +132,8 @@ class Dpa(object):
132132
OR the updated sequence (cata_indoor_dist, cata_indoor_6m_dist,
133133
cata_outdoor_dist, cata_outdoor_6m_dist, catb_dist, catb_6m_dist)
134134
monitor_type: The DPA monitoring category, either 'esc' or 'portal'.
135-
apply_clutter_and_network_loss: Use updatd DPA pathloss which includes
136-
clutter and network loss.
135+
apply_clutter_network_loss_and_50_percent: Use updated DPA pathloss which includes
136+
clutter,network loss, and median for interference calc
137137
138138
move_lists: A list of move list (set of |CbsdGrantInfo|) per channel.
139139
nbor_lists: A list of neighbor list (set of |CbsdGrantInfo|) per channel.
@@ -176,7 +176,7 @@ def __init__(self, protected_points,
176176
freq_ranges_mhz=[DPA_DEFAULT_FREQ_RANGE],
177177
neighbor_distances=DPA_DEFAULT_DISTANCES,
178178
monitor_type='esc',
179-
apply_clutter_and_network_loss=False):
179+
apply_clutter_network_loss_and_50_percent=False):
180180
"""Initialize the DPA attributes."""
181181
self.name = name
182182
self.geometry = geometry
@@ -187,7 +187,7 @@ def __init__(self, protected_points,
187187
self.beamwidth = beamwidth
188188
self.neighbor_distances = neighbor_distances
189189
self.monitor_type = monitor_type
190-
self.apply_clutter_and_network_loss = apply_clutter_and_network_loss
190+
self.apply_clutter_network_loss_and_50_percent = apply_clutter_network_loss_and_50_percent
191191
self._channels = None
192192
self._grants = []
193193
self._has_th_grants = False
@@ -291,7 +291,7 @@ def ComputeMoveLists(self):
291291
min_azimuth=self.azimuth_range[0],
292292
max_azimuth=self.azimuth_range[1],
293293
neighbor_distances=self.neighbor_distances,
294-
apply_clutter_and_network_loss=self.apply_clutter_and_network_loss)
294+
apply_clutter_network_loss_and_50_percent=self.apply_clutter_network_loss_and_50_percent)
295295

296296
move_list, nbor_list = list(
297297
zip(*pool.map(moveListConstraint, self.protected_points)))
@@ -381,7 +381,7 @@ def CalcKeepListInterference(self, channel, num_iter=None):
381381
max_azimuth=self.azimuth_range[1],
382382
neighbor_distances=self.neighbor_distances,
383383
do_max=True,
384-
apply_clutter_and_network_loss=self.apply_clutter_and_network_loss)
384+
apply_clutter_network_loss_and_50_percent=self.apply_clutter_network_loss_and_50_percent)
385385

386386
pool = mpool.Pool()
387387
max_interf = pool.map(interfCalculator,
@@ -392,7 +392,8 @@ def CheckInterference(self, sas_uut_active_grants, margin_db,
392392
channel=None, num_iter=None,
393393
do_abs_check_single_uut=False,
394394
extensive_print=True,
395-
output_data=None):
395+
output_data=None,
396+
apply_clutter_network_loss_and_50_percent=False):
396397
"""Checks interference of keep list of SAS UUT vs test harness.
397398
398399
This compares the aggregated interference (within some margin) generated by:
@@ -427,6 +428,7 @@ def CheckInterference(self, sas_uut_active_grants, margin_db,
427428
interference results (|DpaInterferenceResult|) for each protected point
428429
and channel. Indexing is [chan_idx, point_idx], unless channel is unique,
429430
in which case indexing is [point_idx].
431+
apply_clutter_network_loss_and_50_percent: if true, add signal and clutter loss and use median
430432
431433
Returns:
432434
True if all SAS UUT aggregated interference are within margin, False otherwise
@@ -441,7 +443,7 @@ def CheckInterference(self, sas_uut_active_grants, margin_db,
441443
for k, chan in enumerate(self._channels):
442444
if not self.CheckInterference(sas_uut_active_grants, margin_db, chan, num_iter,
443445
do_abs_check_single_uut, extensive_print,
444-
output_data[k]):
446+
output_data[k], apply_clutter_network_loss_and_50_percent):
445447
test_passed = False
446448
return test_passed
447449

@@ -463,13 +465,17 @@ def CheckInterference(self, sas_uut_active_grants, margin_db,
463465
margin_db = float(margin_db[idx1+1:idx2].strip())
464466

465467
# Find the keep list component of TH: SAS UUT and peer SASes.
466-
keep_list = self.GetKeepList(channel)
467-
keep_list_th_other_sas = [
468-
grant for grant in self._grants
469-
if (not grant.is_managed_grant and grant in keep_list)]
470-
keep_list_th_managing_sas = [
471-
grant for grant in self._grants
472-
if (grant.is_managed_grant and grant in keep_list)]
468+
if apply_clutter_network_loss_and_50_percent:
469+
keep_list_th_other_sas = []
470+
keep_list_th_managing_sas = []
471+
else:
472+
keep_list = self.GetKeepList(channel)
473+
keep_list_th_other_sas = [
474+
grant for grant in self._grants
475+
if (not grant.is_managed_grant and grant in keep_list)]
476+
keep_list_th_managing_sas = [
477+
grant for grant in self._grants
478+
if (grant.is_managed_grant and grant in keep_list)]
473479

474480
# Makes sure we have a list of SAS UUT active grants
475481
sas_uut_active_grants = list(sas_uut_active_grants)
@@ -515,7 +521,7 @@ def CheckInterference(self, sas_uut_active_grants, margin_db,
515521
num_iter=num_iter,
516522
azimuth_range=self.azimuth_range,
517523
neighbor_distances=self.neighbor_distances,
518-
apply_clutter_and_network_loss=self.apply_clutter_and_network_loss,
524+
apply_clutter_network_loss_and_50_percent=self.apply_clutter_network_loss_and_50_percent,
519525
threshold=hard_threshold
520526
)
521527
pool = mpool.Pool()
@@ -697,7 +703,7 @@ def _CalcTestPointInterfDiff(point,
697703
num_iter,
698704
azimuth_range,
699705
neighbor_distances,
700-
apply_clutter_and_network_loss,
706+
apply_clutter_network_loss_and_50_percent,
701707
threshold=None):
702708
"""Calculate difference of aggregate interference between reference and SAS UUT.
703709
@@ -733,7 +739,7 @@ def _CalcTestPointInterfDiff(point,
733739
or
734740
[cata_indoor_dist, cata_indoor_6m_dist, cata_outdoor_dist,
735741
cata_outdoor_6m_dist, catb_dist, catb_6m_dist]
736-
apply_clutter_and_network_loss: if true, add signal and clutter loss
742+
apply_clutter_network_loss_and_50_percent: if true, add signal and clutter loss and use median
737743
threshold: If set, do an absolute threshold check of SAS UUT interference against
738744
threshold. Otherwise compare against the reference model aggregated interference.
739745
@@ -758,7 +764,7 @@ def _CalcTestPointInterfDiff(point,
758764
min_azimuth=azimuth_range[0],
759765
max_azimuth=azimuth_range[1],
760766
neighbor_distances=neighbor_distances,
761-
apply_clutter_and_network_loss=apply_clutter_and_network_loss)
767+
apply_clutter_network_loss_and_50_percent=apply_clutter_network_loss_and_50_percent)
762768
if threshold is not None:
763769
max_diff = np.max(uut_interferences - threshold)
764770
logging.debug('%s UUT interf @ %s Thresh %sdBm Diff %sdB: %s',
@@ -784,7 +790,7 @@ def _CalcTestPointInterfDiff(point,
784790
min_azimuth=azimuth_range[0],
785791
max_azimuth=azimuth_range[1],
786792
neighbor_distances=neighbor_distances,
787-
apply_clutter_and_network_loss=apply_clutter_and_network_loss)
793+
apply_clutter_network_loss_and_50_percent=apply_clutter_network_loss_and_50_percent)
788794

789795
max_diff = np.max(uut_interferences - th_interferences)
790796
logging.debug(
@@ -808,7 +814,7 @@ def _CalcTestPointInterfDiff(point,
808814

809815

810816
def BuildDpa(dpa_name, protection_points_method=None, portal_dpa_filename=None,
811-
use_updated_neighborhoods=False, apply_clutter_and_network_loss=False):
817+
use_updated_neighborhoods=False, apply_clutter_network_loss_and_50_percent=False):
812818
"""Builds a DPA parameterized correctly.
813819
814820
The DPA special parameters are obtained from the DPA database.
@@ -840,8 +846,7 @@ def BuildDpa(dpa_name, protection_points_method=None, portal_dpa_filename=None,
840846
+ other 'my_method (p1, p2, ..pk)': The 'my_method` will be checked against registered
841847
methods in which case it will be used, and passing to it the parameters p1, p2,...
842848
use_updated_neighborhoods: If true, use the updated set of 6 neighborhoods
843-
apply_clutter_and_network_loss: Use updatd DPA pathloss which includes
844-
clutter and network loss.
849+
apply_clutter_network_loss_and_50_percent: if true, add signal and clutter loss and use median
845850
846851
Returns:
847852
A Dpa object.
@@ -892,4 +897,4 @@ def BuildDpa(dpa_name, protection_points_method=None, portal_dpa_filename=None,
892897
freq_ranges_mhz=freq_ranges_mhz,
893898
neighbor_distances=neighbor_distances,
894899
monitor_type=monitor_type,
895-
apply_clutter_and_network_loss=apply_clutter_and_network_loss)
900+
apply_clutter_network_loss_and_50_percent=apply_clutter_network_loss_and_50_percent)

src/harness/reference_models/dpa/dpa_mgr_test.py

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,81 @@ def test_computeMoveListAndCheckInterf(self):
143143
extensive_print=True)
144144
self.assertEqual(result, False)
145145

146+
def test_cbsdInsideDpaInMoveList_Rel1Ext(self):
147+
dpa = dpa_mgr.BuildDpa('Alameda',
148+
protection_points_method='default(10,2,0,0)',
149+
use_updated_neighborhoods=True,
150+
apply_clutter_network_loss_and_50_percent=True)
151+
dpa.ResetFreqRange([(3540, 3650)])
152+
alameda_geom = zones.GetCoastalDpaZones()['Alameda'].geometry
153+
# Assign grants inside the DPA and inband + OOB in mix of CatA and CatB
154+
dpa.ResetFreqRange([(3550, 3650)])
155+
np.random.seed(1234)
156+
cbsds_a = entities.GenerateCbsdsInPolygon(
157+
3, entities.CBSD_TEMPLATE_CAT_A_OUTDOOR, alameda_geom)
158+
cbsds_b = entities.GenerateCbsdsInPolygon(
159+
2, entities.CBSD_TEMPLATE_CAT_B, alameda_geom)
160+
cbsds_a[1] = cbsds_a[1]._replace(eirp_dbm_mhz=-100)
161+
cbsds_b[1] = cbsds_b[1]._replace(eirp_dbm_mhz=-100)
162+
grants = []
163+
grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_a[0:2], 3550, 3560))
164+
grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_a[2:3], 3660, 3670))
165+
grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_b[0:1], 3550, 3570))
166+
grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_b[1:2], 3630, 3670))
167+
dpa.SetGrantsFromList(grants)
168+
169+
dpa.ComputeMoveLists()
170+
171+
self.assertSetEqual(dpa.GetMoveList((3550, 3560)),
172+
{grants[0], grants[1], grants[3]})
173+
self.assertSetEqual(dpa.GetMoveList((3640, 3650)),
174+
{grants[4]})
175+
176+
def test_computeMoveListAndCheckInterf_Rel1Ext(self):
177+
protection_points = [ProtectionPoint(latitude=36.9400, longitude=-75.9989),
178+
ProtectionPoint(latitude=37.7579, longitude=-75.4105),
179+
ProtectionPoint(latitude=36.1044, longitude=-73.3147),
180+
ProtectionPoint(latitude=36.1211, longitude=-75.5939)]
181+
regs = [json_load(os.path.join(TEST_DIR, 'RegistrationRequest_%d.json' % k))
182+
for k in range(1, 7)]
183+
grants = [json_load(os.path.join(TEST_DIR, 'GrantRequest_%d.json' % k))
184+
for k in range(1, 7)]
185+
grants_uut = data.getGrantsFromRequests(regs[:4], grants[:4])
186+
grants_th = data.getGrantsFromRequests(regs[4:], grants[4:])
187+
channel = (3600, 3610)
188+
dpa = dpa_mgr.Dpa(protection_points,
189+
geometry=sgeo.Polygon([(pt.longitude, pt.latitude)
190+
for pt in protection_points]),
191+
name='test(East1)',
192+
threshold=-144,
193+
beamwidth=3,
194+
radar_height=50,
195+
neighbor_distances=(150, 190, 0, 25),
196+
freq_ranges_mhz=[channel],
197+
apply_clutter_network_loss_and_50_percent=True)
198+
dpa.SetGrantsFromList(grants_uut + grants_th)
199+
expected_grants = set(grants_uut[0:3])
200+
# Testing move list
201+
dpa.ComputeMoveLists()
202+
self.assertSetEqual(dpa.GetMoveList(channel),
203+
expected_grants)
204+
# Testing interference calculation
205+
interf = dpa.CalcKeepListInterference(channel)
206+
self.assertLess(max(interf), -144)
207+
# Testing check
208+
result = dpa.CheckInterference([grants_uut[3], grants_th[1]],
209+
margin_db=0.01,
210+
do_abs_check_single_uut=True,
211+
extensive_print=False,
212+
apply_clutter_network_loss_and_50_percent=True)
213+
self.assertEqual(result, True)
214+
result = dpa.CheckInterference([grants_uut[2], grants_th[1]],
215+
margin_db=0.01,
216+
do_abs_check_single_uut=True,
217+
extensive_print=True,
218+
apply_clutter_network_loss_and_50_percent=True)
219+
self.assertEqual(result, False)
220+
146221

147222
if __name__ == '__main__':
148223
unittest.main()

0 commit comments

Comments
 (0)