-
David Verelst authoredDavid Verelst authored
dlcplots.py 48.65 KiB
# -*- coding: utf-8 -*-
"""
Created on Tue Sep 16 10:21:11 2014
@author: dave
"""
from __future__ import print_function
from __future__ import division
from __future__ import unicode_literals
from __future__ import absolute_import
from builtins import str
from future import standard_library
standard_library.install_aliases()
#print(*objects, sep=' ', end='\n', file=sys.stdout)
import os
import socket
import gc
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
#from matplotlib.figure import Figure
#from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigCanvas
#from scipy import interpolate as interp
#from scipy.optimize import fmin_slsqp
#from scipy.optimize import minimize
#from scipy.interpolate import interp1d
#import scipy.integrate as integrate
#http://docs.scipy.org/doc/scipy/reference/tutorial/interpolate.html
import pandas as pd
#import openpyxl as px
#import numpy as np
#import windIO
from wetb.prepost import mplutils
from wetb.prepost import Simulations as sim
from wetb.prepost import dlcdefs
plt.rc('font', family='serif')
plt.rc('xtick', labelsize=10)
plt.rc('ytick', labelsize=10)
plt.rc('axes', labelsize=12)
# do not use tex on Gorm
if not socket.gethostname()[:2] in ['g-', 'je']:
plt.rc('text', usetex=True)
plt.rc('legend', fontsize=11)
plt.rc('legend', numpoints=1)
plt.rc('legend', borderaxespad=0)
# =============================================================================
### STAT PLOTS
# =============================================================================
def plot_stats(sim_ids, post_dirs, fig_dir_base=None):
"""
For each wind speed, take the max of the max.
Only one or two sim_ids are supported. When they are from different
models/projects, specify for each sim_id a different post_dir
Parameters
----------
sim_ids : list
list of sim_id's, 1 or 2
post_dirs
list of post_dir's, 1 or 2. If 2, should correspond to sim_ids
fig_dir_base : str, default=None
"""
# if sim_id is a list, combine the two dataframes into one
df_stats = pd.DataFrame()
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
cc = sim.Cases(post_dir, sim_id, rem_failed=True)
if ii == 0:
df_stats, _, _ = cc.load_stats()
else:
# because there is no unique index, we will ignore it
df_stats, _, _ = pd.concat([df_stats, cc.load_stats()],
ignore_index=True)
else:
sim_id = sim_ids
sim_ids = False
post_dir = post_dirs
cc = sim.Cases(post_dir, sim_id, rem_failed=True)
df_stats, _, _ = cc.load_stats()
# if force_dir:
# cc.change_results_dir(resdir=force_dir)
# for case in cc.cases:
# sim_id = cc.cases[case]['[post_dir]']
# cc.cases[case]['[post_dir]'] = post_dir
# # add DLC category
# f = lambda x: x.split('_')[0]
# df_stats['DLC'] = df_stats['[Case id.]'].map(f)
# fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(12,8), num=1)
# define the number of positions you want to have the color for
N = 22
# select a color map
cmap = mpl.cm.get_cmap('jet', N)
# convert to array
cmap_arr = cmap(np.arange(N))
# color=cmap_arr[icol][0:3]
# make a stastics plot for each channel
gb_ch = df_stats.groupby(df_stats.channel)
# channel selection
plot_chans = {}
plot_chans['DLL-2-inpvec-2'] = 'P_e'
plot_chans['bearing-shaft_rot-angle_speed-rpm'] = 'RPM'
plot_chans['tower-tower-node-001-momentvec-x'] = 'M_x T_B'
plot_chans['tower-tower-node-001-momentvec-y'] = 'M_y T_B'
plot_chans['tower-tower-node-001-momentvec-z'] = 'M_z T_B'
plot_chans['tower-tower-node-008-momentvec-z'] = 'M_x T_T'
plot_chans['tower-tower-node-008-momentvec-z'] = 'M_y T_T'
plot_chans['tower-tower-node-008-momentvec-z'] = 'M_z T_T'
plot_chans['shaft-shaft-node-004-momentvec-x'] = 'M_x Shaft_{MB}'
plot_chans['shaft-shaft-node-004-momentvec-y'] = 'M_y Shaft_{MB}'
plot_chans['shaft-shaft-node-004-momentvec-z'] = 'M_z Shaft_{MB}'
plot_chans['blade1-blade1-node-003-momentvec-x'] = 'M_x B1_{root}'
plot_chans['blade1-blade1-node-003-momentvec-y'] = 'M_y B1_{root}'
plot_chans['blade1-blade1-node-003-momentvec-z'] = 'M_z B1_{root}'
plot_chans['blade2-blade2-node-003-momentvec-x'] = 'M_x B2_{root}'
plot_chans['blade2-blade2-node-003-momentvec-y'] = 'M_y B2_{root}'
plot_chans['blade2-blade2-node-003-momentvec-z'] = 'M_z B2_{root}'
plot_chans['blade3-blade3-node-003-momentvec-x'] = 'M_x B3_{root}'
plot_chans['blade3-blade3-node-003-momentvec-y'] = 'M_y B3_{root}'
plot_chans['blade3-blade3-node-003-momentvec-z'] = 'M_z B3_{root}'
plot_chans['DLL-5-inpvec-1'] = 'Min tower clearance'
plot_chans['bearing-pitch1-angle-deg'] = 'B1_{pitch}'
plot_chans['bearing-pitch2-angle-deg'] = 'B2_{pitch}'
plot_chans['bearing-pitch3-angle-deg'] = 'B3_{pitch}'
plot_chans['setbeta-bladenr-1-flapnr-1'] = 'B1_{flap}'
plot_chans['setbeta-bladenr-2-flapnr-1'] = 'B2_{flap}'
plot_chans['setbeta-bladenr-3-flapnr-1'] = 'B3_{flap}'
mfcs1 = ['k', 'w']
mfcs2 = ['b', 'w']
mfcs3 = ['r', 'w']
stds = ['r', 'b']
for nr, (ch_name, gr_ch) in enumerate(gb_ch):
if ch_name not in plot_chans:
continue
for dlc_name, gr_ch_dlc in gr_ch.groupby(df_stats['[DLC]']):
print('start plotting: %s %s' % (str(dlc_name).ljust(7), ch_name))
fig, axes = mplutils.make_fig(nrows=1, ncols=1, figsize=(7,5))
ax = axes[0,0]
# seperate figure for the standard deviations
fig2, axes2 = mplutils.make_fig(nrows=1, ncols=1, figsize=(7,5))
ax2 = axes2[0,0]
if fig_dir_base is None and not sim_ids:
res_dir = gr_ch_dlc['[res_dir]'][:1].values[0]
run_dir = gr_ch_dlc['[run_dir]'][:1].values[0]
fig_dir = os.path.join(fig_dir_base, res_dir)
elif fig_dir_base is None and isinstance(sim_ids, list):
fig_dir = os.path.join(fig_dir_base, '-'.join(sim_ids))
elif fig_dir_base and not sim_ids:
res_dir = gr_ch_dlc['[res_dir]'][:1].values[0]
fig_dir = os.path.join(fig_dir_base, res_dir)
elif sim_ids and 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
ii = 0
sid_names = []
for run_dir, gr_ch_dlc_sid in gr_ch_dlc.groupby(df_stats['[run_dir]']):
sid_name = run_dir.split('/')[-2]
sid_names.append(sid_name)
print(sid_name)
wind = gr_ch_dlc_sid['[Windspeed]'].values
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 not sim_ids:
lab1 = 'mean'
lab2 = 'min'
lab3 = 'max'
lab4 = 'std'
else:
lab1 = 'mean %s' % sid_name
lab2 = 'min %s' % sid_name
lab3 = 'max %s' % sid_name
lab4 = 'std %s' % sid_name
mfc1 = mfcs1[ii]
mfc2 = mfcs2[ii]
mfc3 = mfcs3[ii]
ax.plot(wind, dmean, mec='k', marker='o', mfc=mfc1, ls='',
label=lab1, alpha=0.7)
ax.plot(wind, dmin, mec='b', marker='^', mfc=mfc2, ls='',
label=lab2, alpha=0.7)
ax.plot(wind, dmax, mec='r', marker='v', mfc=mfc3, ls='',
label=lab3, alpha=0.7)
ax2.plot(wind, dstd, mec=stds[ii], marker='s', mfc=stds[ii], ls='',
label=lab4, alpha=0.7)
ii += 1
# 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)
ax.grid()
ax.set_xlim([3, 27])
leg = ax.legend(loc='best', ncol=2)
leg.get_frame().set_alpha(0.7)
ax.set_title(r'{DLC%s} $%s$' % (dlc_name, plot_chans[ch_name]))
ax.set_xlabel('Wind speed [m/s]')
fig.tight_layout()
fig.subplots_adjust(top=0.92)
if not sim_ids:
fig_path = os.path.join(fig_dir,
ch_name.replace(' ', '_') + '.png')
else:
sids = '_'.join(sid_names)
# fig_dir = run_dir.split('/')[:-1] + 'figures/'
fname = '%s_%s.png' % (ch_name.replace(' ', '_'), sids)
fig_path = os.path.join(fig_dir, 'dlc%s/' % dlc_name)
if not os.path.exists(fig_path):
os.makedirs(fig_path)
fig_path = fig_path + fname
fig.savefig(fig_path)#.encode('latin-1')
# canvas.close()
fig.clear()
print('saved: %s' % fig_path)
ax2.grid()
ax2.set_xlim([3, 27])
leg = ax2.legend(loc='best', ncol=2)
leg.get_frame().set_alpha(0.7)
ax2.set_title(r'{DLC%s} $%s$' % (dlc_name, plot_chans[ch_name]))
ax2.set_xlabel('Wind speed [m/s]')
fig2.tight_layout()
fig2.subplots_adjust(top=0.92)
if not sim_ids:
fig_path = os.path.join(fig_dir,
ch_name.replace(' ', '_') + '_std.png')
else:
sids = '_'.join(sid_names)
fname = '%s_std_%s.png' % (ch_name.replace(' ', '_'), sids)
fig_path = os.path.join(fig_dir, 'dlc%s/' % dlc_name)
if not os.path.exists(fig_path):
os.makedirs(fig_path)
fig_path = fig_path + fname
fig2.savefig(fig_path)#.encode('latin-1')
# canvas.close()
fig2.clear()
print('saved: %s' % fig_path)
def plot_stats2(sim_ids, post_dirs, fig_dir_base=None, labels=None,
post_dir_save=False, dlc_ignore=['00']):
"""
Map which channels have to be compared
"""
plot_chans = {}
plot_chans['B1_{flap}'] = ['setbeta-bladenr-1-flapnr-1']
plot_chans['B2_{flap}'] = ['setbeta-bladenr-2-flapnr-1']
plot_chans['B3_{flap}'] = ['setbeta-bladenr-3-flapnr-1']
plot_chans['M_x B1_{root}'] = ['blade1-blade1-node-003-momentvec-x',
'blade1-blade1-node-004-momentvec-x']
plot_chans['M_y B1_{root}'] = ['blade1-blade1-node-003-momentvec-y',
'blade1-blade1-node-004-momentvec-y']
plot_chans['M_z B1_{root}'] = ['blade1-blade1-node-003-momentvec-z',
'blade1-blade1-node-004-momentvec-z']
plot_chans['B3_{pitch}'] = ['bearing-pitch3-angle-deg']
plot_chans['RPM'] = ['bearing-shaft_rot-angle_speed-rpm']
plot_chans['P_e'] = ['DLL-2-inpvec-2']
plot_chans['P_{mech}'] = ['stats-shaft-power']
plot_chans['M_x B3_{root}'] = ['blade3-blade3-node-003-momentvec-x',
'blade3-blade3-node-004-momentvec-x']
plot_chans['M_y B3_{root}'] = ['blade3-blade3-node-003-momentvec-y',
'blade3-blade3-node-004-momentvec-y']
plot_chans['M_z B3_{root}'] = ['blade3-blade3-node-003-momentvec-z',
'blade3-blade3-node-004-momentvec-z']
plot_chans['B2_{pitch}'] = ['bearing-pitch2-angle-deg']
plot_chans['B3 U_y'] = ['global-blade3-elem-018-zrel-1.00-State pos-y']
plot_chans['M_z B2_{root}'] = ['blade2-blade2-node-003-momentvec-z',
'blade2-blade2-node-004-momentvec-z']
plot_chans['M_x B2_{root}'] = ['blade2-blade2-node-003-momentvec-x',
'blade2-blade2-node-004-momentvec-x']
plot_chans['M_y B2_{root}'] = ['blade2-blade2-node-003-momentvec-y',
'blade2-blade2-node-004-momentvec-y']
plot_chans['B1_{pitch}'] = ['bearing-pitch1-angle-deg']
plot_chans['M_x T_B'] = ['tower-tower-node-001-momentvec-x']
plot_chans['M_y T_B'] = ['tower-tower-node-001-momentvec-y']
plot_chans['M_z T_B'] = ['tower-tower-node-001-momentvec-z']
plot_chans['tower clearance'] = ['DLL-5-inpvec-1']
plot_chans['M_z T_T'] = ['tower-tower-node-008-momentvec-z']
plot_chans['M_y Shaft_{MB}'] = ['shaft-shaft-node-004-momentvec-y']
plot_chans['M_x Shaft_{MB}'] = ['shaft-shaft-node-004-momentvec-x']
plot_chans['M_z Shaft_{MB}'] = ['shaft-shaft-node-004-momentvec-z']
# reduce required memory, only use following columns
cols = ['[run_dir]', '[DLC]', 'channel', '[res_dir]', '[Windspeed]',
'mean', 'max', 'min', 'std', '[wdir]']
# if sim_id is a list, combine the two dataframes into one
df_stats = pd.DataFrame()
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
cc = sim.Cases(post_dir, sim_id, rem_failed=True)
df_stats, _, _ = cc.load_stats(columns=cols, leq=False)
print('%s Cases loaded.' % sim_id)
# if specified, save the merged sims elsewhere
if post_dir_save:
fpath = os.path.join(post_dir_save, '-'.join(sim_ids) + '.h5')
try:
os.makedirs(post_dir_save)
except OSError:
pass
else:
fpath = os.path.join(post_dir, '-'.join(sim_ids) + '.h5')
if ii == 0:
# and save somewhere so we can add the second data frame on
# disc
df_stats.to_hdf(fpath, 'table', mode='w', format='table',
complevel=9, complib='blosc')
print('%s merged stats written to: %s' % (sim_id, fpath))
else:
# instead of doing a concat in memory, add to the hdf store
df_stats.to_hdf(fpath, 'table', mode='r+', format='table',
complevel=9, complib='blosc', append=True)
print('%s merging stats into: %s' % (sim_id, fpath))
# df_stats = pd.concat([df_stats, df_stats2], ignore_index=True)
# df_stats2 = None
# we might run into memory issues
del df_stats, _, cc
gc.collect()
# and load the reduced combined set
print('loading merged stats: %s' % fpath)
df_stats = pd.read_hdf(fpath, 'table')
else:
sim_id = sim_ids
sim_ids = [sim_id]
post_dir = post_dirs
cc = sim.Cases(post_dir, sim_id, rem_failed=True)
df_stats, _, _ = cc.load_stats(leq=False)
mfcs1 = ['k', 'w']
mfcs2 = ['b', 'w']
mfcs3 = ['r', 'w']
stds = ['r', 'b']
# first, take each DLC appart
for dlc_name, gr_dlc in df_stats.groupby(df_stats['[DLC]']):
# do not plot the stats for dlc00
if dlc_name 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):
df_chan = gr_dlc[gr_dlc.channel == ch_names[0]]
fname_base = ch_names[0].replace(' ', '_')
try:
df2 = gr_dlc[gr_dlc.channel == ch_names[1]]
df_chan = pd.concat([df_chan, df2], ignore_index=True)
except IndexError:
pass
else:
ch_name = ch_names
ch_names = [ch_name]
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 = []
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 or lens[1] < 1):
continue
print('start plotting: %s %s' % (str(dlc_name).ljust(7), ch_dscr))
fig, axes = mplutils.make_fig(nrows=1, ncols=1,
figsize=(11,7.15), dpi=120)
ax = axes[0,0]
# seperate figure for the standard deviations
fig2, axes2 = mplutils.make_fig(nrows=1, ncols=1,
figsize=(11,7.15), 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 isinstance(sim_ids, list):
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 sim_ids and 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
ii = 0
sid_names = []
for run_dir, gr_ch_dlc_sid in df_chan.groupby(df_chan['[run_dir]']):
if labels is None:
sid_name = run_dir.split(os.path.sep)[-2]
else:
sid_name = labels[ii]
sid_names.append(sid_name)
print(' sim_id/label:', sid_name)
# FIXME: will this go wrong in PY3?
if str(dlc_name) in ['61', '62']:
xdata = gr_ch_dlc_sid['[wdir]'].values
xlabel = 'wind direction [deg]'
xlims = [0, 360]
else:
xdata = gr_ch_dlc_sid['[Windspeed]'].values
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 not sim_ids:
lab1 = 'mean'
lab2 = 'min'
lab3 = 'max'
lab4 = 'std'
else:
lab1 = 'mean %s' % sid_name
lab2 = 'min %s' % sid_name
lab3 = 'max %s' % sid_name
lab4 = 'std %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)
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)
ax2.plot(xdata, dstd, mec=stds[ii], marker='s', mfc=stds[ii],
ls='', label=lab4, alpha=0.7)
ii += 1
# 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)
ax.grid()
ax.set_xlim(xlims)
leg = ax.legend(loc='best', ncol=3)
leg.get_frame().set_alpha(0.7)
ax.set_title(r'{DLC%s} $%s$' % (dlc_name, ch_dscr))
ax.set_xlabel(xlabel)
fig.tight_layout()
fig.subplots_adjust(top=0.92)
if not sim_ids:
fig_path = os.path.join(fig_dir, fname_base + '.png')
else:
sids = '_'.join(sid_names)
fname = '%s_%s.png' % (fname_base, sids)
fig_path = os.path.join(fig_dir, 'dlc%s/' % dlc_name)
if not os.path.exists(fig_path):
os.makedirs(fig_path)
fig_path = fig_path + fname
fig.savefig(fig_path)#.encode('latin-1')
fig.clear()
print('saved: %s' % fig_path)
ax2.grid()
ax2.set_xlim(xlims)
leg = ax2.legend(loc='best', ncol=3)
leg.get_frame().set_alpha(0.7)
ax2.set_title(r'{DLC%s} $%s$' % (dlc_name, ch_dscr))
ax2.set_xlabel('Wind speed [m/s]')
fig2.tight_layout()
fig2.subplots_adjust(top=0.92)
if not sim_ids:
fig_path = os.path.join(fig_dir, fname_base + '_std.png')
else:
sids = '_'.join(sid_names)
fname = '%s_std_%s.png' % (fname_base, sids)
fig_path = os.path.join(fig_dir, 'dlc%s/' % dlc_name)
if not os.path.exists(fig_path):
os.makedirs(fig_path)
fig_path = fig_path + fname
fig2.savefig(fig_path)#.encode('latin-1')
fig2.clear()
print('saved: %s' % fig_path)
def plot_stats3(df_stats, plot_chans, fig_dir_base, labels=None):
"""
Same as plot_stats2, but give a df with the stats of that sim_id and the
relevant channels.
df_stats columns:
* [DLC]
* [run_dir]
* channel
* stat parameters
"""
mfcs1 = ['k', 'w']
mfcs2 = ['b', 'w']
mfcs3 = ['r', 'w']
stds = ['r', 'b']
# first, take each DLC appart
for dlc_name, gr_dlc in df_stats.groupby(df_stats['[DLC]']):
# 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):
df_chan = gr_dlc[gr_dlc.channel == ch_names[0]]
fname_base = ch_names[0].replace(' ', '_')
try:
df2 = gr_dlc[gr_dlc.channel == ch_names[1]]
df_chan = pd.concat([df_chan, df2], ignore_index=True)
except IndexError:
pass
else:
ch_name = ch_names
ch_names = [ch_name]
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 = []
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 or lens[1] < 1):
continue
print('start plotting: %s %s' % (str(dlc_name).ljust(7), ch_dscr))
fig, axes = mplutils.make_fig(nrows=1, ncols=1,
figsize=(11,7.15), dpi=120)
ax = axes[0,0]
# seperate figure for the standard deviations
fig2, axes2 = mplutils.make_fig(nrows=1, ncols=1,
figsize=(11,7.15), dpi=120)
ax2 = axes2[0,0]
# 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
ii = 0
sid_names = []
for run_dir, gr_ch_dlc_sid in df_chan.groupby(df_chan['[run_dir]']):
if labels is None:
sid_name = run_dir.split(os.path.sep)[-2]
else:
sid_name = labels[ii]
sid_names.append(sid_name)
print(' sim_id/label:', sid_name)
# FIXME: will this go wrong in PY3?
if str(dlc_name) in ['61', '62']:
xdata = gr_ch_dlc_sid['[wdir]'].values
xlabel = 'wind direction [deg]'
xlims = [0, 360]
else:
xdata = gr_ch_dlc_sid['[Windspeed]'].values
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
lab1 = 'mean %s' % sid_name
lab2 = 'min %s' % sid_name
lab3 = 'max %s' % sid_name
lab4 = 'std %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)
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)
ax2.plot(xdata, dstd, mec=stds[ii], marker='s', mfc=stds[ii],
ls='', label=lab4, alpha=0.7)
ii += 1
# 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)
ax.grid()
ax.set_xlim(xlims)
leg = ax.legend(loc='best', ncol=3)
leg.get_frame().set_alpha(0.7)
ax.set_title(r'{DLC%s} $%s$' % (dlc_name, ch_dscr))
ax.set_xlabel(xlabel)
fig.tight_layout()
fig.subplots_adjust(top=0.92)
fig_path = os.path.join(fig_dir_base, 'dlc%s/' % dlc_name)
if not os.path.exists(fig_path):
os.makedirs(fig_path)
fname = os.path.join(fig_path, fname_base + '.png')
fig.savefig(fname)#.encode('latin-1')
fig.clear()
print('saved: %s' % fname)
ax2.grid()
ax2.set_xlim(xlims)
leg = ax2.legend(loc='best', ncol=3)
leg.get_frame().set_alpha(0.7)
ax2.set_title(r'{DLC%s} $%s$' % (dlc_name, ch_dscr))
ax2.set_xlabel('Wind speed [m/s]')
fig2.tight_layout()
fig2.subplots_adjust(top=0.92)
fname = os.path.join(fig_path, fname_base + '_std.png')
fig2.savefig(fname)#.encode('latin-1')
fig2.clear()
print('saved: %s' % fname)
class PlotStats(object):
def __init__(self):
pass
def load_stats(self, sim_ids, post_dirs, post_dir_save=False):
self.sim_ids = sim_ids
self.post_dirs = post_dirs
# reduce required memory, only use following columns
cols = ['[run_dir]', '[DLC]', 'channel', '[res_dir]', '[Windspeed]',
'mean', 'max', 'min', 'std', '[wdir]']
# if sim_id is a list, combine the two dataframes into one
df_stats = pd.DataFrame()
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
cc = sim.Cases(post_dir, sim_id, rem_failed=True)
df_stats, _, _ = cc.load_stats(columns=cols, leq=False)
print('%s Cases loaded.' % sim_id)
# if specified, save the merged sims elsewhere
if post_dir_save:
fpath = os.path.join(post_dir_save, '-'.join(sim_ids) + '.h5')
try:
os.makedirs(post_dir_save)
except OSError:
pass
else:
fpath = os.path.join(post_dir, '-'.join(sim_ids) + '.h5')
if ii == 0:
# and save somewhere so we can add the second data frame on
# disc
df_stats.to_hdf(fpath, 'table', mode='w', format='table',
complevel=9, complib='blosc')
print('%s merged stats written to: %s' % (sim_id, fpath))
else:
# instead of doing a concat in memory, add to the hdf store
df_stats.to_hdf(fpath, 'table', mode='r+', format='table',
complevel=9, complib='blosc', append=True)
print('%s merging stats into: %s' % (sim_id, fpath))
# we might run into memory issues
del df_stats, _, cc
gc.collect()
# and load the reduced combined set
print('loading merged stats: %s' % fpath)
df_stats = pd.read_hdf(fpath, 'table')
else:
sim_id = sim_ids
sim_ids = [sim_id]
post_dir = post_dirs
cc = sim.Cases(post_dir, sim_id, rem_failed=True)
df_stats, _, _ = cc.load_stats(leq=False)
return df_stats
def select_extremes_blade_radial(self, df):
"""
For each radial position of the blade, find the extremes
"""
def selector(x):
"""
select following channels:
'local-blade%1i-node-%03i-momentvec-x'
'blade2-blade2-node-003-momentvec-y'
"""
if x[:11] == 'local-blade' and x[22:31] == 'momentvec':
return True
else:
return False
# find all blade local load channels
criteria = df.channel.map(lambda x: selector(x))
df = df[criteria]
# split channel columns so we can select channels properly
df = df.join(df.channel.apply(lambda x: pd.Series(x.split('-'))))
df_ext = {'dlc':[], 'case':[], 'node':[], 'max':[], 'min':[], 'comp':[]}
def fillvalues(x, ii, maxmin):
x['node'].append(m_group[3].ix[ii])
x['dlc'].append(m_group['[DLC]'].ix[ii])
x['case'].append(m_group['[case_id]'].ix[ii])
x['comp'].append(m_group[5].ix[ii])
if maxmin == 'max':
x['max'].append(m_group['max'].ix[ii])
x['min'].append(np.nan)
else:
x['max'].append(np.nan)
x['min'].append(m_group['min'].ix[ii])
return x
# we take blade1, blade2, and blade3
df_b2 = df[df[0]=='local']
# df_b2 = df_b2[df_b2[1]=='blade2']
df_b2 = df_b2[df_b2[4]=='momentvec']
# df_b2 = df_b2[df_b2[5]=='x']
# make sure we only have blade1, 2 and 3
assert set(df_b2[1].unique()) == set(['blade3', 'blade2', 'blade1'])
# # number of nodes
# nrnodes = len(df_b2[3].unique())
# group by node number, and take the max
for nodenr, group in df_b2.groupby(df_b2[3]):
print(nodenr, end=' ')
for comp, m_group in df_b2.groupby(group[5]):
print(comp)
imax = m_group['max'].argmax()
imin = m_group['min'].argmin()
df_ext = fillvalues(df_ext, imax, 'max')
df_ext = fillvalues(df_ext, imin, 'min')
df_ext = pd.DataFrame(df_ext)
df_ext.sort(columns='node', inplace=True)
return df_ext
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'))
def extract_leq_blade_radial(self, df_leq, fpath):
def selector(x):
"""
select following channels:
'local-blade%1i-node-%03i-momentvec-x'
'blade2-blade2-node-003-momentvec-y'
"""
if x[:11] == 'local-blade' and x[22:31] == 'momentvec':
return True
else:
return False
# find all blade local load channels
criteria = df_leq.channel.map(lambda x: selector(x))
df = df_leq[criteria]
# split channel columns so we can select channels properly
df = df.join(df.channel.apply(lambda x: pd.Series(x.split('-'))))
df.sort(columns=3, inplace=True)
assert set(df[1].unique()) == set(['blade3', 'blade2', 'blade1'])
leqs = list(df.keys())[1:10]
df_ext = {leq:[] for leq in leqs}
df_ext['node'] = []
df_ext['comp'] = []
for nodenr, group in df.groupby(df[3]):
print(nodenr, end=' ')
for comp, m_group in df.groupby(group[5]):
print(comp)
for leq in leqs:
df_ext[leq].append(m_group[leq].max())
df_ext['node'].append(nodenr)
df_ext['comp'].append(comp)
df_ext = pd.DataFrame(df_ext)
df_ext.sort(columns='node', inplace=True)
df_ext[df_ext.comp=='x'].to_excel(fpath.replace('.xls', '_x.xls'))
df_ext[df_ext.comp=='y'].to_excel(fpath.replace('.xls', '_y.xls'))
df_ext[df_ext.comp=='z'].to_excel(fpath.replace('.xls', '_z.xls'))
return df_ext
class PlotPerf(object):
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
def plot(self, res, label_id):
"""
"""
i = self.i
sim_id = label_id
time = res.sig[:,0]
self.t0, self.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-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]
try:
chi = res.ch_dict['Tors_e-1-100.11']['chi']
except KeyError:
chi = res.ch_dict['Tors_e-1-86.50']['chi']
tors_1 = res.sig[:,chi]
# try:
# chi = res.ch_dict['Tors_e-1-96.22']['chi']
# except:
# chi = res.ch_dict['Tors_e-1-83.13']['chi']
# tors_2 = res.sig[:,chi]
try:
chi = res.ch_dict['Tors_e-1-84.53']['chi']
except:
chi = res.ch_dict['Tors_e-1-73.21']['chi']
tors_3 = res.sig[:,chi]
ax = self.axes.ravel()
ax[0].plot(time, wind, self.col[i]+'--', label='%s wind speed' % sim_id,
alpha=self.alf[i])
ax[0].plot(time, pitch, self.col[i]+'-.', label='%s pitch' % sim_id,
alpha=self.alf[i])
ax[0].plot(time, rpm, self.col[i]+'-', label='%s RPM' % sim_id,
alpha=self.alf[i])
ax[1].plot(time, tx, self.col[i]+'--', label='%s Tower FA' % sim_id,
alpha=self.alf[i])
ax[1].plot(time, ty, self.col[i]+'-', label='%s Tower SS' % sim_id,
alpha=self.alf[i])
ax[2].plot(time, power/1e6, self.col[i]+'-', alpha=self.alf[i],
label='%s El Power' % sim_id)
ax[3].plot(time, tors_1, self.col[i]+'--', label='%s torsion tip' % sim_id,
alpha=self.alf[i])
# ax[3].plot(time, tors_2, self.col[i]+'-.', label='%s torsion 96 pc' % sim_id,
# alpha=self.alf[i])
# ax[3].plot(time, tors_3, self.col[i]+'-', label='%s torsion 84 pc' % sim_id,
# alpha=self.alf[i])
self.i += 1
def final(self, fig_path, fig_name):
axs = self.axes.ravel()
for ax in axs:
ax.set_xlim([self.t0, self.t1])
ax.grid()
ax.legend(loc='best')
axs[0].set_xticklabels([])
axs[1].set_xticklabels([])
axs[2].set_xticklabels([])
axs[-1].set_xlabel('time [s]')
self.fig.tight_layout()
self.fig.subplots_adjust(hspace=0.06)
self.fig.subplots_adjust(top=0.98)
if not os.path.exists(fig_path):
os.makedirs(fig_path)
fname = os.path.join(fig_path, fig_name)
print('saving: %s ...' % fname, end='')
self.fig.savefig(fname)#.encode('latin-1')
print('done')
self.fig.clear()
def plot_dlc01_powercurve(sim_ids, post_dirs, run_dirs, fig_dir_base):
"""
Create power curve based on steady DLC01 results
Use the same format as for HS2 for easy comparison!
"""
def plot_dlc00(sim_ids, post_dirs, run_dirs, fig_dir_base=None, labels=None,
cnames=['dlc00_stair_wsp04_25_noturb.htc',
'dlc00_ramp_wsp04_25_04_noturb.htc'], figsize=(14,11)):
"""
This version is an update over plot_staircase.
"""
stairs = []
# 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:
post_dir = post_dirs
stairs.append(sim.Cases(post_dir, sim_id, rem_failed=True))
for cname in cnames:
fp = PlotPerf(figsize=figsize)
for i, cc in enumerate(stairs):
if isinstance(cname, list):
_cname = cname[i]
else:
_cname = cname
if _cname in cc.cases_fail:
print('no result for %s' % cc.sim_id)
continue
cc.change_results_dir(run_dirs[i])
try:
res = cc.load_result_file(cc.cases[_cname])
except KeyError:
for k in sorted(cc.cases.keys()):
print(k)
print('-'*79)
print(cc.sim_id, _cname)
print('-'*79)
raise KeyError
if labels is not None:
label = labels[i]
else:
label = cc.sim_id
fp.plot(res, label)
dlcf = 'dlc' + cc.cases[_cname]['[DLC]']
fig_path = os.path.join(fig_dir_base, dlcf)
fp.final(fig_path, _cname.replace('.htc', '.png'))
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()
if __name__ == '__main__':
# auto configure directories: assume you are running in the root of the
# relevant HAWC2 model
# and assume we are in a simulation case of a certain turbine/project
P_RUN, P_SOURCE, PROJECT, sim_id, P_MASTERFILE, MASTERFILE, POST_DIR \
= dlcdefs.configure_dirs()
# -------------------------------------------------------------------------
# # manually configure all the dirs
# p_root_remote = '/mnt/hawc2sim'
# p_root_local = '/home/dave/DTU/Projects/AVATAR/'
# # project name, sim_id, master file name
# PROJECT = 'DTU10MW'
# sim_id = 'C0014'
# MASTERFILE = 'dtu10mw_master_C0014.htc'
# # MODEL SOURCES, exchanche file sources
# P_RUN = os.path.join(p_root_remote, PROJECT, sim_id+'/')
# P_SOURCE = os.path.join(p_root_local, PROJECT)
# # location of the master file
# P_MASTERFILE = os.path.join(p_root_local, PROJECT, 'htc', '_master/')
# # location of the pre and post processing data
# POST_DIR = os.path.join(p_root_remote, PROJECT, 'python-prepost-data/')
# force_dir = P_RUN
# -------------------------------------------------------------------------
# PLOT STATS, when comparing cases
sim_ids = [sim_id]
run_dirs = [P_RUN]
figdir = os.path.join(P_RUN, '..', 'figures/%s' % sim_id)
print('='*79)
print(' P_RUN: %s' % P_RUN)
print('P_SOURCE: %s' % P_SOURCE)
print(' PROJECT: %s' % PROJECT)
print(' sim_id: %s' % sim_id)
print(' master: %s' % MASTERFILE)
print(' figdir: %s' % figdir)
print('='*79)
plot_stats2(sim_ids, POST_DIR, fig_dir_base=figdir)
plot_dlc00(sim_ids, POST_DIR, run_dirs, fig_dir_base=figdir)