Last active
March 20, 2021 16:43
-
-
Save dpgoldenberg/0d2cc1ca99d11ae97c0b7a1dde150b2a to your computer and use it in GitHub Desktop.
Biol 3515-Chem 3515 Exp 3, Part B
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Biol 3515-Chem 3515 Exp 3, Part B |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
code_dict = {'0GXY02': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.0780933743000794e-05, | |
'bpti_conc': 3.385861355932284e-05, | |
'kcat': 12.479059780623182, | |
'km': 8.563436439963315e-05}, | |
'DD0371': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.943933934989462e-05, | |
'bpti_conc': 3.517617542672528e-05, | |
'kcat': 9.174417463278722, | |
'km': 4.777372487256253e-05}, | |
'X5FX87': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.95266826439055e-05, | |
'bpti_conc': 3.138461537261679e-05, | |
'kcat': 11.789268600290177, | |
'km': 5.58468122174051e-05}, | |
'FG188G': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.285031188273903e-05, | |
'bpti_conc': 3.1851612073108055e-05, | |
'kcat': 13.047612493354922, | |
'km': 7.177787853319616e-05}, | |
'34P10Q': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.722682984532362e-05, | |
'bpti_conc': 3.332900420043714e-05, | |
'kcat': 8.145189509187809, | |
'km': 6.57837365279514e-05}, | |
'Y4N6KZ': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.8906484201970237e-05, | |
'bpti_conc': 3.2455623824540886e-05, | |
'kcat': 13.614464085817126, | |
'km': 5.4379228053721865e-05}, | |
'W5XM03': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.9115719982294164e-05, | |
'bpti_conc': 3.0087175891276203e-05, | |
'kcat': 10.075765236194103, | |
'km': 3.320531258425417e-05}, | |
'9V51PV': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.2972895706886008e-05, | |
'bpti_conc': 3.301735248311078e-05, | |
'kcat': 14.253426350877806, | |
'km': 8.949671739010028e-05}, | |
'942913': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.0249547380195524e-05, | |
'bpti_conc': 3.2738298103130895e-05, | |
'kcat': 11.135081432311162, | |
'km': 7.07376899404837e-05}, | |
'N898UN': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.8674877368836247e-05, | |
'bpti_conc': 3.062565836535658e-05, | |
'kcat': 10.097357504977413, | |
'km': 6.59893141525897e-05}, | |
'H4CGP6': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.4074717025273083e-05, | |
'bpti_conc': 3.17443257141572e-05, | |
'kcat': 10.86527728039156, | |
'km': 4.0295083099196564e-05}, | |
'13KE9N': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.0654600749048573e-05, | |
'bpti_conc': 3.103388919416864e-05, | |
'kcat': 14.476740111724716, | |
'km': 4.664199652900124e-05}, | |
'31PQ53': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.264345369791618e-05, | |
'bpti_conc': 3.0372329090212688e-05, | |
'kcat': 6.560328970813622, | |
'km': 3.930321207228756e-05}, | |
'KK644G': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.9346499463477278e-05, | |
'bpti_conc': 3.387315205215228e-05, | |
'kcat': 8.322469408595582, | |
'km': 4.5568979770163385e-05}, | |
'2TNA45': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.9246819164209123e-05, | |
'bpti_conc': 3.578113635439317e-05, | |
'kcat': 5.953190657380047, | |
'km': 3.994947194229087e-05}, | |
'N6AADQ': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.8630368266346355e-05, | |
'bpti_conc': 3.19547849326813e-05, | |
'kcat': 8.425285215458262, | |
'km': 8.304450919324063e-05}, | |
'SV22HX': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.7310317193021016e-05, | |
'bpti_conc': 3.368622203870609e-05, | |
'kcat': 11.54988636685996, | |
'km': 5.4691251633663635e-05}, | |
'VS8S0J': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.1921188687159537e-05, | |
'bpti_conc': 3.230870033910233e-05, | |
'kcat': 11.169575003686369, | |
'km': 6.197424343338799e-05}, | |
'4U2RCD': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.876088862624062e-05, | |
'bpti_conc': 3.0681927928368936e-05, | |
'kcat': 11.746442846771568, | |
'km': 5.739471754772193e-05}, | |
'ZCRTWU': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.9224581361271966e-05, | |
'bpti_conc': 3.162737039250661e-05, | |
'kcat': 5.076806311887225, | |
'km': 3.228842227365505e-05}, | |
'7182Y1': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.47216027558941e-05, | |
'bpti_conc': 3.0170396309572576e-05, | |
'kcat': 8.241979108276192, | |
'km': 6.0074402918688364e-05}, | |
'W8Y4P3': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.7782485501855382e-05, | |
'bpti_conc': 3.33401281619942e-05, | |
'kcat': 10.195874314801054, | |
'km': 3.488329626913995e-05}, | |
'J9PWB4': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.475736161044849e-05, | |
'bpti_conc': 3.404517806270831e-05, | |
'kcat': 6.754889828781962, | |
'km': 8.773579280310646e-05}, | |
'43479S': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.6621708935755493e-05, | |
'bpti_conc': 3.45845158476193e-05, | |
'kcat': 13.144983394351692, | |
'km': 5.9336652102587744e-05}, | |
'MYX1AX': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.6766972738830726e-05, | |
'bpti_conc': 3.454616610975151e-05, | |
'kcat': 12.914367456489144, | |
'km': 4.940114234055595e-05}, | |
'S0E0YV': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.7032357040088922e-05, | |
'bpti_conc': 3.340431664908145e-05, | |
'kcat': 10.957824559421038, | |
'km': 3.289894725028064e-05}, | |
'DFKPU9': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.723282359923739e-05, | |
'bpti_conc': 3.364544537727849e-05, | |
'kcat': 7.466998500516203, | |
'km': 6.51627417368447e-05}, | |
'9RFXYW': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.5000509553011084e-05, | |
'bpti_conc': 3.416324621738166e-05, | |
'kcat': 6.705684564747556, | |
'km': 5.8051980187978164e-05}, | |
'88PTV8': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.4524217499362522e-05, | |
'bpti_conc': 3.526260165210863e-05, | |
'kcat': 5.011219927285401, | |
'km': 8.251030817940819e-05}, | |
'H0X54M': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.4139816960349272e-05, | |
'bpti_conc': 3.104640020546267e-05, | |
'kcat': 6.589695629876994, | |
'km': 6.600131868852241e-05}, | |
'KD1K2N': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.7172667254962533e-05, | |
'bpti_conc': 3.4168766856849033e-05, | |
'kcat': 10.800375363792174, | |
'km': 4.161401188579533e-05}, | |
'23W0N6': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.922648717519026e-05, | |
'bpti_conc': 3.244865757821224e-05, | |
'kcat': 10.434092819204855, | |
'km': 8.777019172064786e-05}, | |
'GQ5P11': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.7288023178577137e-05, | |
'bpti_conc': 3.372014139433057e-05, | |
'kcat': 8.027464722293182, | |
'km': 8.77400879268201e-05}, | |
'597J70': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.912745303888913e-05, | |
'bpti_conc': 3.56382749381675e-05, | |
'kcat': 10.458568211196791, | |
'km': 4.246737812426825e-05}, | |
'77YE98': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.6706669601780035e-05, | |
'bpti_conc': 3.245311391523635e-05, | |
'kcat': 7.330432197837356, | |
'km': 8.891603561232728e-05}, | |
'994A4U': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.8895005256200494e-05, | |
'bpti_conc': 3.259486743957249e-05, | |
'kcat': 5.174640178640072, | |
'km': 5.320770050272746e-05}, | |
'22NZ8S': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.1267935215025052e-05, | |
'bpti_conc': 3.247345993620789e-05, | |
'kcat': 9.340617525524213, | |
'km': 8.084998120581375e-05}, | |
'33VZHV': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.588140524849908e-05, | |
'bpti_conc': 3.069265913614357e-05, | |
'kcat': 11.929996897914258, | |
'km': 4.824483178683697e-05}, | |
'YD34E7': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.1705054520364497e-05, | |
'bpti_conc': 3.0709011784212644e-05, | |
'kcat': 10.27610221982453, | |
'km': 3.781178868193927e-05}, | |
'B4EV54': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.0354460994888705e-05, | |
'bpti_conc': 3.116014032604333e-05, | |
'kcat': 7.021725135847429, | |
'km': 5.7035565773548506e-05}, | |
'QXQEA0': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.3323423105185772e-05, | |
'bpti_conc': 3.1520993936694644e-05, | |
'kcat': 6.929654495543255, | |
'km': 3.181108783085965e-05}, | |
'RCE9Z2': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.01296550430366e-05, | |
'bpti_conc': 3.348731237039411e-05, | |
'kcat': 13.410636428482128, | |
'km': 6.436577355205234e-05}, | |
'W382SW': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.774481028180708e-05, | |
'bpti_conc': 3.5226383654173546e-05, | |
'kcat': 12.769638907644534, | |
'km': 7.359061292718445e-05}, | |
'Y1UUUA': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.0828543359469805e-05, | |
'bpti_conc': 3.0181583232375123e-05, | |
'kcat': 6.72929920464161, | |
'km': 8.86483930276227e-05}, | |
'240125': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.7918021956761915e-05, | |
'bpti_conc': 3.501677251343129e-05, | |
'kcat': 5.844744273832838, | |
'km': 4.588117735847368e-05}, | |
'0P20E8': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.9706742739803737e-05, | |
'bpti_conc': 3.5919910588591474e-05, | |
'kcat': 11.3167024699186, | |
'km': 8.655867671649303e-05}, | |
'CTZKSB': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.6678519754892104e-05, | |
'bpti_conc': 3.063378110243431e-05, | |
'kcat': 14.698116904941546, | |
'km': 7.633417818129455e-05}, | |
'K60820': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.7891470882886813e-05, | |
'bpti_conc': 3.408969521270859e-05, | |
'kcat': 5.1724040679813585, | |
'km': 8.540103081102389e-05}, | |
'WE21H5': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 1.8244941876266545e-05, | |
'bpti_conc': 3.552211078184191e-05, | |
'kcat': 9.019636410141747, | |
'km': 8.204223957035615e-05}, | |
'N180MF': {'pip_sigma': 0.03, | |
'abs_sigma': 0.001, | |
'e_conc': 2.3419204687993863e-05, | |
'bpti_conc': 3.1431254231335e-05, | |
'kcat': 7.10770397148994, | |
'km': 5.528682797277228e-05}} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: exp_3b_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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## Module for import into Jupyter for simulation of Experiment 3, part B | |
## 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 labcodes import codes | |
from code_dict_exp3 import code_dict | |
display(HTML("<style>div.output_scroll { height: 400ex; }</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_read1 = 0.0 # for uv abs of bpti soln | |
zero_set1= 0.0 # for uv abs of bpti soln | |
abs_read2 = 0.0 # for kin run | |
zero_set2= 0.0 # for kin run | |
# Total time and number of steps for abs reading to settle | |
t_tot = 2 | |
steps = 25 | |
# Title for graph | |
graph_title = 'Experiment 3, Part B' | |
style = {'description_width': 'initial'} | |
def make_code_dict(codes): | |
'''Function to build code dictionary specific to this experiment | |
Don't actually call this function when loading the module, or else | |
the dictionary will change with every execution. Instead save value | |
of dictionary in this module.''' | |
code_dict ={} | |
for code in codes: | |
pip_sigma =0.03 | |
abs_sigma = 0.001 | |
e_conc = (1 + rand.random())*1.5e-5 | |
bpti_conc = (1 + 0.2*rand.random())*3e-5 | |
kcat = (1 + 2*rand.random())*5.0 | |
km = (1 + 2*rand.random())*30e-6 | |
code_dict[code]={} | |
code_dict[code]['pip_sigma']=pip_sigma | |
code_dict[code]['abs_sigma'] = abs_sigma | |
code_dict[code]['e_conc']=e_conc | |
code_dict[code]['bpti_conc']=bpti_conc | |
code_dict[code]['kcat']= kcat | |
code_dict[code]['km']=km | |
return code_dict | |
##----------------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 (μ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! | |
conc_dict = {'trypsin':0.0,'bpti':0,'tris':0.0, 'cacl':0.0,'substr':0.0,'prod':0.0} | |
tube_dict ={} | |
for n in range(1,7): | |
tube_dict[n] = Tube() | |
tube_dict[n].conc = conc_dict.copy() | |
cuv_dict = {} | |
for n in range(1,7): | |
cuv_dict[n] = Cuvette() | |
cuv_dict[n].conc = conc_dict.copy() | |
solns_dict2 = {} | |
solns_dict2['trypsin']=0.0 | |
solns_dict2['bpti']=0.0 | |
solns_dict2['cacl']=0.0 | |
solns_dict={} # used to store stock solution concentrations | |
# trypsin and BPTI concentrations are set when code is read or changed | |
solns_dict['trypsin'] =0.0 | |
solns_dict['bpti'] = 0.0 | |
solns_dict['cacl'] = 20.0*1e-3 # M | |
solns_dict['substr'] = 2.0*1e-3 # M | |
solns_dict['tris'] = 0.2 # M | |
##--------------Tube for BPTI dilution ----------# | |
bpti_dil = Tube() | |
bpti_dil.conc = {'bpti':0.0} | |
#########---------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>' | |
else: | |
solns_dict2['trypsin']=code_dict[lab_code.value]['e_conc']/10 | |
solns_dict['bpti']=code_dict[lab_code.value]['bpti_conc'] | |
code_warn.value ='' | |
deliver_butt1.button_style = 'success' | |
deliver_butt1.description='Pipette!' | |
deliver_butt2.button_style = 'success' | |
deliver_butt2.description='Pipette!' | |
read_uvabs_butt.button_style = 'success' | |
read_uvabs_butt.description='Read Absorbance' | |
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]) | |
## ------- UV Absorbance Measurement of BPTI stock ---------## | |
def on_wl1_ch(value): | |
'''Respond to change in the wavelength widget''' | |
read_uvabs(0) | |
def zero1(change): | |
'''Respond to the Zero button''' | |
global zero_set1 | |
zero_set1 = abs_read1 | |
abs_update1(abs_read1) | |
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_update1(absorb): | |
'''function to set global abs_read1 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_read1 | |
displ_absb = absorb - zero_set1 | |
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_show1(abs_d) | |
abs_read1 = absorb | |
def read_uvabs(change): | |
'''function to responds to Read Abs button ''' | |
# check to see if there is a valid lab code | |
if lab_code.value not in codes: | |
read_uvabs_butt.description='Enter valid lab code' | |
read_uvabs_butt.button_style = 'warning' | |
return | |
bpti_conc = code_dict[lab_code.value]['bpti_conc'] | |
ext_coef = {'260 nm':5400.0/1.7,'280 nm':5400.0, '405 nm':0.0,'595 nm':0.0} | |
h2O_abs = {'260 nm':0.14,'280 nm':0.3, '405 nm':0.6,'595 nm':0.8} | |
if uv_samp.value == 'H2O': | |
absorb = h2O_abs[wl1.value] | |
else: | |
absorb = bpti_conc*ext_coef[wl1.value] + h2O_abs[wl1.value] | |
abs_update1(absorb) | |
def abs_show1(absorb): | |
'''function to displays variable in the spec_dislp HTML widget''' | |
if absorb < -0.03: | |
spec_displ1.value='<h2> Abs: <span style="color:red;"> Err </span></h2>' | |
else: | |
spec_displ1.value='<h2> Abs: <span style="color:red;"> \ | |
{:.3f}'.format(absorb) + '</span></h2>' | |
uv_samp = widgets.RadioButtons( | |
# radio buttons to select sample for UV measurement | |
options = ['H2O','BPTI'], | |
description='Sample:', | |
#layout=widgets.Layout(width='200px',margin='25px 100px 0px 0px') | |
) | |
wl1 = widgets.Dropdown( | |
# Dropdown to select wavelength for spectrophotometer | |
options = [('260 nm'),('280 nm'),('405 nm'),('595 nm')], | |
description = 'Wavelength:', | |
style = style, | |
layout=widgets.Layout(width='200px',margin='0px 0px 20px 0px') | |
) | |
wl1.observe(on_wl1_ch,names=['value']) | |
read_uvabs_butt = widgets.Button( | |
# Button to read absorbance | |
description = 'Read Absorbance', | |
button_style = 'success', | |
#layout=widgets.Layout(width='200px',margin='25px 100px 15px 50px') | |
) | |
read_uvabs_butt.on_click(read_uvabs) | |
spec_displ1 = widgets.HTML( | |
# spectrophotometer display | |
value='0.0', | |
layout=widgets.Layout(margin='-15px 50px 0px 50px') | |
) | |
zero_butt1 = widgets.Button( | |
# button to zero absorbance display | |
description = 'Zero', | |
button_style = 'success' | |
) | |
zero_butt1.on_click(zero1) | |
abs_show1(0) | |
row_uvabs1 = widgets.HBox([uv_samp,wl1]) | |
row_uvabs2 = widgets.HBox([read_uvabs_butt,spec_displ1,zero_butt1]) | |
box_uvabs=widgets.VBox([row_uvabs1,row_uvabs2]) | |
##---------------BPTI Dilution---------------------## | |
def bpti_vol_table_update(vol): | |
'''function to update dilute bpti volume HTML widget''' | |
html_str = ''' | |
<style> | |
table, th, td { | |
border: 1px solid black; | |
} | |
th, td { | |
padding: 5px; | |
} | |
table, {border-collapse: collapse;} | |
</style> | |
<table> | |
<tr> | |
<th style="width:150px"> Dilute BPTI Volume </th> | |
''' | |
html_str += f'<td style="width:100px">{vol:.0f} μL</td></tr>' | |
bpti_vol_table.value=html_str | |
def deliver1(change): | |
'''function for deliver button for bsa dilution''' | |
# check for valid lab code | |
if lab_code.value not in codes: | |
deliver_butt1.description='Enter valid lab code' | |
deliver_butt1.button_style = 'warning' | |
return | |
bpti_conc = code_dict[lab_code.value]['bpti_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 = bpti_dil.vol | |
vol_new = vol_old + vol | |
# calculate increment to amount of BPTI in tube | |
bpti_incr = 0 | |
if solns1.value == 'BPTI': | |
bpti_incr = bpti_conc*vol | |
# update concentration | |
conc_old = bpti_dil.conc['bpti'] | |
bpti_dil.conc['bpti'] = (conc_old*vol_old + bpti_incr)/vol_new | |
# update volume and nominal volume of dilute bpti solution | |
bpti_dil.vol = vol_new | |
bpti_dil.vol_n += pip_vol.value | |
bpti_vol_table_update(bpti_dil.vol_n) | |
# uptate concentration in solns_dict2 | |
solns_dict2['bpti'] = bpti_dil.conc['bpti'] | |
def empty1(change): | |
bpti_dil.vol = 0.0 | |
bpti_dil.vol_n =0.0 | |
bpti_dil.conc['bpti']=0.0 | |
bpti_vol_table_update(0.0) | |
solns1 = widgets.RadioButtons( | |
# solutions for making dilute bsa | |
options=['H20','BPTI'], | |
description='Solutions' | |
) | |
empty_butt1 = widgets.Button( | |
# button to empty tube for bsa dilution | |
description = 'Empty', | |
button_style = 'danger', | |
) | |
empty_butt1.on_click(empty1) | |
bpti_vol_table = widgets.HTML( | |
# display volume of the dilute bpti solution | |
value = '' | |
) | |
deliver_butt1 = widgets.Button( | |
# Button to deliver volume for BSA dilution | |
description = 'Pipette!', | |
button_style = 'success', | |
) | |
deliver_butt1.on_click(deliver1) | |
row_bpti_dil = widgets.HBox([solns1,empty_butt1,bpti_vol_table]) | |
row_pip1 = widgets.HBox([deliver_butt1,pipette,pip_vol]) | |
box_bpti_dil=widgets.VBox([row_bpti_dil,row_pip1]) | |
###-------------Trypsin-BPTI Incubation------------## | |
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(solns2_widget, solns_dict2, tubes_widget, tube_dict) | |
tube_vol_table.update() | |
def empty2(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() | |
solns2_widget = widgets.RadioButtons( | |
# solutions for BPTI-trypsin incubation | |
options=[('Trypsin','trypsin'),('Dilute BPTI','bpti'),('H2O','H2O'),('20 mM CaCl2','cacl')], | |
description='Solutions' | |
) | |
empty_butt2 = widgets.Button( | |
# button to empty tube for bsa dilution | |
description = 'Empty', | |
button_style = 'danger', | |
) | |
empty_butt2.on_click(empty2) | |
tubes_widget=widgets.RadioButtons( | |
# Tubes for BPTIf-trypsin incubation | |
options=[1,2,3,4,5,6], | |
description = 'Tubes:' | |
) | |
tube_vol_table = VolTable(tube_dict,'Tube') | |
bpti_vol_table_update(0) | |
deliver_butt2 = widgets.Button( | |
# Button to deliver volume for BSA dilution | |
description = 'Pipette!', | |
button_style = 'success', | |
) | |
deliver_butt2.on_click(deliver2) | |
tubeVb=widgets.VBox([tubes_widget,empty_butt2], | |
layout=widgets.Layout(width='40%',margin='0px 0px 0px 00px')) | |
row_bpti_trypsin = widgets.HBox([solns2_widget,tubeVb,tube_vol_table]) | |
row_pip2 = widgets.HBox([deliver_butt2,pipette,pip_vol]) | |
box_trypsin_bpti = widgets.VBox([row_bpti_trypsin, row_pip2]) | |
##--------------- Cuvette Setup ------------------## | |
def deliver3(change): | |
if lab_code.value not in codes: | |
deliver_butt.description='Enter valid lab code' | |
deliver_butt.button_style = 'warning' | |
return | |
pip_deliver(solns3, solns_dict, 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_vol_table.update() | |
solns3 = widgets.RadioButtons( | |
# solutions for cuvettes for part A | |
options =[('H20','H2O'), ('0.2 M Tris-Cl, pH 8','tris'), ('20 mM CaCl2','cacl'), | |
('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,5,6], | |
description = 'Cuvettes:' | |
) | |
empty_butt3 = widgets.Button( | |
# button to empty cuvettes for part A | |
description = 'Empty', | |
button_style = 'danger', | |
) | |
empty_butt3.on_click(empty_cuv) | |
cuv_vol_table = VolTable(cuv_dict,'Cuvette') | |
deliver_butt3 = widgets.Button( | |
# Button to deliver volume for BSA dilution | |
description = 'Pipette!', | |
button_style = 'success', | |
) | |
deliver_butt3.on_click(deliver3) | |
cuvVb=widgets.VBox([cuv_widget,empty_butt3], | |
layout=widgets.Layout(width='40%',margin='0px 0px 0px 00px')) | |
row_cuv= widgets.HBox([solns3,cuvVb,cuv_vol_table]) | |
row_pip3 = widgets.HBox([deliver_butt3,pipette,pip_vol], | |
layout=widgets.Layout(margin='15px 0px 0px 0px')) | |
box_cuv1 = widgets.VBox([row_cuv,row_pip3]) | |
## -------------- Final Cuvette additions _________## | |
# The tubes from the BPTI-trypsin incubation serve as the solutions for the final addition. | |
def deliver4(change): | |
if lab_code.value not in codes: | |
deliver_butt.description='Enter valid lab code' | |
deliver_butt.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 | |
reag_list = ['trypsin','bpti','cacl'] | |
# update concentrations | |
for reag in reag_list: | |
incr = vol*tube_dict[tube].conc[reag] | |
conc_old = cuv_dict[cuv].conc[reag] | |
conc_new = (conc_old*vol_old + incr)/vol_new | |
cuv_dict[tube].conc[reag] = conc_new | |
#update volumes | |
cuv_dict[cuv].vol = vol_new | |
cuv_dict[cuv].vol_n += pip_vol.value | |
c_trypsin = cuv_dict[cuv].conc['trypsin'] | |
c_bpti = cuv_dict[cuv].conc['bpti'] | |
c_substr = cuv_dict[cuv].conc['substr'] | |
if c_trypsin >0 and c_substr >0: | |
cuv_dict[cuv].t0 = time() | |
if c_trypsin >= c_bpti: | |
cuv_dict[cuv].conc['trypsin'] -= cuv_dict[cuv].conc['bpti'] | |
cuv_dict[cuv].conc['bpti'] = 0.0 | |
else: | |
cuv_dict[cuv].conc['bpti'] -= cuv_dict[cuv].conc['trypsin'] | |
cuv_dict[cuv].conc['trypsin'] = 0.0 | |
cuv_vol_table.update() | |
deliver_butt4 = widgets.Button( | |
# Button to deliver volume for BSA dilution | |
description = 'Pipette!', | |
button_style = 'success', | |
) | |
deliver_butt4.on_click(deliver4) | |
row_cuv2 = widgets.HBox([tubes_widget,cuv_widget]) | |
row_pip4 = widgets.HBox([deliver_butt4,pipette,pip_vol], | |
layout=widgets.Layout(margin='15px 0px 0px 0px')) | |
box_final_add = widgets.VBox([row_cuv2,row_pip4]) | |
##----------------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(1.5*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.08: | |
# activity is reduced if tris concentration isn't adequate | |
kcat *= 0.5 | |
if cuv_dict[cuv].conc['cacl'] < 0.0008: | |
# 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 ccat 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 wl2.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 | |
kin_sols = kin_sim(cuv_dict,t_tot) | |
sleep(1) | |
cuv_int =int(60*t_int/n_cuv) | |
delay_t = [0] | |
for cuv in cuv_dict: | |
if cuv_dict[cuv].t0 > 0: | |
delay_t.append(int(time()-cuv_dict[cuv].t0)) | |
else: | |
delay_t.append(0) | |
t=0 | |
tcuv=0 | |
meas = 1 | |
cuv = 1 | |
cuv_show(cuv) | |
abs_start = abs_read2-zero_set2 | |
pts_total = int((t_tot+t_int)*60+cuv_int) | |
for i in range(pts_total): | |
sleep(t_sleep) | |
absorb = kin_sols[cuv-1].y[1][t]*ext_coef + abs_start | |
abs_show2(absorb) | |
if tcuv>=cuv_int: | |
read_t = t + delay_t[cuv] | |
err = rand.normalvariate(0,abs_sigma) | |
absorb = abs_start + (kin_sols[cuv-1].y[1][read_t]*ext_coef)+err | |
abs_data[meas][cuv] = absorb | |
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) | |
ax.set_ylabel('Absorbance at 405 nm',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() | |
reg_table = RegTable(reg_results) | |
with fig_output: | |
display(fig) | |
# Important note 2: In order for the regression table (an HTML widget | |
# created within this function to appear in viola, it has to be put | |
# in an output widget declared globally. | |
with reg_table_output: | |
display(reg_table) | |
def on_wl2_ch(value): | |
'''Respond to change in the wavelength widget''' | |
h2O_abs = {'260 nm':0.14,'280 nm':0.3, '405 nm':0.6,'595 nm':0.8} | |
absorb=h2O_abs[wl2.value] | |
abs_update2(absorb) | |
def zero2(change): | |
'''Respond to the Zero button''' | |
global zero_set2 | |
zero_set2 = abs_read2 | |
abs_update2(abs_read2) | |
def abs_update2(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_read2 | |
displ_absb = absorb - zero_set2 | |
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_show2(abs_d) | |
abs_read2 = absorb | |
def abs_show2(absorb): | |
'''function to displays variable in the spec_dislp HTML widget''' | |
if absorb < -0.03: | |
spec_displ2.value='<h2> Abs: <span style="color:red;"> Err </span></h2>' | |
else: | |
spec_displ2.value='<h2> Abs: <span style="color:red;"> \ | |
{:.3f}'.format(absorb) + '</span></h2>' | |
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_reset(change): | |
abs_table.refresh() | |
reg_table.close() | |
fig_output.clear_output() | |
#cuv_reset(cuv_dict) | |
cuv_vol_table.update() | |
run_butt.disabled = False | |
reset_butt.disabled = True | |
wl2 = widgets.Dropdown( | |
# Dropdown to select wavelength for spectrophotometer | |
options = [('260 nm'),('280 nm'),('405 nm'),('595 nm')], | |
description = 'Wavelength:', | |
style = style, | |
layout=widgets.Layout(width='200px',margin='0px 0px 20px 0px') | |
) | |
wl2.observe(on_wl2_ch,names=['value']) | |
zero_butt2 = widgets.Button( | |
# button to zero absorbance display | |
description = 'Zero', | |
button_style = 'success', | |
layout=widgets.Layout(margin='0px 0px 0px 20px') | |
) | |
zero_butt2.on_click(zero2) | |
abs_table = AbsTable(cuv_dict, 1.5,10.5) | |
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_displ2 = 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', | |
button_style = 'danger', | |
disabled = True, | |
layout=widgets.Layout(margin='0px 0px 0px 20px') | |
) | |
reset_butt.on_click(on_reset) | |
abs_show2(0) | |
cuv_show(1) | |
row_spec1 = widgets.HBox([wl2,zero_butt2]) | |
row_spec2 = widgets.HBox([run_butt, cuv_displ, spec_displ2, reset_butt]) | |
fig_output = widgets.Output(layout={'border': '1px solid black','width':'500px'}) | |
reg_table_output=widgets.Output() | |
##----------------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 | |
# sets up state before final addition of bpti-trypsin incubation mixture | |
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['cacl']=20e-3*40/760 | |
cuv_dict[cuv].conc['tris']=0.2*400.0/760 | |
cuv_dict[cuv].conc['substr']= (160.0/760)*s_stock | |
cuv_dict[cuv].t0 = 10*cuv | |
cuv_vol_table.update() | |
def test_cuv2(): | |
# A function for quickly setting up cuvettes for testing | |
# sets up state after final addition of bpti-trypsin incubation mixture | |
test_tube() | |
test_cuv() | |
s_stock = 0.002 | |
for cuv in cuv_dict: | |
pipette.value = 200.0 | |
pip_vol.value = 40.0 | |
cuv_widget.value = cuv | |
tubes_widget.value = cuv | |
deliver4(0) | |
def test_tube(): | |
tube_reset(tube_dict) | |
# A function for quickly setting up the bpti-trypsin incubation tubes for testing. | |
trypsin_conc= code_dict[lab_code.value]['e_conc']/10.0 | |
bpti_conc = code_dict[lab_code.value]['bpti_conc']/10.0 | |
cacl_conc = 0.02 # from trypsin solution | |
for tube in tube_dict: | |
tube_dict[tube].vol = 1000.0 | |
tube_dict[tube].vol_n = 1000.0 | |
tube_dict[tube].conc['trypsin'] = trypsin_conc/20.0 | |
tube_dict[tube].conc['cacl'] = cacl_conc/20.0 | |
tube_dict[1].conc['bpti'] = 0.0*bpti_conc/1000.0 | |
tube_dict[2].conc['bpti'] = 10.0*bpti_conc/1000.0 | |
tube_dict[3].conc['bpti'] = 20.0*bpti_conc/1000.0 | |
tube_dict[4].conc['bpti'] = 30.0*bpti_conc/1000.0 | |
tube_dict[5].conc['bpti'] = 40.0*bpti_conc/1000.0 | |
tube_dict[6].conc['bpti'] = 50.0*bpti_conc/1000.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 3, Part B: Titration of Trypsin with Bovine Pancreatic Trypsin Inhibitor (BPTI)</h3> | |
<p style="font-size:16px"> | |
This web page simulates the procedures to be carried out in Part B of Experiment 3. The goal of this part of the experiment is to determine the concentration of active trypsin in the solutions used for the other parts of this experiment, as well as in subsequent experiments in the course. This is done by mixing a fixed amount of trypsin with increasing concentrations of BPTI, a small protein inhibitor of trypsin and other serine proteases. BPTI is an exceptionally stable protein and is available in highly purified form. These properties enable us to determine accurately the concentration of a BPTI solution by measuring its absorbance at 280 nm. In addition, the binding of BPTI to trypsin is extremely tight (though forming the complex is relatively slow). By determining the amount of this solution that inhibits all of the trypsin in a solution, the concentration of the trypsin can be determined. | |
<br><br> | |
This experiment requires multiple steps, as reflected in the headings below. In the first part, you will determine the concentration of the BPTI stock solution by UV absorbance. Then you will set up 6 tubes containing a fixed concentration of trypsin and different concentrations of BPTI. In the lab, these mixtures would be incubated for 20 min to ensure complete formation of the BPTI-trypsin complexes, but it is not required to wait before going on to the next steps in the simulation. After the initial incubation, the samples are diluted 10-fold before being added to the cuvettes. The other reagents required to measure the remaining trypsin activity (including substrate and buffer) are added to six cuvettes. The reactions are started by adding a sample from each of the incubation tubes to the corresponding cuvette. | |
<br><br> | |
As in part A of the experiment, you will then simulate a kinetic run as would be carried out in the lab. The simulation 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. | |
<br><br> | |
The graph displayed can be readily copied for use in another program or saved to your computer by right-clicking on the image and choosing the appropriate image. The data in tables cannot be directly saved to a file, but they can be selected using the mouse and copied for use in another program. The rows and columns can be directly copied into the data table of SciDAVis or a spreadsheet. | |
<br><br> | |
As in the earlier experiment simulations, a set of radio buttons is used to select solutions to pipette from and the tubes or cuvettes to be pipetted into. Tables are used to show the nominal volumes in the tubes as reagents are added. | |
<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. BPTI absorbance measurement</h2>' | |
) | |
b2header = widgets.HTML( | |
# header for part B, part 2 | |
value = '<h2> 2. BPTI dilution </h2>' | |
) | |
b3header = widgets.HTML( | |
# header for part B, part 3 | |
value = '<h2> 3. BPTI-trypsin incubation </h2>' | |
) | |
b4header = widgets.HTML( | |
# header for part B, part 4 | |
value = '<h2> 4. Cuvette set up </h2>' | |
) | |
b5header = widgets.HTML( | |
# header for part B, part 5 | |
value = '<h2> 5. Final additions to cuvettes </h2>' | |
) | |
b6header = widgets.HTML( | |
# header for part B, part 5 | |
value = '<h2> 6. Kinetic run </h2>' | |
) | |
##---------------- Display Everything -------------------# | |
#lab_code.value='0GXY02' | |
display(header) | |
display(hrule) | |
display(row_code) | |
display(hrule) | |
display(b1header) | |
display(box_uvabs) | |
display(hrule) | |
display(b2header) | |
display(box_bpti_dil) | |
display(hrule) | |
display(b3header) | |
display(box_trypsin_bpti) | |
display(hrule) | |
display(b4header) | |
display(box_cuv1) | |
display(hrule) | |
display(b5header) | |
display(box_final_add) | |
display(hrule) | |
display(b6header) | |
display(row_spec1) | |
display(hrule) | |
display(row_spec2) | |
display(abs_table) | |
display(fig_output) | |
display(reg_table_output) | |
display(footer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
codes =['0GXY02', | |
'DD0371', | |
'X5FX87', | |
'FG188G', | |
'34P10Q', | |
'Y4N6KZ', | |
'W5XM03', | |
'9V51PV', | |
'942913', | |
'N898UN', | |
'H4CGP6', | |
'13KE9N', | |
'31PQ53', | |
'KK644G', | |
'2TNA45', | |
'N6AADQ', | |
'SV22HX', | |
'VS8S0J', | |
'4U2RCD', | |
'ZCRTWU', | |
'7182Y1', | |
'W8Y4P3', | |
'J9PWB4', | |
'43479S', | |
'MYX1AX', | |
'S0E0YV', | |
'DFKPU9', | |
'9RFXYW', | |
'88PTV8', | |
'H0X54M', | |
'KD1K2N', | |
'23W0N6', | |
'GQ5P11', | |
'597J70', | |
'77YE98', | |
'994A4U', | |
'22NZ8S', | |
'33VZHV', | |
'YD34E7', | |
'B4EV54', | |
'QXQEA0', | |
'RCE9Z2', | |
'W382SW', | |
'Y1UUUA', | |
'240125', | |
'0P20E8', | |
'CTZKSB', | |
'K60820', | |
'WE21H5', | |
'N180MF'] | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment