def calculateAggregateInterferenceForFssCochannel(fss_record, grants):
    """Calculates per-channel aggregate interference for FSS co-channel.

  Args:
    fss_record: A FSS record (dict).
    grants: An iterable of CBSD grants of type |data.CbsdGrantInfo|.

  Returns:
    Aggregate interference to FSS co-channel in the nested dictionary format:
      {latitude : {longitude: [aggr_interf1(mW), ..., aggr_interfK(mW)]}}
    The list contains the value per protected channel.
  """
    # Get the FSS infos
    fss_point, fss_info, fss_freq_range = data.getFssInfo(fss_record)
    fss_low_freq, fss_high_freq = fss_freq_range

    # Get channels for co-channel CBSDs
    if fss_high_freq < interf.CBRS_HIGH_FREQ_HZ:
        raise ValueError(
            'FSS high frequency should not be less than CBRS high frequency')

    protection_channels = interf.getProtectedChannels(fss_low_freq,
                                                      interf.CBRS_HIGH_FREQ_HZ)

    logging.info(
        'Computing aggregateInterferenceForPoint for FSS Coch: channels (%s), '
        'point (%s), grants (%s), fss_info (%s)', protection_channels,
        fss_point, grants, fss_info)

    interferences = aggregateInterferenceForPoint(
        fss_point, protection_channels, grants, fss_info, None,
        data.ProtectedEntityType.FSS_CO_CHANNEL, None)
    return InterferenceDict(interferences)
    def test_computeFssBlocking(self):
        # Mock things propag and FSS antenna. -70dBm at 30km
        wf_itm.CalcItmPropagationLoss = testutils.FakePropagationPredictor(
            dist_type='REAL', factor=1.0, offset=70 - 30.0)
        antenna.GetFssAntennaGains = mock.create_autospec(
            antenna.GetFssAntennaGains, return_value=2.8)
        # Create FSS and a CBSD at 30km
        fss_point, fss_info, _ = data.getFssInfo(TestAggInterf.fss_record)
        fss_freq_range = (3650e6, 3750e6)
        cbsd_lat, cbsd_lon, _ = vincenty.GeodesicPoint(fss_point[1],
                                                       fss_point[0], 30, 0)
        cbsd = entities.CBSD_TEMPLATE_CAT_A_OUTDOOR._replace(
            latitude=cbsd_lat, longitude=cbsd_lon)
        grant = entities.ConvertToCbsdGrantInfo([cbsd], 3640, 3680)[0]
        constraint = data.ProtectionConstraint(
            fss_point[1], fss_point[0], 3550e6, fss_freq_range[0],
            data.ProtectedEntityType.FSS_BLOCKING)

        itf = interf.computeInterferenceFssBlocking(grant, constraint,
                                                    fss_info, grant.max_eirp)
        self.assertAlmostEqual(
            itf,
            20 +  # EIRP/MHZ
            10 +  # 10MHz effective bandwidth
            -70  # pathloss
            + 2.8  # FSS antenna gain
            - 3.1634,  # FSS mask loss for adjacent 10MHz
            4)
