Skip to content

Instantly share code, notes, and snippets.

@dpgoldenberg
Last active March 20, 2021 17:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dpgoldenberg/2a268c8c518aabb95051a9a8ba18a381 to your computer and use it in GitHub Desktop.
Save dpgoldenberg/2a268c8c518aabb95051a9a8ba18a381 to your computer and use it in GitHub Desktop.
Smulation of Biol 3415/Chem 3515 Experiment 4, part B
code_dict = {'0GXY02':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.0780933743000794e-05,'kcat':12.479059780623182,'km':8.563436439963315e-05,'ki':1.2818504047186639e-05,'i_type':'n','k2aebsf':2.770090118806899},
'DD0371':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.943933934989462e-05,'kcat':9.174417463278722,'km':4.777372487256253e-05,'ki':2.0921044815624033e-05,'i_type':'n','k2aebsf':3.0756264469580783},
'X5FX87':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.95266826439055e-05,'kcat':11.789268600290177,'km':5.58468122174051e-05,'ki':3.1855951319526476e-05,'i_type':'u','k2aebsf':2.0458927928518547},
'FG188G':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.285031188273903e-05,'kcat':13.047612493354922,'km':7.177787853319616e-05,'ki':2.2387336355080515e-05,'i_type':'c','k2aebsf':2.5569285418417063},
'34P10Q':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.722682984532362e-05,'kcat':8.145189509187809,'km':6.57837365279514e-05,'ki':2.4766261675168723e-05,'i_type':'u','k2aebsf':3.7500007792456365},
'Y4N6KZ':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.8906484201970237e-05,'kcat':13.614464085817126,'km':5.4379228053721865e-05,'ki':2.8526273760851988e-05,'i_type':'n','k2aebsf':2.373916885321159},
'W5XM03':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.9115719982294164e-05,'kcat':10.075765236194103,'km':3.320531258425417e-05,'ki':1.788466321473838e-05,'i_type':'u','k2aebsf':3.951721032682042},
'9V51PV':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.2972895706886008e-05,'kcat':14.253426350877806,'km':8.949671739010028e-05,'ki':2.242595915972425e-05,'i_type':'u','k2aebsf':2.9026754774137578},
'942913':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.0249547380195524e-05,'kcat':11.135081432311162,'km':7.07376899404837e-05,'ki':1.530979579819587e-05,'i_type':'n','k2aebsf':2.419878129417387},
'N898UN':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.8674877368836247e-05,'kcat':10.097357504977413,'km':6.59893141525897e-05,'ki':1.6104691193010986e-05,'i_type':'c','k2aebsf':3.7578493435838753},
'H4CGP6':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.4074717025273083e-05,'kcat':10.86527728039156,'km':4.0295083099196564e-05,'ki':1.8838579326954804e-05,'i_type':'u','k2aebsf':2.5753654110654987},
'13KE9N':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.0654600749048573e-05,'kcat':14.476740111724716,'km':4.664199652900124e-05,'ki':3.565278871613589e-05,'i_type':'c','k2aebsf':2.416169532527277},
'31PQ53':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.264345369791618e-05,'kcat':6.560328970813622,'km':3.930321207228756e-05,'ki':1.7996658903832847e-05,'i_type':'c','k2aebsf':3.027494799911106},
'KK644G':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.9346499463477278e-05,'kcat':8.322469408595582,'km':4.5568979770163385e-05,'ki':2.786600023760229e-05,'i_type':'n','k2aebsf':3.8406155198096887},
'2TNA45':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.9246819164209123e-05,'kcat':5.953190657380047,'km':3.994947194229087e-05,'ki':3.118850349923123e-05,'i_type':'n','k2aebsf':3.3292057548084224},
'N6AADQ':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.8630368266346355e-05,'kcat':8.425285215458262,'km':8.304450919324063e-05,'ki':3.275462952212665e-05,'i_type':'n','k2aebsf':2.043910942913139},
'SV22HX':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.7310317193021016e-05,'kcat':11.54988636685996,'km':5.4691251633663635e-05,'ki':1.4258000433727466e-05,'i_type':'n','k2aebsf':2.7928271592636262},
'VS8S0J':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.1921188687159537e-05,'kcat':11.169575003686369,'km':6.197424343338799e-05,'ki':3.4772457082954824e-05,'i_type':'u','k2aebsf':2.896016126282032},
'4U2RCD':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.876088862624062e-05,'kcat':11.746442846771568,'km':5.739471754772193e-05,'ki':2.7617474463042558e-05,'i_type':'n','k2aebsf':2.6015673358114046},
'ZCRTWU':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.9224581361271966e-05,'kcat':5.076806311887225,'km':3.228842227365505e-05,'ki':2.641539836528339e-05,'i_type':'n','k2aebsf':2.082179293635174},
'7182Y1':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.47216027558941e-05,'kcat':8.241979108276192,'km':6.0074402918688364e-05,'ki':2.9141558444201385e-05,'i_type':'c','k2aebsf':2.763782291732746},
'W8Y4P3':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.7782485501855382e-05,'kcat':10.195874314801054,'km':3.488329626913995e-05,'ki':2.6688208538208135e-05,'i_type':'u','k2aebsf':3.3156359342254533},
'J9PWB4':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.475736161044849e-05,'kcat':6.754889828781962,'km':8.773579280310646e-05,'ki':3.7817954389229254e-05,'i_type':'u','k2aebsf':3.2475775452027933},
'43479S':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.6621708935755493e-05,'kcat':13.144983394351692,'km':5.9336652102587744e-05,'ki':1.2109968155410305e-05,'i_type':'c','k2aebsf':2.101901970702785},
'MYX1AX':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.6766972738830726e-05,'kcat':12.914367456489144,'km':4.940114234055595e-05,'ki':2.3969134784314207e-05,'i_type':'c','k2aebsf':2.426506564801504},
'S0E0YV':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.7032357040088922e-05,'kcat':10.957824559421038,'km':3.289894725028064e-05,'ki':3.7799881099811013e-05,'i_type':'u','k2aebsf':2.317476189522253},
'DFKPU9':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.723282359923739e-05,'kcat':7.466998500516203,'km':6.51627417368447e-05,'ki':3.141311275224014e-05,'i_type':'n','k2aebsf':2.12220666540577},
'9RFXYW':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.5000509553011084e-05,'kcat':6.705684564747556,'km':5.8051980187978164e-05,'ki':3.193666437729011e-05,'i_type':'n','k2aebsf':2.321114542381777},
'88PTV8':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.4524217499362522e-05,'kcat':5.011219927285401,'km':8.251030817940819e-05,'ki':3.075851375645226e-05,'i_type':'n','k2aebsf':3.4749436702803305},
'H0X54M':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.4139816960349272e-05,'kcat':6.589695629876994,'km':6.600131868852241e-05,'ki':1.31444625377903e-05,'i_type':'u','k2aebsf':2.557925418572501},
'KD1K2N':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.7172667254962533e-05,'kcat':10.800375363792174,'km':4.161401188579533e-05,'ki':1.6146814125369517e-05,'i_type':'n','k2aebsf':3.8487277594720775},
'23W0N6':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.922648717519026e-05,'kcat':10.434092819204855,'km':8.777019172064786e-05,'ki':3.765713498947328e-05,'i_type':'n','k2aebsf':3.5945905424214617},
'GQ5P11':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.7288023178577137e-05,'kcat':8.027464722293182,'km':8.77400879268201e-05,'ki':3.871522144226405e-05,'i_type':'c','k2aebsf':2.865635423999882},
'597J70':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.912745303888913e-05,'kcat':10.458568211196791,'km':4.246737812426825e-05,'ki':2.2091709053964623e-05,'i_type':'c','k2aebsf':2.8561055227197865},
'77YE98':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.6706669601780035e-05,'kcat':7.330432197837356,'km':8.891603561232728e-05,'ki':2.385063694003913e-05,'i_type':'n','k2aebsf':3.149992146329768},
'994A4U':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.8895005256200494e-05,'kcat':5.174640178640072,'km':5.320770050272746e-05,'ki':3.484928283677721e-05,'i_type':'c','k2aebsf':3.3935777441032755},
'22NZ8S':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.1267935215025052e-05,'kcat':9.340617525524213,'km':8.084998120581375e-05,'ki':1.9846990411649675e-05,'i_type':'c','k2aebsf':3.977405526302869},
'33VZHV':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.588140524849908e-05,'kcat':11.929996897914258,'km':4.824483178683697e-05,'ki':1.7953941761962762e-05,'i_type':'n','k2aebsf':3.1173189298940516},
'YD34E7':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.1705054520364497e-05,'kcat':10.27610221982453,'km':3.781178868193927e-05,'ki':3.679368703360593e-05,'i_type':'u','k2aebsf':3.643297534636481},
'B4EV54':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.0354460994888705e-05,'kcat':7.021725135847429,'km':5.7035565773548506e-05,'ki':3.4492201250642305e-05,'i_type':'c','k2aebsf':2.080642313124938},
'QXQEA0':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.3323423105185772e-05,'kcat':6.929654495543255,'km':3.181108783085965e-05,'ki':1.329762648384744e-05,'i_type':'u','k2aebsf':3.8249402421942125},
'RCE9Z2':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.01296550430366e-05,'kcat':13.410636428482128,'km':6.436577355205234e-05,'ki':2.9553712571334308e-05,'i_type':'u','k2aebsf':3.867029011846259},
'W382SW':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.774481028180708e-05,'kcat':12.769638907644534,'km':7.359061292718445e-05,'ki':2.857701690770212e-05,'i_type':'c','k2aebsf':2.1432721546280664},
'Y1UUUA':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.0828543359469805e-05,'kcat':6.72929920464161,'km':8.86483930276227e-05,'ki':2.8642829571428845e-05,'i_type':'n','k2aebsf':2.4690982070117036},
'240125':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.7918021956761915e-05,'kcat':5.844744273832838,'km':4.588117735847368e-05,'ki':1.1957994609795895e-05,'i_type':'u','k2aebsf':3.4201212841230206},
'0P20E8':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.9706742739803737e-05,'kcat':11.3167024699186,'km':8.655867671649303e-05,'ki':3.677451188680347e-05,'i_type':'c','k2aebsf':3.2511311962353737},
'CTZKSB':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.6678519754892104e-05,'kcat':14.698116904941546,'km':7.633417818129455e-05,'ki':2.3006367565448628e-05,'i_type':'n','k2aebsf':2.3344780449502913},
'K60820':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.7891470882886813e-05,'kcat':5.1724040679813585,'km':8.540103081102389e-05,'ki':1.5968880094004856e-05,'i_type':'u','k2aebsf':3.4364501187667256},
'WE21H5':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':1.8244941876266545e-05,'kcat':9.019636410141747,'km':8.204223957035615e-05,'ki':2.1798577252831622e-05,'i_type':'n','k2aebsf':3.8098962164574193},
'N180MF':{'pip_sigma':0.015,'abs_sigma':0.001,'e_conc':2.3419204687993863e-05,'kcat':7.10770397148994,'km':5.528682797277228e-05,'ki':1.8279751160378784e-05,'i_type':'u','k2aebsf':2.1463055653327103}}
name: exp_4b_sim
channels:
- conda-forge
- defaults
- conda-forge/label/broken
dependencies:
- python=3.8.3
- numpy=1.19.2
- scipy = 1.5.2
- matplotlib=3.3.2
- ipython=7.19.0
- ipywidgets=7.5.1
- voila=0.2.6
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
## Module for import into Jupyter for simulation of Experiment 4, part B
## Irreversible inhibition of trypsin by AEBSF
## in Biology 3515/Chem 3515 at the University of Utah, Spring 2021
## https://goldenberg.biology.utah.edu/courses/biol3515/
## David P. Goldenberg, January 2021
## goldenberg@biology.utah.edu
import random as rand
import numpy as np
import matplotlib.pyplot as plt
import ipywidgets as widgets
from IPython.display import display, HTML
from time import sleep, time
import threading
from scipy.integrate import solve_ivp
import functools
from scipy.stats import linregress
from code_dict_exp4b import code_dict
codes = list(code_dict)
display(HTML("<style>div.output_scroll { height: 600ex; }</style>"))
##----------Global Parameters--------------------##
# delay time while filling the absorbance table
# Use 0 for testing and 0.2 for production to make the simulation run about
# 5-x the actual speed.
t_sleep = 0.2
# initial values of absorbance reading and background absorbance
abs_read = 0.0
zero_set= 0.0
# Total time and number of steps for abs reading to settle
t_tot = 2
steps = 25
# Title for graph
graph_title = 'Experiment 4, Part B'
style = {'description_width': 'initial'}
##----------------Classes----------------------##
class Tube():
'''Tube class for putting stuff in'''
def __init__(self,vol=0.0,vol_n=0,max_vol=1.0,conc={}):
self.vol = vol # actual volume
self.vol_n= vol_n # nominal volume, reflecting pipette settings, vs actual delivered volumes
self.max_vol = max_vol # max volume of tube
self.conc = conc # concentrations of compounds
class Cuvette():
'''Cuvette class, like Tube but with additional
attributes for sample name and reactions start time, t0'''
def __init__(self):
self.vol = 0.0
self.vol_n = 0.0
self.conc = {}
self.t0 =0.0
class VolTable(widgets.HTML):
def __init__(self,tube_dict,head):
super().__init__(
value='',
layout=widgets.Layout(width='250px'))
self.tube_dict = tube_dict
self.head = head
self.update()
def update(self):
'''function to update the table of tube or cuvette volumes'''
html_str = '''
<style>
table, th, td {
border: 1px solid black;
}
th, td {
padding: 5px;
}
table, {border-collapse: collapse;}
</style>
<table>
<tr>'''
html_str += f'<th style="width:100px"> {self.head} </th>'
html_str += '''<th style="width:100px"> Volume (&mu;L)</th></tr>'''
for tube in self.tube_dict:
vol = self.tube_dict[tube].vol_n
html_str += f'<tr><td>{tube}</td><td>{vol:.0f} </td></tr>\n'
html_str += '</table>'
self.value=html_str
class AbsTable(widgets.HTML):
def __init__(self,cuv_dict,t_int,t_tot):
super().__init__(
value='',
layout=widgets.Layout(width='600px'))
self.cuv_dict = cuv_dict
self.t_int = t_int
self.t_tot = t_tot
self.abs_data = []
self.n_meas = int(t_tot/t_int)+1
self.n_cuv = len(self.cuv_dict)
self.refresh()
self.update()
def refresh(self):
self.abs_data=[['Time (min)']]
for cuv in self.cuv_dict:
self.abs_data[0].append('Cuvette ' + str(cuv))
for i in range(self.n_meas):
t = i*self.t_int
self.abs_data.append([t]+[None]*self.n_cuv)
self.update()
def update(self):
html_str = '''
<style>
table, th, td {
border: 1px solid black;
}
th, td {
padding: 5px;
}
table, {border-collapse: collapse;}
</style>
<table>
<tr>
<th style="width:100px"> Time (min) </th>'''
for i in range(self.n_cuv):
html_str += f'<th style="width:100px"> {self.abs_data[0][i+1]} </th>'
html_str += '</tr>\n'
for i in range(self.n_meas):
html_str += f'<tr><td> {self.abs_data[i+1][0]}</td>'
for j in range(self.n_cuv):
if self.abs_data[i+1][j+1] != None:
html_str += f'<td>{self.abs_data[i+1][j+1]:0.3f}</td>'
else:
html_str += '<td></td>'
html_str += '</tr>\n'
html_str += '</table>'
self.value=html_str
class RegTable(widgets.HTML):
def __init__(self,reg_results):
super().__init__(
value='',
layout=widgets.Layout(width='500px'))
self.reg_results = reg_results
self.update()
def update(self):
'''function to update the table of results from linear regression'''
n_cuv = len(self.reg_results)
html_str = '''
<style>
table, th, td {
border: 1px solid black;
}
th, td {
padding: 5px;
}
table, {border-collapse: collapse;}
</style>
<table>
<tr>'''
html_str += '''<th style="width:100px"> Cuvette </th>'''
html_str += '''<th style="width:100px"> Rate (min<sup>-1</sup>) </th>'''
html_str += '''<th style="width:100px"> A<sub>0</sub> </th>'''
html_str += '''<th style="width:100px"> R<sup>2</sup> </th></tr>'''
for cuv in range(n_cuv):
html_str += f'<tr><td> {cuv+1}</td>'
slope = self.reg_results[cuv].slope
html_str += f'<td>{slope:.4f}</td>'
a0 = self.reg_results[cuv].intercept
html_str += f'<td>{a0:.4f}</td>'
rsq = self.reg_results[cuv].rvalue**2
html_str += f'<td>{rsq:.3f}</td></tr>'
html_str += '</table>'
self.value=html_str
#
## --------------- Create Dictionaries ------------------##
# This has to come after the Tube and Cuvette classes are defined!
tube_conc_dict = {'trypsin':0.0, 'hepes':0.0, 'cacl':0.0,'aebsf':0.0, 'substr':0.0,'benz':0.0}
cuv_conc_dict = {'trypsin':0.0, 'tris':0.0, 'cacl':0.0,'substr':0.0,'prod':0.0}
tube_dict ={}
for n in range(1,5):
tube_dict[n] = Tube()
tube_dict[n].conc = tube_conc_dict.copy()
cuv_dict = {}
for n in range(1,5):
cuv_dict[n] = Cuvette()
cuv_dict[n].conc = cuv_conc_dict.copy()
solns_dict1={} # used to store stock solution concentrations
# for reaction tubes
solns_dict1['trypsin'] =0.0
solns_dict1['cacl'] = 20.0*1e-3 # M
solns_dict1['aebsf'] = 5.0e-3
solns_dict1['substr'] = 2.0*1e-3 # M
solns_dict1['benz'] = 1.0e-3
solns_dict1['hepes'] = 0.2 # M
# for cuvettes
solns_dict2 = {}
solns_dict2['tris'] = 0.2
solns_dict2['substr'] = 2.0*1e-3 # M
#########---------Widgets and Their Functions --------------########
##----------------Pipettes -----------------------##
# Used for multiple parts of experiment
# The deliver button is specific to each part
def on_pipette_ch(change):
'''Function to changes volume parameters when pipette is changed.'''
pip_vol.max = 1000.0
if pipette.value == 1000.0:
pip_vol.min = 200.0
pip_vol.max = 1000.0
pip_vol.step = 10.0
elif pipette.value == 200.0:
pip_vol.min = 20.0
pip_vol.max = 200.0
pip_vol.step = 1.0
elif pipette.value == 20.0:
pip_vol.min = 1.0
pip_vol.max = 20.0
pip_vol.step = 0.1
pip_vol.value = pip_vol.max
pipette = widgets.Dropdown(
# Choose pipette size
options = [('P1000',1000.0),('P200',200.0),('P20',20.0)],
description = 'Pipette:',
style=style,
layout=widgets.Layout(width='150px',margin='0px 0px 0px 50px')
)
pipette.observe(on_pipette_ch,names=['value'])
pip_vol = widgets.BoundedFloatText(
# Pipette volume setting
value = 1000.0,
min = 200.0,
max = 1000.0,
step = 10.0,
description = 'Volume set (uL):',
style = style,
layout=widgets.Layout(width='200px',margin='0px 0px 0px 50px')
)
def pip_deliver(soln_widget, soln_dict, tube_widget,tube_dict):
tube_list = list(tube_dict)
conc_list = list(tube_dict[tube_list[0]].conc)
pip_sigma = code_dict[lab_code.value]['pip_sigma']
# get pipette err from normal distr
err_pipette = pipette.value*rand.normalvariate(0,pip_sigma)
# calculate delivered volume
vol = pip_vol.value+err_pipette
# save old volume and calculate new
vol_old = tube_dict[tube_widget.value].vol
vol_new = vol_old + vol
tube_list = list(tube_dict)
reag_list = list(tube_dict[tube_list[0]].conc)
incr = {}
for reag in reag_list:
incr[reag]=0.0
# calculate increment in solute amount (mg, moles,etc)
for reag in reag_list:
if reag == soln_widget.value:
incr[reag] = vol*soln_dict[reag]
if 'trypsin' == soln_widget.value:
# special provision for trypsin solution conaining 20 mM CaCl2
incr['cacl'] =vol*0.02
# update concentrations
for reag in reag_list:
conc_old = tube_dict[tube_widget.value].conc[reag]
conc_new = (conc_old*vol_old + incr[reag])/vol_new
tube_dict[tube_widget.value].conc[reag] = conc_new
#update volumes
tube_dict[tube_widget.value].vol = vol_new
tube_dict[tube_widget.value].vol_n += pip_vol.value
##----------------Lab Code Entry ------------------##
def on_code_ch(value):
'''Respond to change in the code entered in the code box'''
if lab_code.value != '' and lab_code.value not in codes:
code_warn.value = '<span style="color:red;">Invalid code</span>'
elif lab_code.value in codes:
solns_dict1['trypsin']=code_dict[lab_code.value]['e_conc']/10
code_warn.value =''
deliver_butt1.button_style = 'success'
deliver_butt1.description='Pipette!'
deliver_butt2.button_style = 'success'
deliver_butt2.description='Pipette!'
# run_butt.button_style = 'success'
# run_butt.description='Run!'
code_label = widgets.HTML(
value = ''' <h3>Lab code: </h3>'''
)
lab_code = widgets.Text(
# text-entry widget to enter lab code
value = '',
placeholder='',
#description = 'Lab code',
layout=widgets.Layout(width='100px',margin='20px 0px 0px 15px')
)
lab_code.observe(on_code_ch,names=['value'])
code_warn = widgets.HTML(
# warning when invalid lab code is entered
value = '',
layout=widgets.Layout(width='200px',margin='15px 50px 15px 0px')
)
row_code = widgets.HBox([code_label,lab_code,code_warn])
###-------------Reaction Tubes------------##
def deliver1(change):
if lab_code.value not in codes:
deliver_butt1.description='Enter valid lab code'
deliver_butt1.button_style = 'warning'
return
pip_deliver(solns1_widget, solns_dict1, tubes_widget, tube_dict)
tube_vol_table.update()
def empty1(change):
tube = tube_dict[tubes_widget.value]
for conc in tube.conc:
tube.conc[conc]=0.0
tube.vol = 0.0
tube.vol_n = 0.0
tube_vol_table.update()
solns1_widget = widgets.RadioButtons(
# solutions for reaction tubes
options=[('H2O','H2O'),('0.2 M HEPES, pH 8', 'hepes'),('20 mM CaCl2','cacl'),('5 mM AEBSF','aebsf'),('2 mM substrate','substr'),('1 mM benzamidine','benz'),('Trypsin','trypsin')],
description='Solutions'
)
empty_butt1 = widgets.Button(
# button to empty tube for bsa dilution
description = 'Empty',
button_style = 'danger',
)
empty_butt1.on_click(empty1)
tubes_widget=widgets.RadioButtons(
# Tubes for BPTIf-trypsin incubation
options=[1,2,3,4],
description = 'Tubes:'
)
tube_vol_table = VolTable(tube_dict,'Tube')
deliver_butt1 = widgets.Button(
# Button to deliver volume for BSA dilution
description = 'Pipette!',
button_style = 'success',
)
deliver_butt1.on_click(deliver1)
tubeVb=widgets.VBox([tubes_widget,empty_butt1],
layout=widgets.Layout(width='40%',margin='0px 0px 0px 00px'))
row_tubes = widgets.HBox([solns1_widget,tubeVb,tube_vol_table],
layout=widgets.Layout(margin='0px 0px 50px 00px'))
row_pip1 = widgets.HBox([deliver_butt1,pipette,pip_vol])
box_rxn_tubes = widgets.VBox([row_tubes, row_pip1])
###---------------Start Reactions-------------------###
def irrev_de(t,y,k2,b_conc,b_ki,s_conc,km,kcat):
'''Differential eqns for irreversible inhibition of
trypsin by aebsf, with effects of substrate and benzamidine'''
e_conc=y[0]
i_conc=y[1]
s_conc=y[2]
if b_conc > 0.0:
km = km*(1 + b_ki/b_conc)
e_avail = e_conc/(1+b_conc/b_ki + s_conc/km)
ds_conc = -e_conc*kcat*s_conc/(km + s_conc)
de_conc = -k2*e_avail*i_conc
di_conc = de_conc
return [de_conc,di_conc,ds_conc]
rxn_kin_solns = []
def start_rxns(change):
start_rxn_butt.disabled = True
# kinetic parameters for reactions of trypsin with AEBSF
# k2 for reaction with AEBSF
k2 = code_dict[lab_code.value]['k2aebsf']
# Ki for benzamidine
b_ki = 5e-6 # M
km = code_dict[lab_code.value]['km']
# kcat for substrate under these conditions
# inferred from the actual experiment, about 1/15 of value
# under normal conditions
kcat = code_dict[lab_code.value]['kcat']/15.0
min_tot = 150
sec_tot = min_tot*60
pts = min_tot + 1
for tube in tube_dict:
e_conc = tube_dict[tube].conc['trypsin']
i_conc = tube_dict[tube].conc['aebsf']
b_conc = tube_dict[tube].conc['benz']
s_conc = tube_dict[tube].conc['substr']
soln = solve_ivp(irrev_de,[0.0,sec_tot],[e_conc,i_conc,s_conc],
args=[k2,b_conc,b_ki,s_conc,km,kcat],
method = 'Radau',t_eval=np.linspace(0.0,sec_tot,pts))
rxn_kin_solns.append(soln)
reset_rxn_butt.disabled = False
deliver_butt3.disabled = False
def reset_rxns(change):
global rxn_kin_solns
rxn_kin_solns.clear()
tube_reset(tube_dict)
tube_vol_table.update()
start_rxn_butt.disabled=False
deliver_butt3.disabled = True
reset_rxn_butt.disabled = True
start_rxn_butt = widgets.Button(
# Button to start simulated kinetics run
description = 'Start Reactions!',
button_style = 'success',
disabled = False,
layout=widgets.Layout(margin='0px 0px 0px 0px')
)
start_rxn_butt.on_click(start_rxns)
reset_rxn_butt = widgets.Button(
# Button to start simulated kinetics run
description = 'Reset Reactions',
button_style = 'danger',
disabled = True,
layout=widgets.Layout(margin='0px 0px 0px 20px')
)
reset_rxn_butt.on_click(reset_rxns)
row_rxn_butt = widgets.HBox([start_rxn_butt,reset_rxn_butt])
##----------------Cuvette Setup --------------------------##
def deliver2(change):
if lab_code.value not in codes:
deliver_butt2.description='Enter valid lab code'
deliver_butt2.button_style = 'warning'
return
pip_deliver(solns_widget2, solns_dict2, cuv_widget, cuv_dict)
c_trypsin = cuv_dict[cuv_widget.value].conc['trypsin']
c_substr = cuv_dict[cuv_widget.value].conc['substr']
if c_trypsin >0 and c_substr >0:
cuv_dict[cuv_widget.value].t0 = time()
cuv_vol_table.update()
def empty_cuv(change):
cuv = cuv_dict[cuv_widget.value]
for conc in cuv.conc:
cuv.conc[conc]=0.0
cuv.vol = 0.0
cuv.vol_n = 0.0
cuv.t0=0.0
cuv_vol_table.update()
solns_widget2 = widgets.RadioButtons(
# solutions for cuvettes for part A
options =[('H20','H2O'), ('0.2 M Tris-Cl, pH 8','tris'),
('2 mM substrate','substr')],
description='Solutions',
layout=widgets.Layout(width='30%',margin='0px 0px 0px 0px')
)
cuv_widget = widgets.RadioButtons(
# Cuvettes for part A
options=[1,2,3,4],
description = 'Cuvettes:'
)
empty_cuv_butt = widgets.Button(
# button to empty cuvettes for part A
description = 'Empty',
button_style = 'danger',
)
empty_cuv_butt.on_click(empty_cuv)
cuv_vol_table = VolTable(cuv_dict,'Cuvette')
deliver_butt2 = widgets.Button(
# Button to deliver volume for BSA dilution
description = 'Pipette!',
button_style = 'success',
)
deliver_butt2.on_click(deliver2)
cuvVb=widgets.VBox([cuv_widget,empty_cuv_butt],
layout=widgets.Layout(width='40%',margin='0px 0px 0px 00px'))
row_cuv = widgets.HBox([solns_widget2,cuvVb,cuv_vol_table])
row_pip = widgets.HBox([deliver_butt2,pipette,pip_vol],
layout=widgets.Layout(margin='15px 0px 0px 0px'))
box_cuv = widgets.VBox([row_cuv,row_pip])
## -------------- Final Cuvette additions _________##
# The tubes from the AEBSF reactions serve as the solutions for the final addition.
def deliver3(change):
if lab_code.value not in codes:
deliver_butt3.description='Enter valid lab code'
deliver_butt3.button_style = 'warning'
return
if len(rxn_kin_solns)<4:
deliver_butt3.description='Start reactions'
deliver_butt3.button_style = 'warning'
return
if not (0 <= rxn_time.value <= 150):
deliver_butt3.description='Enter valid rxn time'
deliver_butt3.button_style = 'warning'
return
pip_sigma = code_dict[lab_code.value]['pip_sigma']
tube = tubes_widget.value
cuv = cuv_widget.value
# get pipette err from normal distr
err_pipette = pipette.value*rand.normalvariate(0,pip_sigma)
# calculate delivered volume
vol = pip_vol.value+err_pipette
# save old volume and calculate new
vol_old = cuv_dict[cuv].vol
vol_new = vol_old + vol
# active enzyme concentration comes from the simulation of
# the AEBSF reaction
# we ignore everything else in the reaction tubes!
t_rxn= rxn_time.value
e_conc = rxn_kin_solns[tubes_widget.value-1].y[0][t_rxn]
incr = vol*e_conc
conc_old = cuv_dict[cuv].conc['trypsin']
cuv_dict[cuv].conc['trypsin'] = (conc_old*vol_old + incr)/vol_new
#update volumes
cuv_dict[tube].vol = vol_new
cuv_dict[tube].vol_n += pip_vol.value
c_trypsin = cuv_dict[cuv].conc['trypsin']
c_substr = cuv_dict[cuv].conc['substr']
if c_trypsin >0 and c_substr >0:
cuv_dict[cuv].t0 = time()
cuv_vol_table.update()
def on_time_ch(change):
if 0 <= rxn_time.value <= 150:
deliver_butt3.description='Pipette!'
deliver_butt3.button_style = 'success'
rxn_time = widgets.IntText(
# text box for reaction time
description = 'Reaction Time (min):',
value= 0,
layout=widgets.Layout(width='200px',margin='20px 0px 0px 15px'),
style=style,
disabled = False
)
rxn_time.observe(on_time_ch,names=['value'])
deliver_butt3 = widgets.Button(
# Button to deliver volume for BSA dilution
description = 'Pipette!',
button_style = 'success',
disabled = True
)
deliver_butt3.on_click(deliver3)
row_cuv2 = widgets.HBox([tubes_widget,cuv_widget])
row_pip3 = widgets.HBox([deliver_butt3,pipette,pip_vol],
layout=widgets.Layout(margin='15px 0px 0px 0px'))
box_final_add = widgets.VBox([row_cuv2,row_pip3])
##---------------Kinetic Run --------------------=##
def mm_de(t,y,e_conc,km,kcat):
s_conc = y[0]
p_conc = y[1]
dp_conc = e_conc*kcat*s_conc/(km+s_conc)
ds_conc = -dp_conc
return [ds_conc,dp_conc]
def kin_sim(cuv_dict,t_tot):
# simulation is run for twice t_tot, to allow for starting delay
# and continued absorbance readings after the run
pts = int(2*t_tot*60)
kin_sols =[]
km=code_dict[lab_code.value]['km']
kcat=code_dict[lab_code.value]['kcat']
for cuv in cuv_dict:
s_conc = cuv_dict[cuv].conc['substr']
p_conc = 0.0
e_conc =cuv_dict[cuv].conc['trypsin']
if cuv_dict[cuv].conc['tris'] < 0.09:
# activity is reduced if tris concentration isn't adequate
kcat *= 0.5
if cuv_dict[cuv].conc['cacl'] < 0.0009:
# some of the enzyme is lost if CaCl2 concentration isn't adequate
e_conc *= 0.5
kin_sols.append(solve_ivp(mm_de,[0.0,float(pts)],[s_conc,p_conc],
args=[e_conc,km,kcat],t_eval=np.linspace(0.0,float(pts),pts+1)))
# return kcat to its original value
kcat=code_dict[lab_code.value]['kcat']
return kin_sols
def kin_run(abs_table,change):
if lab_code.value not in codes:
run_butt.description='Enter valid lab code'
run_butt.button_style = 'warning'
return
run_butt.disabled = True
abs_sigma = code_dict[lab_code.value]['abs_sigma']
abs_table.refresh()
if wl.value == '402 nm':
ext_coef=0.9e4
elif wl.value == '405 nm':
ext_coef=1e4
else:
ext_coef=0.0
t_int = abs_table.t_int
t_tot = abs_table.t_tot
n_cuv = abs_table.n_cuv
n_meas = abs_table.n_meas
cuv_dict = abs_table.cuv_dict
abs_data = abs_table.abs_data
# a bit to introduce some variation from run to run,
# as might arise from loss of enzyme activity
e_var = 0.9 + 0.2 * rand.random()
for cuv in cuv_dict:
cuv_dict[cuv].conc['trypsin'] *= e_var
kin_sols = kin_sim(cuv_dict,t_tot)
sleep(1)
cuv_int =int(60*t_int/n_cuv)
delay_t = []
for cuv in cuv_dict:
if cuv_dict[cuv].t0 > 0:
delay = int(time()-cuv_dict[cuv].t0)
delay_t.append(delay)
else:
delay_t.append(0)
t=0
tcuv=0
meas = 1
cuv = 1
cuv_show(cuv)
abs_start = abs_read-zero_set
pts_total = int((t_tot+t_int)*60+cuv_int)
for i in range(pts_total):
sleep(t_sleep)
read_t = t + delay_t[cuv-1]
absorb = kin_sols[cuv-1].y[1][read_t]*ext_coef + abs_start
abs_show(absorb)
if tcuv>=cuv_int:
err = rand.normalvariate(0,abs_sigma)
abs_data[meas][cuv] = absorb + err
abs_table.update()
if cuv < n_cuv:
cuv+=1
else:
cuv=1
meas +=1
cuv_show(cuv)
tcuv=0
tcuv+=1
t += 1
make_plot(abs_table.abs_data)
reset_butt.disabled = False
def make_plot(abs_data):
global reg_table
prop_cycle = plt.rcParams['axes.prop_cycle']
colors = prop_cycle.by_key()['color']
colors.pop(2) # remove green
#colors.pop(4) # remove brown
#colors.pop(5) # remove grey
plot_data = [[]]
n_meas = abs_table.n_meas
n_cuv = abs_table.n_cuv
abs_data = abs_table.abs_data
for j in range(n_meas):
plot_data[0].append(abs_data[j+1][0])
for i in range(n_cuv):
plot_data.append([])
for j in range(n_meas):
plot_data[i+1].append(abs_data[j+1][i+1])
plot_data = np.array(plot_data)
reg_results = []
for i in range(n_cuv):
reg = linregress(plot_data[0],plot_data[i+1])
reg_results.append(reg)
reg_x = np.array([0.0,plot_data[0,-1]])
fig = plt.figure(figsize=(7.5,5))
ax= fig.add_subplot(1,1,1)
for i in range(n_cuv):
reg_yint = reg_results[i].intercept
reg_slope = reg_results[i].slope
reg_y = reg_x*reg_slope+reg_yint
ax.plot(plot_data[0],plot_data[i+1],'o',color=colors[i])
ax.plot(reg_x,reg_y,color=colors[i], label =f'Cuvette {i+1}')
ax.set_title(graph_title,fontsize=18)
ax.set_xlabel('Time (min)',fontsize=14)
ylabel_str = 'Absorbance at ' + wl.value
ax.set_ylabel(ylabel_str,fontsize=14)
data_min = plot_data.min()
if data_min < 0.0:
ax.set_ylim(data_min,)
else:
ax.set_ylim(0,)
ax.set_xlim(0,)
ax.legend()
# Important note: close the plot so that it doesn't automatically
# display in Jupyter. Otherwise, it will never go away!
# display the fig in Output widget, which can be made to go away!
plt.close()
with fig_output:
display(fig)
reg_table = RegTable(reg_results)
# Important note 2: In order for the regression table (an HTML widget
# created within this function) to appear in voila, it has to be put
# in an output widget declared globally.
with reg_table_output:
display(reg_table)
def cuv_show(cuv):
'''function to display the cuvette number in the cuv_display HTML widget'''
cuv_displ.value=f'<h2>Cuvette:<span style="color:red;">\
{cuv} </span></h2>'
def on_wl_ch(value):
'''Respond to change in the wavelength widget'''
h2O_abs = {'260 nm':0.14,'280 nm':0.3, '402 nm':0.4, '405 nm':0.6,'595 nm':0.8}
absorb=h2O_abs[wl.value]
abs_update(absorb)
def zero(change):
'''Respond to the Zero button'''
global zero_set
zero_set = abs_read
abs_update(abs_read)
def damp_sin(t,nu,tau):
'''damped sine function to simulate settling
of absorbance reading. Input arguments:
t: time
nu: sine-function frequency
tau: exponential-decay time constant
'''
d_sin = np.exp(-t/tau)*np.sin(t*nu*2*np.pi)
return d_sin
def abs_update(absorb):
'''function to set global abs_read2 variable and
Updates absorbance display, with settling time
Input arguments:
absb: settled absorbance value
global variables used:
t_tot: total time for reading to settle
steps: number of times to update display
as it settles.
'''
global abs_read
displ_absb = absorb - zero_set
tau = 0.2*t_tot
nu = 5/t_tot
for i in range(steps+1):
t = t_tot*i/steps
abs_d = displ_absb*(1+damp_sin(t,nu,tau))
sleep(t_tot/steps)
abs_show(abs_d)
abs_read = absorb
def abs_show(absorb):
'''function to displays variable in the spec_dislp HTML widget'''
if absorb < -0.03:
spec_displ.value='<h2> Abs: <span style="color:red;"> Err </span></h2>'
else:
spec_displ.value='<h2> Abs: <span style="color:red;"> \
{:.3f}'.format(absorb) + '</span></h2>'
def cuv_reset(cuv_dict):
'''Reset volumes, concentrations and t0 in all of the cuvettes in cuv_dict'''
for cuv in cuv_dict:
cuv_dict[cuv].vol = 0.0
cuv_dict[cuv].vol_n = 0.0
for c in cuv_dict[cuv].conc:
cuv_dict[cuv].conc[c] = 0.0
cuv_dict[cuv].t0=0.0
def on_reset(change):
abs_table.refresh()
reg_table.close()
fig_output.clear_output()
#cuv_reset(cuv_dict)
cuv_vol_table.update()
# reset clock on cuvettes so that a run can be restarted without risk
# of running out of time points.
for cuv in cuv_dict:
cuv_dict[cuv].t0=0.0
run_butt.disabled = False
reset_butt.disabled = True
abs_table = AbsTable(cuv_dict, 1.0,5.0)
wl = widgets.Dropdown(
# Dropdown to select wavelength for spectrophotometer
options = [('260 nm'),('280 nm'),('402 nm'),('405 nm'),('595 nm')],
description = 'Wavelength:',
style = style,
layout=widgets.Layout(width='200px',margin='0px 0px 20px 0px')
)
wl.observe(on_wl_ch,names=['value'])
zero_butt = widgets.Button(
# button to zero absorbance display
description = 'Zero',
button_style = 'success',
layout=widgets.Layout(margin='0px 0px 0px 20px')
)
zero_butt.on_click(zero)
run_butt = widgets.Button(
# Button to start simulated kinetics run
description = 'Run!',
button_style = 'success',
layout=widgets.Layout(margin='0px 0px 0px 0px')
)
run_butt.on_click(functools.partial(kin_run,abs_table))
cuv_displ=widgets.HTML(
# cuvette number display
value='1',
layout=widgets.Layout(margin='-15px 0px 0px 20px')
)
spec_displ = widgets.HTML(
# spectrophotometer display
value='0.0',
layout=widgets.Layout(width='140px',margin='-15px 0px 0px 20px')
)
reset_butt = widgets.Button(
# button to reset kinetic simulation
description ='Reset spec run',
button_style = 'danger',
disabled = True,
layout=widgets.Layout(margin='0px 0px 0px 20px')
)
reset_butt.on_click(on_reset)
abs_show(0)
cuv_show(1)
row_spec1 = widgets.HBox([wl,zero_butt])
row_spec2 = widgets.HBox([run_butt, cuv_displ, spec_displ, reset_butt])
fig_output = widgets.Output(layout={'border': '1px solid black','width':'500px'})
reg_table_output=widgets.Output()
##---------------- Special Functions -----------------------##
def tube_reset(tube_dict):
'''Reset volumes and concentrations in all of the tubes in tube_dict'''
for tube in tube_dict:
tube_dict[tube].vol = 0.0
tube_dict[tube].vol_n = 0.0
for c in tube_dict[tube].conc:
tube_dict[tube].conc[c] = 0.0
def cuv_reset(cuv_dict):
'''Reset volumes, concentrations and t0 in all of the cuvettes in cuv_dict'''
for cuv in cuv_dict:
cuv_dict[cuv].vol = 0.0
cuv_dict[cuv].vol_n = 0.0
for c in cuv_dict[cuv].conc:
cuv_dict[cuv].conc[c] = 0.0
cuv_dict[cuv].t0=0.0
def test_cuv():
cuv_reset(cuv_dict)
# A function for quickly setting up cuvettes for testing
e_stock = 0
s_stock = 0.002
for cuv in cuv_dict:
cuv_dict[cuv].vol = 760.0
cuv_dict[cuv].vol_n = 760.0
cuv_dict[cuv].conc['tris']=0.2*400.0/760
cuv_dict[cuv].conc['substr']= (80.0/760)*s_stock
cuv_dict[cuv].t0 = 10*cuv
cuv_vol_table.update()
def test_tube():
tube_reset(tube_dict)
# A function for quickly setting up the reaction tubes for testing.
trypsin_conc= code_dict[lab_code.value]['e_conc']/10.0
cacl_conc = 0.02 # stock solution
for tube in tube_dict:
tube_dict[tube].vol = 800.0
tube_dict[tube].vol_n = 800.0
tube_dict[tube].conc['hepes'] = 0.1
tube_dict[tube].conc['trypsin'] = trypsin_conc/10.0
tube_dict[tube].conc['cacl'] = cacl_conc/8.0
if tube != 1:
tube_dict[tube].conc['aebsf'] = 40.0*5e-3/800.0
tube_dict[3].conc['substr'] = 180.0*2e-3/800.0
tube_dict[4].conc['benz'] = 80.0*1e-3/800.0
tube_vol_table.update()
##-------------- Widgets ----------------------#
##-------------- Decorative and Informational Widgets ----------------------#
hrule = widgets.HTML(
# general purpose horizontal rule
value ='<hr border-width:6px, color:black>')
header_html = """
<h2> Biology 3515/Chemistry 3515
<br>
Biological Chemistry Laboratory
<br>
University of Utah </h2>
<h3> Spring 2021 </h3>
<h3> Experiment 4, Part B: Irreversible Inhibition of Trypsin</h3>
<p style="font-size:16px">
This web page simulates the procedures to be carried out in Part B of Experiment 4. In this experiment, the goal is to measure the rate of inactivation of trypsin by 4-(2-aminoethyl)-benzenesulfonyl fluoride (AEBSF) and the effects of two other compounds on the inhibition kinetics.
<br><br>
This experiment requires multiple steps, as reflected in the headings below. The first step is to set up four reaction tubes, each containing the same amount of trypsin, with and without AEBSF, a substrate and a competitive inhibitor. The specific contents of the tubes are specified in the lab manual. After the trypsin has been added to all of the tubes, a button must be pressed to start the simulation of the reactions (something that is not required in the real lab!) At specific times after the reactions are started, samples are withdrawn from the tubes and added to cuvettes already containing buffer and substrate. The absorbance of these cuvettes is then monitored to determine the fraction of the initial trypsin that is still active in the tubes.
<br><br>
Samples are withdrawn from the reaction tubes immediately after the reactions are started and after 15, 30, 60, 90 and 120 min. However, you do not need to wait so long in the simulated experiment! Instead, there is a text entry box in which to specify the time for each of the assay sets, and they can be carried out sequentially without delays.
<br><br>
As in the last few experiments, you will simulate kinetic runs on the spectrophotometer as would be carried out in the lab. The simulations will output a table of absorbance values recorded at time intervals and make a plot of the data. The program also prints a table of data from least-squares fit of the data to a straight line. As before, these should be copied to your LabArchives notebook with clear annotations indicating the time points.
<br><br>
The simulation of the kinetic run is sped up by a factor of about 5-fold from what the real experiment takes.
<br><br>
Like the previous experiments, this simulations requires a lab code to function, and your group should use the same code assigned earlier. If you do not have an assigned code, but want to experiment with this simulation, use the code "0GXY02".
"""
header = widgets.HTML(
value=header_html
)
footer = widgets.HTML(
value='''
<hr border-width:6px, color:black>
David P. Goldenberg, February 2021<br>
<a href="mailto:goldenberg@biology.utah.edu" target="new">goldenberg@biology.utah.edu</a><br>
School of Biological Sciences, University of Utah<br>
Salt Lake City, Utah 8412-0840<br>
<a href="https://goldenberg.biology.utah.edu/courses/biol3515/index.shtml"
target="new">https://goldenberg.biology.utah.edu/courses/biol3550.</a>
''')
hrule = widgets.HTML(
# general purpose horizontal rule
value ='<hr border-width:6px, color:black>')
b1header = widgets.HTML(
# header for part B, part 1
value = '<h2> 1. Reaction tube setup</h2>'
)
b2header = widgets.HTML(
# header for part B, part 2
value = '<h2> 2. Reaction start</h2>'
)
b3header = widgets.HTML(
# header for part B, part 3
value = '<h2> 3. Cuvette setup </h2>'
)
b4header = widgets.HTML(
# header for part B, part 4
value = '<h2> 4. Sample transfer from reaction tubes to cuvettes</h2>'
)
b5header = widgets.HTML(
# header for part B, part 5
value = '<h2> 5. Kinetic run </h2>'
)
##---------------- Display Everything -------------------#
#lab_code.value='0GXY02'
display(header)
display(hrule)
display(row_code)
display(hrule)
display(b1header)
display(box_rxn_tubes)
display(hrule)
display(b2header)
display(row_rxn_butt)
display(hrule)
display(b3header)
display(box_cuv)
display(hrule)
display(b4header)
display(rxn_time)
display(box_final_add)
display(hrule)
display(b5header)
display(row_spec1)
display(row_spec2)
display(abs_table)
display(fig_output)
display(reg_table_output)
display(footer)
#display(footer)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment