Exemplo n.º 1
0
def test_avar(
    setup_prop_to_test_avar,
    setup_prop_to_test_avar_uarea,
):
    """
    Test the statistics generating function avar which finds the quantiles of attenuation
    (Section V of "The ITS Irregular Terrain Model, version 1.2.2: The Algorithm").

    The imported setup parameters are imported from tests/conftest.py via the fixture
    setup_prop_to_test_avar.

    The first test is derived from the original test for Longley-Rice between for Crystal
    Palace (South London) to Mursley, England (See Stark, 1967).

    The 'actual_answer' variable is the avar1 metric which corresponds to the additional
    attenuation from the median given user defined quantiles in time, location, and
    situation.

    """
    actual_answer, actual_prop = avar(1.2817, 0, 1.2817,
                                      setup_prop_to_test_avar)

    expected_answer = 20.877472366318642

    assert actual_answer == expected_answer

    actual_answer, actual_prop = avar(0, 0, 0, setup_prop_to_test_avar_uarea)

    expected_answer = 33.44778607772954

    assert actual_answer == expected_answer
Exemplo n.º 2
0
def itmlogic_p2p(main_user_defined_parameters, surface_profile_m):
    """
    Run itmlogic in point to point (p2p) prediction mode.

    Parameters
    ----------
    main_user_defined_parameters : dict
        User defined parameters.
    surface_profile_m : list
        Contains surface profile measurements in meters.

    Returns
    -------
    output : list of dicts
        Contains model output results.

    """
    prop = main_user_defined_parameters

    #DEFINE ENVIRONMENTAL PARAMETERS
    # Terrain relative permittivity
    prop['eps'] = 15

    # Terrain conductivity (S/m)
    prop['sgm'] = 0.005

    # Climate selection (1=equatorial,
    # 2=continental subtropical, 3=maritime subtropical,
    # 4=desert, 5=continental temperate,
    # 6=maritime temperate overland,
    # 7=maritime temperate, oversea (5 is the default)
    prop['klim'] = 5

    # Surface refractivity (N-units): also controls effective Earth radius
    prop['ens0'] = 314

    #DEFINE STATISTICAL PARAMETERS
    # Confidence  levels for predictions
    qc = [50, 90, 10]

    # Reliability levels for predictions
    qr = [1, 10, 50, 90, 99]

    # Number of points describing profile -1
    pfl = []
    pfl.append(len(surface_profile_m) - 1)
    pfl.append(0)

    for profile in surface_profile_m:
        pfl.append(profile)

    # Refractivity scaling ens=ens0*exp(-zsys/9460.)
    # (Average system elev above sea level)
    zsys = 0

    # Note also defaults to a continental temperate climate

    # Setup some intermediate quantities
    # Initial values for AVAR control parameter: LVAR=0 for quantile change,
    # 1 for dist change, 2 for HE change, 3 for WN change, 4 for MDVAR change,
    # 5 for KLIM change
    prop['lvar'] = 5

    # Inverse Earth radius
    prop['gma'] = 157E-9

    # Conversion factor to db
    db = 8.685890

    #Number of confidence intervals requested
    nc = len(qc)

    #Number of reliability intervals requested
    nr = len(qr)

    #Length of profile in km
    dkm = prop['d']

    #Profile range step, select option here to define range step from profile
    #length and # of points
    xkm = 0

    #If DKM set <=0, find DKM by mutiplying the profile step by number of
    #points (not used here)
    if dkm <= 0:
        dkm = xkm * pfl[0]

    #If XKM is <=0, define range step by taking the profile length/number
    #of points in profile
    if xkm <= 0:

        xkm = dkm // pfl[0]

        #Range step in meters stored in PFL(2)
        pfl[1] = dkm * 1000 / pfl[0]

        #Store profile in prop variable
        prop['pfl'] = pfl
        #Zero out error flag
        prop['kwx'] = 0
        #Initialize omega_n quantity
        prop['wn'] = prop['fmhz'] / 47.7
        #Initialize refractive index properties
        prop['ens'] = prop['ens0']

    #Scale this appropriately if zsys set by user
    if zsys != 0:
        prop['ens'] = prop['ens'] * math.exp(-zsys / 9460)

    #Include refraction in the effective Earth curvature parameter
    prop['gme'] = prop['gma'] * (1 - 0.04665 * math.exp(prop['ens'] / 179.3))

    #Set surface impedance Zq parameter
    zq = complex(prop['eps'], 376.62 * prop['sgm'] / prop['wn'])

    #Set Z parameter (h pol)
    prop['zgnd'] = np.sqrt(zq - 1)

    #Set Z parameter (v pol)
    if prop['ipol'] != 0:
        prop['zgnd'] = prop['zgnd'] / zq

    #Flag to tell qlrpfl to set prop.klim=prop.klimx and set lvar to initialize avar routine
    prop['klimx'] = 0

    #Flag to tell qlrpfl to use prop.mdvar=prop.mdvarx and set lvar to initialize avar routine
    prop['mdvarx'] = 11

    #Convert requested reliability levels into arguments of standard normal distribution
    zr = qerfi([x / 100 for x in qr])
    #Convert requested confidence levels into arguments of standard normal distribution
    zc = qerfi([x / 100 for x in qc])

    #Initialization routine for point-to-point mode that sets additional parameters
    #of prop structure
    prop = qlrpfl(prop)

    ## Here HE = effective antenna heights, DL = horizon distances,
    ## THE = horizon elevation angles
    ## MDVAR = mode of variability calculation: 0=single message mode,
    ## 1=accidental mode, 2=mobile mode, 3 =broadcast mode, +10 =point-to-point,
    ## +20=interference

    #Free space loss in db
    fs = db * np.log(2 * prop['wn'] * prop['dist'])

    #Used to classify path based on comparison of current distance to computed
    #line-of-site distance
    q = prop['dist'] - prop['dlsa']

    #Scaling used for this classification
    q = max(q - 0.5 * pfl[1], 0) - max(-q - 0.5 * pfl[1], 0)

    #Report dominant propagation type predicted by model according to parameters
    #obtained from qlrpfl
    if q < 0:
        print('Line of sight path')
    elif q == 0:
        print('Single horizon path')
    else:
        print('Double-horizon path')
    if prop['dist'] <= prop['dlsa']:
        print('Diffraction is the dominant mode')
    elif prop['dist'] > prop['dx']:
        print('Tropospheric scatter is the dominant mode')

    print('Estimated quantiles of basic transmission loss (db)')
    print('Free space value {} db'.format(str(fs)))

    print('Confidence levels {}, {}, {}'.format(str(qc[0]), str(qc[1]),
                                                str(qc[2])))

    # Confidence  levels for predictions
    qc = [50, 90, 10]

    # Reliability levels for predictions
    qr = [1, 10, 50, 90, 99]

    output = []
    for jr in range(0, (nr)):
        for jc in range(0, nc):
            #Compute corrections to free space loss based on requested confidence
            #and reliability quantities
            avar1, prop = avar(zr[jr], 0, zc[jc], prop)
            output.append({
                'distance_km': prop['d'],
                'reliability_level_%': qr[jr],
                'confidence_level_%': qc[jc],
                'propagation_loss_dB':
                fs + avar1  #Add free space loss and correction
            })

    return output