Example #3
0
def performIapForFssBlocking(fss_record, sas_uut_fad_object,
                             sas_th_fad_objects):
    """Computes post IAP interference margin for FSS Blocking incumbent.

  FSS protection is provided over blocking pass band.

  Args:
    fss_record: A FSS record (dict).
    sas_uut_fad_object: FAD object from SAS UUT
    sas_th_fad_object: a list of FAD objects from SAS Test Harness
  Returns:
    ap_iap_ref: The post-IAP allowed interference, as a dict formatted as:
        {latitude : {longitude : [interference(mW/IAPBW), .., interference(mW/IAPBW)]}}
      where the list holds all values per channel of that protection point.
  """
    # Actual protection threshold used for IAP - calculated by applying
    # a pre-defined Pre-IAP headroom (Mg) at each protection threshold(Q)
    fss_blocking_iap_threshold = interf.dbToLinear(
        THRESH_FSS_BLOCKING_DBM_PER_RBW - MARGIN_FSS_BLOCKING_DB)

    grants = data.getGrantObjectsFromFAD(sas_uut_fad_object,
                                         sas_th_fad_objects)

    # Get number of SAS
    num_sas = len(sas_th_fad_objects) + 1

    # Get FSS T&C Flag value
    fss_ttc_flag = fss_record['ttc']

    # Get the FSS infos
    fss_point, fss_info, fss_freq_range = data.getFssInfo(fss_record)
    fss_low_freq, fss_high_freq = fss_freq_range

    # FSS Passband is between 3700 and 4200 and TT&C flag is set to FALSE
    if (fss_low_freq >= interf.FSS_TTC_LOW_FREQ_HZ
            and fss_high_freq <= interf.FSS_TTC_HIGH_FREQ_HZ
            and fss_ttc_flag is False):
        raise Exception(
            "IAP for FSS not applied for FSS Pass band 3700 to 4200 "
            "and TT&C flag set to false, please check the inputs.")

    logging.debug('$$$$ Calling FSS blocking Protection $$$$')
    # 5MHz channelization is not required for Blocking protection
    protection_channels = [(interf.CBRS_LOW_FREQ_HZ, fss_low_freq)]

    iap_interfs = iapPointConstraint(fss_point, protection_channels,
                                     interf.CBRS_LOW_FREQ_HZ, fss_low_freq,
                                     grants, fss_info, None, None,
                                     fss_blocking_iap_threshold,
                                     data.ProtectedEntityType.FSS_BLOCKING)

    ap_iap_ref = calculatePostIapAggregateInterference(
        interf.dbToLinear(THRESH_FSS_BLOCKING_DBM_PER_RBW), num_sas,
        iap_interfs)
    return ap_iap_ref
Example #4
0
def performIapForFssCochannel(fss_record, sas_uut_fad_object,
                              sas_th_fad_objects):
    """Computes post IAP interference margin for FSS Co-channel incumbent.

  FSS protection is provided over co-channel pass band.

  Args:
    fss_record: A FSS record (dict).
    sas_uut_fad_object: A FAD object from SAS UUT
    sas_th_fad_object: A list of FAD objects from SAS Test Harness
  Returns:
    ap_iap_ref: The post-IAP allowed interference, as a dict formatted as:
        {latitude : {longitude : [interference(mW/IAPBW), .., interference(mW/IAPBW)]}}
      where the list holds all values per channel of that protection point.
  """
    fss_cochannel_thresh_q = THRESH_FSS_CO_CHANNEL_DBM_PER_IAPBW

    # Actual protection threshold used for IAP - calculated by applying
    # a pre-defined Pre-IAP headroom (Mg) at each protection threshold(Q)
    fss_cochannel_iap_threshold = interf.dbToLinear(fss_cochannel_thresh_q -
                                                    MARGIN_FSS_CO_CHANNEL_DB)

    grants = data.getGrantObjectsFromFAD(sas_uut_fad_object,
                                         sas_th_fad_objects)

    # Get number of SAS
    num_sas = len(sas_th_fad_objects) + 1

    # Get the FSS infos
    fss_point, fss_info, fss_freq_range = data.getFssInfo(fss_record)
    fss_low_freq, fss_high_freq = fss_freq_range

    # Get channels for co-channel CBSDs
    if fss_high_freq < interf.CBRS_HIGH_FREQ_HZ:
        raise ValueError(
            'FSS high frequency should not be less than CBRS high frequency(Hz)'
        )
    protection_channels = interf.getProtectedChannels(fss_low_freq,
                                                      interf.CBRS_HIGH_FREQ_HZ)

    # FSS Co-channel algorithm
    logging.debug('$$$$ Calling FSS co-channel Protection $$$$')
    iap_interfs = iapPointConstraint(fss_point, protection_channels,
                                     fss_low_freq, interf.CBRS_HIGH_FREQ_HZ,
                                     grants, fss_info, None, None,
                                     fss_cochannel_iap_threshold,
                                     data.ProtectedEntityType.FSS_CO_CHANNEL)

    ap_iap_ref = calculatePostIapAggregateInterference(
        interf.dbToLinear(fss_cochannel_thresh_q), num_sas, iap_interfs)

    return ap_iap_ref
