In [83]:
def basic_plot_format(subplot_label,x_label,y_label,major_grid,minor_grid,legend):
# General plot formatting for relatively good plots. adjustments may be necessary
# sub_plot_label, usually defined by 'ax' and a number
# x_label and y_label must be type 'str'... Can use LaTeX for typsetting
# major_grid, minor_grid, and legend are boolean
plt.style.use('classic')
font = {'family' : 'Times New Roman',
'weight' : 0,
'size' : 16}
plt.rc('font',**font)
subplot_label.spines['right'].set_color('none')
subplot_label.spines['top'].set_color('none')
subplot_label.yaxis.set_ticks_position('left')
subplot_label.xaxis.set_ticks_position('bottom')
subplot_label.minorticks_on()
subplot_label.set_xlabel(x_label,fontsize=18)
subplot_label.set_ylabel(y_label,fontsize=18)
subplot_label.grid(b=major_grid,which='major')
subplot_label.grid(b=minor_grid,which='minor')
if legend == False:
0
else:
legend = subplot_label.legend(bbox_to_anchor=(1, 1),loc='upper left',frameon=False,fontsize=10)
legend.get_frame().set_facecolor('white')
return legend
In [84]:
import os, glob, numpy as np, csv, math
import matplotlib.pyplot as plt
from scipy import signal, fftpack
dir_path = os.path.dirname(os.path.realpath('plotter_notebook.ipynb'))
wrkdir = os.path.join(dir_path,'data')
csv_files = os.path.join(wrkdir,'*.csv')
meta_files = os.path.join(wrkdir,'*.txt')
trackdata = glob.glob(csv_files)
metadata = glob.glob(meta_files)
n_files = np.size(trackdata)
In [85]:
def get_drop_vars(metadata):
f = open(metadata[0],"r")
drop_vars = list(csv.reader(f))
f.close()
drop_meta = {}
for i in range(n_files):
drop_meta[drop_vars[i+1][0]] = {}
n_meta = np.size(drop_vars[0][1:])
for n in range(n_meta):
drop_meta[drop_vars[i+1][0]][drop_vars[0][n+1].split('_')[0]] = float(drop_vars[i+1][n+1])
meta = drop_meta
return meta
meta is a nested dictionary with global key by drop number and sub keys 'Angle', 'Volume', 'ILfront', 'ILback', and 'Scale'
In [86]:
def gen_data_repos(wrkdir,csv_files,trackdata,n_files):
total_drop_data = {}
for i in range(n_files):
(location, name) = os.path.split( trackdata[i] )
f = open(trackdata[i],"r")
drop_data = list(csv.reader(f))
f.close()
col_names = drop_data[0]
n_col = np.size(drop_data[0])
drop_data = np.asarray(drop_data[1:],dtype=float)
total_drop_data[name[:-4]] = {}
for j in range(n_col):
total_drop_data[name[:-4]][col_names[j]] = drop_data[:,j]
return total_drop_data
In [87]:
def plot_data(data,meta,volumes,location):
fig = plt.figure(facecolor="white")
plt.style.use('classic')
font = {'family' : 'Times New Roman',
'weight' : 'bold',
'size' : 16}
plt.rc('font',**font)
for key in sorted(data):
drop_num = key
if(meta[drop_num]['Volume'] in volumes ):
if(meta[drop_num]['Volume'] == 0.5):
color = 'r'
elif(meta[drop_num]['Volume'] == 1.0):
color = 'k'
elif(meta[drop_num]['Volume'] == 2.0):
color = 'b'
ax = fig.add_subplot(1,1,1)
ax.plot(data[drop_num]['time'],data[drop_num][location],c=color,marker='.',linestyle='None',\
label=str(meta[drop_num]['Volume'])+'ml '+str( meta[drop_num]['ILback'])+'mm '+drop_num)
ax.spines['right'].set_color('none')
ax.spines['top'].set_color('none')
ax.yaxis.set_ticks_position('left')
ax.xaxis.set_ticks_position('bottom')
ax.minorticks_on()
ax.legend(bbox_to_anchor=(1, 1),loc='upper left',frameon=False,fontsize=12,facecolor="white")
ax.set_xlabel('t (s)',fontsize=18)
ax.set_ylabel('x (mm)',fontsize=18)
ax.grid(b=True,which='major')
ax.grid(b=True,which='minor')
plt.show()
In [88]:
def filtering_data(data,meta,volumes,angles,location):
fig1 = plt.figure(facecolor="white")
fig2 = plt.figure(facecolor="white")
#plt.style.use('classic')
#font = {'family' : 'Times New Roman',
# 'weight' : 'bold',
# 'size' : 16}
#plt.rc('font',**font)
v_norm = {}
x_max = {}
for key in sorted(meta, key = lambda x: meta[x]['ILback']):
if(meta[key]['Volume'] in volumes and meta[key]['Angle'] in angles): # checks for called volumes and angles
dat = data[key][location][1:]
t = data[key]['time'][1:]
slice_num = 5
dat_sliced = dat[::slice_num]
t_sliced = t[::slice_num]
x_max[key] = max(dat_sliced)
nn = int(((np.ceil(np.size(dat_sliced)/2))*2-1)-10)
nn2 = nn-10
nn3 = nn
poly_fit = 5
x1 = signal.savgol_filter(dat_sliced,nn,poly_fit)
x2 = signal.savgol_filter(x1,nn,poly_fit)
x3 = signal.savgol_filter(x2,nn3,poly_fit)
data_filt = signal.savgol_filter(x3,slice_num+2,poly_fit)
#print('nn1='+str(nn)+' nn2='+str(nn2)+' nn3='+str(nn3))
ax = fig1.add_subplot(1,1,1)
# some plot formatting stuff, setting marker colors/types for various volumes
if(meta[key]['Volume'] == 0.5):
color = 'k'
style = None
elif(meta[key]['Volume'] == 1.0):
color = 'c'
style = None
elif(meta[key]['Volume'] == 2.0):
color = 'b'
style = None
elif(meta[key]['Volume'] == 5.0):
color = 'r'
style = None
elif(meta[key]['Volume'] == 10.0):
color = 'y'
style = None
if(meta[key]['Angle'] == 2.0):
style2 = 'o'
elif(meta[key]['Angle'] == 3.5):
style2 = 's'
elif(meta[key]['Angle'] == 5.0):
style2 = '^'
dropno = key+' '
vol = str(meta[key]['Volume'])+'ml '
angl = str(meta[key]['Angle'])+'deg '
IL = str( data[key][location][0])+'mm '
legend_label = dropno+vol+angl+IL
ax.plot(t_sliced,dat_sliced,'.',marker=style2, c = color,fillstyle='none',markeredgewidth=1.5,ms=8)
ax.plot(t_sliced,data_filt,c=color,marker=style,linewidth=1,label = legend_label)
legend1 = basic_plot_format(subplot_label = ax, \
x_label = '$t$ (s)', \
y_label = '$x$ (mm)', \
major_grid = True, \
minor_grid = True, \
legend = True)
dxdt_savgol = np.zeros(np.size(dat_sliced)-2)
for i in range(np.size(dat_sliced)-2):
dxdt_savgol[i] = (data_filt[i+2]-data_filt[i])/(2*(t_sliced[i+1]-t_sliced[i]))
dxdt_centraldiff = np.zeros(np.size(dat_sliced)-2)
for i in range(np.size(dat_sliced)-2):
dxdt_centraldiff[i] = (dat_sliced[i+2]-dat_sliced[i])/(2*(t_sliced[i+1]-t_sliced[i]))
ax2 = fig2.add_subplot(1,1,1)
ax2.plot(t_sliced[1:-1],dxdt_centraldiff,marker=style2,linewidth=0, c = color,fillstyle='none',markeredgewidth=1.5,ms=8)
ax2.plot(t_sliced[1:-1],dxdt_savgol,c=color,marker=style,linewidth=1,label = legend_label)
legend2 = basic_plot_format(subplot_label = ax2, \
x_label = '$t$ (s)', \
y_label = '$U$ (mm/s)', \
major_grid = True, \
minor_grid = True, \
legend = False)
ax2.set_xlim([0,2.1])
# ax2.set_ylim([0,150])
fig1.savefig('Figures/positions.png',dpi=100,bbox_extra_artists=(legend1,), bbox_inches='tight')
fig2.savefig('Figures/velocities.png',dpi=100, bbox_inches='tight')
v_norm[key] = max(dxdt_centraldiff)
return v_norm, x_max
In [89]:
def normalized_variables(meta,data,location):
xi_norm = {}
for key in sorted(data):
xi = data[key][location][0]/1000 # m
V = meta[key]['Volume']*(10**(-6)) # m^3
alpha = (meta[key]['Angle']/2.)*(math.pi/180.) # rad
xi_norm[key] = xi*((4*math.pi)/(3*V))**(1/3.)*math.sin(alpha)
return xi_norm
In [90]:
location = 'average'
volumes = [0.5,1.0,2.0,5.0,10.0]
angles= [2.0,3.5,5.0]
data = gen_data_repos(wrkdir,csv_files,trackdata,n_files)
meta = get_drop_vars(metadata)
#plot_data(data,meta,volumes,location)
[v_norm,x_max] = filtering_data(data,meta,volumes,angles,location)
xi_norm = normalized_variables(meta,data,location)
plt.show()
In [91]:
xi_vector = np.zeros(n_files-1)
v_vector = np.zeros(n_files-1)
i = int(0)
for key in xi_norm:
if key != '07261':
xi_vector[i] = xi_norm[key]
v_vector[i] = v_norm[key]
i=i+1
else:
print()
fit = np.polyfit(xi_vector,v_vector,1)
fit_fn = np.poly1d(fit)
In [101]:
from matplotlib.lines import Line2D
v_max = ((4*0.072*9.81)/1000)**(1/4.)*1000
fig1 = plt.figure(facecolor="white")
for key in xi_norm:
R = ((3000*meta[key]['Volume'])/(4*math.pi))**(1/3)
sin_angl = math.sin((meta[key]['Angle']/2)*(math.pi/180))
x_max_theo = (R/sin_angl)
if x_max[key]>x_max_theo:
fill = 'none'
w = 1.5
elif x_max[key]<=x_max_theo:
fill = 'full'
w=0
if meta[key]['Angle']== 2.0:
clr = 'c'
elif meta[key]['Angle']== 3.5:
clr = 'b'
elif meta[key]['Angle']== 5.0:
clr = 'r'
if meta[key]['Volume']== 0.5:
style = '^'
elif meta[key]['Volume']== 1.0:
style = 's'
elif meta[key]['Volume']== 2.0:
style = 'o'
elif meta[key]['Volume']== 5.0:
style = 'p'
elif meta[key]['Volume']== 10.0:
style = 'D'
ax = fig1.add_subplot(1,1,1)
dropno = key+' '
vol = str(meta[key]['Volume'])+'ml '
angl = str(meta[key]['Angle'])+'deg '
IL = str( data[key][location][0])+'mm '
xii = ' '+str(xi_norm[key])
legend_label = dropno+xii
ax.plot(xi_norm[key],v_norm[key]/v_max,\
marker=style,\
c = clr,\
ms=9,\
fillStyle=fill,\
markeredgewidth=w,\
label = legend_label,\
linewidth = 0
)
ax.plot(xi_vector,fit_fn(xi_vector)/v_max,'k')
legend1 = basic_plot_format(subplot_label = ax, \
x_label = '$x_i^*$', \
y_label
= '$U_{max,msrd}/U_{limit}$', \
major_grid = True, \
minor_grid = True, \
legend = True
)
ax.set_xlim([0,1])
ax.set_ylim([0,0.75])
fig1.savefig('Figures/dimensionalplot.png',dpi=300,bbox_extra_artists=(legend1,), bbox_inches='tight')
plt.show()
In [93]:
fit/v_max
Out[93]:
Blue = $5.0^o$
Light Blue = $3.5^o$
Red = $2.0^o$
Triangle = $0.5$mL
Square = $1.0$mL
Circle = $2.0$mL
Hexagon = $5.0$mL
Diamond = $10.0$mL
linear trend of max velocity? Non-dimensional parameter $x_i^* = x_i \sin\alpha(\frac{4 \pi}{3 V})^{1/3} $ where $x_i$ is the initial location of the droplet relative to the wedge vertex, $V$ is the droplet volume, and $\alpha$ is the wedge half angle. $U_{limit}$ is found by thermodynamic principles of conservation of energy: negative difference in surface energy associated with confined and unconfined states is transferred to kinetic energy. Under limits of large volume small angle experiments, a theoretical velocity is found to be $U_{limit} = (\frac{\sigma g}{\rho})^{1/4}$
In [126]:
Vtheo = np.linspace(0.5,20)
Hcap = 2*(0.072/(1000*9.81))**(1/2)*1000
term1 = -2*math.cos(150*(math.pi/180))
term2 = 2*((math.pi*Hcap**3)/(Vtheo*1000))**(1/2)
term3 = -6**(2/3)*((math.pi*Hcap**3)/(Vtheo*1000))**(1/3)
Utheo = (0.072*9.81/1000)**(1/4)*(term1+term2+term3)**(1/2)
plt.plot(Vtheo,Utheo*(1000/v_max))
plt.show()
In [112]:
Hcap
Out[112]: