Beispiel #1
0
def Br_for_ml(r, th, ph, g, h, m, l, a=6371.2):
    """
    Calculates the Br contribution for one set of m,l, using the potential field.

    Inputs
    ------
    r:
        radius location (km)
    th:
        latitude location (radians)
    ph:
        longitude location (radians)
    g:
        Gauss coefficient (cos term)
    h:
        Gauss coefficient (sin term)
    m:
        Order of calculation
    l:
        Degree of calculation
    a:
        Radius (km) at which Gauss coefficients are calculated

    Returns
    -------
    Br contribution in Tesla at a particular point from a particular degree and order.
    """
    return (l + 1.) * a**(l + 2.) / abs(r)**(l + 2.) * (
        g * _cos(m * ph) + h * _sin(m * ph)) * Pml(_cos(th), l, m)
Beispiel #2
0
def Br_for_ml(r,th,ph,g,h,m,l, a=6371.2):
    """
    Calculates the Br contribution for one set of m,l, using the potential field.

    Inputs
    ------
    r:
        radius location (km)
    th:
        latitude location (radians)
    ph:
        longitude location (radians)
    g:
        Gauss coefficient (cos term)
    h:
        Gauss coefficient (sin term)
    m:
        Order of calculation
    l:
        Degree of calculation
    a:
        Radius (km) at which Gauss coefficients are calculated

    Returns
    -------
    Br contribution in Tesla at a particular point from a particular degree and order.
    """
    return (l+1.)*a**(l+2.)/abs(r)**(l+2.)*(g*_cos(m*ph) + h*_sin(m*ph))*Pml(_cos(th), l, m)
Beispiel #3
0
    def _dphi_Br_for_ml_complex(self, r, th, ph, c, m, l, a=6371.2):
        """
        Calculates the d_phi(Br)/(R*sin(th)) contribution for one set of m,l, using the potential field.

        Inputs
        ------
        r:
            radius location (km)
        th:
            latitude location (radians)
        ph:
            longitude location (radians)
        c:
            complex gauss coefficient
        m:
            Order of calculation
        l:
            Degree of calculation
        a:
            Radius (km) at which Gauss coefficients are calculated

        Returns
        -------
        d_phi(Br)/(R*sin(th)) in Tesla/m at a particular point from a particular degree and order.
        """
        return 1j*m/(r*_sin(th))*self._Br_for_ml_complex(r, th, ph, c, m, l, a=a)
Beispiel #4
0
def rcosfir(beta, sps, span=None):
    """Generates a raised cosine FIR filter.

    :param beta: shape of the raised cosine filter (0-1)
    :param sps: number of samples per symbol
    :param span: length of the filter in symbols (None => automatic selection)

    >>> import arlpy
    >>> rc = arlpy.comms.rcosfir(0.25, 6)
    >>> bb = arlpy.comms.modulate(arlpy.comms.random_data(100), arlpy.comms.psk())
    >>> pb = arlpy.comms.upconvert(bb, 6, 27000, 18000, rc)
    """
    if beta < 0 or beta > 1:
        raise ValueError('Beta must be between 0 and 1')
    if span is None:
        # from http://www.commsys.isy.liu.se/TSKS04/lectures/3/MichaelZoltowski_SquareRootRaisedCosine.pdf
        # since this recommendation is for root raised cosine filter, it is conservative for a raised cosine filter
        span = 33 - int(44 * beta) if beta < 0.68 else 4
    delay = int(span * sps / 2)
    t = _np.arange(-delay, delay + 1, dtype=_np.float) / sps
    denom = 1 - (2 * beta * t)**2
    eps = _np.finfo(float).eps
    idx1 = _np.nonzero(_np.abs(denom) > _sqrt(eps))
    b = _np.full_like(t, beta * _sin(_pi / (2 * beta)) / (2 * sps))
    b[idx1] = _np.sinc(t[idx1]) * _cos(
        _pi * beta * t[idx1]) / denom[idx1] / sps
    b /= _sqrt(_np.sum(b**2))
    return b
