Conductance of Electrical Current through Various Aqueous Solutions
Stephen Lukacs (2) iquanta.org/instruct/python
"""
reference: https://iquanta.org/instruct/python ::: Chemistry 10: Conductance/Conductivity ::: Stephen Lukacs, Ph.D. ©2023-01-23
"""
from py4web import URL, request
from ombott.request_pkg.helpers import FileUpload
from yatl.helpers import *
from iquanta.mcp import request_to_boolean, is_str_float, is_str_int, str_to_float, str_to_int, extra_x
from iquanta.chmpy import convert_vernier_raw_file__to__data
from numpy import array, mean, std, polyfit, diag, sqrt
from scipy import optimize
import plotly.graph_objects as go
BR, B = TAG['br/'], TAG['b']
sample_knowns = r'"Simple Drops" is the experiment exactly as prescribed in Lab 10 of the chm1025 and chm2045 lab manual. Three separate solutions of NaCl, CaCl2, and AlCl3 are each made to precisely 0.500 M. Press "Upload Data" to see the results. With all experimental parameters and environments the same between each trial, except for one item, why are the slopes of the three compounds so consistent and linear within a single compound and trial and why are the slopes so different between the different compounds and trials?\n\nVernier Format 2\r\nL10conductivity.txt 10/12/2018 22:16:2\r\nRun 1\r\ndrop\tConductivity\t\r\nd\tC\t\r\n\t\xb5S/cm\t\r\n\r\n0\t0\t\r\n1\t40\t\r\n2\t84\t\r\n3\t132\t\r\n4\t176\t\r\n5\t219\t\r\n6\t262\t\r\n7\t299\t\r\n8\t336\t\r\n9\t418\t\r\n10\t441\t\r\n11\t472\t\r\n12\t511\t\r\n13\t535\t\r\n14\t570\t\r\n15\t607\t\r\n16\t645\t\r\n\t\t\r\n\t\t\r\nVernier Format 2\r\nL10conductivity.txt 10/12/2018 22:16:2\r\nRun 2\r\ndrop\tConductivity\t\r\nd\tC\t\r\n\t\xb5S/cm\t\r\n\r\n0\t0\t\r\n1\t77\t\r\n2\t154\t\r\n3\t216\t\r\n4\t287\t\r\n5\t365\t\r\n6\t426\t\r\n7\t486\t\r\n8\t558\t\r\n9\t624\t\r\n10\t691\t\r\n11\t756\t\r\n12\t831\t\r\n13\t909\t\r\n14\t985\t\r\n15\t1051\t\r\n16\t1114\t\r\n\t\t\r\nVernier Format 2\r\nL10conductivity.txt 10/12/2018 22:16:2\r\nRun 3\r\ndrop\tConductivity\t\r\nd\tC\t\r\n\t\xb5S/cm\t\r\n\r\n0\t0\t\r\n1\t132\t\r\n2\t254\t\r\n3\t343\t\r\n4\t432\t\r\n5\t528\t\r\n6\t638\t\r\n7\t733\t\r\n8\t842\t\r\n9\t935\t\r\n10\t1022\t\r\n11\t1106\t\r\n12\t1187\t\r\n13\t1276\t\r\n14\t1373\t\r\n15\t1463\t\r\n16\t1554\t\r\n\t\t\r\n'
rtn = FORM(_action=None, _method="post", _enctype="multipart/form-data")
data, txttype, txt = convert_vernier_raw_file__to__data(request.POST.get('labQ2file') if request.POST.get('labQ2file') else request.forms.get('txtfile'), False)
rtn.append(CAT(DIV(P("Imagine the most simple instrument. Two wires dipped into a solution and applying a voltage to input some power. Measuring the current through pure water reads zero amps. Add the smallest pinch of any kind of salt and a current is registered. One can fairly easily imagine the cations migrating towards the negative electrode (anode) and the anions towards the positive electrode (cathode), thus bridging the electron flow between the two electrodes through the resistive pure water solution. Add another exact pinch and the current doubles. Add a third amount, and again an increase by the same exact proportion. Again, conceptually, higher concentration of ions, more ions, a thicker bridge of electrons crossing the insulating pure water and thus a greater measured conductivity. What is going on there?", *[BR()]*2, r"With that essential concept, it must be that dissolved and dissociated ions in aquaeous solution must be the cause of electrons flowing through the solution. Recall that dissociation of any salts (also electrolyts bonded by ionic bonds) looks like: $$NaCl_{(s)} \rightarrow Na^+_{(aq)} + Cl^-_{(aq)}$$ so, what are the total number of ions from the dissociation of NaCl in water?", *[BR()]*2, XML(r"And, we can extend that idea of dissociation of salts to our other two compounds: $$CaCl_{2(s)} \rightarrow Ca^{+2}_{(aq)} + 2Cl^-_{(aq)}$$ $$AlCl_{3(s)} \rightarrow Al^{+3}_{(aq)} + 3Cl^-_{(aq)}$$ where \(3Cl^-\) is three separate unbonded chlorines whereas the subscripted \(Cl^-_{3}\) would be three bonded chlorines. A subtle, not really so subtle, difference."), *[BR()]*2, r"Therefore, there is a huge difference between simply dissolving a solute in solution because of polar and nonpolar compounds and salts or ionic compounds dissociating in solution as shown above. Now that the distinction should be clear, how many ions are present in the solution given the dissociation reactions shown above?", *[BR()]*2, "And, now apply that understanding to the below results or your own uploaded or manually-typed data from your own experiment..."))))
rtn.append(CAT(DIV(
DIV("Designed to upload LabQuest2 text (txt) outputs...", BR(), INPUT(_type="file", _name="labQ2file"), XML(", Copy in Demo: "), SELECT(OPTION(""), OPTION("Reset/Clear All Inputs...", _value="clear"), OPTION("Demo 1: Simple Drops.", _value="demo1"), OPTION("Demo 2: Drops to Probe's Maximum Limit.", _value="demo2"), OPTION("Demo 3: Drops to 20,000 µS/cm.", _value="demo3"), _id="demo"), B(", OR,"), _style="background-color:none;"),
DIV(XML("Manually enter a calibration curve below..."), BR(), "(drops, L (µS/cm)) Data Entry.. .", BR(), TEXTAREA(txtfile if ('txtfile' in locals()) else sample_knowns.encode().decode('unicode-escape'), _name="txtfile"), BR(), "Enter for example \"Run 1\" at the top of each run or trial.", _style="float: left;"),
DIV("Column for X Series: ", INPUT(_type="text", _class="integer", _name="xseries", _value=xseries if ('xseries' in locals()) else 1), XML(" "), BR(), "Column for Y Series: ", INPUT(_type="text", _class="integer", _name="yseries", _value=yseries if ('yseries' in locals()) else 2), _style="float:left; width:440px; margin-right:9px; background-color:none;"),
DIV(BR(), INPUT(_type="submit", _value="Upload Data"), ", or, just Upload to run the demonstration.", "" if (txt is None) else CAT(" ", SPAN(txttype, _style="font-weight:bold; color:maroon;")), _style="float:left; max-width:550px; background-color:none;"),
_style="float:left; width:100%; background-color:none;"),
DIV(_style="float:none; clear:both;")))
def fit_polynomial(x, y, deg=1):
fit, ymean = polyfit(x, y, deg, full=True), mean(y)
#RSquared verified with Mathematica LinearModelFit["RSquared"]
SSres, SStot = fit[1][0], sum([(d - ymean)**2 for d in y])
return fit[0], (1 - SSres / SStot)
linear = lambda x, m, b: m*x + b
if (data is not None):
rtn.append(str(data))
pcolors = ('darkred', 'darkorange', 'darkblue', 'darkgreen', 'darkviolet',) #plotly colors
plcolors = ('red', 'orange', 'blue', 'green', 'violet',) #plotly colors
ix, iy, ir = str_to_int(xseries)-1, str_to_int(yseries)-1, data[0]['axes']
#rtn.append(DIV(ix, ' ... ', iy, ' ... ', str(ir), _class="error"))
try:
fig, t = go.Figure(), TABLE(_class="eq")
for i, run in enumerate(data):
#bos...prepare data and numeric solutions...
run['data'].sort(key=lambda d: d[1])
zipped_data = list(zip(*run['data']))
x, y = zipped_data[ix], zipped_data[iy]
(mb, RSquared) = fit_polynomial(x, y)
#eos...prepare data and numeric solutions.
#bos...plot series...
minypt, maxypt = run['data'][0], run['data'][-1] #minypt, maxypt = tuple(map(min, zip(*data))), tuple(map(max, zip(*data))) #get the datapoints of the minimum and maximum y, respectively.
xss = [minypt[0], maxypt[0],]
fig.add_trace(go.Scatter(x=xss, y=[linear(d, *mb) for d in xss], mode='lines', name=f"Linear Fit #{i+1}", line=go.scatter.Line(width=1, color=plcolors[i], dash="dot")))
fig.add_trace(go.Scatter(x=x, y=y, mode='markers', name=f"Run #{i+1}", marker=go.scatter.Marker(size=9, color=pcolors[i], line={ 'width':0.75, 'color':"darkgreen" })))
#eos...plot series.
fig.update_layout(xaxis=go.XAxis(title="Concentration (#drops)", type="linear"), yaxis=go.YAxis(title="Conductivity, L (uS/cm)", anchor='x', side='left', type="linear"))
fig.update_layout(title_text="Conductivity Calibration Curve", height=1050, showlegend=True)
html = fig.to_html()
rtn.append(XML(html[html.find('<div>'):html.rfind('</div>')+6].replace('<div>', '<div id="plotly">')))
rtn.append(t)
except Exception as E:
rtn.append(DIV(f'Could not process or display the plot or solutions. Message: "{E}"', _class="error"))
rtn.append(CAT("lecture by Stephen Lukacs, Ph.D., ©2011 - 2023; updated: March 7, 2023. all data confirmed via ", A("lecture_data_analysis.nb", _href=URL('static', "pdf/lecture_data_analysis8.pdf"), _target="data_analysis"), "."))
<page_scripts>
<style>
input[type=text] { width: 70px; text-align: center; border-radius: 7px; }
input[type=file] { width: 500px; font-size: 12pt; background-color: yellow; }
input[type=file]::file-selector-button { width: 170px; border-radius: 7px; }
textarea { margin: 0px 2px; width: 410px; height: 230px; font-size: 12pt; border-radius: 5px; }
p { margin: 2px 0px; padding: 8px; border-radius: 10px; border: 2px solid silver; }
div.eq { display: block; color: black; font-size: 16pt; background-color: white; }
span.eq { color: maroon; font-size: 20pt; font-weight: bold; }
div.error { display: block; color: red; font-weight: bold; font-size: 16pt; background-color: white; }
</style>
<script>
/*back-quote in javascript is a literal string just as r-string is in python. and a literal string is what we want because we do not want anything system processing these following strings until this code is presented to the client-side javascript processor...*/
var demo1 = `{{=XML(sample_knowns)}}`;
var demo2 = `Instead of 0.500 M solutions as in "Simple Drops", this experiment was run with 1.00 M solutions, thereby maxing out the upper threshold of the conductivity probe.\n\nVernier Format 2\nL10conductivity2022_1.txt 4/14/2019 2:14:12\nRun 1\ndrops\tConductivity\t\nd\tC\t\n\t\xb5S/cm\t\n\n0\t-1\t\n1\t294\t\n2\t523\t\n3\t697\t\n4\t842\t\n5\t1033\t\n6\t1213\t\n7\t1368\t\n8\t1538\t\n9\t1707\t\n10\t1774\t\n11\t1918\t\n12\t2058\t\n13\t2230\t\n14\t2382\t\n15\t2507\t\n16\t2654\t\n17\t2810\t\n18\t2936\t\n19\t3078\t\n20\t3224\t\n21\t3358\t\n22\t3471\t\n23\t3615\t\n24\t3726\t\n25\t3827\t\n26\t3897\t\n27\t3966\t\n28\t4010\t\n29\t4042\t\n30\t4066\t\n31\t4072\t\n32\t4075\t\n33\t4079\t\n34\t4078\t\n35\t4079\t\n36\t4080\t\n37\t4080\t\n38\t4080\t\n39\t4080\t\n40\t4080\t\nVernier Format 2\nL10conductivity2022_1.txt 4/14/2019 2:14:12\nRun 2\ndrops\tConductivity\t\nd\tC\t\n\t\xb5S/cm\t\n\n0\t-1\t\n1\t144\t\n2\t233\t\n3\t381\t\n4\t521\t\n5\t648\t\n6\t805\t\n7\t893\t\n8\t1057\t\n9\t1170\t\n10\t1266\t\n11\t1417\t\n12\t1498\t\n13\t1580\t\n14\t1769\t\n15\t1888\t\n16\t2007\t\n17\t2128\t\n18\t2268\t\n19\t2417\t\n20\t2549\t\n21\t2689\t\n22\t2813\t\n23\t2934\t\n24\t3073\t\n25\t3200\t\n26\t3314\t\n27\t3451\t\n28\t3572\t\n29\t3654\t\n30\t3671\t\n31\t3805\t\n32\t3862\t\n33\t3920\t\n34\t3959\t\n35\t3984\t\n36\t4004\t\n37\t4010\t\n38\t4012\t\n39\t4012\t\n40\t4016\t\nVernier Format 2\nL10conductivity2022_1.txt 4/14/2019 2:14:12\nRun 3\ndrops\tConductivity\t\nd\tC\t\n\t\xb5S/cm\t\n\n0\t-1\t\n1\t76\t\n2\t160\t\n3\t251\t\n4\t338\t\n5\t426\t\n6\t549\t\n7\t641\t\n8\t731\t\n9\t818\t\n10\t892\t\n11\t977\t\n12\t1046\t\n13\t1114\t\n14\t1196\t\n15\t1268\t\n16\t1353\t\n17\t1447\t\n18\t1530\t\n19\t1605\t\n20\t1677\t\n21\t1759\t\n22\t1834\t\n23\t1912\t\n24\t2006\t\n25\t2085\t\n26\t2152\t\n27\t2224\t\n28\t2308\t\n29\t2380\t\n30\t2459\t\n31\t2531\t\n32\t2602\t\n33\t2660\t\n34\t2738\t\n35\t2795\t\n36\t2874\t\n37\t2947\t\n38\t3004\t\n39\t3074\t\n40\t3141\t\n`;
var demo3 = `And this experiment was run with the 1.00 M solutions but with the sensitivity or range of the conductivity probe set to 20,000\xb5S/cm and not 2,000\xb5S/cm. Notice that the curves are not reaching the probe\'s maximum but at the same time there is a distinctive curve to each compound and trial. This curvature is covered in more detailed under Lab 12: Analytic Conductance.\n\nVernier Format 2\nL10conductivity2022_2.txt 4/14/2019 3:17:5\nRun 1\ndrops\tConductivity\t\nd\tC\t\n\t\xb5S/cm\t\n\n0\t1\t\n1\t441\t\n2\t915\t\n3\t1317\t\n4\t1671\t\n5\t2155\t\n6\t2430\t\n7\t2792\t\n8\t3020\t\n9\t3375\t\n10\t3572\t\n11\t3727\t\n12\t4037\t\n13\t4350\t\n14\t4590\t\n15\t4852\t\n16\t5124\t\n17\t5408\t\n18\t5630\t\n19\t5861\t\n20\t6172\t\n21\t6465\t\n22\t6725\t\n23\t6932\t\n24\t7210\t\n25\t7455\t\n26\t7683\t\n27\t7922\t\n28\t8141\t\n29\t8381\t\n30\t8614\t\n31\t8832\t\n35\t9687\t\n40\t10675\t\n43\t11252\t\n45\t11627\t\n47\t11995\t\n50\t12592\t\n53\t13099\t\n55\t13493\t\n56\t13678\t\n57\t13850\t\n58\t14063\t\n59\t14250\t\n60\t14409\t\n65\t15285\t\n70\t16070\t\n75\t16881\t\n80\t17655\t\n85\t18396\t\n90\t19110\t\n91\t19271\t\n92\t19399\t\n93\t19538\t\n94\t19672\t\n95\t19841\t\n96\t19979\t\n97\t20105\t\n98\t20246\t\n99\t20376\t\n100\t20484\t\n\t\t\nVernier Format 2\nL10conductivity2022_2.txt 4/14/2019 3:17:5\nRun 2\ndrops\tConductivity\t\nd\tC\t\n\t\xb5S/cm\t\n\n0\t-1\t\n1\t280\t\n2\t676\t\n3\t988\t\n4\t1300\t\n5\t1602\t\n6\t1885\t\n7\t2220\t\n8\t2505\t\n9\t2763\t\n10\t3033\t\n11\t3323\t\n12\t3561\t\n13\t3836\t\n14\t4033\t\n16\t4582\t\n17\t4812\t\n18\t5062\t\n19\t5234\t\n20\t5535\t\n21\t5747\t\n22\t6038\t\n23\t6287\t\n24\t6504\t\n25\t6708\t\n27\t7281\t\n28\t7507\t\n29\t7744\t\n30\t7942\t\n35\t8956\t\n40\t9947\t\n41\t10174\t\n42\t10359\t\n43\t10552\t\n44\t10729\t\n45\t10894\t\n46\t11114\t\n47\t11279\t\n48\t11512\t\n49\t11673\t\n50\t11768\t\n53\t12313\t\n56\t12813\t\n59\t13299\t\n60\t13475\t\n61\t13627\t\n62\t14031\t\n63\t14191\t\n64\t14336\t\n65\t14498\t\n66\t14685\t\n67\t14819\t\n69\t14978\t\n70\t15150\t\n75\t15873\t\n80\t16553\t\n85\t17282\t\n90\t17933\t\n95\t18531\t\n96\t18649\t\n97\t18898\t\n98\t18890\t\n99\t18973\t\n100\t19078\t\nVernier Format 2\nL10conductivity2022_2.txt 4/14/2019 3:17:5\nRun 3\ndrops\tConductivity\t\nd\tC\t\n\t\xb5S/cm\t\n\n0\t-2\t\n1\t145\t\n2\t316\t\n3\t496\t\n4\t666\t\n5\t836\t\n6\t1025\t\n7\t1201\t\n8\t1362\t\n9\t1517\t\n10\t1648\t\n15\t2485\t\n20\t3256\t\n21\t3397\t\n22\t3512\t\n23\t3681\t\n24\t3807\t\n25\t3969\t\n26\t4085\t\n27\t4227\t\n28\t4376\t\n29\t4521\t\n30\t4526\t\n35\t5302\t\n40\t5974\t\n41\t6096\t\n42\t6215\t\n43\t6325\t\n44\t6439\t\n45\t6540\t\n46\t6688\t\n47\t6815\t\n48\t6970\t\n49\t7027\t\n50\t7182\t\n55\t7707\t\n60\t8271\t\n65\t8824\t\n70\t9330\t\n75\t9831\t\n80\t10318\t\n85\t10767\t\n90\t11250\t\n95\t11692\t\n100\t12112\t\nVernier Format 2\nL10conductivity2022_2.txt 4/14/2019 3:17:5\nRun 4\ndrops\tConductivity\t\nd\tC\t\n\t\xb5S/cm\t\n\n0\t0\t\n5\t2347\t\n10\t4090\t\n15\t5851\t\n20\t7406\t\n25\t8889\t\n30\t10258\t\n35\t11630\t\n40\t12676\t\n45\t13812\t\n50\t14907\t\n55\t15952\t\n60\t16904\t\n65\t17859\t\n70\t18793\t\n75\t19618\t\n80\t20379\t\n85\t21085\t\n90\t21684\t\n95\t22292\t\n100\t22847\t\n`;
jQuery(function() {
jQuery('select#demo').change(function(obj) {
var select = jQuery(this);
console.log('changed: "'+select.prop('id')+'", '+select.val());
if (select.val() == 'clear') {
jQuery('textarea[name="txtfile"]').val("");
} else if (select.val() == 'demo1') {
jQuery('textarea[name="txtfile"]').val(demo1);
} else if (select.val() == 'demo2') {
jQuery('textarea[name="txtfile"]').val(demo2);
} else if (select.val() == 'demo3') {
jQuery('textarea[name="txtfile"]').val(demo3);
}
});
});
jQuery(document).ready( function () {
var sx = "jQuery.version: "+jQuery.fn.jquery; //+" | jQuery.ui.version: "+jQuery.ui.version;
console.log("jQuery.document.ready from Chemistry10.js begin..."+sx);
//jQuery('textarea[name="txtfile"]').val(demo1);
console.log("reference: https://iquanta.org/instruct/python ::: Chemistry 10: Conductance/Conductivity ::: Stephen Lukacs, Ph.D. ©2023-01-23");
console.log("jQuery.document.ready from Chemistry10.js end");
});
</script>
</page_scripts>