def contour_plane(plane, axis_vals, avg_data, y_mode, PhyTime): if plane not in ['xy', 'zy', 'xz']: plane = plane[::-1] if plane not in ['xy', 'zy', 'xz']: msg = "The contour slice must be either %s" % ['xy', 'yz', 'xz'] raise KeyError(msg) slice_set = set(plane) coord_set = set(list('xyz')) coord = "".join(coord_set.difference(slice_set)) axis_vals = misc_utils.check_list_vals(axis_vals) if coord == 'y': tg_post = True if all( [x == 'None' for x in avg_data.flow_AVGDF.outer_index]) else False if not tg_post: norm_val = 0 elif tg_post: norm_val = PhyTime else: raise ValueError("problems") norm_vals = [norm_val] * len(axis_vals) if avg_data is None: msg = f'For contour slice {slice}, avg_data must be provided' raise ValueError(msg) axis_index = y_coord_index_norm(avg_data, axis_vals, norm_vals, y_mode) else: axis_index = coord_index_calc(avg_data.CoordDF, coord, axis_vals) if not hasattr(axis_index, '__iter__'): axis_index = [axis_index] # print(axis_index) return plane, coord, axis_index
def _inst_extract(self,time,meta_data=None,path_to_folder='.',abs_path = True,tgpost=False): """ Instantiates CHAPSim_Inst by extracting data from the CHAPSim rawdata results folder Parameters ---------- time : int, float, or list Physical times to extract from results folder meta_data : CHAPSim_meta, optional a metadata instance, if not provided, it will be extracted, by default None path_to_folder : str, optional Path to the results folder, by default '.' abs_path : bool, optional Whether the path provided is an absolute path, by default True tgpost : bool, optional Whether the turbulence generator or spatially developing region are processed, by default False """ if meta_data is None: meta_data = self._module._meta_class(path_to_folder,abs_path,tgpost) self._meta_data = meta_data time = misc_utils.check_list_vals(time) for PhyTime in time: if not hasattr(self, 'InstDF'): self.InstDF = self._flow_extract(PhyTime,path_to_folder,abs_path,tgpost) else: #Variable already exists local_DF = self._flow_extract(PhyTime,path_to_folder,abs_path,tgpost) # concat_DF = [self.InstDF,local_DF] self.InstDF.concat(local_DF)
def plot_vector(self,plane,modes,axis_vals,y_mode='half_channel',spacing=(1,1),scaling=1,fig=None,ax=None,quiver_kw=None,**kwargs): FluctDF = self._getFluctDF(modes) plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) plane, coord = FluctDF.CoordDF.check_plane(plane) if coord == 'y': axis_vals = indexing.ycoords_from_coords(self.avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(self.avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) x_size, z_size = FluctDF.get_unit_figsize(plane) figsize=[x_size,z_size*len(axis_vals)] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i, val in enumerate(int_vals): fig, ax[i] = FluctDF.plot_vector(plane,val,time=None,spacing=spacing,scaling=scaling, fig=fig,ax=ax[i],quiver_kw=quiver_kw) ax[i].axes.set_xlabel(r"$%s/\delta$"%slice[0]) ax[i].axes.set_ylabel(r"$%s/\delta$"%slice[1]) ax[i].axes.set_title(r"$%s = %.2g$"%(title_symbol,axis_vals[i]),loc='right') if axes_output: return fig, ax[0] else: return fig, ax
def coord_index_calc(CoordDF, comp, coord_list): coords = CoordDF[comp] coord_list = misc_utils.check_list_vals(coord_list) index_list = [] for coord in coord_list: try: for i in range(coords.size): if coords[i + 1] > coord: if abs(coords[i + 1] - coord) > abs(coords[i] - coord): index_list.append(i) break else: index_list.append(i + 1) break except IndexError: coord_end_plus = 2 * coords[coords.size - 1] - coords[coords.size - 2] if coord_end_plus > coord: index_list.append(i) else: warnings.warn("\033[1;33Value in coord_list out of bounds: "\ + "%s coordinate given: %g, max %s coordinate:" % (comp,coord,comp)\ + " %g. Ignoring values beyond this" % max(coords)) return index_list return index_list
def plot_Q_criterion(self,vals_list,x_split_pair=None,PhyTime=None,y_limit=None,y_mode='half_channel',Y_plus=True,avg_data=None,colors=None,surf_kw=None,fig=None,ax=None,**kwargs): PhyTime = self.check_PhyTime(PhyTime) vals_list = misc_utils.check_list_vals(vals_list) if y_limit is not None: y_lim_int = indexing.ycoords_from_norm_coords(self.avg_data,[y_limit],mode=y_mode)[0][0] else: y_lim_int = None kwargs = cplt.update_subplots_kw(kwargs,subplot_kw={'projection':'3d'}) fig, ax = cplt.create_fig_ax_with_squeeze(fig=fig,ax=ax,**kwargs) Q = self.Q_crit_calc(PhyTime) for i,val in enumerate(vals_list): if colors is not None: color = colors[i%len(colors)] surf_kw['facecolor'] = color fig, ax1 = Q.plot_isosurface('Q',val,time=PhyTime,y_limit=y_lim_int, x_split_pair=x_split_pair,fig=fig,ax=ax, surf_kw=surf_kw) ax.axes.set_ylabel(r'$x/\delta$') ax.axes.set_xlabel(r'$z/\delta$') ax.axes.invert_xaxis() return fig, ax1
def y_coord_index_norm(avg_data, coord_list, x_vals=None, mode='half_channel'): if mode == 'half_channel': norm_distance = np.ones((avg_data.NCL[0])) elif mode == 'disp_thickness': norm_distance, _, _ = avg_data._int_thickness_calc( avg_data.flow_AVGDF.index[0][0]) elif mode == 'mom_thickness': _, norm_distance, _ = avg_data._int_thickness_calc( avg_data.flow_AVGDF.index[0][0]) elif mode == 'wall': _, norm_distance = avg_data._wall_unit_calc( avg_data.flow_AVGDF.index[0][0]) else: raise ValueError("The mode of normalisation must be 'half_channel', 'disp_thickness','mom_thickness',"+\ " or 'wall. Value used was %s\n"%mode) if x_vals is None: x_index = list(range(avg_data.shape[-1])) else: x_vals = misc_utils.check_list_vals(x_vals) x_index = [avg_data._return_index(x) for x in x_vals] y_indices = [] for i, x in enumerate(x_index): norm_coordDF = (1 - abs(avg_data.CoordDF)) / norm_distance[x] y_index = coord_index_calc(norm_coordDF, 'y', coord_list) y_indices.append(y_index) return y_indices
def spectrum_contour(self, comp, axis_vals, axis_mode='half_channel', fig=None, ax=None, pcolor_kw=None, **kwargs): if not comp in ('x', 'z'): raise ValueError(" Variable `comp' must eiher be 'x' or 'z'\n") axis_vals = misc_utils.check_list_vals(axis_vals) y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, axis_vals, None, axis_mode) Ruu_all = self.autocorrDF[comp] #[:,axis_vals,:] shape = Ruu_all.shape Ruu = np.zeros((shape[0], len(axis_vals), shape[2])) for i, vals in zip(range(shape[2]), y_index_axis_vals): Ruu[:, :, i] = Ruu_all[:, vals, i] kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 4 * len(axis_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals), fig=fig, ax=ax, **kwargs) coord = self._meta_data.CoordDF[comp].copy()[:shape[0]] x_axis = self._avg_data._return_xaxis() pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) for i in range(len(axis_vals)): wavenumber_spectra = np.zeros((int(0.5 * shape[0]) + 1, shape[2]), dtype=np.complex128) for j in range(shape[2]): wavenumber_spectra[:, j] = fft.rfft(Ruu[:, i, j]) comp_size = shape[0] wavenumber_comp = 2 * np.pi * fft.rfftfreq(comp_size, coord[1] - coord[0]) X, Y = np.meshgrid(x_axis, wavenumber_comp) ax[i] = ax[i].pcolormesh(X, Y, np.abs(wavenumber_spectra), **pcolor_kw) ax[i].axes.set_ylabel(r"$\kappa_%s$" % comp) title = r"$%s=%.3g$"%("y" if axis_mode=='half_channel' \ else r"\delta_u" if axis_mode=='disp_thickness' \ else r"\theta" if axis_mode=='mom_thickness' else "y^+", axis_vals[i] ) ax[i].axes.set_ylim( [np.amin(wavenumber_comp[1:]), np.amax(wavenumber_comp)]) ax[i].axes.set_title(title) # ,fontsize=15,loc='left') fig.colorbar(ax[i], ax=ax[i].axes) return fig, ax
def plot_lambda2(self,vals_list,x_split_pair=None,PhyTime=None,y_limit=None,y_mode='half_channel',Y_plus=True,avg_data=None,colors=None,surf_kw=None,fig=None,ax=None,**kwargs): """ Creates isosurfaces for the lambda 2 criterion Parameters ---------- vals_list : list of floats isovalues to be plotted x_split_list : list, optional Separating domain into different streamwise lengths useful if the domain is much longer than its width, by default None PhyTime : float, optional Physical time to be plotted, None can be used if the instance contains a single time, by default None ylim : float, optional wall-normal extent of the isosurface plot, by default None Y_plus : bool, optional Whether the above value is in wall units, by default True avg_data : CHAPSim_AVG, optional Instance of avg_data need if Y_plus is True, by default None colors : list of str, optional list to represent the order of the colors to be plotted, by default None fig : %(fig)s, optional Pre-existing figure, by default None ax : %(ax)s, optional Pre-existing axes, by default None Returns ------- %(fig)s, %(ax)s output figure and axes objects """ PhyTime = self.check_PhyTime(PhyTime) vals_list = misc_utils.check_list_vals(vals_list) if y_limit is not None: y_lim_int = indexing.ycoords_from_norm_coords(self.avg_data,[y_limit],mode=y_mode)[0][0] else: y_lim_int = None kwargs = cplt.update_subplots_kw(kwargs,subplot_kw={'projection':'3d'}) fig, ax = cplt.create_fig_ax_with_squeeze(fig=fig,ax=ax,**kwargs) lambda_2DF = self.lambda2_calc(PhyTime) for i,val in enumerate(vals_list): if colors is not None: color = colors[i%len(colors)] surf_kw['facecolor'] = color fig, ax1 = lambda_2DF.plot_isosurface('lambda_2',val,time=PhyTime,y_limit=y_lim_int, x_split_pair=x_split_pair,fig=fig,ax=ax, surf_kw=surf_kw) ax.axes.set_ylabel(r'$x/\delta$') ax.axes.set_xlabel(r'$z/\delta$') ax.axes.invert_xaxis() return fig, ax1
def autocorr_contour_x(self, comp, axis_vals, axis_mode='half_channel', norm=True, fig=None, ax=None, pcolor_kw=None, **kwargs): if not comp in ('x', 'z'): raise ValueError(" Variable `comp' must eiher be 'x' or 'z'\n") axis_vals = misc_utils.check_list_vals(axis_vals) y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, axis_vals, None, axis_mode) Ruu_all = self.autocorrDF[comp].copy() shape = Ruu_all.shape Ruu = np.zeros((shape[0], len(axis_vals), shape[2])) for i, vals in zip(range(shape[2]), y_index_axis_vals): Ruu[:, :, i] = Ruu_all[:, vals, i] if norm: Ruu_0 = Ruu[0].copy() for i in range(shape[0]): Ruu[i] /= Ruu_0 kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 4 * len(axis_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals), fig=fig, ax=ax, **kwargs) x_axis = self._avg_data._return_xaxis() coord = self._meta_data.CoordDF[comp].copy()[:shape[0]] pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) ax_out = [] for i in range(len(axis_vals)): X, Y = np.meshgrid(x_axis, coord) ax[i] = ax[i].pcolormesh(X, Y, Ruu[:, i], **pcolor_kw) ax[i].axes.set_ylabel(r"$\Delta %s/\delta$" % comp) title = r"$%s=%.3g$"%("y" if axis_mode=='half_channel' \ else r"\delta_u" if axis_mode=='disp_thickness' \ else r"\theta" if axis_mode=='mom_thickness' else r"y^+", axis_vals[i] ) ax[i].axes.set_title(title, loc='left') fig.colorbar(ax[i], ax=ax[i].axes) fig.tight_layout() return fig, ax
def plot_fluct3D_xz(self, comp, y_vals, y_mode='half-channel', PhyTime=None, x_split_pair=None, fig=None, ax=None, surf_kw=None, **kwargs): y_vals = misc_utils.check_list_vals(y_vals) PhyTime = self.check_PhyTime(PhyTime) y_int_vals = indexing.ycoords_from_norm_coords(self.avg_data, y_vals, mode=y_mode)[0] axes_output = True if isinstance(ax, mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs, subplot_kw={'projection': '3d'}, antialiased=True) fig, ax = cplt.create_fig_ax_without_squeeze(len(y_int_vals), fig=fig, ax=ax, **kwargs) for i, val in enumerate(y_int_vals): fig, ax[i] = self.fluctDF.plot_surf(comp, 'xz', val, time=PhyTime, x_split_pair=x_split_pair, fig=fig, ax=ax[i], surf_kw=surf_kw) ax[i].axes.set_ylabel(r'$x/\delta$') ax[i].axes.set_xlabel(r'$z/\delta$') ax[i].axes.set_zlabel(r'$%s^\prime$' % comp) ax[i].axes.invert_xaxis() if axes_output: return fig, ax[0] else: return fig, ax
def plot_contour(self,comp,modes,axis_vals,plane='xz',y_mode='wall',fig=None,ax=None,pcolor_kw=None,**kwargs): FluctDF = self._getFluctDF(modes) plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) plane, coord = FluctDF.CoordDF.check_plane(plane) if coord == 'y': axis_vals = indexing.ycoords_from_coords(self.avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(self.avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) # int_vals = indexing.coord_index_calc(self.CoordDF,coord,axis_vals) x_size, z_size = FluctDF.get_unit_figsize(plane) figsize=[x_size,z_size*len(axis_vals)] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i,val in enumerate(int_vals): fig, ax1 = FluctDF.plot_contour(comp,plane,val,time=None,fig=fig,ax=ax[i],pcolor_kw=pcolor_kw) ax1.axes.set_xlabel(r"$%s/\delta$" % plane[0]) ax1.axes.set_ylabel(r"$%s/\delta$" % plane[1]) ax1.axes.set_title(r"$%s=%.2g$"%(title_symbol,axis_vals[i]),loc='right') cbar=fig.colorbar(ax1,ax=ax[i]) cbar.set_label(r"$%s^\prime$"%comp) ax[i]=ax1 ax[i].axes.set_aspect('equal') if axes_output: return fig, ax[0] else: return fig, ax
def plot_mode_contour(self, comp, modes, fig=None, ax=None, pcolor_kw=None, **kwargs): modes = misc_utils.check_list_vals(modes) ax_layout = len(modes) figsize = [10, 3 * len(modes)] kwargs = cplt.update_subplots_kw(kwargs, figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(ax_layout, fig=fig, ax=ax, **kwargs) pcolor_kw = cplt.update_pcolor_kw(pcolor_kw) x_coords = self.avg_data.CoordDF[self._plane[0]] y_coords = self.avg_data.CoordDF[self._plane[1]] X, Y = np.meshgrid(x_coords, y_coords) PODmodes = self.POD_modesDF[None, comp] coord = list('xyz') coord.remove(self._plane[0]) coord.remove(self._plane[1]) for i, mode in enumerate(modes): ax[i] = ax[i].pcolormesh(X, Y, PODmodes[:, :, mode], **pcolor_kw) ax[i].axes.set_xlabel(r"$%s/\delta$" % self._plane[0]) ax[i].axes.set_ylabel(r"$%s/\delta$" % self._plane[1]) ax[i].axes.set_title(r"Mode %d" % (mode + 1), loc='left') ax[i].axes.set_title(r"$%s/\delta$" % coord[0], loc='right') return fig, ax
def plot_vorticity_contour(self,comp,plane,axis_vals,PhyTime=None,avg_data=None,x_split_list=None,y_mode='half_channel',pcolor_kw=None,fig=None,ax=None,**kwargs): """ Creates a contour plot of the vorticity contour Parameters ---------- comp : str Component of the vorticity to be extracted e.g. "x" for \omega_z, the spanwise vorticity plane : str, optional Plane for the contour plot for example "xz" or "rtheta" (for pipes), by default 'xz' axis_vals : int, float (or list of them) locations in the third axis to be plotted PhyTime : float, optional Physical time to be plotted, None can be used if the instance contains a single time, by default None avg_data : CHAPSim_AVG Used to aid plotting certain locations using in the y direction if wall units are used for example x_split_list : list, optional Separating domain into different streamwise lengths useful if the domain is much longer than its width, by default None y_mode : str, optional Only relevant if the xz plane is being used. The y value can be selected using a number of different normalisations, by default 'wall' fig : %(fig)s, optional Pre-existing figure, by default None ax : %(ax)s, optional Pre-existing axes, by default None Returns ------- %(fig)s, %(ax)s output figure and axes objects """ VorticityDF = self.vorticity_calc(PhyTime=PhyTime) plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) PhyTime = self.check_PhyTime(PhyTime) plane, coord = VorticityDF.CoordDF.check_plane(plane) if coord == 'y': if avg_data is None: msg = "If the xz plane is selected the avg_data variable must be set" raise TypeError(msg) axis_vals = indexing.ycoords_from_coords(avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) x_size, z_size = VorticityDF.get_unit_figsize(plane) figsize=[x_size,z_size*len(axis_vals)] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i,val in enumerate(int_vals): fig, ax1 = VorticityDF.plot_contour(comp,plane,val,time=PhyTime,fig=fig,ax=ax[i],pcolor_kw=pcolor_kw) ax1.axes.set_xlabel(r"$%s/\delta$" % plane[0]) ax1.axes.set_ylabel(r"$%s/\delta$" % plane[1]) ax1.axes.set_title(r"$%s=%.2g$"%(title_symbol,axis_vals[i]),loc='right') ax1.axes.set_title(r"$t^*=%s$"%PhyTime,loc='left') cbar=fig.colorbar(ax1,ax=ax[i]) cbar.set_label(r"$%s^\prime$"%comp) ax[i]=ax1 ax[i].axes.set_aspect('equal') if axes_output: return fig, ax[0] else: return fig, ax
def plot_autocorr_line(self, comp, axis_vals, y_vals, y_mode='half_channel', norm_xval=None, norm=True, fig=None, ax=None, **kwargs): if not comp in ('x', 'z'): msg = f"comp must be the string 'x' or 'z' not {comp} " axis_vals = misc_utils.check_list_vals(axis_vals) y_vals = misc_utils.check_list_vals(y_vals) axis_index = [ self._avg_data._return_index(x) for x in axis_vals ] #CT.coord_index_calc(self._meta_data.CoordDF,'x',axis_vals) Ruu = self.autocorrDF[comp].copy() shape = Ruu.shape if norm: Ruu_0 = Ruu[0].copy() for i in range(shape[0]): Ruu[i] /= Ruu_0 kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 5 * len(y_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(y_vals), fig=fig, ax=ax, **kwargs) if norm_xval is not None: if norm_xval == 0: norm_xval = np.amin(self._avg_data._return_xaxis()) x_axis_vals = [norm_xval] * len(axis_vals) else: x_axis_vals = axis_vals y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, y_vals, x_axis_vals, y_mode) coord = self._meta_data.CoordDF[comp][:shape[0]] for j, _ in enumerate(y_vals): for i, _ in enumerate(axis_index): ax[j].cplot(coord, Ruu[:, y_index_axis_vals[i][j], axis_index[i]]) #creating title label y_unit=r"y" if y_mode=='half_channel' \ else r"\delta_u" if y_mode=='disp_thickness' \ else r"\theta" if y_mode=='mom_thickness' \ else r"y^+" if norm_xval is None else r"y^{+0}" ax[j].set_title(r"$%s=%.3g$" % (y_unit, y_vals[j]), loc='left') ax[j].set_ylabel(r"$R_{%s%s}$" % self.comp) ax[j].set_xlabel(r"$%s/\delta$" % comp) return fig, ax
def plot_vector(self,plane,axis_vals,avg_data,PhyTime=None,y_mode='half_channel',spacing=(1,1),scaling=1,fig=None,ax=None,quiver_kw=None,**kwargs): """ Create vector plot of a plane of the instantaneous flow Parameters ---------- plane : str, optional Plane for the contour plot for example "xz" or "rtheta" (for pipes), by default 'xz' axis_vals : int, float (or list of them) locations in the third axis to be plotted avg_data : CHAPSim_AVG Used to aid plotting certain locations using in the y direction if wall units are used for example PhyTime : float, optional Physical time to be plotted, None can be used if the instance contains a single time, by default None y_mode : str, optional Only relevant if the xz plane is being used. The y value can be selected using a number of different normalisations, by default 'wall' spacing : tuple, optional [description], by default (1,1) scaling : int, optional [description], by default 1 x_split_list : list, optional Separating domain into different streamwise lengths useful if the domain is much longer than its width, by default None fig : %(fig)s, optional Pre-existing figure, by default None ax : %(ax)s, optional Pre-existing axes, by default None quiver_kw : dict, optional Argument passed to matplotlib quiver plot, by default None Returns ------- %(fig)s, %(ax)s output figure and axes objects """ plane = self.Domain.out_to_in(plane) axis_vals = misc_utils.check_list_vals(axis_vals) PhyTime = self.check_PhyTime(PhyTime) plane, coord = self.InstDF.CoordDF.check_plane(plane) if coord == 'y': if avg_data is None: msg = "If the xz plane is selected the avg_data variable must be set" raise TypeError(msg) axis_vals = indexing.ycoords_from_coords(avg_data,axis_vals,mode=y_mode)[0] int_vals = indexing.ycoords_from_norm_coords(avg_data,axis_vals,mode=y_mode)[0] else: int_vals = axis_vals = indexing.true_coords_from_coords(self.CoordDF,coord,axis_vals) x_size, z_size = self.InstDF.get_unit_figsize(plane) figsize=[x_size*len(axis_vals),z_size] axes_output = True if isinstance(ax,mpl.axes.Axes) else False kwargs = cplt.update_subplots_kw(kwargs,figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(axis_vals),fig=fig,ax=ax,**kwargs) title_symbol = misc_utils.get_title_symbol(coord,y_mode,False) for i, val in enumerate(int_vals): fig, ax[i] = self.InstDF.plot_vector(plane,val,time=PhyTime,spacing=spacing,scaling=scaling, fig=fig,ax=ax[i],quiver_kw=quiver_kw) ax[i].axes.set_xlabel(r"$%s/\delta$"%slice[0]) ax[i].axes.set_ylabel(r"$%s/\delta$"%slice[1]) ax[i].axes.set_title(r"$%s = %.2g$"%(title_symbol,axis_vals[i]),loc='right') ax[i].axes.set_title(r"$t^*=%s$"%PhyTime,loc='left') if axes_output: return fig, ax[0] else: return fig, ax
def create_video(cls, axis_vals, comp, avg_data=None, contour=True, plane='xz', meta_data=None, path_to_folder='.', time_range=None, abs_path=True, tgpost=False, x_split_list=None, plot_kw=None, lim_min=None, lim_max=None, ax_func=None, fluct_func=None, fluct_args=(), fluct_kw={}, fig=None, ax=None, **kwargs): times = misc_utils.time_extract(path_to_folder, abs_path) max_time = np.amax(times) if time_range is None else time_range[1] if avg_data is None and not tgpost: time0 = time_range[0] if time_range is not None else None avg_data = cls._module._avg_class(max_time, meta_data, path_to_folder, time0, abs_path, tgpost=cls.tgpost) axis_vals = misc_utils.check_list_vals(axis_vals) if x_split_list is None: if meta_data is None: meta_data = cls._module._meta_class(path_to_folder, abs_path, tgpost=tgpost) x_coords = meta_data.CoordDF['x'] x_split_list = [np.min(x_coords), np.max(x_coords)] if fig is None: if 'figsize' not in kwargs.keys(): kwargs['figsize'] = [ 7 * len(axis_vals), 3 * (len(x_split_list) - 1) ] fig = cplt.figure(**kwargs) if contour: plot_kw = cplt.update_pcolor_kw(plot_kw) def func(fig, time): axes = fig.axes for ax in axes: ax.remove() fluct_data = cls(time, avg_data, path_to_folder=path_to_folder, abs_path=abs_path) if contour: fig, ax = fluct_data.plot_contour(comp, axis_vals, plane=plane, PhyTime=time, x_split_list=x_split_list, fig=fig, pcolor_kw=plot_kw) else: fig, ax = fluct_data.plot_fluct3D_xz(axis_vals, comp, time, x_split_list, fig, **plot_kw) ax[0].axes.set_title(r"$t^*=%.3g$" % time, loc='left') if fluct_func is not None: fluct_func(fig, ax, time, *fluct_args, **fluct_kw) if ax_func is not None: ax = ax_func(ax) for im in ax: im.set_clim(vmin=lim_min) im.set_clim(vmax=lim_max) fig.tight_layout() return ax return cplt.create_general_video(fig, path_to_folder, abs_path, func, time_range=time_range)
def plot_mode_contour(self, comp, modes, axis_val, plane='xz', y_mode='wall', fig=None, ax=None, pcolor_kw=None, **kwargs): modes = misc_utils.check_list_vals(modes) axes_output = True if isinstance(ax, mpl.axes.Axes) else False axis_val = misc_utils.check_list_vals(axis_val) if len(axis_val) > 1: msg = "This routine can only process one slice in a single call" raise ValueError(msg) for i, mode in enumerate(modes): PODmodes = self.POD_modesDF.values[:, :, :, :, mode] POD_modeDF = cd.flowstruct3D(self._coorddata, PODmodes, index=self.POD_modesDF.index) plane, coord = POD_modeDF.CoordDF.check_plane(plane) if coord == 'y': val = indexing.ycoords_from_coords(self.avg_data, axis_val, mode=y_mode)[0][0] int_val = indexing.ycoords_from_norm_coords(self.avg_data, axis_val, mode=y_mode)[0][0] else: int_val = val = indexing.true_coords_from_coords( self.CoordDF, coord, axis_val)[0] if i == 0: x_size, z_size = POD_modeDF.get_unit_figsize(plane) figsize = [x_size, z_size * len(modes)] kwargs = cplt.update_subplots_kw(kwargs, figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(len(modes), fig=fig, ax=ax, **kwargs) title_symbol = misc_utils.get_title_symbol(coord, y_mode, False) fig, ax[i] = POD_modeDF.plot_contour(comp, plane, int_val, time=None, fig=fig, ax=ax[i], pcolor_kw=pcolor_kw) ax[i].axes.set_xlabel(r"$%s/\delta$" % plane[0]) ax[i].axes.set_ylabel(r"$%s/\delta$" % plane[1]) ax[i].axes.set_title(r"$%s=%.2g$" % (title_symbol, val), loc='right') ax[i].axes.set_title(r"Mode %d" % (mode + 1), loc='left') cbar = fig.colorbar(ax[i], ax=ax[i].axes) ax[i].axes.set_aspect('equal') if axes_output: return fig, ax[0] else: return fig, ax
def _budget_plot(self, PhyTime, x_list, budget_terms=None, wall_units=True, fig=None, ax=None, line_kw=None, **kwargs): u_tau_star, delta_v_star = self.avg_data._wall_unit_calc(PhyTime) budget_scale = u_tau_star**3 / delta_v_star Y_extent = int(self.avg_data.shape[0] / 2) if wall_units: Y_coords = self.avg_data._y_plus_calc(PhyTime) else: Y = np.zeros(self.avg_data.shape[::-1]) for i in range(self.avg_data.shape[1]): Y[i] = self.avg_data.CoordDF['y'] Y_coords = (1 - np.abs(Y[:, :Y_extent])) if isinstance(x_list, list): ax_size = len(x_list) else: ax_size = 1 ax_size = (int(np.ceil(ax_size / 2)), 2) if ax_size > 2 else (ax_size, 1) lower_extent = 0.2 gridspec_kw = {'bottom': lower_extent} figsize = [7 * ax_size[1], 5 * ax_size[0] + 1] kwargs = cplt.update_subplots_kw(kwargs, gridspec_kw=gridspec_kw, figsize=figsize) fig, ax = cplt.create_fig_ax_without_squeeze(*ax_size, fig=fig, ax=ax, **kwargs) ax = ax.flatten() budget_terms = self._check_terms(budget_terms) x_list = misc_utils.check_list_vals(x_list) line_kw = cplt.update_line_kw(line_kw) for i, x_loc in enumerate(x_list): for comp in budget_terms: budget_values = self.budgetDF[PhyTime, comp].copy() x = self.avg_data._return_index(x_loc) if wall_units: budget = budget_values[:Y_extent, x] / budget_scale[x] else: budget = budget_values[:Y_extent, x] if self.comp == 'uv': budget = budget * -1.0 ax[i].cplot(Y_coords[x, :].squeeze(), budget, label=comp.title(), **line_kw) if wall_units: ax[i].set_xscale('log') # ax[i].set_xlim(left=1.0) ax[i].set_xlabel(r"$y^+$") else: x_label = self.Domain.in_to_out(r"$y/\delta$") ax[i].set_xlabel(x_label) if mpl.rcParams['text.usetex'] == True: ax[i].set_ylabel(r"Loss\ \ \ \ \ \ \ \ Gain") else: ax[i].set_ylabel(r"Loss Gain") return fig, ax
def plot_spectra(self, comp, axis_vals, y_vals, y_mode='half_channel', norm_xval=None, fig=None, ax=None, **kwargs): if not comp in ('x', 'z'): raise ValueError(" Variable `comp' must eiher be 'x' or 'z'\n") axis_vals = misc_utils.check_list_vals(axis_vals) y_vals = misc_utils.check_list_vals(y_vals) axis_index = [ self._avg_data._return_index(x) for x in axis_vals ] #CT.coord_index_calc(self._meta_data.CoordDF,'x',axis_vals) Ruu = self.autocorrDF[comp] shape = Ruu.shape kwargs = cplt.update_subplots_kw(kwargs, figsize=[10, 5 * len(y_vals)]) fig, ax = cplt.create_fig_ax_without_squeeze(len(y_vals), fig=fig, ax=ax, **kwargs) if norm_xval is not None: if norm_xval == 0: x_axis_vals = [np.amin(self._avg_data._return_xaxis()) ] * len(axis_vals) else: x_axis_vals = [norm_xval] * len(axis_vals) else: x_axis_vals = axis_vals coord = self._meta_data.CoordDF[comp][:shape[0]] y_index_axis_vals = indexing.y_coord_index_norm( self._avg_data, y_vals, x_axis_vals, y_mode) for j, _ in enumerate(y_vals): for i, _ in enumerate(axis_index): wavenumber_spectra = fft.rfft(Ruu[:, y_index_axis_vals[i][j], axis_index[i]].squeeze()) delta_comp = coord[1] - coord[0] comp_size = Ruu[:, y_index_axis_vals[i][j], axis_index[i]].size wavenumber_comp = 2 * np.pi * fft.rfftfreq( comp_size, delta_comp) y_unit=r"y" if y_mode=='half_channel' \ else r"\delta_u" if y_mode=='disp_thickness' \ else r"\theta" if y_mode=='mom_thickness' \ else r"y^+" if norm_xval !=0 else r"y^{+0}" ax[j].cplot(wavenumber_comp, 2 * np.abs(wavenumber_spectra)) ax[j].set_title(r"$%s=%.3g$" % (y_unit, y_vals[j]), loc='left') string = (ord(self.comp[0]) - ord('u') + 1, ord(self.comp[1]) - ord('u') + 1, comp) ax[j].set_ylabel(r"$E_{%d%d}(\kappa_%s)$" % string) ax[j].set_xlabel(r"$\kappa_%s$" % comp) return fig, ax