def test_cbsdInsideDpaInMoveList(self): dpa = dpa_mgr.BuildDpa('Alameda', protection_points_method='default(10,2,0,0)') dpa.ResetFreqRange([(3540, 3650)]) alameda_geom = zones.GetCoastalDpaZones()['Alameda'].geometry # Assign grants inside the DPA and inband + OOB in mix of CatA and CatB np.random.seed(1234) cbsds_a = entities.GenerateCbsdsInPolygon( 3, entities.CBSD_TEMPLATE_CAT_A_OUTDOOR, alameda_geom) cbsds_b = entities.GenerateCbsdsInPolygon( 2, entities.CBSD_TEMPLATE_CAT_B, alameda_geom) cbsds_a[1] = cbsds_a[1]._replace(eirp_dbm_mhz=-100) cbsds_b[1] = cbsds_b[1]._replace(eirp_dbm_mhz=-100) grants = [] grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_a[0:2], 3550, 3560)) grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_a[2:3], 3660, 3670)) grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_b[0:1], 3550, 3570)) grants.extend(entities.ConvertToCbsdGrantInfo(cbsds_b[1:2], 3630, 3670)) dpa.SetGrantsFromList(grants) dpa.ComputeMoveLists() self.assertSetEqual(dpa.GetMoveList((3550, 3560)), set([grants[0], grants[1], grants[3]])) self.assertSetEqual(dpa.GetMoveList((3640, 3650)), set([grants[4]])) self.assertSetEqual(dpa.GetMoveList((3540, 3550)), set(grants))
def test_read_coastal_dpa(self): z = zones.GetCoastalDpaZones() for name, zone in z.items(): self.assertTrue(zone.geometry.is_valid) self.assertAlmostEqual(z['East5'].geometry.area, 6, 1) self.assertEqual(z['East5'].freqRangeMHz, [(3550, 3650)]) self.assertEqual(z['East5'].protectionCritDbmPer10MHz, -144) self.assertEqual(z['East5'].refHeightMeters, 50) self.assertEqual(z['East5'].minAzimuthDeg, 0) self.assertEqual(z['East5'].maxAzimuthDeg, 360) self.assertEqual(z['East5'].catBNeighborhoodDistanceKm, 368)
def FindOrBuildDpa(dpas, options, grants): """Find or build DPA for simulation purpose. If several DPA, select the one with most grants around (but DPA simulation options always override the logic). """ if options.dpa: dpa_kml_file = options.dpa_kml or None dpa = dpa_mgr.BuildDpa(options.dpa, None, portal_dpa_filename=dpa_kml_file) else: if not dpas: raise ValueError( 'Config file not defining a DPA and no --dpa option used.') if len(dpas) == 1: dpa = dpas[0] else: # Roughly find the DPA wth most CBSD within 200km all_cbsds = sgeo.MultiPoint([(g.longitude, g.latitude) for g in grants]) num_cbsds_inside = [ len(dpa.geometry.buffer(2.5).intersection(all_cbsds)) for dpa in dpas ] dpa = dpas[np.argmax(num_cbsds_inside)] try: dpa.margin_db except AttributeError: dpa.margin_db = 'linear(1.5)' try: dpa.geometry except AttributeError: try: dpa_geometry = zones.GetCoastalDpaZones()[dpa.name] except KeyError: dpa_geometry = zones.GetPortalDpaZones( kml_path=dpa_kml_file)[dpa.name] dpa.geometry = dpa_geometry.geometry if options.dpa_builder: dpa.protected_points = dpa_builder.DpaProtectionPoints( dpa.name, dpa.geometry, options.dpa_builder) if options.margin_db: # Override `movelistMargin` directive. try: dpa.margin_db = float(options.margin_db) except ValueError: dpa.margin_db = options.margin_db return dpa
def _McpConfigRead(config): """Extracts DPA and grants from MCP config JSON. Note: returns all grants involved in the test irrespective of iteration process. Args: config: A JSON dictionary. Returns: A tuple (dpas, grants) where: dpas: a list of objects of type |dpa_mgr.Dpa|. grants: a list of |data.CbsdGrantInfo|. """ if ('iterationData' not in config or 'dpas' not in config or 'initialCbsdRequestsWithDomainProxies' not in config): raise ValueError( 'Unsupported config file. Please use a MCP1 config file') # Build the DPAs. dpas = [] for dpa_id, dpa_data in config['dpas'].items(): dpa = dpa_mgr.BuildDpa( dpa_id, protection_points_method=dpa_data['points_builder']) # - add extra properties for the geometry and margin. dpa.margin_db = dpa_data['movelistMargin'] try: dpa_zone = zones.GetCoastalDpaZones()[dpa_id] except KeyError: dpa_zone = zones.GetPortalDpaZones(kml_path=dpa_kml_file)[dpa_id] dpa.geometry = dpa_zone.geometry # - read also the activation list and freq range. dpa.activation = None for iter_data in config['iterationData']: for activation in iter_data['dpaActivationList']: if activation['dpaId'] == dpa_id: dpa.activation = activation['frequencyRange'] break dpas.append(dpa) # Read the CBSDs, assuming all granted, into list of |CbsdGrantInfo|. # - initial stuff into SAS UUT grants = [] for records in config['initialCbsdRequestsWithDomainProxies']: grant_requests = records['grantRequests'] reg_requests = MergeConditionalData( records['registrationRequests'], records['conditionalRegistrationData']) grants.extend( data.getGrantsFromRequests(reg_requests, grant_requests, is_managing_sas=True)) for record in config['initialCbsdRecords']: grant_request = [record['grantRequest']] reg_request = MergeConditionalData( [record['registrationRequest']], [record['conditionalRegistrationData']]) grants.append( data.getGrantsFromRequests(reg_requests, grant_requests, is_managing_sas=True)) # - then iterations for TH and UUT for iter_data in config['iterationData']: for th_data in iter_data['sasTestHarnessData']: th_grants = data.getAllGrantInfoFromCbsdDataDump( th_data['cbsdRecords'], is_managing_sas=False) grants.extend([g for g in th_grants]) for records in iter_data['cbsdRequestsWithDomainProxies']: grant_requests = records['grantRequests'] reg_requests = MergeConditionalData( records['registrationRequests'], records['conditionalRegistrationData']) uut_grants = data.getGrantsFromRequests(reg_requests, grant_requests, is_managing_sas=True) grants.extend([g for g in uut_grants]) for record in iter_data['cbsdRecords']: grant_request = [record['grantRequest']] reg_request = MergeConditionalData( [record['registrationRequest']], [record['conditionalRegistrationData']]) uut_grant = data.getGrantsFromRequests(reg_requests, grant_requests, is_managing_sas=True) grants.append(uut_grant) return grants, dpas
def _IprConfigRead(config): """Extracts DPA and grants from IPR config JSON. Note: All IPT suppprted except IPR1. Args: config: A JSON dictionary. Returns: A tuple (dpas, grants) where: dpas: a list of objects of type |dpa_mgr.Dpa|. grants: a list of |data.CbsdGrantInfo|. """ dpa_cfgs = None if 'portalDpa' in config: dpa_cfgs = [config['portalDpa']] elif 'escDpa' in config: dpa_cfgs = [config['escDpa']] if dpa_cfgs is None: if 'dpas' in config: dpa_cfgs = config['dpas'] elif 'dpa' in config: dpa_cfgs = [config['dpa']] if dpa_cfgs is None or ('domainProxies' not in config and 'registrationRequest' not in config): raise ValueError( 'Unsupported config file. Please use a IPR config file') # Build the DPAs dpas = [] for dpa_cfg in dpa_cfgs: dpa_id = dpa_cfg['dpaId'] try: dpa_kml_file = config['dpaDatabaseConfig']['filePath'] except KeyError: dpa_kml_file = None try: points_builder = dpa_cfg['points_builder'] except KeyError: points_builder = None try: dpa = dpa_mgr.BuildDpa(dpa_id, protection_points_method=points_builder, portal_dpa_filename=dpa_kml_file) except IOError: print('Portal KML File not found: %s ' % dpa_kml_file) raise try: freq_range_mhz = (dpa_cfg['frequencyRange']['lowFrequency'] / 1.e6, dpa_cfg['frequencyRange']['highFrequency'] / 1.e6) dpa.ResetFreqRange([freq_range_mhz]) except KeyError: pass # - add extra properties for the geometry and margin try: dpa.margin_db = dpa_cfg['movelistMargin'] except KeyError: dpa_margin_db = 'linear(1.5)' try: dpa_zone = zones.GetCoastalDpaZones()[dpa_id] except KeyError: dpa_zone = zones.GetPortalDpaZones(kml_path=dpa_kml_file)[dpa_id] dpa.geometry = dpa_zone.geometry dpas.append(dpa) # Read the CBSDs, assuming all granted, into list of |CbsdGrantInfo|. grants = [] if 'domainProxies' in config: # - first the SAS UUT for domain_proxy_config in config['domainProxies']: grant_requests = domain_proxy_config['grantRequests'] reg_requests = MergeConditionalData( domain_proxy_config['registrationRequests'], domain_proxy_config['conditionalRegistrationData']) grants.extend( data.getGrantsFromRequests(reg_requests, grant_requests, is_managing_sas=True)) # - now the peer SASes. if 'sasTestHarnessConfigs' in config: for th_config in config['sasTestHarnessConfigs']: dump_records = th_config['fullActivityDumpRecords'][0] grants.extend( data.getAllGrantInfoFromCbsdDataDump( dump_records, is_managing_sas=False)) elif 'registrationRequest' in config: grants.extend( data.getGrantsFromRequests( MergeConditionalData([config['registrationRequest']], [config['conditionalRegistrationData']]), [config['grantRequest']], is_managing_sas=True)) return grants, dpas
def BuildDpa(dpa_name, protection_points_method=None, portal_dpa_filename=None): """Builds a DPA parameterized correctly. The DPA special parameters are obtained from the DPA database. The DPA protection points are generated either from a file, or using a provided default method. Args: dpa_name: The DPA official name. protection_points_method: Three methods are supported for getting the protection points: + a path pointing to the file holding the protected points location defined as a geojson MultiPoint or Point geometry. The path can be either absolute or relative to the running script (normally the `harness/` directory). + 'default <parameters>': A simple default method. Parameters is a tuple defining the number of points to use for different part of the DPA: num_pts_front_border: Number of points in the front border num_pts_back_border: Number of points in the back border num_pts_front_zone: Number of points in the front zone num_pts_back_zone: Number of points in the back zone front_us_border_buffer_km: Buffering of US border for delimiting front/back. min_dist_front_border_pts_km: Minimum distance between front border points (km). min_dist_back_border_pts_km: Minimum distance between back border points (km). min_dist_front_zone_pts_km: Minimum distance between front zone points (km). min_dist_back_zone_pts_km: Minimum distance between back zone points (km). Example of encoding: 'default (200,50,20,5)' Note the default values are (25, 10, 10, 5, 40, 0.2, 1, 0.5, 3) Only the passed parameters will be redefined. The result are only approximate (actual distance and number of points may differ). + other 'my_method (p1, p2, ..pk)': The 'my_method` will be checked against registered methods in which case it will be used, and passing to it the parameters p1, p2,... Returns: A Dpa object. Raises: IOError: if the provided file cannot be found. ValueError: in case of other errors, such as invalid file or parameters. """ try: dpa_zone = zones.GetCoastalDpaZones()[dpa_name] monitor_type = 'esc' except KeyError: try: dpa_zone = zones.GetPortalDpaZones( kml_path=portal_dpa_filename)[dpa_name] monitor_type = 'portal' except KeyError: raise ValueError('DPA %s not found in DPA database' % dpa_name) # Get the DPA protection points protection_points = dpa_builder.DpaProtectionPoints( dpa_name, dpa_zone.geometry, protection_points_method) # Set all DPA operational parameters protection_threshold = dpa_zone.protectionCritDbmPer10MHz radar_height = dpa_zone.refHeightMeters radar_beamwidth = dpa_zone.antennaBeamwidthDeg azimuth_range = (dpa_zone.minAzimuthDeg, dpa_zone.maxAzimuthDeg) freq_ranges_mhz = dpa_zone.freqRangeMHz neighbor_distances = (dpa_zone.catANeighborhoodDistanceKm, dpa_zone.catBNeighborhoodDistanceKm, dpa_zone.catAOOBNeighborhoodDistanceKm, dpa_zone.catBOOBNeighborhoodDistanceKm) return Dpa(protection_points, name=dpa_name, threshold=protection_threshold, radar_height=radar_height, beamwidth=radar_beamwidth, azimuth_range=azimuth_range, freq_ranges_mhz=freq_ranges_mhz, neighbor_distances=neighbor_distances, monitor_type=monitor_type)
def PrepareSimulation(): # Read the DPA zone print 'Preparing Zones' dpa_zone = zones.GetCoastalDpaZones()[dpa_name] dpa_geometry = dpa_zone.geometry us_border = zones.GetUsBorder() urban_areas = zones.GetUrbanAreas() if do_inside_urban_area else None protection_zone = zones.GetCoastalProtectionZone() # Distribute random CBSD of various types around the FSS. print 'Distributing random CBSDs in DPA neighborhood' # - Find the zone where to distribute the CBSDs typical_lat = dpa_geometry.centroid.y km_per_lon_deg = 111. * np.cos(typical_lat * np.pi / 180) extend_cata_deg = max_dist_cat_a / km_per_lon_deg extend_catb_deg = max_dist_cat_b / km_per_lon_deg zone_cata = dpa_geometry.buffer(extend_cata_deg).intersection(us_border) zone_catb = dpa_geometry.buffer(extend_catb_deg).intersection(us_border) if urban_areas is not None: # simplify the huge urban_areas for quicker inclusion tests urban_areas = urban_areas.intersection(zone_catb) # - Distribute the CBSDs print ' - Cat A indoor' cbsds_cat_a_indoor = entities.GenerateCbsdsInPolygon( num_sites * ratio_cat_a_indoor, entities.CBSD_TEMPLATE_CAT_A_INDOOR, zone_cata, drive.nlcd_driver, urban_areas) print ' - Cat A outdoor' cbsds_cat_a_outdoor = entities.GenerateCbsdsInPolygon( num_sites * ratio_cat_a_outdoor, entities.CBSD_TEMPLATE_CAT_A_OUTDOOR, zone_cata, drive.nlcd_driver, urban_areas) print ' - Cat B' cbsds_cat_b = entities.GenerateCbsdsInPolygon(num_sites * ratio_cat_b, entities.CBSD_TEMPLATE_CAT_B, zone_catb, drive.nlcd_driver, urban_areas) all_cbsds = cbsds_cat_a_indoor + cbsds_cat_a_outdoor + cbsds_cat_b # - Convert them into proper registration and grant requests reg_requests = [ entities.GetCbsdRegistrationRequest(cbsd) for cbsd in all_cbsds ] grant_requests = [ entities.GetCbsdGrantRequest(cbsd, fmin, fmax) for cbsd in all_cbsds ] # Plot on screen the elements of calculation ax = plt.axes(projection=ccrs.PlateCarree()) margin = 0.1 box = zone_catb.union(dpa_geometry) ax.axis([ box.bounds[0] - margin, box.bounds[2] + margin, box.bounds[1] - margin, box.bounds[3] + margin ]) ax.coastlines() ax.stock_img() ax.plot(*dpa_geometry.exterior.xy, color='r') ax.plot(*zone_cata.exterior.xy, color='b', linestyle='--') ax.plot(*zone_catb.exterior.xy, color='g', linestyle='--') ax.plot(*protection_zone[0].exterior.xy, color='m', linestyle=':') ax.plot(*protection_zone[1].exterior.xy, color='m', linestyle=':') ax.scatter([cbsd.longitude for cbsd in all_cbsds], [cbsd.latitude for cbsd in all_cbsds], color='g', marker='.') ax.set_title('DPA: %s' % dpa_name) plt.show(block=False) return (all_cbsds, reg_requests, grant_requests, protection_zone, (len(cbsds_cat_a_indoor), len(cbsds_cat_a_outdoor), len(cbsds_cat_b)), ax)