def subplot_data(fig: matplotlib.figure.Figure,
                     subplot_params: tuple,
                     timestamps: list,
                     data: np.array,
                     x_label: str,
                     y_label: str,
                     event_timestamps: list = None,
                     data_label: str = None,
                     fontsize: int = 30,
                     event_annotation_color='g') -> None:
        '''Plots a given time series data on a subplot.

        Keyword arguments:
        fig -- matplotlib figure handle
        subplot_params -- a tuple with three subplot parameters: number of rows,
                          number of columns, and the number of the current subplot
        timestamps -- a list of timestamps (plotted over the x-axis)
        data -- a one-dimensional numpy array of data items (plotted over the y-axis)
        x_label -- x axis label
        y_label -- y axis label
        event_timestamps -- optional list of timestamps for data
                            annotation; the annotations are plotted as
                            lines at the given timestamps
                            (default None, in which case there are no annotations)
        data_label -- optional label for the plotted data; if a label is given,
                      a legend is added to the plot (default None)
        fontsize -- fontsize for the x and y axes labels (default 30)
        event_annotation_color -- color of event annotation lines (default 'g')

        '''
        fig.add_subplot(*subplot_params)

        # we plot the data
        if data_label:
            plt.plot(timestamps, data, label=data_label)
        else:
            plt.plot(timestamps, data)

        # we add event annotations to the plot if there are any events
        if event_timestamps is not None and len(event_timestamps) > 0:
            plt.plot([event_timestamps, event_timestamps],
                     [np.nanmin(data), np.nanmax(data)],
                     event_annotation_color)

        plt.xlabel(x_label, fontsize=fontsize)
        plt.ylabel(y_label, fontsize=fontsize)

        # we add a legend only if a data label is assigned
        if data_label:
            plt.legend()
Example #2
0
def hfss_plot_convergences_report(convergence_t: pd.core.frame.DataFrame,
                                  convergence_f: pd.core.frame.DataFrame,
                                  fig: mpl.figure.Figure = None,
                                  _display=True):
    """Plot convergence frequency vs. pass number if fig is None.
    Plot delta frequency and solved elements vs. pass number.
    Plot delta frequency vs. solved elements.

    Args:
        convergence_t (pandas.core.frame.DataFrame): Convergence vs pass number of the eigenemode freqs.
        convergence_f (pandas.core.frame.DataFrame): Convergence vs pass number of the eigenemode freqs.
        fig (matplotlib.figure.Figure, optional): A mpl figure. Defaults to None.
        _display (bool, optional): Display the plot? Defaults to True.
    """

    if fig is None:
        fig = plt.figure(figsize=(11, 3.))

        # Grid spec and axes;    height_ratios=[4, 1], wspace=0.5
        gs = mpl.gridspec.GridSpec(1, 3, width_ratios=[1.2, 1.5, 1])
        axs = [fig.add_subplot(gs[i]) for i in range(3)]

        ax0t = axs[1].twinx()
        plot_convergence_f_vspass(axs[0], convergence_f)
        plot_convergence_max_df(axs[1], convergence_t.iloc[:, 1])
        plot_convergence_solved_elem(ax0t, convergence_t.iloc[:, 0])
        plot_convergence_maxdf_vs_sol(axs[2], convergence_t.iloc[:, 1],
                                      convergence_t.iloc[:, 0])

        fig.tight_layout(w_pad=0.1)  # pad=0.0, w_pad=0.1, h_pad=1.0)
def setup_ax(fig: matplotlib.figure.Figure,
             pos: tuple[int, int, int] = (1, 1, 1),
             ) -> matplotlib.axes.Axes:
    '''
    Args
    - fig: matplotlib.figure.Figure
    - pos: 3-tuple of int, axes position (nrows, ncols, index)

    Returns: matplotlib.axes.Axes
    '''
    ax = fig.add_subplot(*pos, projection=ccrs.PlateCarree())

    # draw land (better version of cfeature.LAND)
    # land = cfeature.NaturalEarthFeature(
    #     category='physical', name='land', scale='10m',
    #     edgecolor='face', facecolor=cfeature.COLORS['land'], zorder=-1)
    ax.add_feature(cfeature.LAND)

    # draw borders of countries (better version of cfeature.BORDERS)
    countries = cfeature.NaturalEarthFeature(
        category='cultural', name='admin_0_boundary_lines_land', scale='10m',
        edgecolor='black', facecolor='none')
    ax.add_feature(countries)

    # draw coastline (better version of cfeature.COASTLINE)
    coastline = cfeature.NaturalEarthFeature(
        category='physical', name='coastline', scale='10m',
        edgecolor='black', facecolor='none')
    ax.add_feature(coastline)

    # draw lakes (better version of cfeature.LAKES)
    lakes = cfeature.NaturalEarthFeature(
        category='physical', name='lakes', scale='10m',
        edgecolor='face', facecolor=cfeature.COLORS['water'])
    ax.add_feature(lakes)

    # draw ocean (better version of cfeature.OCEAN)
    ocean = cfeature.NaturalEarthFeature(
        category='physical', name='ocean', scale='50m',
        edgecolor='face', facecolor=cfeature.COLORS['water'], zorder=-1)
    ax.add_feature(ocean)

    # draw rivers (better version of cfeature.RIVERS)
    rivers = cfeature.NaturalEarthFeature(
        category='physical', name='rivers_lake_centerlines', scale='10m',
        edgecolor=cfeature.COLORS['water'], facecolor='none')
    ax.add_feature(rivers)

    # draw borders of states/provinces internal to a country
    states_provinces = cfeature.NaturalEarthFeature(
        category='cultural', name='admin_1_states_provinces_lines', scale='50m',
        edgecolor='gray', facecolor='none')
    ax.add_feature(states_provinces)

    ax.set_aspect('equal')
    gridliner = ax.gridlines(draw_labels=True)
    gridliner.top_labels = False
    gridliner.right_labels = False
    return ax
Example #4
0
    def plot_convergences(self,
                          convergence_t: pd.DataFrame = None,
                          convergence_f: pd.DataFrame = None,
                          fig: mpl.figure.Figure = None,
                          _display: bool = True):
        """Creates 3 plots, useful to determin the convergence achieved by the renderer:
        * convergence frequency vs. pass number if fig is None.
        * delta frequency and solved elements vs. pass number.
        * delta frequency vs. solved elements.

        Args:
            convergence_t (pd.DataFrame): Convergence vs pass number of the eigenemode freqs.
            convergence_f (pd.DataFrame): Convergence vs pass number of the eigenemode freqs.
            fig (matplotlib.figure.Figure, optional): A mpl figure. Defaults to None.
            _display (bool, optional): Display the plot? Defaults to True.
        """

        if convergence_t is None:
            convergence_t = self.convergence_t
        if convergence_f is None:
            convergence_f = self.convergence_f

        if fig is None:
            fig = plt.figure(figsize=(11, 3.))

            # Grid spec and axes;    height_ratios=[4, 1], wspace=0.5
            gspec = mpl.gridspec.GridSpec(1, 3, width_ratios=[1.2, 1.5, 1])
            axs = [fig.add_subplot(gspec[i]) for i in range(3)]

            ax0t = axs[1].twinx()
            plot_convergence_f_vspass(axs[0], convergence_f)
            plot_convergence_max_df(axs[1], convergence_t.iloc[:, 1])
            plot_convergence_solved_elem(ax0t, convergence_t.iloc[:, 0])
            plot_convergence_maxdf_vs_sol(axs[2], convergence_t.iloc[:, 1],
                                          convergence_t.iloc[:, 0])

            fig.tight_layout(w_pad=0.1)  # pad=0.0, w_pad=0.1, h_pad=1.0)
