예제 #1
0
    def __init__(self, nrows=4, ncols=1, figsize=(14, 11)):

        self.fig, self.axes = mplutils.make_fig(nrows=nrows,
                                                ncols=ncols,
                                                figsize=figsize)
        #        self.axs = self.axes.ravel()
        self.col = ['r', 'k']
        self.alf = [1.0, 0.7]
        self.i = 0
예제 #2
0
    def plot_extremes_blade_radial(self, df_ext, fpath):
        nrows = 2
        ncols = 2
        figsize = (11, 7.15)
        fig, axes = mplutils.make_fig(nrows=nrows,
                                      ncols=ncols,
                                      figsize=figsize)

        #        self.col = ['r', 'k']
        #        self.alf = [1.0, 0.7]
        #        self.i = 0

        mx_max = df_ext['max'][df_ext.comp == 'x'].dropna()
        mx_min = df_ext['min'][df_ext.comp == 'x'].dropna()
        my_max = df_ext['max'][df_ext.comp == 'y'].dropna()
        my_min = df_ext['min'][df_ext.comp == 'y'].dropna()
        #        nodes = df_ext.node.ix[mx_max.index]
        axes[0, 0].plot(mx_max, 'r^', label='$M_{x_{max}}$')
        axes[0, 1].plot(mx_min, 'bv', label='$M_{x_{min}}$')
        axes[1, 0].plot(my_max, 'r^', label='$M_{y_{max}}$')
        axes[1, 1].plot(my_min, 'bv', label='$M_{y_{min}}$')

        axs = axes.ravel()
        for ax in axs:
            ax.grid()
            ax.legend(loc='best')


#        axs[0].set_xticklabels([])
#        axs[1].set_xticklabels([])
#        axs[2].set_xticklabels([])
#        axs[-1].set_xlabel('time [s]')

        fig.tight_layout()
        fig.subplots_adjust(hspace=0.06)
        fig.subplots_adjust(top=0.98)

        fdir = os.path.dirname(fpath)
        #        fname = os.path.basename(fpath)

        if not os.path.exists(fdir):
            os.makedirs(fdir)
        print('saving: %s ...' % fpath, end='')
        fig.savefig(fpath)  #.encode('latin-1')
        print('done')
        fig.clear()

        # save as tables
        df_ext.ix[mx_max.index].to_excel(fpath.replace('.png', '_mx_max.xls'))
        df_ext.ix[mx_min.index].to_excel(fpath.replace('.png', '_mx_min.xls'))
        df_ext.ix[my_max.index].to_excel(fpath.replace('.png', '_my_max.xls'))
        df_ext.ix[my_min.index].to_excel(fpath.replace('.png', '_my_min.xls'))