Exemplo n.º 3
0
def test_itmlogic_area():
    """
    Test the model in area prediction mode.

    """
    prop = {}

    #Antenna height 1 (m), Antenna height 2 (m)
    prop['hg'] = [3.3, 1.3]

    #Frequency (MHz)
    prop['fmhz'] = 20

    #Terrain irregularity parameter dh (m)
    prop['dh'] = 102

    #Surface refractivity (N-units)
    prop['ens0'] = 301

    #Relative permittivity of ground
    prop['eps'] = 15

    #Conductivity (S/m) of ground
    prop['sgm'] = 0.001

    #Climate selection (1=equatorial, 2=continental subtropical,
    #3=maritime subtropical, 4=desert, 5=continental temperate,
    #6=maritime temperate overland, 7=maritime temperate,
    #oversea (5 is the default)
    prop['klimx'] = 5

    #0 = horizontal polarization, 1 = vertical
    prop['ipol'] = 1

    #Mode of variability: Single Message=0, Accidental=1,
    #Mobile=2, Broadcast=3
    prop['mdvarx'] = 3

    #Percent of time requested for computation
    QT = [50]

    #Percent of locations requested for computation
    QL = [50]

    #Confidence levels of computation
    QC = [50, 90, 10]

    #Initial distance (km) for loop over range
    D0 = 10

    #Max distance 1 (km) for loop over range
    D1 = 150

    #Increment 1 (km) for loop over range
    DS1 = 10

    #Max distance 2 (km) for coarser loop over range (starts beyond D1)
    D2 = 500

    #Increment 2 (km) for coarser loop over range
    DS2 = 50

    #Siting criterion for antenna 1, 0=random, 1= careful, 2= very careful
    KST = [2, 2]

    #Refractivity scaling ens=ens0*exp(-zsys/9460.);
    #(Average system elev above sea level)
    zsys = 0

    #Rescale requested percentages into their corresponding normal distribution arguments
    ZT = qerfi([x / 100 for x in QT])[0]
    ZL = qerfi([x / 100 for x in QL])[0]
    ZC = qerfi([x / 100 for x in QC])

    #The number of confidence intervals requested
    NC = len(QC)

    #Don't allow negative distances
    if (D0 <= 0):
        D0 = DS1

    #Set initial distance to 2 km if D0<=0
    if (D0 <= 0):
        D0 = 2

    #If final distance less than initial, only do one distance
    if (D1 <= D0) or (DS1 <= 0):
        ND = 1
        D1 = D0
    #Otherwise compute the number of distance points in the loop
    #and recompute the final distance using this grid
    else:
        DS = DS1
        ND = math.floor((D1 - D0) / DS + 1.75)
        D1 = D0 + (ND - 1) * DS

    #Repeat these corrections for the "coarse" grid in range that follows the fine grid
    if (D2 <= D1) or (DS2 <= 0):
        NDC = 0  #If input parameters are wrong, don't do a coarse grid
    #Otherwise set up appropriate coarse grid
    else:
        NDC = ND
        ND = math.floor((D2 - D1) / DS2 + 0.75)
        D2 = D1 + ND * DS2
        ND = NDC + ND

    #Standard Earth curvature parameter
    prop['gma'] = 157E-9
    #Scale factor for converting Np/km to dB/km
    DB = 8.685890
    #Scale factor to convert km to m
    AKM = 1000

    #Initialize error flag to 0
    prop['kwx'] = 0
    #Initialize the omega_n parameter
    prop['wn'] = prop['fmhz'] / 47.7
    #Initialize the surface refractivity
    prop['ens'] = prop['ens0']

    #Adjust surface refractivity parameter if zsys set by user
    if (zsys != 0):
        prop['ens'] = prop['ens'] * math.exp(-zsys / 9460)

    #Implement refractive effects on Earth curvature
    prop['gme'] = prop['gma'] * (1 - 0.04665 * math.exp(prop['ens'] / 179.3))

    #Initialize lvar parameter (this is used when updating AVAR with new input parameters)
    prop['lvar'] = 0

    #Compute ground effective impedance zq parameter
    zq = complex(prop['eps'], 376.62 * prop['sgm'] / prop['wn'])

    #Compute ground effective impedance z parameter (horizontal pol)
    prop['zgnd'] = math.sqrt(zq.real - 1)

    #Compute ground effective impedance z parameter (vertical pol)
    if (prop['ipol'] != 0):
        prop['zgnd'] = prop['zgnd'] / zq

    #Qlra initializes all the required parameters for area-prediction mode given
    #siting type and other params already set in "prop"
    prop = qlra(KST, prop)

    #Starting distances for loop over range
    D = D0
    #First range step is that of the fine grid
    DT = DS

    FS = []
    DD = []

    output = []

    for JD in range(0, ND):  #0-22

        #Ensure that AVAR routines adjust only for distance (not quantiles which are set)
        prop['lvar'] = max(1, prop['lvar'])

        #Compute baseline propagation loss at current range
        prop = lrprop(D * AKM, prop)

        #Compute and store baseline loss
        FS.append(DB * np.log(2 * prop['wn'] * prop['dist']))

        #Store distance at this increment
        DD.append(D)

        #Loop over confidence intervals requested by user
        for JC in range(0, NC):  #0-3

            #Get confidence interval
            confidence_level = QC[JC]

            #Compute adjustment for specified confidence levels
            avar1, prop = avar(ZT, ZL, ZC[JC], prop)

            #Store results
            output.append({
                'distance_km': D,
                'confidence_level_%': confidence_level,
                'propagation_loss_dB':
                FS[JD] + avar1  #Add in the adjustment for this level
            })

        #Switch to the coarse grid increment in range when we get there
        if JD + 1 == NDC:
            DT = DS2

        #Increment range
        D = D + DT

    for result in output:
        if result['distance_km'] == 10 and result['confidence_level_%'] == 50:
            assert result['propagation_loss_dB'] == 111.69200844812511
        if result['distance_km'] == 10 and result['confidence_level_%'] == 90:
            assert result['propagation_loss_dB'] == 121.59437954264777
        if result['distance_km'] == 10 and result['confidence_level_%'] == 10:
            assert result['propagation_loss_dB'] == 101.78963735360244
        if result['distance_km'] == 500 and result['confidence_level_%'] == 50:
            assert result['propagation_loss_dB'] == 215.27421197676375
        if result['distance_km'] == 500 and result['confidence_level_%'] == 90:
            assert result['propagation_loss_dB'] == 221.71014370503855
        if result['distance_km'] == 500 and result['confidence_level_%'] == 10:
            assert result['propagation_loss_dB'] == 208.83828024848896