Example #5
0
def plot_avg_decay_data(t_sol: Union[np.ndarray, List[np.array]],
                        list_sim_data: List[np.array],
                        list_exp_data: List[np.array] = None,
                        state_labels: List[str] = None,
                        concentration: Conc = None,
                        atol: float = A_TOL,
                        colors: Union[str, Tuple[ColorMap, ColorMap]] = 'rk',
                        fig: mpl.figure.Figure = None,
                        title: str = '') -> None:
    ''' Plot the list of simulated and experimental data (optional) against time in t_sol.
        If concentration is given, the legend will show the concentrations.
        colors is a string with two chars. The first is the sim color,
        the second the exp data color.
    '''
    num_plots = len(list_sim_data)
    num_rows = 3
    num_cols = int(np.ceil(num_plots / 3))

    # optional lists default to list of None
    list_exp_data = list_exp_data or [None] * num_plots
    state_labels = state_labels or [''] * num_plots

    list_t_sim = t_sol if len(
        t_sol) == num_plots else [t_sol] * num_plots  # type: List[np.array]

    if concentration:
        conc_str = '_' + str(concentration.S_conc) + 'S_' + str(
            concentration.A_conc) + 'A'


#        state_labels = [label+conc_str for label in state_labels]
    else:
        conc_str = ''

    sim_color = colors[0]
    exp_color = colors[1]
    exp_size = 2  # marker size
    exp_marker = '.'

    if fig is None:
        fig = plt.figure()

    fig.suptitle(title + '. Time in ms.')

    list_axes = fig.get_axes()  # type: List
    if not list_axes:
        for num in range(num_plots):
            fig.add_subplot(num_rows, num_cols, num + 1)
        list_axes = fig.get_axes()

    for sim_data, t_sim, exp_data, state_label, axes\
        in zip(list_sim_data, list_t_sim, list_exp_data, state_labels, list_axes):

        if state_label:
            axes.set_title(
                state_label.replace('_', ' '), {
                    'horizontalalignment': 'center',
                    'verticalalignment': 'center',
                    'fontweight': 'bold',
                    'fontsize': 10
                })

        if sim_data is None or np.isnan(sim_data).any() or not np.any(
                sim_data > 0):
            continue

        # no exp data: either a GS or simply no exp data available
        if exp_data is 0 or exp_data is None:
            # nonposy='clip': clip non positive values to a very small positive number
            axes.semilogy(t_sim * 1000,
                          sim_data,
                          color=sim_color,
                          label=state_label + conc_str)

            axes.axis('tight')
            axes.set_xlim(left=t_sim[0] * 1000.0)
            # add some white space above and below
            margin_factor = np.array([0.7, 1.3])
            axes.set_ylim(*np.array(axes.get_ylim()) * margin_factor)
            if axes.set_ylim()[0] < atol:
                axes.set_ylim(bottom=atol)  # don't show noise below atol
                # detect when the simulation goes above and below atol
                above = sim_data > atol
                change_indices = np.where(np.roll(above, 1) != above)[0]
                # make sure change_indices[-1] happens when the population is going BELOW atol
                if change_indices.size > 1 and sim_data[
                        change_indices[-1]] < atol:  # pragma: no cover
                    # last time it changes
                    max_index = change_indices[-1]
                    # show simData until it falls below atol
                    axes.set_xlim(right=t_sim[max_index] * 1000)
            min_y = min(*axes.get_ylim())
            max_y = max(*axes.get_ylim())
            axes.set_ylim(bottom=min_y, top=max_y)
        else:  # exp data available
            sim_handle, = axes.semilogy(t_sim * 1000,
                                        sim_data,
                                        color=sim_color,
                                        label=state_label + conc_str,
                                        zorder=10)
            # convert exp_data time to ms
            exp_handle, = axes.semilogy(exp_data[:, 0] * 1000,
                                        exp_data[:, 1] * np.max(sim_data),
                                        color=exp_color,
                                        marker=exp_marker,
                                        linewidth=0,
                                        markersize=exp_size,
                                        zorder=1)
            axes.axis('tight')
            axes.set_ylim(top=axes.get_ylim()[1] *
                          1.2)  # add some white space on top
            tmin = min(exp_data[-1, 0], t_sim[0])
            axes.set_xlim(left=tmin * 1000.0, right=exp_data[-1, 0] *
                          1000)  # don't show beyond expData

    if conc_str:
        list_axes[0].legend(loc="best", fontsize='small')
        curr_handles, curr_labels = list_axes[0].get_legend_handles_labels()
        new_labels = [
            label.replace(state_labels[0] + '_', '').replace('_', ', ')
            for label in curr_labels
        ]
        list_axes[0].legend(curr_handles,
                            new_labels,
                            markerscale=5,
                            loc="best",
                            fontsize='small')

    fig.subplots_adjust(top=0.918,
                        bottom=0.041,
                        left=0.034,
                        right=0.99,
                        hspace=0.275,
                        wspace=0.12)
    def subplot_data_lists(fig: matplotlib.figure.Figure,
                           subplot_params: tuple,
                           timestamps: list,
                           data: np.array,
                           x_label: str,
                           y_label: str,
                           event_timestamps: list = None,
                           data_labels: list = None,
                           data_colors: list = None,
                           fontsize: int = 30,
                           event_annotation_color='g') -> None:
        '''Plots multiple time series on a single subplot.

        Keyword arguments:
        fig -- matplotlib figure handle
        subplot_params -- a tuple with three subplot parameters: number of rows,
                          number of columns, and the number of the current subplot
        timestamps -- a list of timestamps (plotted over the x-axis)
        data -- a 2D numpy array of time series (plotted over the y-axis), where
                each column represents a single time series
        x_label -- x axis label
        y_label -- y axis label
        event_timestamps -- optional list of timestamps for data
                            annotation; the annotations are plotted as
                            green lines at the given timestamps
                            (default None, in which case there are no annotations)
        data_labels -- a list of optional labels for the plotted data, where the size
                       of the list should match the number of columns in "data";
                       if this parameter is passed, a legend is added to the plot
                       (default None)
        data_colors -- a list of optional colors for the plotted data, where the size
                       of the list should match the number of columns in "data"
        fontsize -- fontsize for the x and y axes labels (default 30)
        event_annotation_color -- color of event annotation lines (default 'g')

        '''
        if data_labels:
            try:
                assert data.shape[1] == len(data_labels)
            except AssertionError:
                print(
                    'The length of data_labels should match the number of columns in data'
                )
                return

        if data_colors:
            try:
                assert data.shape[1] == len(data_colors)
            except AssertionError:
                print(
                    'The length of data_colors should match the number of columns in data'
                )
                return

        fig.add_subplot(*subplot_params)

        # we plot the data
        if data_labels and data_colors:
            for i in range(data.shape[1]):
                plt.plot(timestamps,
                         data[:, i],
                         label=data_labels[i],
                         color=data_colors[i])
        elif data_labels:
            for i in range(data.shape[1]):
                plt.plot(timestamps, data[:, i], label=data_labels[i])
        elif data_colors:
            for i in range(data.shape[1]):
                plt.plot(timestamps, data[:, i], color=data_colors[i])
        else:
            for i in range(data.shape[1]):
                plt.plot(timestamps, data[:, i])

        # we add event annotations to the plot if there are any events
        if event_timestamps is not None and len(event_timestamps) > 0:
            plt.plot([event_timestamps, event_timestamps],
                     [np.nanmin(data), np.nanmax(data)],
                     event_annotation_color)

        plt.xlabel(x_label, fontsize=fontsize)
        plt.ylabel(y_label, fontsize=fontsize)

        # we add a legend only if a data label is assigned
        if data_labels:
            plt.legend()