Example #5
0
def fssPurgeReferenceModel(sas_uut_fad, sas_test_harness_fads, fss_records):
    """Performs FSS purge model as described in R2-SGN-29.

  The FSS purge list model removes grants from the CBSD records of the FAD (Full Activity
  Dump) objects for both SAS UUT and SAS Test Harness.

  Args:
    sas_uut_fad: A |FullActivityDump| object containing the FAD records of SAS UUT.
    sas_test_harness_fads: A list of |FullActivityDump| objects containing the FAD records
      from SAS test harnesses.
    fss_records: A list of FSS record dictionary.
  """
    # Get the CBSD list from the FAD Object.
    cbsds = sas_uut_fad.getCbsdRecords()
    for fad in sas_test_harness_fads:
        cbsds.extend(fad.getCbsdRecords())

    grants_to_purged_for_all_fss = []
    ids_to_purge = set()

    for fss_record in fss_records:
        fss_point, fss_info, freq_range = data.getFssInfo(fss_record)
        _, fss_high_freq = freq_range
        # If the FSS is of TT&C type and the FSS high frequency is above 3700 MHz then perform the FSS purge model for the FSS.
        if fss_record['ttc'] and fss_high_freq > interf.FSS_TTC_LOW_FREQ_HZ:
            logging.info('Running purge list for FSS record (%s).', fss_record)
            neighboring_cbsds_with_grants = pre_iap_util.getFssNeighboringCbsdsWithGrants(
                cbsds, fss_point, 40)
            if neighboring_cbsds_with_grants:
                grants_to_purge_for_fss = generatePurgeListForFssPoint(
                    neighboring_cbsds_with_grants, fss_point, fss_info)
                # Grants to be purged is updated checking against the cbsd id and grant id
                # to eliminate the duplicate entries
                grants_to_purged_for_all_fss.extend(
                    purge_data for purge_data in grants_to_purge_for_fss
                    if (purge_data.grant['id'],
                        purge_data.cbsd['id']) not in ids_to_purge)
                ids_to_purge.update([
                    (purge_data.grant['id'], purge_data.cbsd['id'])
                    for purge_data in grants_to_purge_for_fss
                ])

    # Removing grant requests that are in the grants to purge list from the CBSDs.
    logging.info(
        'As a result of all FSS purge list calculations, purging the following: %s',
        grants_to_purged_for_all_fss)
    for purge_data in grants_to_purged_for_all_fss:
        purge_data.cbsd['grants'].remove(purge_data.grant)
def calculateAggregateInterferenceForFssBlocking(fss_record, grants):
    """Calculates per-channel aggregate interference for FSS blocking.

  Args:
    fss_record: A FSS record (dict).
    grants: An iterable of CBSD grants of type |data.CbsdGrantInfo|.

  Returns:
    Aggregate interference to FSS blocking in the nested dictionary format.
      {latitude : {longitude: [aggr_interf1(mW), ..., aggr_interfK(mW)]}}
    The list contains the value per protected channel.
  """
    fss_ttc_flag = fss_record['ttc']

    # Get the FSS infos
    fss_point, fss_info, fss_freq_range = data.getFssInfo(fss_record)
    fss_low_freq, fss_high_freq = fss_freq_range

    # FSS Passband is between 3700 and 4200 and TT&C flag is set to FALSE
    if (fss_low_freq >= interf.FSS_TTC_LOW_FREQ_HZ
            and fss_high_freq <= interf.FSS_TTC_HIGH_FREQ_HZ
            and fss_ttc_flag is False):
        raise Exception(
            "AggInterf for FSS not applied for FSS Pass band 3700 to 4200 "
            "and TT&C flag set to false, please check the inputs.")

    # 5MHz channelization is not required for Blocking protection
    # FSS TT&C Blocking Algorithm
    protection_channels = [(interf.CBRS_LOW_FREQ_HZ, fss_low_freq)]

    logging.info(
        'Computing aggregateInterferenceForPoint for FSS Blocking: channels (%s), '
        'point (%s), grants (%s), fss_info (%s)', protection_channels,
        fss_point, grants, fss_info)

    interferences = aggregateInterferenceForPoint(
        fss_point, protection_channels, grants, fss_info, None,
        data.ProtectedEntityType.FSS_BLOCKING, None)

    return InterferenceDict(interferences)
def zonePurgeReferenceModel(sas_uut_fad, sas_test_harness_fads,
                            ppa_records, pal_records, gwpz_records, fss_records):
  """Executes the Zone PPA, GWPZ and FSS+GWBL purge reference model.

  CBSDs from the FAD objects of SAS UUT and SAS test harnesses that lie within the
  PPA area or GWPZ area or within 150 KMs from the FSS site will have their grant
  purged if the grant overlaps with frequency range of the protected entities.

  A frequency range of 3650-3700 MHz is considered for all the FSSs.
  It is assumed that the FSS records passed as input have a GWBL station within
  150 KMs and thus the FSS exclusion zone is activated.

  Grants are purged directly from the input FADs.

  Args:
    sas_uut_fad: A |FullActivityDump| object containing the FAD records of SAS UUT.
    sas_test_harness_fads: A list of |FullActivityDump| objects containing the FAD records
      from SAS test harnesses.
    ppa_records: List of PPA record dictionaries.
    pal_records: List of PAL record dictionaries.
    gwpz_records: List of GWPZ record dictionaries.
    fss_records: List of FSS record dictionaries. All the FSSs in this list should have
      at least one GWBL within 150KMs.
  """
  logging.info('Performing zone purge with PPA (%s), PAL (%s), GWPZ (%s), and FSS with GWBL (%s)',
               ppa_records, pal_records, gwpz_records, fss_records)

  # Get the list of all CBSDs from the FAD objects of UUT and test harness
  cbsds = sas_uut_fad.getCbsdRecords()
  for fad in sas_test_harness_fads:
    cbsds.extend(fad.getCbsdRecords())

  # Perform purge for each PPA
  for ppa_record in ppa_records:
    logging.info('Purging in PPA (%s)', ppa_record)
    # Get all the CBSDs within the PPA polygon
    cbsds_within_ppa = pre_iap_util.getCbsdsWithinPolygon(cbsds, ppa_record['zone'])
    logging.info('CBSDs within PPA: %s', cbsds_within_ppa)
    if cbsds_within_ppa:
      # Get all the cbsds that are not part of the PPA cluster list
      cbsds_not_part_of_ppa_cluster = data.getCbsdsNotPartOfPpaCluster(
                                                   cbsds_within_ppa, ppa_record)
      logging.info('CBSDs which are not part of the PPA cluster list: %s',
                   cbsds_not_part_of_ppa_cluster)
      if cbsds_not_part_of_ppa_cluster:
        # Get the frequency of the PPA
        ppa_frequency_range = pre_iap_util.getPpaFrequencyRange(ppa_record, pal_records)
        logging.info('PPA frequency range: %s', ppa_frequency_range)
        # Purge the grants of CBSDs that are overlapping PPA frequency
        pre_iap_util.purgeOverlappingGrants(cbsds_not_part_of_ppa_cluster,
                                            ppa_frequency_range)

  # Perform purge for each GWPZ
  for gwpz_record in gwpz_records:
    logging.info('Purging in GWPZ (%s)', gwpz_record)
    # Get the CBSDs that are witin the GWPZ polygon
    cbsds_within_gwpz = pre_iap_util.getCbsdsWithinPolygon(cbsds, gwpz_record['zone'])
    logging.info('CBSDs within GWPZ: %s', cbsds_within_gwpz)
    if cbsds_within_gwpz:
      # Purge the overlapping grants
      pre_iap_util.purgeOverlappingGrants(cbsds_within_gwpz,
                                          gwpz_record['record']['deploymentParam'][0]
                                          ['operationParam']['operationFrequencyRange'])

  # Perform GWBL+FSS purge for each FSS
  for fss_record in fss_records:
    logging.info('Purging near FSS (%s)', fss_record)
    fss_point, fss_info, _ = data.getFssInfo(fss_record)
    # Get the CBSDs that are present within 150kms of FSS entity
    cbsds_neighboring_fss = pre_iap_util.getFssNeighboringCbsdsWithGrants(
        cbsds, fss_point, pre_iap_util.FSS_GWBL_PROTECTION_DISTANCE_KM)
    logging.info('CBSDs near the FSS: %s', cbsds_neighboring_fss)
    if cbsds_neighboring_fss:
      # Purge the overlapping grants
      pre_iap_util.purgeOverlappingGrants(cbsds_neighboring_fss,
                                          pre_iap_util.FSS_GWBL_PROTECTION_FREQ_RANGE)