예제 #3
0
def plot_staircase(sim_ids,
                   post_dirs,
                   run_dirs,
                   fig_dir_base=None,
                   cname='dlc00_stair_wsp04_25_noturb.htc'):
    """
    Default stair and ramp names:

    dlc00_stair_wsp04_25_noturb
    dlc00_ramp_wsp04_25_04_noturb
    """

    stairs = []

    col = ['r', 'k']
    alf = [1.0, 0.7]

    # if sim_id is a list, combine the two dataframes into one
    if type(sim_ids).__name__ == 'list':
        for ii, sim_id in enumerate(sim_ids):
            if isinstance(post_dirs, list):
                post_dir = post_dirs[ii]
            else:
                post_dir = post_dirs
            stairs.append(sim.Cases(post_dir, sim_id, rem_failed=True))
    else:
        sim_id = sim_ids
        sim_ids = [sim_id]
        post_dir = post_dirs
        stairs.append(sim.Cases(post_dir, sim_id, rem_failed=True))

    fig, axes = mplutils.make_fig(nrows=3, ncols=1, figsize=(14, 10))
    ax = axes.ravel()

    for i, cc in enumerate(stairs):
        if cname in cc.cases_fail:
            print('no result for %s' % cc.sim_id)
            continue
        cc.change_results_dir(run_dirs[i])
        res = cc.load_result_file(cc.cases[cname])
        respath = cc.cases[cname]['[run_dir]']
        fname = os.path.join(respath, cname)
        df_respost = pd.read_hdf(fname + '_postres.h5', 'table')
        sim_id = cc.sim_id
        time = res.sig[:, 0]
        t0, t1 = time[0], time[-1]

        # find the wind speed
        for channame, chan in res.ch_dict.items():
            if channame.startswith('windspeed-global-Vy-0.00-0.00'):
                break
        wind = res.sig[:, chan['chi']]
        chi = res.ch_dict['bearing-pitch1-angle-deg']['chi']
        pitch = res.sig[:, chi]

        chi = res.ch_dict['bearing-shaft_rot-angle_speed-rpm']['chi']
        rpm = res.sig[:, chi]

        chi = res.ch_dict['bearing-pitch1-angle-deg']['chi']
        pitch = res.sig[:, chi]

        chi = res.ch_dict['tower-tower-node-001-momentvec-x']['chi']
        tx = res.sig[:, chi]

        chi = res.ch_dict['tower-tower-node-001-momentvec-y']['chi']
        ty = res.sig[:, chi]

        chi = res.ch_dict['DLL-2-inpvec-2']['chi']
        power = res.sig[:, chi]

        chi = res.ch_dict['DLL-2-inpvec-2']['chi']
        power_mech = df_respost['stats-shaft-power']

        ax[0].plot(time,
                   wind,
                   col[i] + '--',
                   label='%s wind speed' % sim_id,
                   alpha=alf[i])
        ax[0].plot(time,
                   pitch,
                   col[i] + '-.',
                   label='%s pitch' % sim_id,
                   alpha=alf[i])
        ax[0].plot(time,
                   rpm,
                   col[i] + '-',
                   label='%s RPM' % sim_id,
                   alpha=alf[i])

        ax[1].plot(time,
                   tx,
                   col[i] + '--',
                   label='%s Tower FA' % sim_id,
                   alpha=alf[i])
        ax[1].plot(time,
                   ty,
                   col[i] + '-',
                   label='%s Tower SS' % sim_id,
                   alpha=alf[i])

        ax[2].plot(time,
                   power / 1e6,
                   col[i] + '-',
                   label='%s El Power' % sim_id,
                   alpha=alf[i])
        ax[2].plot(time,
                   power_mech / 1e3,
                   col[i] + '-',
                   alpha=alf[i],
                   label='%s Mech Power' % sim_id)

    ax[0].set_xlim([t0, t1])
    ax[0].grid()
    ax[0].legend(loc='best')
    ax[0].set_xticklabels([])
    #    ax[0].set_xlabel('time [s]')

    ax[1].set_xlim([t0, t1])
    ax[1].grid()
    ax[1].legend(loc='best')
    ax[1].set_xticklabels([])
    #    ax[1].set_xlabel('time [s]')

    ax[2].set_xlim([t0, t1])
    ax[2].grid()
    ax[2].legend(loc='best')
    ax[2].set_xlabel('time [s]')

    fig.tight_layout()
    fig.subplots_adjust(hspace=0.06)
    fig.subplots_adjust(top=0.92)

    if not os.path.exists(fig_dir_base):
        os.makedirs(fig_dir_base)
    fig_path = os.path.join(fig_dir_base, '-'.join(sim_ids) + '_stair.png')
    print('saving: %s ...' % fig_path, end='')
    fig.savefig(fig_path)  #.encode('latin-1')
    print('done')
    fig.clear()