Beispiel #5
0
def rrcosfir(beta, sps, span=None):
    """Generates a root raised cosine FIR filter.

    :param beta: shape of the root raised cosine filter (0-1)
    :param sps: number of samples per symbol
    :param span: length of the filter in symbols (None => automatic selection)

    >>> import arlpy
    >>> rrc = arlpy.comms.rrcosfir(0.25, 6)
    >>> bb = arlpy.comms.modulate(arlpy.comms.random_data(100), arlpy.comms.psk())
    >>> pb = arlpy.comms.upconvert(bb, 6, 27000, 18000, rrc)
    """
    if beta < 0 or beta > 1:
        raise ValueError('Beta must be between 0 and 1')
    if span is None:
        # from http://www.commsys.isy.liu.se/TSKS04/lectures/3/MichaelZoltowski_SquareRootRaisedCosine.pdf
        span = 33 - int(44 * beta) if beta < 0.68 else 4
    delay = int(span * sps / 2)
    t = _np.arange(-delay, delay + 1, dtype=_np.float) / sps
    b = _np.empty_like(t)
    b[delay] = -1 / (_pi * sps) * (_pi * (beta - 1) - 4 * beta)
    eps = _np.finfo(float).eps
    idx2 = _np.nonzero(_np.abs(_np.abs(4 * beta * t) - 1) < _sqrt(eps))
    if len(idx2) > 0:
        b[idx2] = (_pi * (beta + 1) * _sin(_pi * (beta + 1) / (4 * beta)) -
                   4 * beta * _sin(_pi * (beta - 1) / (4 * beta)) + _pi *
                   (beta - 1) * _cos(_pi * (beta - 1) /
                                     (4 * beta))) / (2 * _pi * sps)
    ind = _np.arange(len(t))
    ind = _np.delete(ind, _np.append(idx2, delay))
    nind = t[ind]
    b[ind] = -4 * beta / sps * (_cos((1 + beta) * _pi * nind) + _sin(
        (1 - beta) * _pi * nind) / (4 * beta * nind)) / (_pi * (
            (4 * beta * nind)**2 - 1))
    b /= _sqrt(_np.sum(b**2))
    return b
Beispiel #6
0
def _do_dispersal(spp,
                  parent_midpoint_x,
                  parent_midpoint_y,
                  dispersal_distance_distr_param1,
                  dispersal_distance_distr_param2,
                  mu_dir=0,
                  kappa_dir=0):
    within_landscape = False
    while not within_landscape:
        # choose direction using movement surface, if applicable
        if spp._disp_surf:
            # and use those choices to draw movement directions
            direction = spp._disp_surf._draw_directions(
                [int(parent_midpoint_x)], [int(parent_midpoint_y)])[0]
        # else, choose direction using a random walk with a uniform vonmises
        elif not spp._disp_surf:
            direction = _r_vonmises(mu_dir, kappa_dir)
        if spp.dispersal_distance_distr == 'levy':
            distance = _s_levy.rvs(loc=spp.dispersal_distance_distr_param1,
                                   scale=spp.dispersal_distance_distr_param2)
        elif spp.dispersal_distance_distr == 'wald':
            distance = _wald(mean=dispersal_distance_distr_param1,
                             scale=dispersal_distance_distr_param2)
        elif spp.dispersal_distance_distr == 'lognormal':
            distance = _lognormal(mean=spp.dispersal_distance_distr_param1,
                                  sigma=spp.dispersal_distance_distr_param2)

        # decompose distance into x and y components
        dist_x = _cos(direction) * distance
        dist_y = _sin(direction) * distance
        # multiply the x and y distances by the land's resolution-ratios,
        # if they're not 1 and 1 (e.g. using a non-square-resolution raster)
        if spp._land_res_ratio[0] != 1:
            dist_x *= spp._land_res_ratio[0]
        if spp._land_res_ratio[1] != 1:
            dist_y *= spp._land_res_ratio[1]
        offspring_x = parent_midpoint_x + dist_x
        offspring_y = parent_midpoint_y + dist_y
        offspring_x = np.clip(offspring_x,
                              a_min=0,
                              a_max=spp._land_dim[0] - 0.001)
        offspring_y = np.clip(offspring_y,
                              a_min=0,
                              a_max=spp._land_dim[1] - 0.001)
        within_landscape = (
            (offspring_x > 0 and offspring_x < spp._land_dim[0])
            and (offspring_y > 0 and offspring_y < spp._land_dim[1]))
    return (offspring_x, offspring_y)
