Exemplo n.º 1
0
def plot_rose(directions,
              velocities,
              width_dir,
              width_vel,
              metadata=None,
              flood=None,
              ebb=None):
    """
    Creates a polar histogram. Direction angles from binned histogram must 
    be specified such that 0  degrees is north.

    Parameters
    ----------
    directions: array-like
        Directions in degrees with 0 degrees specified as true north
    velocities: array-like
        Velocities in m/s
    width_dir: float 
        Width of directional bins for histogram in degrees
    width_vel: float 
        Width of velocity bins for histogram in m/s
    metadata: dictonary
        If provided needs keys ['name', 'lat', 'lon'] for plot title
        and information box on plot
    flood: float
        Direction in degrees added to theta ticks 
    ebb: float
        Direction in degrees added to theta ticks
    Returns
    -------
    ax: figure
        Water current rose plot
    """
    assert isinstance(velocities,(np.ndarray, pd.Series)), \
        'velocities  must be of type np.ndarry or pd.Series'
    assert isinstance(directions,(np.ndarray, pd.Series)), \
        'directions  must be of type np.ndarry or pd.Series'
    assert len(velocities) == len(directions),  \
        'velocities and directions  must have the same length'
    assert all(velocities.values >= 0),\
        'All velocities must be positive'
    assert all(directions.values >= 0) and all(directions.values <= 360),\
        'directions must be between 0 and 360 degrees'
    assert isinstance(flood, (int, float, type(None))), \
        'flood must be of type int or float'
    assert isinstance(ebb, (int, float, type(None))), \
        'ebb must be of type int or float'
    if flood:
        assert flood >=0 and flood <=360,\
            'flood must be between 0 and 360 degrees'
    if ebb:
        assert ebb >=0 and ebb <=360,\
            'ebb must be between 0 and 360 degrees'
    assert isinstance(width_dir, (int, float)), \
        'width_dir must be of type int or float'
    assert isinstance(width_vel, (int, float)), \
        'width_vel must be of type int or float'
    assert width_dir >=0 ,\
        'width_dir must be greater than 0'
    assert width_vel >=0 ,\
        'width_vel must be greater than 0'

    # Calculate the 2D histogram
    H, dir_edges, vel_edges = _histogram(directions, velocities, width_dir,
                                         width_vel)
    # Determine number of bins
    dir_bins = H.shape[0]
    vel_bins = H.shape[1]
    # Create the angles
    thetas = np.arange(0, 2 * np.pi, 2 * np.pi / dir_bins)
    # Initialize the polar polt
    ax = _initialize_polar(metadata=metadata, flood=flood, ebb=ebb)
    # Set bar color based on wind speed
    colors = plt.cm.viridis(np.linspace(0, 1.0, vel_bins))
    # Set the current speed bin label names
    # Calculate the 2D histogram
    labels = [
        f'{i:.1f}-{j:.1f}' for i, j in zip(vel_edges[:-1], vel_edges[1:])
    ]
    # Initialize the vertical-offset (polar radius) for the stacked bar chart.
    r_offset = np.zeros(dir_bins)
    for vel_bin in range(vel_bins):
        # Plot fist set of bars in all directions
        ax = plt.bar(thetas,
                     H[:, vel_bin],
                     width=(2 * np.pi / dir_bins),
                     bottom=r_offset,
                     color=colors[vel_bin],
                     label=labels[vel_bin])
        # Increase the radius offset in all directions
        r_offset = r_offset + H[:, vel_bin]
    # Add the a legend for current speed bins
    plt.legend(loc='best',
               title='Velocity bins [m/s]',
               bbox_to_anchor=(1.29, 1.00),
               ncol=1)
    # Get the r-ticks (polar y-ticks)
    yticks = plt.yticks()
    # Format y-ticks with  units for clarity
    rticks = [f'{y:.1f}%' for y in yticks[0]]
    # Set the y-ticks
    plt.yticks(yticks[0], rticks)
    return ax