예제 #4
0
def plot_dlc_stats(df_stats,
                   plot_chans,
                   fig_dir_base,
                   labels=None,
                   figsize=(8, 6),
                   dlc_ignore=['00'],
                   run_dirs=None,
                   sim_ids=[],
                   eps=False,
                   ylabels=None,
                   title=True,
                   chans_ms_1hz={}):
    """Create for each DLC an overview plot of the statistics.

    df_stats required columns:
    * [DLC]
    * [run_dir]
    * [wdir]
    * [Windspeed]
    * channel
    * stat parameters

    Parameters
    ----------

    df_stats : pandas.DataFrame

    plot_chans : dict
        Dictionary of channels to be plotted. Key is used for the plot title,
        value is a list of unique channel names that will be included for
        the statistic values. For example,
        plot_chans['$B123 M_x$'] = ['blade1-blade1-node-003-momentvec-x',
        'blade2-blade2-node-003-momentvec-x']

    fig_dir_base : str
        Base directory of where to store all the figures. A new sub-directory
        will be created for each DLC.

    labels : list, default=None
        Labels used in the legend when comparing various DLB's

    figsize : tuple, default=(8,6)

    dlc_ignore : list, default=['dlc00']
        By default all but dlc00 (stair case, wind ramp) are plotted. Add
        more dlc numbers here if necessary.

    run_dirs : list, default=None
        If run_dirs is not defined it will be taken from the unique values
        in the DataFrame. The order of the elements in this list needs to be
        consistent with labels, sim_ids (if defined).

    sim_ids : list, default=[]
        Only used when creating the file name of the figures: appended at
        the end of the file name (which starts with the unique channel name).

    chans_ms_1hz : dict, default={}
        Key/value pairs of channel and list of to be plotten m values. Channel
        refers to plot title/label as used as the key value in plot_chans.

    """
    def fig_epilogue(fig, ax, fname_base):
        ax.grid()
        ax.set_xlim(xlims)
        leg = ax.legend(bbox_to_anchor=(1, 1), loc='lower right', ncol=3)
        leg.get_frame().set_alpha(0.7)
        title_space = 0.0
        if title:
            fig_title = '%s %s' % (dlc_name, ch_dscr)
            # FIXME: dlc_name is assumed to be not in math mode ($$), so
            # escape underscores to avoid latex going bananas
            if mpl.rcParams['text.usetex']:
                fig_title = '%s %s' % (dlc_name.replace('_', '\\_'), ch_dscr)
            fig.suptitle(fig_title)
            title_space = 0.02
        ax.set_xlabel(xlabel)
        if ylabels is not None:
            ax.set_ylabel(ylabels[ch_name])
        fig.tight_layout()
        spacing = 0.94 - title_space - (0.065 * (ii + 1))
        fig.subplots_adjust(top=spacing)
        fig_path = os.path.join(fig_dir, dlc_name)
        if len(sim_ids) == 1:
            fname = fname_base + '.png'
        else:
            fname = '%s_%s.png' % (fname_base, '_'.join(sim_ids))
        if not os.path.exists(fig_path):
            os.makedirs(fig_path)
        fig_path = os.path.join(fig_path, fname)
        fig.savefig(fig_path)  #.encode('latin-1')
        if eps:
            fig.savefig(fig_path.replace('.png', '.eps'))
        fig.clear()
        print('saved: %s' % fig_path)

    mfcs1 = ['k', 'w']
    mfcs2 = ['b', 'w']
    mfcs3 = ['r', 'w']
    mfcs4 = ['k', 'b']
    mark4 = ['s', 'o', '<', '>']
    mfls4 = ['-', '--']

    required = [
        '[DLC]', '[run_dir]', '[wdir]', '[Windspeed]', '[res_dir]',
        '[Case folder]'
    ]
    cols = df_stats.columns
    for col in required:
        if col not in cols:
            print('plot_dlc_stats requires DataFrame with following columns:')
            print(required)
            print('following column is missing in stats DataFrame:', col)
            return

    if run_dirs is None:
        run_dirs = df_stats['[run_dir]'].unique()

    if not sim_ids:
        sim_ids = []
        for run_dir in run_dirs:
            # in case this is a windows path:
            tmp = run_dir.replace('\\', '/').replace(':', '')
            sim_ids.append(tmp.split('/')[-2])

    # first, take each DLC appart
    for gr_name, gr_dlc in df_stats.groupby(df_stats['[Case folder]']):
        dlc_name = gr_name
        if dlc_name[:3].lower() == 'dlc':
            # FIXME: this is messy since this places a hard coded dependency
            # between [Case folder] and [Case id.] when the tag [DLC] is
            # defined in dlcdefs.py
            dlc_name = gr_name.split('_')[0]
        # do not plot the stats for dlc00
        if dlc_name.lower() in dlc_ignore:
            continue
        # cycle through all the target plot channels
        for ch_dscr, ch_names in plot_chans.items():
            # second, group per channel. Note that when the channel names are not
            # identical, we need to manually pick them.
            # figure file name will be the first channel
            if isinstance(ch_names, list):
                ch_name = ch_names[0]
                fname_base = ch_names[0].replace('/', '_')
                df_chan = gr_dlc[gr_dlc.channel.isin(ch_names)]
            else:
                ch_name = ch_names
                ch_names = [ch_names]
                df_chan = gr_dlc[gr_dlc.channel == ch_names]
                fname_base = ch_names.replace('/', '_')

            # if not, than we are missing a channel description, or the channel
            # is simply not available in the given result set
