Atkins Dynamic graph: 6A.1

6a_1_posn_of_equil_with_grid_1000
import math
import numpy as np
import matplotlib.pyplot as plt
from matplotlib import figure
from ipywidgets import interact
from ipywidgets import interact, fixed, FloatSlider, HBox, VBox, Layout, Output, Label, Box, GridspecLayout, GridBox
import ipywidgets as widgets
from matplotlib import ticker

# returns Gm(x) for given parameters: a, b, xx
def fvee(a,b,xx):
  fval = xx*(a + 5*math.log(xx))+(1-xx)*(b + 5*math.log(1-xx))
  return fval

# returns slope of Gm(x) for given parameters: a, b, xx
def slfvee(a,b,xx):
  sl = a - b + 5* math.log(xx/(1-xx))
  return sl

#set up how range of plot, ticks, grid

px=1.0/96 #pixel in inches
xmin=0.000001
xmax=0.999999
xrange=xmax-xmin
xgrid=.1
x_ticks = np.arange(xmin,xmax+xgrid,xgrid)
show_x_ticks=False
show_x_tick_labels=False
ymin=-6
ymax=12.
yrange=ymax-ymin
ygrid=2.5
show_y_ticks=False
show_y_tick_labels=False
y_ticks = np.arange(ymin, ymax+ygrid, ygrid)
show_grid=True
npts=100
x = np.linspace(xmin, xmax, npts)
Gm=np.linspace(0.0, 1.0, npts)
def Gplot(a,b,xsl):
  for i in range (0,npts):
    Gm[i] = x[i]*(a + 5*math.log(x[i]))+(1-x[i])*(b + 5*math.log(1-x[i]))
  # minimum value of Gm(x) 
  xmin = 1/(1+math.exp(-(b-a)/5))
  fmin= fvee(a,b,xmin)
#designed for figsize=(8,4.94) {Golden ratio, 1.618}
#  fig = plt.figure() 
  fig = plt.figure(figsize=(900*px,556*px),dpi=96) 
  ax = fig.add_subplot(111)
  plt.plot(x,Gm,linewidth=2,linestyle='-',color='red',clip_on=True)
  plt.axis([xmin,xmax,ymin,ymax])
  plt.ylabel(r'Gibbs energy, $G$',fontsize='x-large')
  plt.xlabel(r'Extent of reaction, $\xi$',fontsize='x-large')
  plt.xticks(x_ticks)
  plt.yticks(y_ticks)
  if show_grid: plt.grid(True,color='blue',linewidth=.25)
  if not show_x_tick_labels: ax.set_xticklabels([])
  if not show_y_tick_labels: ax.set_yticklabels([])
  plt.tick_params(axis='x',which='both',bottom = show_x_ticks, top= False)
  plt.tick_params(axis='y',which='both',left = show_y_ticks, right= False)
  plt.text(0.02,-5.5,'pure reactants',horizontalalignment='center',fontsize=12,rotation='vertical')
  plt.text(0.,-7.25,'0',horizontalalignment='center',fontsize=12)
  plt.text(0.98,-5.5,'pure products',horizontalalignment='center',fontsize=12,rotation='vertical')
#  plt.text(-.25,-7,r'$\xi$',horizontalalignment='center',fontsize=12)
#  plt.annotate("1",xy=(0,0),xytext=(0.995,-0.05),xycoords='axes fraction',fontsize=12)

