def test_getProtectedChannels(self):
     self.assertEqual(interf.getProtectedChannels(3660e6, 3675e6),
                      [(3660e6, 3665e6), (3665e6, 3670e6),
                       (3670e6, 3675e6)])
     self.assertEqual(interf.getProtectedChannels(3662e6, 3671e6),
                      [(3660e6, 3665e6), (3665e6, 3670e6),
                       (3670e6, 3675e6)])
     self.assertEqual(interf.getProtectedChannels(3540e6, 3555e6),
                      [(3550e6, 3555e6)])
     self.assertEqual(interf.getProtectedChannels(3692e6, 3722e6),
                      [(3690e6, 3695e6), (3695e6, 3700e6)])
def calculateAggregateInterferenceForEsc(esc_record, grants):
    """Calculates per-channel aggregate interference for ESC.

  Args:
    esc_record: An ESC record (dict of schema |EscSensorRecord|).
    grants: An iterable of CBSD grants of type |data.CbsdGrantInfo|.

  Returns:
    Aggregate interference to ESC in the nested dictionary format.
      {latitude : {longitude: [aggr_interf1(mW), ..., aggr_interfK(mW)]}}
    The list contains the value per protected channel.
  """
    # Get the ESC infos
    protection_point, esc_antenna_info = data.getEscInfo(esc_record)

    # Get ESC passband 3550-3680 MHz protection channels
    protection_channels = interf.getProtectedChannels(interf.ESC_LOW_FREQ_HZ,
                                                      interf.ESC_HIGH_FREQ_HZ)

    logging.info(
        'Computing aggregateInterferenceForPoint for ESC: channels (%s), '
        'point (%s), grants (%s), antenna_info (%s)', protection_channels,
        protection_point, grants, esc_antenna_info)

    interferences = aggregateInterferenceForPoint(protection_point,
                                                  protection_channels, grants,
                                                  None, esc_antenna_info,
                                                  data.ProtectedEntityType.ESC,
                                                  None)

    return InterferenceDict(interferences)
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)
Beispiel #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
def calculateAggregateInterferenceForGwpz(gwpz_record, grants):
    """Calculates per-channel aggregate interference for GWPZ.

  Args:
    gwpz_record: A GWPZ record dict.
    grants: An iterable of CBSD grants of type |data.CbsdGrantInfo|.

  Returns:
    Aggregate interference to GWPZ in the nested dictionary format.
      {latitude : {longitude: [aggr_interf1(mW), ..., aggr_interfK(mW)]}}
    The list contains the value per protected channel.
  """
    gwpz_region = gwpz_record['landCategory']

    # Get Fine Grid Points for a GWPZ protection area
    protection_points = utils.GridPolygon(
        gwpz_record['zone']['features'][0]['geometry'], GWPZ_GRID_RES_ARCSEC)
    gwpz_freq_range = gwpz_record['record']['deploymentParam'][0]\
                                 ['operationParam']['operationFrequencyRange']
    gwpz_low_freq = gwpz_freq_range['lowFrequency']
    gwpz_high_freq = gwpz_freq_range['highFrequency']

    # Get channels over which area incumbent needs partial/full protection
    protection_channels = interf.getProtectedChannels(gwpz_low_freq,
                                                      gwpz_high_freq)

    # Calculate aggregate interference from each protection constraint with a
    # pool of parallel processes.
    logging.info(
        'Computing aggregateInterferenceForPoint for PPA (%s), channels (%s), '
        'nPoints (%d), grants (%s), region_type (%s)', gwpz_record,
        protection_channels, len(protection_points), grants, gwpz_region)
    logging.debug('  points: %s', protection_points)

    interfCalculator = partial(
        aggregateInterferenceForPoint,
        channels=protection_channels,
        grants=grants,
        fss_info=None,
        esc_antenna_info=None,
        protection_ent_type=data.ProtectedEntityType.GWPZ_AREA,
        region_type=gwpz_region)

    pool = mpool.Pool()
    interferences = pool.map(interfCalculator, protection_points)
    return InterferenceDict(interferences)