#            if not len(df_chan.channel.unique()) == len(ch_names):
#                continue
            lens = []
            # instead of groupby, select the run_dir in the same order as
            # occuring in the labels and post_dirs lists
            for run_dir in run_dirs:
                lens.append(len(df_chan[df_chan['[run_dir]'] == run_dir]))
#            for key, gr_ch_dlc_sid in df_chan.groupby(df_chan['[run_dir]']):
#                lens.append(len(gr_ch_dlc_sid))
# when the channel is simply not present
            if len(lens) == 0:
                continue
            # when only one of the channels was present, but the set is still
            # complete.
            # FIXME: what if both channels are present?
            if len(ch_names) > 1 and (lens[0] < 1):
                continue
            elif len(ch_names) > 1 and len(lens) == 2 and lens[1] < 1:
                continue

            print('start plotting:  %s %s' % (dlc_name.ljust(10), ch_dscr))

            fig, axes = mplutils.make_fig(nrows=1,
                                          ncols=1,
                                          figsize=figsize,
                                          dpi=120)
            ax = axes[0, 0]
            # seperate figure for the mean of the 1Hz equivalent loads
            fig2, axes2 = mplutils.make_fig(nrows=1,
                                            ncols=1,
                                            figsize=figsize,
                                            dpi=120)
            ax2 = axes2[0, 0]

            if fig_dir_base is None and len(sim_ids) < 2:
                res_dir = df_chan['[res_dir]'][:1].values[0]
                fig_dir = os.path.join(fig_dir_base, res_dir)
            elif fig_dir_base is None and len(sim_ids) > 0:
                fig_dir = os.path.join(fig_dir_base, '-'.join(sim_ids))
#            elif fig_dir_base and len(sim_ids) < 2:
#                res_dir = df_chan['[res_dir]'][:1].values[0]
#                fig_dir = os.path.join(fig_dir_base, res_dir)
            elif fig_dir_base is not None:
                # create the compare directory if not defined
                fig_dir = fig_dir_base

            # if we have a list of different cases, we also need to group those
            # because the sim_id wasn't saved before in the data frame,
            # we need to derive that from the run dir
            # if there is only one run dir nothing changes
#            sid_names = []
# for clarity, set off-set on wind speed when comparing two DLB's
            if len(lens) == 2:
                windoffset = [-0.2, 0.2]
                dirroffset = [-5, 5]
            else:
                windoffset = [0]
                dirroffset = [0]
            # in case of a fully empty plot xlims will remain None and there
            # is no need to save the plot
            xlims = None
            # instead of groupby, select the run_dir in the same order as
            # occuring in the labels, post_dirs lists
            for ii, run_dir in enumerate(run_dirs):
                gr_ch_dlc_sid = df_chan[df_chan['[run_dir]'] == run_dir]
                if len(gr_ch_dlc_sid) < 1:
                    print('no data for run_dir:', run_dir)
                    continue
