Skip to content

Instantly share code, notes, and snippets.

@dpgoldenberg
Last active February 20, 2021 21:01
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/be5a5819667834d8d98cf19f2e7bb45a to your computer and use it in GitHub Desktop.
Save dpgoldenberg/be5a5819667834d8d98cf19f2e7bb45a to your computer and use it in GitHub Desktop.
Simulation of Experiment 2, for Biol 3515/Chem 3515
code_dict = {'0GXY02': {'bsa_init': 0.6302333104590135,
'coli_pr': 0.02045782192688574,
'coli_na': 0.028069149086216168,
'curve_a': 7.628994080420339,
'curve_b': 79.97496754863742,
'brad_bkg': 0.21581014164096682},
'DD0371': {'bsa_init': 1.4101514851390147,
'coli_pr': 0.03767113005479135,
'coli_na': 0.021727273260539227,
'curve_a': 5.23824112385952,
'curve_b': 49.18698368309747,
'brad_bkg': 0.12212849875848655},
'X5FX87': {'bsa_init': 0.559451632519114,
'coli_pr': 0.020957560308467255,
'coli_na': 0.033079965658528755,
'curve_a': 5.159240302043729,
'curve_b': 53.65818471296826,
'brad_bkg': 0.1669654048420614},
'FG188G': {'bsa_init': 0.6211684083261407,
'coli_pr': 0.03231224514606566,
'coli_na': 0.026218962171618555,
'curve_a': 4.009863518780299,
'curve_b': 35.88984445266249,
'brad_bkg': 0.13737469662134283},
'34P10Q': {'bsa_init': 1.376685391815398,
'coli_pr': 0.02528454078577475,
'coli_na': 0.026161032352047427,
'curve_a': 7.13139579450825,
'curve_b': 70.80233394254888,
'brad_bkg': 0.2968686705047867},
'Y4N6KZ': {'bsa_init': 1.2751079559604972,
'coli_pr': 0.03820446885747479,
'coli_na': 0.024273280915330177,
'curve_a': 2.8301783474888142,
'curve_b': 21.632619148181345,
'brad_bkg': 0.2027842300758498},
'W5XM03': {'bsa_init': 1.1098918536440845,
'coli_pr': 0.02945901590496184,
'coli_na': 0.03527986928720504,
'curve_a': 8.758868767465232,
'curve_b': 96.11014225234263,
'brad_bkg': 0.16024179290090854},
'9V51PV': {'bsa_init': 1.476152886320615,
'coli_pr': 0.021399381745099116,
'coli_na': 0.02969956384856809,
'curve_a': 3.2098048344317665,
'curve_b': 22.17740636850572,
'brad_bkg': 0.17408720658127075},
'942913': {'bsa_init': 1.1354799906443611,
'coli_pr': 0.038162190388555825,
'coli_na': 0.028272147919856546,
'curve_a': 4.284229436479604,
'curve_b': 41.84982405373382,
'brad_bkg': 0.18584116162074565},
'N898UN': {'bsa_init': 0.7268642396965732,
'coli_pr': 0.02340531599438036,
'coli_na': 0.03737296299646256,
'curve_a': 2.8702311632457067,
'curve_b': 24.509429893330523,
'brad_bkg': 0.10255978643675266},
'H4CGP6': {'bsa_init': 0.899176843584752,
'coli_pr': 0.038362154215435075,
'coli_na': 0.03077414844871194,
'curve_a': 4.007799049683165,
'curve_b': 28.920431744257,
'brad_bkg': 0.2591649173049998},
'13KE9N': {'bsa_init': 1.4006400447689598,
'coli_pr': 0.02128436030706538,
'coli_na': 0.023598989771235163,
'curve_a': 1.9842431271785594,
'curve_b': 9.846622888606351,
'brad_bkg': 0.21255397035988005},
'31PQ53': {'bsa_init': 1.3030738346518123,
'coli_pr': 0.028280419363943814,
'coli_na': 0.038391045658602754,
'curve_a': 3.575812623335131,
'curve_b': 27.90323833988697,
'brad_bkg': 0.2532292114888188},
'KK644G': {'bsa_init': 1.44262262813991,
'coli_pr': 0.024414664331468473,
'coli_na': 0.03970182089468849,
'curve_a': 8.295133070123354,
'curve_b': 90.51583976879485,
'brad_bkg': 0.18424263040479463},
'2TNA45': {'bsa_init': 0.6573819881083176,
'coli_pr': 0.0295529286164187,
'coli_na': 0.032997819386657995,
'curve_a': 3.243219996073975,
'curve_b': 20.58218884087249,
'brad_bkg': 0.14928077253905697},
'N6AADQ': {'bsa_init': 0.9165464914272847,
'coli_pr': 0.0208135230951118,
'coli_na': 0.0270873260762834,
'curve_a': 5.126060104627027,
'curve_b': 49.212607378598726,
'brad_bkg': 0.14632573829835882},
'SV22HX': {'bsa_init': 1.2102861771752291,
'coli_pr': 0.02149718745729806,
'coli_na': 0.033603419002110536,
'curve_a': 2.169141768180557,
'curve_b': 9.187564457478402,
'brad_bkg': 0.13652892317839213},
'VS8S0J': {'bsa_init': 0.8210403031893194,
'coli_pr': 0.03214794331807181,
'coli_na': 0.03755449581376081,
'curve_a': 2.7969844949982896,
'curve_b': 16.4075363572732,
'brad_bkg': 0.18558565154117743},
'4U2RCD': {'bsa_init': 0.7469661758621895,
'coli_pr': 0.03210384852556212,
'coli_na': 0.03297312294071977,
'curve_a': 2.156737850263122,
'curve_b': 14.403610349405195,
'brad_bkg': 0.2869805591773925},
'ZCRTWU': {'bsa_init': 1.3020990551424825,
'coli_pr': 0.036710243358538966,
'coli_na': 0.029314088966354887,
'curve_a': 7.289548559659246,
'curve_b': 79.7497851901377,
'brad_bkg': 0.20324338496663644},
'7182Y1': {'bsa_init': 1.1147758578790397,
'coli_pr': 0.02686741656253151,
'coli_na': 0.031419781501426165,
'curve_a': 3.2516262455678944,
'curve_b': 25.12834609400917,
'brad_bkg': 0.19758276403588176},
'W8Y4P3': {'bsa_init': 1.2173774020841588,
'coli_pr': 0.02387166620444361,
'coli_na': 0.029855130181537716,
'curve_a': 8.528339986272549,
'curve_b': 94.60510182724437,
'brad_bkg': 0.29618691038962786},
'J9PWB4': {'bsa_init': 0.764189959208705,
'coli_pr': 0.020779208498265186,
'coli_na': 0.026119937104039558,
'curve_a': 7.10698263726603,
'curve_b': 71.09173203849825,
'brad_bkg': 0.16283605321341776},
'43479S': {'bsa_init': 0.6405217918195514,
'coli_pr': 0.020302646047041423,
'coli_na': 0.03664699312309894,
'curve_a': 6.593018254224056,
'curve_b': 74.08008540507063,
'brad_bkg': 0.1480061012211324},
'MYX1AX': {'bsa_init': 1.324833083691523,
'coli_pr': 0.037507549113220434,
'coli_na': 0.02750541064719787,
'curve_a': 6.272254329896093,
'curve_b': 58.12404333640464,
'brad_bkg': 0.26349046432563117},
'S0E0YV': {'bsa_init': 0.5519978390278825,
'coli_pr': 0.020219007481144108,
'coli_na': 0.022951831385046556,
'curve_a': 6.727483299840219,
'curve_b': 64.3491054091928,
'brad_bkg': 0.2109578898211646},
'DFKPU9': {'bsa_init': 0.5780804111841383,
'coli_pr': 0.035962532226912314,
'coli_na': 0.03865254889537133,
'curve_a': 4.083122690178636,
'curve_b': 35.137770058310714,
'brad_bkg': 0.1099716479937468},
'9RFXYW': {'bsa_init': 0.5840088935776985,
'coli_pr': 0.025060748749074303,
'coli_na': 0.028553407441499038,
'curve_a': 1.8180500300948523,
'curve_b': 8.173002694225502,
'brad_bkg': 0.23280671380526333},
'88PTV8': {'bsa_init': 0.6231275554173443,
'coli_pr': 0.02883746390785842,
'coli_na': 0.027125170963581857,
'curve_a': 7.570713178623864,
'curve_b': 85.2025846227128,
'brad_bkg': 0.24376978590583756},
'H0X54M': {'bsa_init': 1.1321608009884556,
'coli_pr': 0.0385521238979127,
'coli_na': 0.03492765707915852,
'curve_a': 4.80734250970189,
'curve_b': 47.48176109145393,
'brad_bkg': 0.17255058087818656},
'KD1K2N': {'bsa_init': 0.93302708835257,
'coli_pr': 0.03810359867424335,
'coli_na': 0.039373415170982154,
'curve_a': 6.971818997674599,
'curve_b': 74.67099883372816,
'brad_bkg': 0.1309919905971541},
'23W0N6': {'bsa_init': 0.6482481699668515,
'coli_pr': 0.03597725617249658,
'coli_na': 0.027584702873477467,
'curve_a': 4.967113767289612,
'curve_b': 44.45956548525093,
'brad_bkg': 0.2810893702596993},
'GQ5P11': {'bsa_init': 1.1277885478456056,
'coli_pr': 0.03941397156292144,
'coli_na': 0.03461178123080865,
'curve_a': 8.161992763569723,
'curve_b': 91.65048116557341,
'brad_bkg': 0.2107638583476281},
'597J70': {'bsa_init': 1.1365077115146103,
'coli_pr': 0.027385812947625533,
'coli_na': 0.02622429133424256,
'curve_a': 7.3277594095638445,
'curve_b': 81.98070594169553,
'brad_bkg': 0.18827152305933278},
'77YE98': {'bsa_init': 0.5963367750165631,
'coli_pr': 0.032655092026546456,
'coli_na': 0.024988468904814275,
'curve_a': 8.502338778781453,
'curve_b': 87.69796000054274,
'brad_bkg': 0.17526926659291908},
'994A4U': {'bsa_init': 0.570985042171707,
'coli_pr': 0.025353537885538697,
'coli_na': 0.021490311974125587,
'curve_a': 8.52267011879738,
'curve_b': 99.50445959145006,
'brad_bkg': 0.24570163717107646},
'22NZ8S': {'bsa_init': 0.9509898167137367,
'coli_pr': 0.03143947404778345,
'coli_na': 0.024006452599770123,
'curve_a': 2.3281500642172497,
'curve_b': 5.7608664652106185,
'brad_bkg': 0.20818558044013602},
'33VZHV': {'bsa_init': 1.4058631822395942,
'coli_pr': 0.0373458404174298,
'coli_na': 0.024709811656972162,
'curve_a': 5.982193055726704,
'curve_b': 54.507989580099796,
'brad_bkg': 0.12465571443314515},
'YD34E7': {'bsa_init': 1.4251831768823449,
'coli_pr': 0.03979283010807402,
'coli_na': 0.023466399008471604,
'curve_a': 5.662020644704536,
'curve_b': 51.946138776999106,
'brad_bkg': 0.1000674305851464},
'B4EV54': {'bsa_init': 1.0613831943977985,
'coli_pr': 0.03412782658362859,
'coli_na': 0.0365328039154178,
'curve_a': 5.480578184396049,
'curve_b': 59.22235384904483,
'brad_bkg': 0.24923821797427856},
'QXQEA0': {'bsa_init': 1.452191010481251,
'coli_pr': 0.03749655741528499,
'coli_na': 0.0206458168695719,
'curve_a': 7.61201780339441,
'curve_b': 85.99366245627897,
'brad_bkg': 0.1663318114344157},
'RCE9Z2': {'bsa_init': 1.4604226493305035,
'coli_pr': 0.03165903021438017,
'coli_na': 0.025043850037061718,
'curve_a': 2.346241287267522,
'curve_b': 17.1769935120656,
'brad_bkg': 0.2833063738696384},
'W382SW': {'bsa_init': 1.038445633316786,
'coli_pr': 0.038586439441352136,
'coli_na': 0.02681400144547896,
'curve_a': 3.73871352496779,
'curve_b': 32.58280973396393,
'brad_bkg': 0.24368297263640382},
'Y1UUUA': {'bsa_init': 0.8729008931178693,
'coli_pr': 0.03157452594746815,
'coli_na': 0.021987245586348642,
'curve_a': 4.37913797898254,
'curve_b': 33.19143710008858,
'brad_bkg': 0.14328566320524383},
'240125': {'bsa_init': 1.1580376473676264,
'coli_pr': 0.03154744238990789,
'coli_na': 0.025978305481204698,
'curve_a': 2.1520860602697325,
'curve_b': 10.922141767168352,
'brad_bkg': 0.2471519026095803},
'0P20E8': {'bsa_init': 1.0222939756638887,
'coli_pr': 0.03882095525311787,
'coli_na': 0.02490080412321647,
'curve_a': 4.116207451793762,
'curve_b': 37.88070290591054,
'brad_bkg': 0.2276461792673584},
'CTZKSB': {'bsa_init': 0.9043556567257972,
'coli_pr': 0.02071372149014222,
'coli_na': 0.03533266822319614,
'curve_a': 6.551683617811493,
'curve_b': 73.40920582461186,
'brad_bkg': 0.20424716060973047},
'K60820': {'bsa_init': 1.0268399981969911,
'coli_pr': 0.0322084380814433,
'coli_na': 0.033458076385320765,
'curve_a': 5.74675831527346,
'curve_b': 50.39276748870875,
'brad_bkg': 0.2569968969963384},
'WE21H5': {'bsa_init': 1.1047891362709161,
'coli_pr': 0.030276340460969622,
'coli_na': 0.020162556978298336,
'curve_a': 7.028432486851976,
'curve_b': 73.01961704325916,
'brad_bkg': 0.2299952113925479},
'N180MF': {'bsa_init': 1.1881707717833925,
'coli_pr': 0.0378287611835832,
'coli_na': 0.02999539373677519,
'curve_a': 5.623675669865823,
'curve_b': 54.45278003042385,
'brad_bkg': 0.14742752267277526}}
name: exp_2_sim
channels:
- conda-forge
- defaults
- conda-forge/label/broken
dependencies:
- python=3.7.3
- numpy=1.16.4
- ipython=7.6.1
- ipywidgets=7.5.0
- 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 2
## 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 numpy as np
import random as rand
import ipywidgets as widgets
from IPython.display import display, HTML
display(HTML("<style>div.output_scroll { height: 100ex; }</style>"))
from time import sleep
import threading
from multiprocessing import Process
from labcodes import codes
from codeDictionary import code_dict
def make_code_dict():
'''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.'''
for code in codes:
bsa_init = 0.5 + rand.random()
coli_pr = 0.02 + 0.02*rand.random()
coli_na = 0.02 + 0.02*rand.random()
brad_bkg = 0.1 + 0.2*rand.random()
b = 5 + 95*rand.random()
a = 0.075*b + 1 + rand.random()
code_dict[code]={}
code_dict[code]['bsa_init']=bsa_init
code_dict[code]['coli_pr'] = coli_pr
code_dict[code]['coli_na']=coli_na
code_dict[code]['curve_a']=a
code_dict[code]['curve_b']=b
code_dict[code]['brad_bkg']=brad_bkg
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
##-------------Create the tube dictionary-------------------#
tube_names = ['std 1','std 2','std 3','std 4','std 5','std 6','std 7','std 8','std 9',
'E.coli 1', 'E.coli 2','E.coli 3']
tube_dict = {}
conc_dict = {'BSA':0.0, 'coliExtr':0.0,'bradford':0.0}
for name in tube_names:
tube_dict[name] = Tube()
tube_dict[name].conc = conc_dict.copy()
# A special tube for the dilute BSA
dil_bsa = Tube(conc=0,vol=0)
##--------------Some global variables ----------------#
# standard deviation for pipette errors
# Errors are based on max volume of the pipette used
pip_sigma = 0.04
# Total time and number of steps for abs reading to settle
t_tot = 2
steps = 25
# Background absorbance of blank solutions
a260_bkg = 0.07
a280_bkg = 0.03
##----------------Functions-----------------##
def tube_reset():
'''Reset volumes and concentrations in all of the tubes'''
for tube in tube_dict:
tube_dict[tube].vol = 0
tube_dict[tube].vol_n = 0
tube_dict[tube].conc['BSA'] = 0
tube_dict[tube].conc['coliExtr'] = 0
tube_dict[tube].conc['bradford'] = 0
dil_bsa.vol = 0
dil_bsa.vol_n = 0
dil_bsa.conc = 0
vol_table_update()
dilbsa_vol_update(0)
def a260_280(prot_conc,na_conc):
'''Calculate absorbance for protein and nucleic acid
solutions, using Warburg/Christian values'''
e_p260=0.512
e_p280 = 0.894
e_na260=22.1
e_na280=10.8
a260= prot_conc*e_p260 + na_conc*e_na260
a280 = prot_conc*e_p280 + na_conc*e_na280
return a260,a280
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:
code_warn.value =''
read_uvabs_butt.button_style = 'success'
read_uvabs_butt.description='Read Absorbance'
deliver_butt1.button_style = 'success'
deliver_butt1.description='Pipette!'
deliver_butt2.description='Pipette!'
deliver_butt2.button_style = 'success'
read_bradford_butt.button_style = 'success'
read_bradford_butt.description='Read Absorbance'
def on_wl_ch_a(value):
'''Respond to change in the wavelength widget'''
global zero_set
read_uvabs(0)
def on_wl_ch_b(value):
'''Respond to change in the wavelength widget'''
global zero_set
read_bradford(0)
def zero(change):
'''Respond to the Zero button'''
global zero_set
zero_set += abs_read
abs_update(0)
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(absb):
'''function to set global abs_read 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
abs_read = absb
tau = 0.2*t_tot
nu = 5/t_tot
for i in range(steps+1):
t = t_tot*i/steps
abs_d = absb*(1+damp_sin(t,nu,tau))
sleep(t_tot/steps)
abs_show(abs_d)
def abs_show(absb):
'''function to displays variable in the spec_dislp HTML widget'''
spec_displ.value='<h2> Abs: <span style="color:red;">\
{:.3f}'.format(absb) + '</span></h>'
def read_uvabs(change):
'''function to responds to Read Abs button for Part A, uv abs'''
# 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
a595 = 0
if UV_samp.value == 'BSA':
# for BSA sample use specific extinction coefficients
pr = code_dict[lab_code.value]['bsa_init']
e280 = 0.67 # mg/ml ext coef
e260 = 0.6*e280
a260 = pr*e260
a280 = pr*e280
if UV_samp.value=='E. coli extract':
# for coli extract, use Warburg/Christian estimate
pr = code_dict[lab_code.value]['coli_pr']
na = code_dict[lab_code.value]['coli_na']
a260,a280 = a260_280(pr,na)
if UV_samp.value == 'H2O':
a260 = 0.0
a280 = 0.0
if wl_a.value == '260 nm':
abs_update(a260+a260_bkg-zero_set)
elif wl_a.value == '280 nm':
abs_update(a280+a280_bkg-zero_set)
elif wl_a.value == '595 nm':
abs_update(a595)
def dilbsa_vol_update(vol):
'''function to update dilute bsa HTML widget'''
vol = vol/1000
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 BSA Volume </th>
'''
html_str += f'<td style="width:100px">{vol:.3f} mL</td></tr>'
dilbsa_vol.value=html_str
def vol_table_update():
'''function to update the table of volumes for the bradford assay'''
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"> Tube </th>
<th style="width:100px"> Volume </th>
</tr>
'''
for name in tube_names:
vol = tube_dict[name].vol_n
html_str += f'<tr><td>{name}</td><td>{vol:.0f} </td></tr>\n'
html_str += '</table>'
vol_table.value=html_str
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
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
bsa_conc = code_dict[lab_code.value]['bsa_init']
# get pipette err from normal distr
err_pipette = pipette.value*rand.normalvariate(0,pip_sigma)
vol = pip_vol.value+err_pipette
# save old volumes and calculate new volume
vol_old = dil_bsa.vol
vol_new = vol_old + vol
dil_bsa.vol = vol_new
dil_bsa.vol_n += pip_vol.value
# calculate increment to amount of BSA in tube
bsa_incr = 0
if solns1.value == 'BSA':
bsa_incr = bsa_conc*pip_vol.value
# update concentration
conc_old = dil_bsa.conc
dil_bsa.conc = (conc_old*vol_old + bsa_incr)/vol_new
# update displayed volume of dilute bsa solution
dilbsa_vol_update(dil_bsa.vol_n)
def empty1(change):
'''Respond to Empty button for BSA dilution'''
dil_bsa.vol = 0
dil_bsa.vol_n = 0
dil_bsa.conc = 0
dilbsa_vol_update(dil_bsa.vol)
def deliver2(change):
'''function for bradford tubes deliver button'''
# check for valid lab coed
if lab_code.value not in codes:
deliver_butt2.description='Enter valid lab code'
deliver_butt2.button_style = 'warning'
return
# concentrations of stock soulions
bsa_conc = dil_bsa.conc
coli_conc = code_dict[lab_code.value]['coli_pr']
bradford_conc = 5
# 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[tubes.value].vol
vol_new = vol_old + vol
# calculate increments of bsa, coli extract and bradford reagent
# as volume_delivered*conc
bsa_incr = 0
coli_incr = 0
bradford_incr = 0
if solns2.value == 'Dilute BSA':
bsa_incr = bsa_conc*vol
elif solns2.value == 'E. coli extract':
coli_incr = coli_conc*vol
elif solns2.value == 'Bradford reagent':
bradford_incr = bradford_conc*vol
# update BSA conc
conc_old = tube_dict[tubes.value].conc['BSA']
conc_new = (conc_old*vol_old + bsa_incr)/vol_new
tube_dict[tubes.value].conc['BSA'] = conc_new
# update E. coli extract conc
conc_old = tube_dict[tubes.value].conc['coliExtr']
conc_new = (conc_old*vol_old + coli_incr)/vol_new
tube_dict[tubes.value].conc['coliExtr'] = conc_new
# update bradford reag conc
conc_old = tube_dict[tubes.value].conc['bradford']
conc_new = (conc_old*vol_old + bradford_incr)/vol_new
tube_dict[tubes.value].conc['bradford'] = conc_new
#update volumes
tube_dict[tubes.value].vol = vol_new
tube_dict[tubes.value].vol_n += pip_vol.value
vol_table_update()
def empty2(change):
'''Function to empty selected tube for bradford'''
tube_dict[tubes.value].vol = 0
tube_dict[tubes.value].vol_n = 0
tube_dict[tubes.value].conc['BSA'] = 0
tube_dict[tubes.value].conc['coliExtr'] = 0
tube_dict[tubes.value].conc['bradford'] = 0
vol_table_update()
def read_bradford(change):
'''function to calculate absorbance for bradford
using rect hyperbola function with parameters from
code dictionary'''
# check for valid lab code
if lab_code.value not in codes:
read_bradford_butt.description='Enter valid lab code'
read_bradford_butt.button_style = 'warning'
return
# check wavelength. Abs = 3 if uv
if wl_b.value != '595 nm':
abs_update(3.000-zero_set)
return
a = code_dict[lab_code.value]['curve_a']
b = code_dict[lab_code.value]['curve_b']
brad_conc = tube_dict[tubes.value].conc['bradford']
bkg = brad_conc*code_dict[lab_code.value]['brad_bkg']
pr_conc = tube_dict[tubes.value].conc['coliExtr'] + \
tube_dict[tubes.value].conc['BSA']
mcg_pr = 1000.0*pr_conc
absorb = brad_conc*mcg_pr*a/(mcg_pr+b)
absorb += bkg-zero_set
abs_update(absorb)
def background():
'''Background task to keep keep the page from timing out on mybinder'''
while True:
sleep(0.1)
abs_show(abs_read)
##----------------------Widgets---------------------------##
header_html = """
<h2> Biology 3515/Chemistry 3515
<br>
Biological Chemistry Laboratory
<br>
University of Utah </h2>
<h3> Spring 2021 </h3>
<h3> Experiment 2: Spectrophotometry and Measurement of Protein Concentration</h3>
<p style="font-size:16px">
This web page simulates the procedures to be carried out in Experiment 2. In the first part, UV absorbance is measured for two samples, a solution of bovine serum albumin and an extract prepared from <i>E. coli</i> bacteria. The second part uses the Bradford dye-binding assay to determine protein concentration. For this part, the BSA solution is diluted and used as a calibration standard, and the protein concentration of the <i>E. coli</i> is estimated using the calibration curve.
<hr border-width:6px, color:black>
<p style="font-size:16px">
For this and the subsequent experiments, each lab group will be assigned a six-character code, which must be entered in the box below in order for the simulation to function. The same code will be used for all of the experiments. This code specifies parameters of the experiment, such as solution concentrations, which will generally be different for different groups. Thus, members of different groups are likely to see significant differences among their results. It is as if, in the lab, everyone was using different sets of reagents. When different members of the same group carry out the simulations, they should obtain similar, but not identical results. Just as in the lab, there will be inevitable experimental errors, particularly in the pipetting operations. The pipetting errors will generally be on the order of 1-2% of the maximum volume of the pipette used.
<br>
For different parts of the experiment, sets of radio buttons are used to select solutions to pipette from and the tubes to be pipetted into. The tables show the nominal volumes in the tubes as reagents are added. (The volumes shown in the table do not account the expected small errors in pipetting). The tables are provided to help you keep track of where you are in the process. But, they won't tell you WHAT is in the tubes, just the total volume. It's up to you to keep track of what have done!
<br><br>
If you do not have an assigned code, but want to experiment with this simulation, use the code "0GXY02".
<hr border-width:6px, color:black>
"""
style = {'description_width': 'initial'}
header = widgets.HTML(
value=header_html
)
footer = widgets.HTML(
value='''
<hr border-width:6px, color:black>
David P. Goldenberg, January 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>')
aheader = widgets.HTML(
# header for part A
value = '<h1> Part A: UV absorbance of protein solutions </h1>'
)
bheader = widgets.HTML(
# header for part B
value= '<h1> Part B: Bradford assay </h1>'
)
b1header = widgets.HTML(
# header for part B, part 1
value = '<h2> 1. Dilution of BSA solution</h2>'
)
b2header = widgets.HTML(
# header for part B, part 2
value = '<h2> 2. Set up tubes for Bradford assay</h2>'
)
b3header = widgets.HTML(
# header for part B, part 3
value = '<h2> 3. Read Bradford absorbances</h2>'
)
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')
)
code_warn = widgets.HTML(
# warning when invalid lab code is entered
value = '',
layout=widgets.Layout(width='200px',margin='15px 50px 15px 0px')
)
# part A UV absorbance
UV_samp = widgets.RadioButtons(
# radio buttons to select sample for UV measurement
options = ['H2O','BSA', 'E. coli extract'],
description='Sample:',
#layout=widgets.Layout(width='200px',margin='25px 100px 0px 0px')
)
wl_a = widgets.Dropdown(
# Dropdown to select wavelength for UV measurement
options = [('260 nm'),('280 nm'),('595 nm')],
description = 'Wavelength:',
style = style,
layout=widgets.Layout(width='200px')
)
wl_b = widgets.Dropdown(
# Dropdown to select wavelength for bradford
options = [('260 nm'),('280 nm'),('595 nm')],
description = 'Wavelength:',
style = style,
layout=widgets.Layout(width='200px')
)
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')
)
spec_displ = widgets.HTML(
# spectrophotometer display
value='',
layout=widgets.Layout(margin='-15px 50px 0px 50px')
)
zero_butt = widgets.Button(
# button to zero absorbance display
description = 'Zero',
button_style = 'success'
)
# part B widgets
# B1 BSA dilution
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')
)
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')
)
deliver_butt1 = widgets.Button(
# Button to deliver volume for BSA dilution
description = 'Pipette!',
button_style = 'success',
)
empty_butt1 = widgets.Button(
# button to empty tube for bsa dilution
description = 'Empty',
button_style = 'danger',
)
solns1 = widgets.RadioButtons(
# solutions for making dilute bsa
options=['H20','BSA'],
description='Solutions'
)
dilbsa_vol = widgets.HTML(
# display volume of the dilute bsa solution
value = ''
)
#B2 bradford tube set up
tubes= widgets.RadioButtons(
# radio buttons to select bradford tubes
options=tube_names,
description='Tubes:',
)
solns2 = widgets.RadioButtons(
# radiou buttons to select solutions for bradford tubes
options = ['H2O','Dilute BSA', 'E. coli extract', 'Bradford reagent'],
description='Solution:',
layout=widgets.Layout(width='30%',margin='0px 0px 0px 0px')
)
empty_butt2 = widgets.Button(
# button to empty selected bradford tube
description = 'Empty',
button_style = 'danger',
layout=widgets.Layout(width='35%',margin='0px 0px 0px 80px')
)
tubesVb=widgets.VBox([tubes,empty_butt2],
layout=widgets.Layout(width='40%',margin='0px 0px 0px 00px'))
vol_table = widgets.HTML(
# HTML table of volumes of bradford tubes
value = '',
layout=widgets.Layout(width='250px')
)
deliver_butt2 = widgets.Button(
# Button to deliver volume for BSA dilution
description = 'Pipette!',
button_style = 'success',
)
# B3 Bradford absorbance readings
read_bradford_butt = widgets.Button(
# Button to read absorbance for bradford
description = 'Read Absorbance',
button_style = 'success',
)
#---------------Layout widgets-------------------------#
# lab code
row0 = widgets.HBox([code_label,lab_code,code_warn])
# uv absorbance
row1 = widgets.HBox([UV_samp,wl_a])
row2 = widgets.HBox([read_uvabs_butt,spec_displ,zero_butt])
# dilute bsa
row3 = widgets.HBox([solns1,dilbsa_vol,empty_butt1])
row4 = widgets.HBox([deliver_butt1,pipette,pip_vol])
# set up bradford tubes
row5 = widgets.HBox([solns2,tubesVb,vol_table])
row6 = widgets.HBox([deliver_butt2,pipette,pip_vol],
layout=widgets.Layout(margin='15px 0px 0px 0px'))
# read bradford abs
row7 = widgets.HBox([tubes,wl_b])
row8 = widgets.HBox([read_bradford_butt,spec_displ,zero_butt])
uvabs_box = widgets.VBox([hrule,aheader,row1,row2,hrule])
bsa_dil_box = widgets.VBox([bheader,b1header,row3,row4])
brad_tube_box = widgets.VBox([hrule,b2header,row5,row6])
brad_abs_box = widgets.VBox([hrule,b3header,row7,row8])
## ----------------Widget actions---------------------------##
lab_code.observe(on_code_ch,names=['value'])
wl_a.observe(on_wl_ch_a,names=['value'])
wl_b.observe(on_wl_ch_b,names=['value'])
pipette.observe(on_pipette_ch,names=['value'])
read_uvabs_butt.on_click(read_uvabs)
zero_butt.on_click(zero)
deliver_butt1.on_click(deliver1)
empty_butt1.on_click(empty1)
deliver_butt2.on_click(deliver2)
empty_butt2.on_click(empty2)
read_bradford_butt.on_click(read_bradford)
##----------------Initialize Widgets--------------------------##
tube_reset()
abs_update(0)
zero_set=0
zero(0)
dilbsa_vol_update(0)
vol_table_update()
##----------------Display Widgets --------------------------##
display(header)
display(row0)
display(uvabs_box)
display(bsa_dil_box)
display(brad_tube_box)
display(brad_abs_box)
display(footer)
#-----------------Start Background Process-------------------#
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