Beispiel #7
0
def _do_movement(spp):
    # get individuals' coordinates (soon to be their old coords, so
    # 'old_x' and 'old_y')
    old_x, old_y = [
        a.flatten() for a in np.split(spp._get_coords(), 2, axis=1)
    ]
    # and get their cells (by rounding down to the int)
    old_x_cells, old_y_cells = [
        a.flatten() for a in np.split(spp._get_cells(), 2, axis=1)
    ]
    # choose direction using movement surface, if applicable
    if spp._move_surf:
        # and use those choices to draw movement directions
        direction = spp._move_surf._draw_directions(old_x_cells, old_y_cells)
        # NOTE: Pretty sure that I don't need to constrain values output
        # for the Gaussian KDE that is approximating the von Mises mixture
        # distribution to 0<=val<=2*pi, because e.g. cos(2*pi + 1) = cos(1),
        # etc...
        # NOTE: indexed out of move_surf as y then x because becuase the
        # list of lists (like a numpy array structure) is indexed i then j,
        # i.e. vertical, then horizontal
    # else, choose direction using a random walk with a uniform vonmises
    elif not spp._move_surf:
        direction = _r_vonmises(spp.direction_distr_mu,
                                spp.direction_distr_kappa,
                                size=len(old_x))

    # choose distance
    # NOTE: Instead of lognormal, could use something with long right tail
    # for Levy-flight type movement, same as below
    if spp.movement_distance_distr == 'levy':
        distance = _s_levy.rvs(loc=spp.movement_distance_distr_param1,
                               scale=spp.movement_distance_distr_param2,
                               size=len(old_x))
    elif spp.movement_distance_distr == 'wald':
        distance = _wald(mean=spp.movement_distance_distr_param1,
                         scale=spp.movement_distance_distr_param2,
                         size=len(old_x))
    elif spp.movement_distance_distr == 'lognormal':
        distance = _lognormal(mean=spp.movement_distance_distr_param1,
                              sigma=spp.movement_distance_distr_param2,
                              size=len(old_x))

    # decompose distance into x and y components
    dist_x = _cos(direction) * distance
    dist_y = _sin(direction) * distance
    # multiply the x and y distances by the land's resolution-ratios,
    # if they're not 1 and 1 (e.g. a non-square-resolution raster was read in)
    if spp._land_res_ratio[0] != 1:
        dist_x *= spp._land_res_ratio[0]
    if spp._land_res_ratio[1] != 1:
        dist_y *= spp._land_res_ratio[1]

    # create the new locations by adding x- and y-dim line segments to their
    # current positions, using trig then clip the values to be within the
    # landscape dimensions
    # NOTE: subtract a small value to avoid having the dimension itself set
    # as a coordinate, when the coordinates are converted to np.float32
    new_x = old_x + dist_x
    new_x = np.clip(new_x, a_min=0, a_max=spp._land_dim[0] - 0.001)
    new_y = old_y + dist_y
    new_y = np.clip(new_y, a_min=0, a_max=spp._land_dim[1] - 0.001)

    # then feed the new locations into each individual's set_pos method
    [ind._set_pos(x, y) for ind, x, y in zip(spp.values(), new_x, new_y)]
def sin(x, unit='rad'):
    if unit == 'rad':
        return _sin(x)
    elif unit == 'deg':
        return _sin(deg_to_rad(x))