#add an arrow to point out Gmin
#arrow is drawn from xytext to xy
#  plt.annotate(r'$G_\mathrm{m, min}}$', xy=(xmin, fmin),  xycoords='data',
#            xytext=(xmin, fmin+4), textcoords='data',
#            horizontalalignment='center', verticalalignment='top',fontsize=14,
#            arrowprops=dict(facecolor='black', shrink=0.2,width=.5,headlength=7,headwidth=5),
#            )
  #add a vertical line up to value of Gmin
  #plt.plot([xmin,xmin], [-3.6,fmin], linestyle='--', lw=1,color='red')
  #draw the slope for an arbitray value of x

  #line ranges over +/- delx from centre - computed to make sure line is constant length  
  deli=0.1 * math.cos(math.atan((xrange/yrange)*slfvee(a,b,xsl)))
  plt.plot([xsl-deli,xsl+deli], [fvee(a,b,xsl)- deli * slfvee(a,b,xsl),fvee(a,b,xsl)+ deli * slfvee(a,b,xsl)], linestyle='-', lw=1.5,color='black')

  #draw a vertical line up to the point where the slope is drawn
  #plt.plot([xsl,xsl], [-3.6,fvee(a,b, xsl)], linestyle='--', lw=1,color='black')
  if slfvee(a,b,xsl) >0.01:
    txt=r'$\Delta_\mathrm{r}G > 0$'
    plt.text(
    xsl, fvee(a,b,xsl), "     ", ha="center", va="center", rotation=0, size=10,
    bbox=dict(boxstyle="larrow,pad=0.3", fc="skyblue", ec="k", lw=1))
  elif slfvee(a,b,xsl) <-0.01:
    txt=r'$\Delta_\mathrm{r}G < 0$'
    plt.plot(xsl, fvee(a,b,xsl), 'o',
        markersize=10, markeredgecolor='black', markerfacecolor='white', markeredgewidth=1)
    plt.text(
    xsl, fvee(a,b,xsl), "     ", ha="center", va="center", rotation=0, size=10,
    bbox=dict(boxstyle="rarrow,pad=0.3", fc="skyblue", ec="k", lw=1))

  else:
    txt=r'$\Delta_\mathrm{r}G = 0$'
  plt.text(xsl,fvee(a,b,xsl)-2,txt,fontsize=12,horizontalalignment='center')
  plt.plot(xmin, fmin, 'o',
     markersize=10, markeredgecolor='black', markerfacecolor='white', markeredgewidth=1)

  plt.show()

#margin='top right bottom left'
a=FloatSlider(description='',min=0, max=12, step=0.1, value=4,continuous_update=False,
orientation='vertical',readout=False,
style=dict(handle_color='lightcoral'),
layout=dict(height='260px',width='100px',margin='20px 0px 0px 0px'))
#300% is to push the bottom of the slider up

a_label=widgets.HTMLMath(value='<center style="font-size:medium">Gibbs energy of pure products</center>',layout=dict(width='100px',margin='0px 0px 0px 0px'))
b_label=widgets.HTMLMath(value='<center style="font-size:medium">Gibbs energy of pure reactants</center>',layout=dict(width='100px',margin='0px 0px 0px 0px'))
xsl_label=widgets.HTMLMath(value='<p style="font-size:medium">Extent</p>',layout=dict(width='50px',margin='0px 0px 0px 0px'))

a_control=VBox([a_label,a],layout=dict(width='110px',height='500px',margin='30px 0px 0px 0px'))


b=FloatSlider(description='',min=0, max=12, step=0.1, value=10,continuous_update=False,
orientation='vertical',readout=False,
style=dict(handle_color='lightblue'),
layout=dict(width='100px', height='260px',margin='20px 0px 0px 0px'))

b_control=VBox([b_label,b],layout=dict(width='110px',height='500px',margin='30px 0px 0px 00px'))

xsl=FloatSlider(description='',min=0.05, max=0.95, step=0.01, value=.25,continuous_update=False,
orientation='horizontal',readout=False,
style=dict(handle_color='gray'),
layout=dict(width='650px', height='25px',margin='0px 0px 0px 0px'))

xsl_control=HBox([xsl_label,xsl],layout=dict(width='770px',height='35px',margin='0px 0px 0px 20px'))

out = widgets.interactive_output(Gplot, {'a': a, 'b': b, 'xsl':xsl})

#the height of the top row is set by the height of the graph
#the slides are 'auto' height, but with a large margin at the bottom
#to place them correctly
# border='solid 1px red'
GridBox(children=[b_control,HBox([out],layout=dict(width='780px',height='500px',margin='60px 0px 0px 0px')),a_control,
        HBox([]),xsl_control,HBox([])],
        layout=Layout(
            width='1000px',height='auto',grid_template_columns='110px 780px 110px',
            grid_template_rows='auto auto'))

Back to top