Beispiel #6
0
def performIapForEsc(esc_record, sas_uut_fad_object, sas_th_fad_objects):
    """Computes post IAP interference margin for ESC.

  IAP algorithm is run over ESC passband 3550-3660MHz for Category A CBSDs and
  3550-3680MHz for Category B CBSDs.

  Args:
    esc_record: An ESC record (dict of schema |EscSensorRecord|).
    sas_uut_fad_object: FAD object from SAS UUT
    sas_th_fad_objects: 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.
  """
    esc_thresh_q = THRESH_ESC_DBM_PER_IAPBW

    # Actual protection threshold used for IAP - calculated by applying
    # a pre-defined Pre-IAP headroom (Mg) at each protection threshold(Q)
    esc_iap_threshold = interf.dbToLinear(esc_thresh_q - MARGIN_ESC_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 ESC infos
    protection_point, esc_antenna_info = data.getEscInfo(esc_record)

    # Get ESC passband 3550-3680 MHz protection channels
    protection_channels = interf.getProtectedChannels(interf.ESC_LOW_FREQ_HZ,
                                                      interf.ESC_HIGH_FREQ_HZ)

    logging.debug('$$$$ Calling ESC Protection $$$$')
    # ESC algorithm
    iap_interfs = iapPointConstraint(protection_point, protection_channels,
                                     interf.ESC_LOW_FREQ_HZ,
                                     interf.ESC_HIGH_FREQ_HZ, grants, None,
                                     esc_antenna_info, None, esc_iap_threshold,
                                     data.ProtectedEntityType.ESC)

    ap_iap_ref = calculatePostIapAggregateInterference(
        interf.dbToLinear(esc_thresh_q), num_sas, iap_interfs)
    return ap_iap_ref
Beispiel #7
0
def performIapForPpa(ppa_record, sas_uut_fad_object, sas_th_fad_objects,
                     pal_records):
    """Computes post IAP interference margin for PPA incumbents.

  Routine to get protection points within PPA protection area and perform
  IAP algorithm on each protection point.

  Args:
    ppa_record: A PPA 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
    pal_records: PAL records associated with a PPA protection area
  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.
  """
    ppa_thresh_q = THRESH_PPA_DBM_PER_IAPBW

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

    grants = data.getGrantObjectsFromFAD(sas_uut_fad_object,
                                         sas_th_fad_objects, ppa_record)

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

    logging.debug('$$$$ Getting GRID points for PPA Protection Area $$$$')

    # Get Fine Grid Points for a PPA protection area
    protection_points = utils.GridPolygon(
        ppa_record['zone']['features'][0]['geometry'], PPA_GRID_RES_ARCSEC)

    # Get the region type of the PPA protection area
    ppa_region = ppa_record['ppaInfo']['ppaRegionType']

    # Find the PAL records for the PAL_IDs defined in PPA records
    ppa_pal_ids = ppa_record['ppaInfo']['palId']

    matching_pal_records = [
        pr for pr in pal_records if pr['palId'] == ppa_pal_ids[0]
    ]
    if not matching_pal_records:
        raise ValueError('No matching PAL record, please check input')

    pal_record = matching_pal_records[0]

    # Get the frequencies from the PAL records
    ppa_freq_range = pal_record['channelAssignment']['primaryAssignment']
    ppa_low_freq = ppa_freq_range['lowFrequency']
    ppa_high_freq = ppa_freq_range['highFrequency']

    # Get channels over which area incumbent needs partial/full protection
    protection_channels = interf.getProtectedChannels(ppa_low_freq,
                                                      ppa_high_freq)

    # Apply IAP for each protection constraint with a pool of parallel
    # processes.
    logging.debug('$$$$ Calling PPA Protection $$$$')
    iapPoint = partial(iapPointConstraint,
                       channels=protection_channels,
                       low_freq=ppa_low_freq,
                       high_freq=ppa_high_freq,
                       grants=grants,
                       fss_info=None,
                       esc_antenna_info=None,
                       region_type=ppa_region,
                       threshold=ppa_iap_threshold,
                       protection_ent_type=data.ProtectedEntityType.PPA_AREA)

    pool = mpool.Pool()
    iap_interfs = pool.map(iapPoint, protection_points)

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

    return ap_iap_ref
Beispiel #8
0
def performIapForGwpz(gwpz_record, sas_uut_fad_object, sas_th_fad_objects):
    """Computes post IAP interference margin for GWPZ incumbents.

  Routine to get protection points within GWPZ protection area and perform
  IAP algorithm on each protection point.

  Args:
    gwpz_record: A GWPZ record dict.
    sas_uut_fad_object: FAD object from SAS UUT
    sas_th_fad_objects: 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.
  """
    gwpz_thresh_q = THRESH_GWPZ_DBM_PER_IAPBW

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

    grants = data.getGrantObjectsFromFAD(sas_uut_fad_object,
                                         sas_th_fad_objects)

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

    logging.debug('$$$$ Getting GRID points for GWPZ Protection Area $$$$')
    # Get Fine Grid Points for a GWPZ protection area
    protection_points = utils.GridPolygon(
        gwpz_record['zone']['features'][0]['geometry'], GWPZ_GRID_RES_ARCSEC)

    gwpz_freq_range = gwpz_record['record']['deploymentParam'][0]\
                                 ['operationParam']['operationFrequencyRange']
    gwpz_low_freq = gwpz_freq_range['lowFrequency']
    gwpz_high_freq = gwpz_freq_range['highFrequency']
    gwpz_region = gwpz_record['landCategory']

    # Get channels over which area incumbent needs partial/full protection
    protection_channels = interf.getProtectedChannels(gwpz_low_freq,
                                                      gwpz_high_freq)

    logging.debug('$$$$ Calling GWPZ Protection $$$$')
    iapPoint = partial(iapPointConstraint,
                       channels=protection_channels,
                       low_freq=gwpz_low_freq,
                       high_freq=gwpz_high_freq,
                       grants=grants,
                       fss_info=None,
                       esc_antenna_info=None,
                       region_type=gwpz_region,
                       threshold=gwpz_iap_threshold,
                       protection_ent_type=data.ProtectedEntityType.GWPZ_AREA)

    pool = mpool.Pool()
    iap_interfs = pool.map(iapPoint, protection_points)

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

    return ap_iap_ref
def calculateAggregateInterferenceForPpa(ppa_record, pal_records, grants):
    """Calculates per-channel aggregate interference for PPA.

  Args:
    ppa_record: A PPA record dict.
    pal_records: PAL records associated with a PPA protection area
    grants: An iterable of CBSD grants of type |data.CbsdGrantInfo|.

  Returns:
    Aggregate interference to PPA in the nested dictionary format.
      {latitude : {longitude: [aggr_interf1(mW), ..., aggr_interfK(mW)]}}
    The list contains the value per protected channel.
  """
    # Get Fine Grid Points for a PPA protection area
    protection_points = utils.GridPolygon(
        ppa_record['zone']['features'][0]['geometry'], PPA_GRID_RES_ARCSEC)

    # Get the region type of the PPA protection area
    ppa_region = ppa_record['ppaInfo']['ppaRegionType']

    # Find the PAL records for the PAL_IDs defined in PPA records
    ppa_pal_ids = ppa_record['ppaInfo']['palId']

    matching_pal_records = [
        pr for pr in pal_records if pr['palId'] == ppa_pal_ids[0]
    ]
    if not matching_pal_records:
        raise ValueError(
            'AggInterf: No matching PAL record, please check input')

    pal_record = matching_pal_records[0]

    # Get the frequencies from the PAL records
    ppa_freq_range = pal_record['channelAssignment']['primaryAssignment']
    ppa_low_freq = ppa_freq_range['lowFrequency']
    ppa_high_freq = ppa_freq_range['highFrequency']

    # Get channels over which area incumbent needs partial/full protection
    protection_channels = interf.getProtectedChannels(ppa_low_freq,
                                                      ppa_high_freq)

    logging.info(
        'Computing aggregateInterferenceForPoint for PPA (%s), channels (%s), '
        'nPoints (%d), grants (%s), region_type (%s)', ppa_record,
        protection_channels, len(protection_points), grants, ppa_region)
    logging.debug('  points: %s', protection_points)

    # Calculate aggregate interference from each protection constraint with a
    # pool of parallel processes.
    interfCalculator = partial(
        aggregateInterferenceForPoint,
        channels=protection_channels,
        grants=grants,
        fss_info=None,
        esc_antenna_info=None,
        protection_ent_type=data.ProtectedEntityType.PPA_AREA,
        region_type=ppa_region)

    pool = mpool.Pool()
    interferences = pool.map(interfCalculator, protection_points)
    return InterferenceDict(interferences)