#            for run_dir, gr_ch_dlc_sid in df_chan.groupby(df_chan['[run_dir]']):
                if labels is None:
                    sid_name = sim_ids[ii]
                else:
                    sid_name = labels[ii]
#                sid_names.append(sid_name)
                print('   sim_id/label:', sid_name)
                # FIXME: will this go wrong in PY3?
                if dlc_name.lower() in ['dlc61', 'dlc62']:
                    key = '[wdir]'
                    xdata = gr_ch_dlc_sid[key].values + dirroffset[ii]
                    xlabel = 'wind direction [deg]'
                    xlims = [0, 360]
                else:
                    key = '[Windspeed]'
                    xdata = gr_ch_dlc_sid[key].values + windoffset[ii]
                    xlabel = 'Wind speed [m/s]'
                    xlims = [3, 27]
                dmin = gr_ch_dlc_sid['min'].values
                dmean = gr_ch_dlc_sid['mean'].values
                dmax = gr_ch_dlc_sid['max'].values
                dstd = gr_ch_dlc_sid['std'].values
                if len(sim_ids) == 1:
                    lab1 = 'mean'
                    lab2 = 'min'
                    lab3 = 'max'
                    lab4 = '1Hz EqL'
                else:
                    lab1 = 'mean %s' % sid_name
                    lab2 = 'min %s' % sid_name
                    lab3 = 'max %s' % sid_name
                    lab4 = '1Hz EqL %s' % sid_name
                mfc1 = mfcs1[ii]
                mfc2 = mfcs2[ii]
                mfc3 = mfcs3[ii]
                ax.errorbar(xdata,
                            dmean,
                            mec='k',
                            marker='o',
                            mfc=mfc1,
                            ls='',
                            label=lab1,
                            alpha=0.7,
                            yerr=dstd,
                            ecolor='k')
                ax.plot(xdata,
                        dmin,
                        mec='b',
                        marker='^',
                        mfc=mfc2,
                        ls='',
                        label=lab2,
                        alpha=0.7)
                ax.plot(xdata,
                        dmax,
                        mec='r',
                        marker='v',
                        mfc=mfc3,
                        ls='',
                        label=lab3,
                        alpha=0.7)

                # mean of 1Hz equivalent loads
                ms = []
                if ch_dscr in chans_ms_1hz:
                    ms = chans_ms_1hz[ch_dscr]
                for im, m in enumerate(ms):
                    # average over seed and possibly yaw angles
                    # wind speed or yaw inflow according to dlc case
                    gr_key = gr_ch_dlc_sid[key]
                    d1hz = gr_ch_dlc_sid[m].groupby(gr_key).mean()

                    ax2.plot(d1hz.index,
                             d1hz.values,
                             mec=mfcs4[ii],
                             alpha=0.7,
                             marker=mark4[im],
                             ls=mfls4[ii],
                             mfc=mfc1,
                             label=lab4,
                             color=mfcs4[ii])


#            for wind, gr_wind in  gr_ch_dlc.groupby(df_stats['[Windspeed]']):
#                wind = gr_wind['[Windspeed]'].values
#                dmin = gr_wind['min'].values#.mean()
#                dmean = gr_wind['mean'].values#.mean()
#                dmax = gr_wind['max'].values#.mean()
##                dstd = gr_wind['std'].mean()
#                ax.plot(wind, dmean, 'ko', label='mean', alpha=0.7)
#                ax.plot(wind, dmin, 'b^', label='min', alpha=0.7)
#                ax.plot(wind, dmax, 'rv', label='max', alpha=0.7)
##                ax.errorbar(wind, dmean, c='k', ls='', marker='s', mfc='w',
##                        label='mean and std', yerr=dstd)
#            if str(dlc_name) not in ['61', '62']:
#                ax.set_xticks(gr_ch_dlc_sid['[Windspeed]'].values)

# don't save empyt plots
            if xlims is None:
                continue

            fig_epilogue(fig, ax, fname_base)

            # don't save empty plots
            if len(ms) < 1:
                continue

            fig_epilogue(fig2, ax2, fname_base + '_1hz_eql')