Exemplo n.º 4
0
def run_itmlogic(surface_profile_m, distance_km):
    """
    Run itmlogic in point to point (p2p) prediction mode.

    Parameters
    ----------
    surface_profile_m : list
        Contains surface profile measurements in meters.
    distance_km : float
        Distance between the transmitter and receiver.

    Returns
    -------
    output : list of dicts
        Contains model output results.

    """
    prop = {}

    #Frequencies used in the campaign (GHz)
    frequencies = [2.488]

    #Polarization selection (0=horizontal, 1=vertical)
    prop['ipol']  = 1

    #Receiver heights (m)
    rxht = [2.56, 2.2]

    #Transmitter heights (m) (UAV)
    txht = list(range(10, (130+1), 1))

    #Terrain relative permittivity
    prop['eps'] = 15

    #Terrain conductivity (S/m)
    prop['sgm'] = 0.005

    #Surface refractivity (N-units): also controls effective Earth radius -> unknown
    prop['ens0'] = 314

    # # Climate selection (1=equatorial,
    # # 2=continental subtropical, 3=maritime subtropical,
    # # 4=desert, 5=continental temperate,
    # # 6=maritime temperate overland,
    # # 7=maritime temperate, oversea (5 is the default)
    prop['klim']  =   5

    #Refractivity scaling;  (Average system elev above sea level)
    zsys = 0

    #Confidence  levels for predictions
    qc = [50]

    #Reliability levels for predictions
    qr = [50]

    #Preliminary calcs
    #Conversion factor to dB
    DB = 8.685890
    NC = len(qc)
    NR = len(qr)
    ZR = qerfi(qr) #ZR = qerfi(qr / 100)
    ZC = qerfi(qc) #ZC = qerfi(qc / 100)

    # Inverse Earth radius
    prop['gma']  = 157E-9

    prop['ens'] = prop['ens0']

    if zsys != 0:
        prop['ens'] = prop['ens'] * math.exp(-zsys / 9460)

    prop['gme'] = prop['gma'] * (1 - 0.04665 * math.exp(prop['ens'] / 179.3))

    PFL = []

    PFL.append(len(distance_km)-1)
    PFL.append(distance_km[1] - distance_km[0])
    PFL = PFL + terrain_height_no_tree

    #Length of profile (km)
    prop['d'] = distance_km[-1]/1000
    prop['pfl'] = PFL

    output = []
    for frequency in range(0, len(frequencies)):

        prop['fmhz'] = frequencies[frequency] * 1000

        prop['wn'] = prop['fmhz'] / 47.7
        zq = complex(prop['eps'], (376.62 * prop['sgm'] / prop['wn']))
        prop['zgnd'] = np.sqrt(zq - 1)

        if prop['ipol'] != 0:
            prop['zgnd'] = prop['zgnd'] / zq

        if frequency == 0:
            #Rx height varies with frequency
            prop['hg'] = [0, 0]
            prop['hg'][0] = rxht[0]
        else:
            prop['hg'] = [0, 0]
            prop['hg'][0] = rxht[1]

        #Tx ht (UAV)
        for iht in range(0, len(txht)):

            hg = txht[iht]

            # Antenna 2 height (m)
            prop['hg'][1] = hg

            #Setup some intermediate quantities
            #Initial values for AVAR control parameter:
            #LVAR=0 for quantile change, 1 for dist change,
            #2 for HE change, 3 for WN change,
            # 4 for MDVAR change, 5 for KLIM change
            prop['lvar'] = 5
            #Zero out error flag
            prop['kwx'] = 0
            prop['klimx'] = 0
            prop['mdvarx'] = 11

            prop = qlrpfl(prop)

            #Here HE = effective antenna heights
            #DL = horizon distances
            #THE = horizon elevation angles
            #MDVAR = mode of variability calculation: 0=single message mode,
                #1=accidental mode, 2=mobile mode, 3=broadcast mode,
                #+10 =point-to-point, +20=interference

            # Free space loss in dB
            FS = DB * np.log(2 * prop['wn'] * prop['dist'])


            for jr in range(0, NR):
                xlb = []
                for jc in range(0, NC):
                    avar1, prop = avar(ZR[jr], 0, ZC[jc], prop)
                    xlb.append(FS + avar1)
                output.append((prop['fmhz'], hg, qr[jr], xlb[0]))

    return output