Exemplo n.º 2
0
def plot_joint_probability_distribution(directions,
                                        velocities,
                                        width_dir,
                                        width_vel,
                                        metadata=None,
                                        flood=None,
                                        ebb=None):
    """
    Creates a polar histogram. Direction angles from binned histogram must 
    be specified such that 0 is north.

    Parameters
    ----------
    directions: array-like
        Directions in degrees with 0 degrees specified as true north
    velocities: array-like
        Velocities in m/s
    width_dir: float 
        Width of directional bins for histogram in degrees
    width_vel: float 
        Width of velocity bins for histogram in m/s
    metadata: dictonary
        If provided needs keys ['name', 'Lat', 'Lon'] for plot title
        and information box on plot
    flood: float
        Direction in degrees added to theta ticks 
    ebb: float
        Direction in degrees added to theta ticks
    Returns
    -------
    ax: figure
       Joint probability distribution  
    """
    assert isinstance(velocities,(np.ndarray, pd.Series)), \
        'velocities  must be of type np.ndarry or pd.Series'
    assert isinstance(directions,(np.ndarray, pd.Series)), \
        'directions  must be of type np.ndarry or pd.Series'
    assert len(velocities) == len(directions),  \
        'velocities and directions  must have the same length'
    assert all(velocities.values >= 0),\
        'All velocities must be positive'
    assert all(directions.values >= 0) and all(directions.values <= 360),\
        'directions must be between 0 and 360 degrees'
    assert isinstance(flood, (int, float, type(None))), \
        'flood must be of type int or float'
    assert isinstance(ebb, (int, float, type(None))), \
        'ebb must be of type int or float'
    if flood:
        assert flood >=0 and flood <=360,\
            'flood must be between 0 and 360 degrees'
    if ebb:
        assert ebb >=0 and ebb <=360,\
            'ebb must be between 0 and 360 degrees'
    assert isinstance(width_dir, (int, float)), \
        'width_dir must be of type int or float'
    assert isinstance(width_vel, (int, float)), \
        'width_vel must be of type int or float'
    assert width_dir >=0 ,\
        'width_dir must be greater than 0'
    assert width_vel >=0 ,\
        'width_vel must be greater than 0'

    # Calculate the 2D histogram
    H, dir_edges, vel_edges = _histogram(directions, velocities, width_dir,
                                         width_vel)
    # Initialize the polar polt
    ax = _initialize_polar(metadata=metadata, flood=flood, ebb=ebb)
    # Set the current speed bin label names
    labels = [
        f'{i:.1f}-{j:.1f}' for i, j in zip(vel_edges[:-1], vel_edges[1:])
    ]
    # Set vel & dir bins to middle of bin except at ends
    dir_bins = 0.5 * (dir_edges[1:] + dir_edges[:-1])  # set all bins to middle
    vel_bins = 0.5 * (vel_edges[1:] + vel_edges[:-1])
    # Reset end of bin range to edge of bin
    dir_bins[0] = dir_edges[0]
    vel_bins[0] = vel_edges[0]
    dir_bins[-1] = dir_edges[-1]
    vel_bins[-1] = vel_edges[-1]
    # Interpolate the bins back to specific data points
    z = _interpn((dir_bins, vel_bins),
                 H,
                 np.vstack([directions, velocities]).T,
                 method="splinef2d",
                 bounds_error=False)
    # Plot the most probable data last
    idx = z.argsort()
    # Convert to radians and order points by probability
    theta, r, z = directions.values[idx] * np.pi / 180., velocities.values[
        idx], z[idx]
    # Create scatter plot colored by probability density
    sx = ax.scatter(theta, r, c=z, s=5, edgecolor=None)
    # Create colorbar
    plt.colorbar(sx, label='Joint Probability [%]')
    # Get the r-ticks (polar y-ticks)
    yticks = plt.yticks()
    # Format y-ticks with  units for clarity
    yticks = [f'{y:.1f} $m/s$' for y in yticks[0]]
    # Set the y-ticks
    ax.set_yticklabels(yticks)
    return ax