{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Calculating Yeast Cell Density" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This tool facilitates determining yeast cell density of a culture if provided the absorbance at 660 nm, a.k.a. optical density at 660 nm, and the dilution factor of the sample.\n", "\n", "This tool is based on the approach described in the Methods in Yeast Gentics Appendix entitled \"Measuring Yeast Cell Density by Spectrophotometry\".\n", "\n", "------\n", "\n", "
\n", "

If you haven't used one of these notebooks before, they're basically web pages in which you can write, edit, and run live code. They're meant to encourage experimentation, so don't feel nervous. Just try running a few cells and see what happens!.

\n", "\n", "

\n", " Some tips:\n", "

\n", "

\n", "\n", "

\n", " To keep in mind when running via MyBinder:\n", "

\n", "

\n", "
\n", "\n", "\n", "\n", "----" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Investigator-determined options:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below enter the absorbance at 660 nm (O.D. 660) of the culture or diluted culture sample. " ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "absorbance = 1.323" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below enter the dilution factor of the sample. \n", "\n", "Enter below the dilution_factor as\n", "\n", " dilution_factor = \"none\"\n", " \n", ", if the sample is undiluted culture.\n", "\n", "(You may have needed to dilute the sample to get the reading to be around 1.0 Absorbance unit or less, which is typically the best range for most spectrohphotometers.) \n", "\n", "Dilution factor, here, is the number do you need to multiply the original culture volume to get the final volume, see [here]( http://www.hemocytometer.org/dilution-factor/). In other words, dilution_factor equals the fold dilution.\n", "\n", "If it is a ten-fold dilution simply enter \n", " dilution_factor = 10 \n", " \n", "Note that quotes are not involved if the dilution factor is numerical and not `none`." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "dilution_factor = \"none\"" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Below set the `haploid` setting to `False` if you are working with a diploid strain. " ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "haploid = True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### That is all that is needed. You can now run this notebook and see the result at the bottom. You can also edit it further to view the individual steps prior to the results." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Calculating yeast cell density of the sample from the standard curve:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### IF YOU JUST WANT THE RESULT BASED ON WHAT YOU ENTERED ABOVE, SKIP TO BOTTOM OF THIS NOTEBOOK." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (This is just the behind the scenes stuff.)" ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "## PREPARATION AND HELPER FUNCTIONS FOR THE CODE ##\n", "import numpy\n", "\n", "# *****Standard Curve *********\n", "# *****************************\n", "\n", "# List of tuples of OD660 vs haploid number of cells per ml. First values is the\n", "# OD660 readings and 2nd are the number of haploid cells in the mL sample, as\n", "# provided for strain A364A. Cell densities for diploids are half those for\n", "# halploids as diploids and some mutants which are abnormally large will\n", "# scatter more light than the wildtype haploids at the same cell density.\n", "yeast_cell_density_by_OD660_tuples = [\n", " (0.000, 0.000e7),\n", " (0.010, 0.015e7),\n", " (0.020, 0.025e7),\n", " (0.030, 0.040e7),\n", " (0.040, 0.053e7),\n", " (0.050, 0.065e7),\n", " (0.060, 0.078e7),\n", " (0.070, 0.090e7),\n", " (0.080, 0.103e7),\n", " (0.090, 0.115e7),\n", " (0.100, 0.128e7),\n", " (0.110, 0.140e7),\n", " (0.120, 0.153e7),\n", " (0.130, 0.165e7),\n", " (0.140, 0.178e7),\n", " (0.150, 0.190e7),\n", " (0.160, 0.204e7),\n", " (0.170, 0.216e7),\n", " (0.180, 0.229e7),\n", " (0.190, 0.241e7),\n", " (0.200, 0.255e7),\n", " (0.210, 0.268e7),\n", " (0.220, 0.280e7),\n", " (0.230, 0.293e7),\n", " (0.240, 0.305e7),\n", " (0.250, 0.319e7),\n", " (0.260, 0.330e7),\n", " (0.270, 0.342e7),\n", " (0.280, 0.356e7),\n", " (0.290, 0.370e7),\n", " (0.300, 0.385e7),\n", " (0.310, 0.399e7),\n", " (0.320, 0.412e7),\n", " (0.330, 0.426e7),\n", " (0.340, 0.440e7),\n", " (0.350, 0.455e7),\n", " (0.360, 0.470e7),\n", " (0.370, 0.484e7),\n", " (0.380, 0.499e7),\n", " (0.390, 0.514e7),\n", " (0.400, 0.530e7),\n", " (0.410, 0.547e7),\n", " (0.420, 0.564e7),\n", " (0.430, 0.580e7),\n", " (0.440, 0.600e7),\n", " (0.450, 0.617e7),\n", " (0.460, 0.633e7),\n", " (0.470, 0.650e7),\n", " (0.480, 0.666e7),\n", " (0.490, 0.683e7),\n", " (0.500, 0.700e7),\n", " (0.510, 0.717e7),\n", " (0.520, 0.733e7),\n", " (0.530, 0.750e7),\n", " (0.540, 0.766e7),\n", " (0.550, 0.783e7),\n", " (0.560, 0.800e7),\n", " (0.570, 0.817e7),\n", " (0.580, 0.833e7),\n", " (0.590, 0.850e7),\n", " (0.600, 0.866e7),\n", " (0.610, 0.883e7),\n", " (0.620, 0.900e7),\n", " (0.630, 0.917e7),\n", " (0.640, 0.933e7),\n", " (0.650, 0.950e7),\n", " (0.660, 0.966e7),\n", " (0.670, 0.983e7),\n", " (0.680, 1.000e7),\n", " (0.690, 1.023e7),\n", " (0.700, 1.046e7),\n", " (0.710, 1.070e7),\n", " (0.720, 1.093e7),\n", " (0.730, 1.116e7),\n", " (0.740, 1.140e7),\n", " (0.750, 1.160e7),\n", " (0.760, 1.180e7),\n", " (0.770, 1.200e7),\n", " (0.780, 1.220e7),\n", " (0.790, 1.240e7),\n", " (0.800, 1.260e7),\n", " (0.810, 1.283e7),\n", " (0.820, 1.306e7),\n", " (0.830, 1.330e7),\n", " (0.840, 1.353e7),\n", " (0.850, 1.376e7),\n", " (0.860, 1.400e7),\n", " (0.870, 1.430e7),\n", " (0.880, 1.460e7),\n", " (0.890, 1.490e7),\n", " (0.900, 1.520e7),\n", " (0.910, 1.550e7),\n", " (0.920, 1.580e7),\n", " (0.930, 1.610e7),\n", " (0.940, 1.640e7),\n", " (0.950, 1.670e7),\n", " (0.960, 1.703e7),\n", " (0.970, 1.736e7),\n", " (0.980, 1.770e7),\n", " (0.990, 1.810e7),\n", " (1.000, 1.850e7),\n", " (1.010, 1.890e7),\n", " (1.020, 1.926e7),\n", " (1.030, 1.963e7),\n", " (1.040, 2.000e7),\n", " (1.050, 2.040e7),\n", " (1.060, 2.080e7),\n", " (1.070, 2.120e7),\n", " (1.080, 2.163e7),\n", " (1.090, 2.206e7),\n", " (1.100, 2.250e7),\n", " (1.110, 2.296e7),\n", " (1.120, 2.343e7),\n", " (1.130, 2.390e7),\n", " (1.140, 2.433e7),\n", " (1.150, 2.476e7),\n", " (1.160, 2.520e7),\n", " (1.170, 2.566e7),\n", " (1.180, 2.613e7),\n", " (1.190, 2.660e7),\n", " (1.200, 2.706e7),\n", " (1.210, 2.753e7),\n", " (1.220, 2.800e7),\n", " (1.230, 2.850e7),\n", " (1.240, 2.900e7),\n", " (1.250, 2.950e7),\n", " (1.260, 3.002e7),\n", " (1.270, 3.055e7),\n", " (1.280, 3.107e7),\n", " (1.290, 3.160e7),\n", " (1.300, 3.220e7),\n", " (1.310, 3.280e7),\n", " (1.320, 3.340e7),\n", " (1.330, 3.400e7),\n", " (1.340, 3.460e7),\n", " (1.350, 3.520e7),\n", " (1.360, 3.580e7),\n", " (1.370, 3.640e7),\n", " (1.380, 3.700e7),\n", " (1.390, 3.760e7),\n", " (1.400, 3.820e7),\n", " (1.410, 3.880e7),\n", " (1.420, 3.940e7),\n", " (1.430, 4.000e7),\n", " (1.440, 4.065e7),\n", " (1.450, 4.130e7),\n", " (1.460, 4.200e7),\n", " (1.470, 4.270e7),\n", " (1.480, 4.340e7),\n", " (1.490, 4.410e7),\n", " (1.500, 4.480e7),\n", " (1.510, 4.550e7),\n", " (1.520, 4.625e7),\n", " (1.530, 4.700e7),\n", " (1.540, 4.775e7),\n", " (1.550, 4.850e7),\n", " (1.560, 4.925e7),\n", " (1.570, 5.000e7),\n", " (1.580, 5.075e7),\n", " (1.590, 5.150e7),\n", " (1.600, 5.225e7),\n", " (1.610, 5.300e7),\n", " (1.620, 5.380e7),\n", " (1.630, 5.460e7),\n", " (1.640, 5.540e7),\n", " (1.650, 5.630e7),\n", " (1.660, 5.700e7),\n", " (1.670, 5.800e7),\n", " (1.680, 5.890e7),\n", " (1.690, 5.980e7),\n", " (1.700, 6.070e7)\n", "]\n", "\n", "\n", "def unzip(iterable):\n", " '''\n", " function unzips 2-item tuples to lists of each separate item\n", " based on\n", " http://stackoverflow.com/questions/19339/a-transpose-unzip-function-in-python-inverse-of-zip\n", " and\n", " http://stackoverflow.com/questions/13635032/what-is-the-inverse-function-of-zip-in-python\n", " '''\n", " return zip(*iterable)\n", "\n", "def abs_in_range(abs):\n", " '''\n", " The function checks to make sure value of absorbance provided is in range\n", " of OD660 values covered by standard curve. Numpy linear interpolation I'll\n", " use doesn't cover handling if value to be checked on curve is not in between\n", " at least two points on curve. Defaults to just giving highest or lowest\n", " corresponding value as shown at http://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html\n", " when value of 0 given.\n", "\n", " Returns true if in range or False when out of range.\n", "\n", " Based on\n", " http://stackoverflow.com/questions/618093/how-to-find-whether-a-number-belongs-to-a-particular-range-in-python.\n", " \n", " Note that for the unzip, in Python 2 you can get it to seemingly work, or at least not report\n", " an error, if only include one variable to unzip the two items into. However, Python 3 throws \n", " an error for the next line because unpacking gets done wrong and/or cannot compare to a \n", " integers to tuples, which is what it is if not unpacked right. And so best to unpack\n", " both, putting the unused one into the `values_not_used_in_this_function`.\n", " \n", " '''\n", " od660_values_list, values_not_used_in_this_function = unzip(\n", " yeast_cell_density_by_OD660_tuples)\n", " return True if min(od660_values_list) <= abs <= max(\n", " od660_values_list) else False\n", "\n", "\n", "\n", "\n", "\n", "def obtain_value_from_std_curve(abs660):\n", " '''\n", " Function takes absorbance at 660 nm and determines cells per ml using\n", " standard curve of OD660 vs cell density.\n", "\n", " Returns cells per ml for the sample.\n", "\n", " Approach based on http://stackoverflow.com/questions/25057943/getting-y-value-of-a-curve-given-an-x-value\n", " and\n", " http://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html\n", " '''\n", " # cast the standard curve tuples list for use as x and y values of\n", " # curve in numpy interpolation\n", " od660_values_list, cells_per_ml_values_list = unzip(\n", " yeast_cell_density_by_OD660_tuples)\n", "\n", " # use one-dimensional linear interpolation by Numpy\n", " # http://docs.scipy.org/doc/numpy/reference/generated/numpy.interp.html\n", " return numpy.interp(abs660, od660_values_list, cells_per_ml_values_list)\n", "\n", "\n", "def represents_float(v):\n", " '''\n", " function to see if an varibale can be typecast a float. Returns True if it\n", " can.\n", "\n", " based on\n", " http://stackoverflow.com/questions/1265665/python-check-if-a-string-represents-an-int-without-using-try-except\n", " '''\n", " try:\n", " float(v)\n", " return True\n", " except ValueError:\n", " return False\n", "\n", "\n", "def cells_per_ml_calc (abs, dilution_factor):\n", " '''\n", " The function takes an absorbance at 660 nm and dilution factor and then\n", " returns an approximation of the number of yeast cells per ml sample and a\n", " boolean indicating if errors involving the provided dilution_factor are\n", " detected. The approach described in the Methods in Yeast Gentics Appendix\n", " entitled \"Measuring Yeast Cell Density by Spectrophotometry\".\n", "\n", "\n", " It is an approximation because it is based on a standard curve genrated for\n", " yeast strain A364A and may not be valid for all yeast. If you need accurate\n", " numbers, you should count your cells, or make a standard curve for your own\n", " future use, with a Coulter counter or a hemocytometer.\n", "\n", " Dilution factor is in the terms of what number do you need to multiply the\n", " original culture volume to get the final volume,\n", " see http://www.hemocytometer.org/dilution-factor/ . In other words,\n", " dilution_factor equals the fold dilution.\n", " Some examples:\n", " * For a 10-fold dilution, on other words 1 parts original culure plus 9 parts\n", " diluent, the dilution_factor argument is 10.\n", " * For a 5-fold dilution, on other words 1 parts original culure plus 4 parts\n", " diluent, the dilution_factor is 5.\n", " * For a 2-fold or `1-to-1` dilution, on other words 1 parts original culure\n", " plus 1 parts diluent, the dilution_factor is 2.\n", "\n", " Technically, no dilution means this factor will be 1 for that case.\n", " However, as calculating that is a bit much to ask of anyone not\n", " actually diluting a sample, to make things easy the dilution factor\n", " argument can be a string 'None', without quotes, and the calculations will\n", " be handled appropriately. Likewise, dilution_factor can also simply be\n", " designated the number `0` treat the sample as undiluted.\n", "\n", " The function also returns a Boolean as to whether the dilution_factor was\n", " needed in a calculation, but was not provided in form that can be converted\n", " to a float for multiplication.\n", " '''\n", " # Use provided absorbance to determine cells per ml using standard curve of\n", " # OD660 vs cell density.\n", " calculated_cells_per_ml = obtain_value_from_std_curve(abs)\n", "\n", "\n", " #**** ACCOUNTING FOR DILUTION FACTOR SECTION*****\n", " # Was planning to typecast dilution_factor to a string to more easily handle comparisons\n", " # next. This conversion allows dilution_factor string case to be lowered for\n", " # comparison; otherwise, when the `.lower()` method is applied in a series\n", " # of comparisons, it throws an error if it is not a string at the time.\n", " # However, oddly in the comparison, it did not throw an error when I tested in IPython. So I didn't onvert first.\n", "\n", " dilution_factor_needed_but_not_float_error = False # State will be examined\n", " # if dilution_factor calculation needs to be done later. Helps in feedback\n", " # for when typecast dilution_factor back to float for calculation step.\n", "\n", " # NOW APPPLY dilution_factor TO CALCULATION, handling the exception cases of\n", " # dilution_factor of `1`, `none`, or `0` as indicating no dilution of the\n", " # sample.\n", " if (dilution_factor != \"1\") or (dilution_factor.lower() != \"none\") or (\n", " dilution_factor.lower() != \"zero\") or (dilution_factor != \"1\"):\n", " if represents_float(dilution_factor):\n", " calculated_cells_per_ml = calculated_cells_per_ml * float(dilution_factor)\n", " else:\n", " dilution_factor_needed_but_not_float_error = True\n", " #**** END ACCOUNTING FOR DILUTION FACTOR SECTION *****\n", "\n", " return calculated_cells_per_ml, dilution_factor_needed_but_not_float_error\n", "\n", "def transformation_inoculation_volume_calc (cells_per_ml):\n", " '''\n", " The function takes the cells per ml of a yeast culture and calculates what\n", " volume to use to inoculate a total of 50 mL of media for carrying out a\n", " typical yeast cell transformation per the approach described in the Methods\n", " in Yeast Gentics Appendix entitled \"High-efficiency Transformation of Yeast\".\n", " '''\n", " #### *** Use provided cells per ml to determine volume. *** ###\n", " # Final need is 50 ml at 5.0E+06 cells per mL or 2.50E+08 total cells in\n", " # 50 mL.\n", " volume = 2.50E+08/cells_per_ml\n", " return volume" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Make sure provided absorbance in range covered by standard curve\n", "out_of_range_error = abs_in_range(absorbance)\n", "# TO DO: ADD HANDLING OF ERROR" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**The standard curve resulting from the data points is represented in a visual way in the `Out` cell below.** \n", "It is interactive." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [ { "data": { "text/html": [ " \n", " " ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.plotly.v1+json": { "config": { "plotlyServerURL": "https://plot.ly" }, "data": [ { "type": "scatter", "x": [ 0, 0.015, 0.025, 0.04, 0.053, 0.065, 0.078, 0.09, 0.103, 0.115, 0.128, 0.14, 0.153, 0.165, 0.178, 0.19, 0.204, 0.216, 0.229, 0.241, 0.255, 0.268, 0.28, 0.293, 0.305, 0.319, 0.33, 0.342, 0.356, 0.37, 0.385, 0.399, 0.412, 0.426, 0.44, 0.455, 0.47, 0.484, 0.499, 0.514, 0.53, 0.547, 0.564, 0.58, 0.6, 0.617, 0.633, 0.65, 0.666, 0.683, 0.7, 0.717, 0.733, 0.75, 0.766, 0.783, 0.8, 0.817, 0.833, 0.85, 0.866, 0.883, 0.9, 0.917, 0.933, 0.95, 0.966, 0.983, 1, 1.023, 1.046, 1.07, 1.093, 1.116, 1.14, 1.16, 1.18, 1.2, 1.22, 1.24, 1.26, 1.283, 1.306, 1.33, 1.353, 1.376, 1.4, 1.43, 1.46, 1.49, 1.52, 1.55, 1.58, 1.61, 1.64, 1.67, 1.703, 1.736, 1.77, 1.81, 1.85, 1.89, 1.926, 1.963, 2, 2.04, 2.08, 2.12, 2.163, 2.206, 2.25, 2.296, 2.343, 2.39, 2.433, 2.476, 2.52, 2.566, 2.613, 2.66, 2.706, 2.753, 2.8, 2.85, 2.9, 2.95, 3.002, 3.055, 3.107, 3.16, 3.22, 3.28, 3.34, 3.4, 3.46, 3.52, 3.58, 3.64, 3.7, 3.76, 3.82, 3.88, 3.94, 4, 4.065, 4.13, 4.2, 4.27, 4.34, 4.41, 4.48, 4.55, 4.625, 4.7, 4.775, 4.85, 4.925, 5, 5.075, 5.15, 5.225, 5.3, 5.38, 5.46, 5.54, 5.63, 5.7, 5.8, 5.89, 5.98, 6.07 ], "y": [ 0, 0.01, 0.02, 0.03, 0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1, 0.11, 0.12, 0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2, 0.21, 0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3, 0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4, 0.41, 0.42, 0.43, 0.44, 0.45, 0.46, 0.47, 0.48, 0.49, 0.5, 0.51, 0.52, 0.53, 0.54, 0.55, 0.56, 0.57, 0.58, 0.59, 0.6, 0.61, 0.62, 0.63, 0.64, 0.65, 0.66, 0.67, 0.68, 0.69, 0.7, 0.71, 0.72, 0.73, 0.74, 0.75, 0.76, 0.77, 0.78, 0.79, 0.8, 0.81, 0.82, 0.83, 0.84, 0.85, 0.86, 0.87, 0.88, 0.89, 0.9, 0.91, 0.92, 0.93, 0.94, 0.95, 0.96, 0.97, 0.98, 0.99, 1, 1.01, 1.02, 1.03, 1.04, 1.05, 1.06, 1.07, 1.08, 1.09, 1.1, 1.11, 1.12, 1.13, 1.14, 1.15, 1.16, 1.17, 1.18, 1.19, 1.2, 1.21, 1.22, 1.23, 1.24, 1.25, 1.26, 1.27, 1.28, 1.29, 1.3, 1.31, 1.32, 1.33, 1.34, 1.35, 1.36, 1.37, 1.38, 1.39, 1.4, 1.41, 1.42, 1.43, 1.44, 1.45, 1.46, 1.47, 1.48, 1.49, 1.5, 1.51, 1.52, 1.53, 1.54, 1.55, 1.56, 1.57, 1.58, 1.59, 1.6, 1.61, 1.62, 1.63, 1.64, 1.65, 1.66, 1.67, 1.68, 1.69, 1.7 ] } ], "layout": { "template": { "data": { "bar": [ { "error_x": { "color": "#2a3f5f" }, "error_y": { "color": "#2a3f5f" }, "marker": { "line": { "color": "#E5ECF6", "width": 0.5 } }, "type": "bar" } ], "barpolar": [ { "marker": { "line": { "color": "#E5ECF6", "width": 0.5 } }, "type": "barpolar" } ], "carpet": [ { "aaxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "baxis": { "endlinecolor": "#2a3f5f", "gridcolor": "white", "linecolor": "white", "minorgridcolor": "white", "startlinecolor": "#2a3f5f" }, "type": "carpet" } ], "choropleth": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "choropleth" } ], "contour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "contour" } ], "contourcarpet": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "contourcarpet" } ], "heatmap": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmap" } ], "heatmapgl": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "heatmapgl" } ], "histogram": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "histogram" } ], "histogram2d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2d" } ], "histogram2dcontour": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "histogram2dcontour" } ], "mesh3d": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "type": "mesh3d" } ], "parcoords": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "parcoords" } ], "pie": [ { "automargin": true, "type": "pie" } ], "scatter": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter" } ], "scatter3d": [ { "line": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatter3d" } ], "scattercarpet": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattercarpet" } ], "scattergeo": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergeo" } ], "scattergl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattergl" } ], "scattermapbox": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scattermapbox" } ], "scatterpolar": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolar" } ], "scatterpolargl": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterpolargl" } ], "scatterternary": [ { "marker": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "type": "scatterternary" } ], "surface": [ { "colorbar": { "outlinewidth": 0, "ticks": "" }, "colorscale": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "type": "surface" } ], "table": [ { "cells": { "fill": { "color": "#EBF0F8" }, "line": { "color": "white" } }, "header": { "fill": { "color": "#C8D4E3" }, "line": { "color": "white" } }, "type": "table" } ] }, "layout": { "annotationdefaults": { "arrowcolor": "#2a3f5f", "arrowhead": 0, "arrowwidth": 1 }, "coloraxis": { "colorbar": { "outlinewidth": 0, "ticks": "" } }, "colorscale": { "diverging": [ [ 0, "#8e0152" ], [ 0.1, "#c51b7d" ], [ 0.2, "#de77ae" ], [ 0.3, "#f1b6da" ], [ 0.4, "#fde0ef" ], [ 0.5, "#f7f7f7" ], [ 0.6, "#e6f5d0" ], [ 0.7, "#b8e186" ], [ 0.8, "#7fbc41" ], [ 0.9, "#4d9221" ], [ 1, "#276419" ] ], "sequential": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ], "sequentialminus": [ [ 0, "#0d0887" ], [ 0.1111111111111111, "#46039f" ], [ 0.2222222222222222, "#7201a8" ], [ 0.3333333333333333, "#9c179e" ], [ 0.4444444444444444, "#bd3786" ], [ 0.5555555555555556, "#d8576b" ], [ 0.6666666666666666, "#ed7953" ], [ 0.7777777777777778, "#fb9f3a" ], [ 0.8888888888888888, "#fdca26" ], [ 1, "#f0f921" ] ] }, "colorway": [ "#636efa", "#EF553B", "#00cc96", "#ab63fa", "#FFA15A", "#19d3f3", "#FF6692", "#B6E880", "#FF97FF", "#FECB52" ], "font": { "color": "#2a3f5f" }, "geo": { "bgcolor": "white", "lakecolor": "white", "landcolor": "#E5ECF6", "showlakes": true, "showland": true, "subunitcolor": "white" }, "hoverlabel": { "align": "left" }, "hovermode": "closest", "mapbox": { "style": "light" }, "paper_bgcolor": "white", "plot_bgcolor": "#E5ECF6", "polar": { "angularaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "radialaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "scene": { "xaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "yaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" }, "zaxis": { "backgroundcolor": "#E5ECF6", "gridcolor": "white", "gridwidth": 2, "linecolor": "white", "showbackground": true, "ticks": "", "zerolinecolor": "white" } }, "shapedefaults": { "line": { "color": "#2a3f5f" } }, "ternary": { "aaxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "baxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" }, "bgcolor": "#E5ECF6", "caxis": { "gridcolor": "white", "linecolor": "white", "ticks": "" } }, "title": { "x": 0.05 }, "xaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 }, "yaxis": { "automargin": true, "gridcolor": "white", "linecolor": "white", "ticks": "", "title": { "standoff": 15 }, "zerolinecolor": "white", "zerolinewidth": 2 } } }, "title": { "text": "Optical Density vs. Cell Density" }, "xaxis": { "title": { "text": "$\\text{cells per ml (}\\times 10^7{)}$" } }, "yaxis": { "title": { "text": "$\\text{OD}_{660}$" } } } }, "text/html": [ "
\n", " \n", " \n", "
\n", " \n", "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import plotly.graph_objects as go\n", "import pandas as pd\n", "\n", "# code for this originally documented at https://gist.github.com/fomightez/7f445311a78484c83c3210cbd5540192\n", "# but now added in as Plotly version with non-server mode now allows LaTeX in the \n", "# axis labels and now works without credentials being needed in the set-up steps\n", "\n", "od660_values_list, cells_per_ml_values_list = unzip(yeast_cell_density_by_OD660_tuples)\n", "cells_per_ml_values_list = [(x/1.0e7) for x in cells_per_ml_values_list] # trying to get them in scale, see http://stackoverflow.com/questions/32542957/control-tick-labels-in-python-seaborn-package\n", "data_dict = {'od':od660_values_list, 'cells_per_ml':cells_per_ml_values_list} # see http://www.gregreda.com/2013/10/26/intro-to-pandas-data-structures/\n", "data_df = pd.DataFrame(data_dict,columns=['od','cells_per_ml']) # see http://www.gregreda.com/2013/10/26/intro-to-pandas-data-structures/\n", "\n", "data = [\n", " go.Scatter(\n", " x=data_df['cells_per_ml'], # assign x as the dataframe column 'x'\n", " y=data_df['od']\n", " )\n", "]\n", "\n", "layout = go.Layout(\n", "title='Optical Density vs. Cell Density',\n", "xaxis=dict(\n", " title='$\\\\text{cells per ml (}\\\\times 10^7{)}$' #latex help from https://plot.ly/python/LaTeX/\n", " ),\n", "yaxis=dict(\n", " title='$\\\\text{OD}_{660}$'\n", " )\n", ")\n", "\n", "# IPython notebook\n", "fig=go.Figure(data=data,layout=layout)\n", "fig.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The standard curve above is interactive; hover over the curve to easily read values for both variables any where along the curve.\n", "\n", "The plot above uses Plotly was has a rich feature set with nice aesthetics by default. Plus, if you go to view this notebook statically at nbviewer, the Plotly plot above is still displayed.\n", "\n", "Below the same data is plotted with Bokeh which has nice feature in that you can add a hover tool to make the report you get when you hove over the line more informative. The drawback is that at the time I was writing this it didn't handle nice formatting of the axis labels, specifically [LaTeX](https://github.com/bokeh/bokeh/issues/6031). Additionally, the Bokeh plot seen below won't render in the static form of this notebook on nbviewer. (<-- Also, need to check if now any hover tool in Plotly now.)" ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "
\n", " \n", " Loading BokehJS ...\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " var force = true;\n", "\n", " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", " root._bokeh_onload_callbacks = [];\n", " root._bokeh_is_loading = undefined;\n", " }\n", "\n", " var JS_MIME_TYPE = 'application/javascript';\n", " var HTML_MIME_TYPE = 'text/html';\n", " var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", " var CLASS_NAME = 'output_bokeh rendered_html';\n", "\n", " /**\n", " * Render data to the DOM node\n", " */\n", " function render(props, node) {\n", " var script = document.createElement(\"script\");\n", " node.appendChild(script);\n", " }\n", "\n", " /**\n", " * Handle when an output is cleared or removed\n", " */\n", " function handleClearOutput(event, handle) {\n", " var cell = handle.cell;\n", "\n", " var id = cell.output_area._bokeh_element_id;\n", " var server_id = cell.output_area._bokeh_server_id;\n", " // Clean up Bokeh references\n", " if (id != null && id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", "\n", " if (server_id !== undefined) {\n", " // Clean up Bokeh references\n", " var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", " cell.notebook.kernel.execute(cmd, {\n", " iopub: {\n", " output: function(msg) {\n", " var id = msg.content.text.trim();\n", " if (id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", " }\n", " }\n", " });\n", " // Destroy server and session\n", " var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", " cell.notebook.kernel.execute(cmd);\n", " }\n", " }\n", "\n", " /**\n", " * Handle when a new output is added\n", " */\n", " function handleAddOutput(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", "\n", " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", " if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", "\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", "\n", " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n", " // store reference to embed id on output_area\n", " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " }\n", " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", " }\n", "\n", " function register_renderer(events, OutputArea) {\n", "\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[toinsert.length - 1]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " /* Handle when an output is cleared or removed */\n", " events.on('clear_output.CodeCell', handleClearOutput);\n", " events.on('delete.Cell', handleClearOutput);\n", "\n", " /* Handle when a new output is added */\n", " events.on('output_added.OutputArea', handleAddOutput);\n", "\n", " /**\n", " * Register the mime type and append_mime function with output_area\n", " */\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " /* Is output safe? */\n", " safe: true,\n", " /* Index of renderer in `output_area.display_order` */\n", " index: 0\n", " });\n", " }\n", "\n", " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", " if (root.Jupyter !== undefined) {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", "\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " }\n", "\n", " \n", " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " var NB_LOAD_WARNING = {'data': {'text/html':\n", " \"
\\n\"+\n", " \"

\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"

\\n\"+\n", " \"\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded() {\n", " var el = document.getElementById(\"1001\");\n", " if (el != null) {\n", " el.textContent = \"BokehJS is loading...\";\n", " }\n", " if (root.Bokeh !== undefined) {\n", " if (el != null) {\n", " el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(display_loaded, 100)\n", " }\n", " }\n", "\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", "\n", " function on_error() {\n", " console.error(\"failed to load \" + url);\n", " }\n", "\n", " for (var i = 0; i < css_urls.length; i++) {\n", " var url = css_urls[i];\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " }\n", "\n", " for (var i = 0; i < js_urls.length; i++) {\n", " var url = js_urls[i];\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " };var element = document.getElementById(\"1001\");\n", " if (element == null) {\n", " console.error(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n", " return false;\n", " }\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " \n", " var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.4.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.4.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.4.0.min.js\"];\n", " var css_urls = [];\n", " \n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " function(Bokeh) {\n", " \n", " \n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " \n", " if (root.Bokeh !== undefined || force === true) {\n", " \n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }\n", " if (force === true) {\n", " display_loaded();\n", " }} else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " } else if (force !== true) {\n", " var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n", " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", " }\n", "\n", " }\n", "\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(css_urls, js_urls, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(window));" ], "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n var el = document.getElementById(\"1001\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };var element = document.getElementById(\"1001\");\n if (element == null) {\n console.error(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n return false;\n }\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n \n var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.4.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.4.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.4.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.4.0.min.js\"];\n var css_urls = [];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function embed_document(root) {\n", " \n", " var docs_json = {\"d92349ed-8d5a-4579-a7ca-0f8c920c4b32\":{\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1014\",\"type\":\"LinearAxis\"}],\"center\":[{\"id\":\"1018\",\"type\":\"Grid\"},{\"id\":\"1023\",\"type\":\"Grid\"}],\"left\":[{\"id\":\"1019\",\"type\":\"LinearAxis\"}],\"renderers\":[{\"id\":\"1029\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"1004\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"1024\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"1006\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"1010\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"1008\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"1012\",\"type\":\"LinearScale\"}},\"id\":\"1003\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"text\":\"Optical Density vs. Cell Density\"},\"id\":\"1004\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1015\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"1036\",\"type\":\"Selection\"},{\"attributes\":{\"line_color\":\"#1f77b4\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1027\",\"type\":\"Line\"},{\"attributes\":{\"callback\":null},\"id\":\"1006\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1037\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"dimension\":1,\"ticker\":{\"id\":\"1020\",\"type\":\"BasicTicker\"}},\"id\":\"1023\",\"type\":\"Grid\"},{\"attributes\":{\"ticker\":{\"id\":\"1015\",\"type\":\"BasicTicker\"}},\"id\":\"1018\",\"type\":\"Grid\"},{\"attributes\":{\"callback\":null},\"id\":\"1008\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1020\",\"type\":\"BasicTicker\"},{\"attributes\":{\"axis_label\":\"OD_660\",\"formatter\":{\"id\":\"1032\",\"type\":\"BasicTickFormatter\"},\"ticker\":{\"id\":\"1020\",\"type\":\"BasicTicker\"}},\"id\":\"1019\",\"type\":\"LinearAxis\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1002\",\"type\":\"HoverTool\"}]},\"id\":\"1024\",\"type\":\"Toolbar\"},{\"attributes\":{\"callback\":null,\"data\":{\"x\":{\"__ndarray__\":\"AAAAAAAAAAC4HoXrUbiOP5qZmZmZmZk/exSuR+F6pD+JQWDl0CKrP6RwPQrXo7A/K4cW2c73sz8K16NwPQq3P5HtfD81Xro/cT0K16NwvT/8qfHSTWLAP+xRuB6F68E/L90kBoGVwz8fhetRuB7FP2IQWDm0yMY/UrgehetRyD/pJjEIrBzKP9nO91Pjpcs/HVpkO99PzT8MAiuHFtnOP1K4HoXrUdA/9P3UeOkm0T/sUbgehevRP42XbhKDwNI/hetRuB6F0z/RItv5fmrUPx+F61G4HtU/F9nO91Pj1T9iEFg5tMjWP65H4XoUrtc/pHA9Ctej2D/wp8ZLN4nZP5HtfD81Xto/3SQGgZVD2z8pXI/C9SjcPx+F61G4Ht0/FK5H4XoU3j9g5dAi2/neP1YOLbKd798/ppvEILBy4D/2KFyPwvXgPxsv3SQGgeE/PzVeukkM4j+PwvUoXI/iPzMzMzMzM+M/WDm0yHa+4z+oxks3iUHkP83MzMzMzOQ/HVpkO99P5T9CYOXQItvlP2ZmZmZmZuY/i2zn+6nx5j/b+X5qvHTnPwAAAAAAAOg/UI2XbhKD6D91kxgEVg7pP5qZmZmZmek/vp8aL90k6j8OLbKd76fqPzMzMzMzM+s/g8DKoUW26z+oxks3iUHsP83MzMzMzOw/8tJNYhBY7T9CYOXQItvtP2ZmZmZmZu4/tvP91Hjp7j/b+X5qvHTvPwAAAAAAAPA/ke18PzVe8D8j2/l+arzwPx+F61G4HvE/sHJoke188T9CYOXQItvxPz0K16NwPfI/j8L1KFyP8j/hehSuR+HyPzMzMzMzM/M/hetRuB6F8z/Xo3A9CtfzPylcj8L1KPQ/ukkMAiuH9D9MN4lBYOX0P0jhehSuR/U/2c73U+Ol9T9qvHSTGAT2P2ZmZmZmZvY/4XoUrkfh9j9cj8L1KFz3P9ejcD0K1/c/UrgehetR+D/NzMzMzMz4P0jhehSuR/k/w/UoXI/C+T89CtejcD36P7gehetRuPo/c2iR7Xw/+z8tsp3vp8b7P1K4HoXrUfw/9ihcj8L1/D+amZmZmZn9Pz0K16NwPf4/N4lBYOXQ/j+cxCCwcmj/PwAAAAAAAABAUrgehetRAECkcD0K16MAQPYoXI/C9QBA5/up8dJNAUDZzvdT46UBQAAAAAAAAAJAke18PzVeAkBYObTIdr4CQB+F61G4HgNAEFg5tMh2A0ACK4cW2c4DQClcj8L1KARAukkMAiuHBECBlUOLbOcEQEjhehSuRwVA2c73U+OlBUCgGi/dJAYGQGZmZmZmZgZAzczMzMzMBkAzMzMzMzMHQJqZmZmZmQdAarx0kxgECEBxPQrXo3AIQEJg5dAi2whASOF6FK5HCUDD9Shcj8IJQD0K16NwPQpAuB6F61G4CkAzMzMzMzMLQK5H4XoUrgtAKVyPwvUoDECkcD0K16MMQB+F61G4Hg1AmpmZmZmZDUAUrkfhehQOQI/C9Shcjw5ACtejcD0KD0CF61G4HoUPQAAAAAAAABBAw/UoXI9CEECF61G4HoUQQM3MzMzMzBBAFK5H4XoUEUBcj8L1KFwRQKRwPQrXoxFA7FG4HoXrEUAzMzMzMzMSQAAAAAAAgBJAzczMzMzMEkCamZmZmRkTQGZmZmZmZhNAMzMzMzOzE0AAAAAAAAAUQM3MzMzMTBRAmpmZmZmZFEBmZmZmZuYUQDMzMzMzMxVAhetRuB6FFUDXo3A9CtcVQClcj8L1KBZAhetRuB6FFkDNzMzMzMwWQDMzMzMzMxdAj8L1KFyPF0DsUbgehesXQEjhehSuRxhA\",\"dtype\":\"float64\",\"shape\":[171]},\"y\":{\"__ndarray__\":\"AAAAAAAAAAB7FK5H4XqEP3sUrkfhepQ/uB6F61G4nj97FK5H4XqkP5qZmZmZmak/uB6F61G4rj/sUbgeheuxP3sUrkfherQ/CtejcD0Ktz+amZmZmZm5Pylcj8L1KLw/uB6F61G4vj+kcD0K16PAP+xRuB6F68E/MzMzMzMzwz97FK5H4XrEP8P1KFyPwsU/CtejcD0Kxz9SuB6F61HIP5qZmZmZmck/4XoUrkfhyj8pXI/C9SjMP3E9CtejcM0/uB6F61G4zj8AAAAAAADQP6RwPQrXo9A/SOF6FK5H0T/sUbgehevRP4/C9Shcj9I/MzMzMzMz0z/Xo3A9CtfTP3sUrkfhetQ/H4XrUbge1T/D9Shcj8LVP2ZmZmZmZtY/CtejcD0K1z+uR+F6FK7XP1K4HoXrUdg/9ihcj8L12D+amZmZmZnZPz0K16NwPdo/4XoUrkfh2j+F61G4HoXbPylcj8L1KNw/zczMzMzM3D9xPQrXo3DdPxSuR+F6FN4/uB6F61G43j9cj8L1KFzfPwAAAAAAAOA/UrgehetR4D+kcD0K16PgP/YoXI/C9eA/SOF6FK5H4T+amZmZmZnhP+xRuB6F6+E/PQrXo3A94j+PwvUoXI/iP+F6FK5H4eI/MzMzMzMz4z+F61G4HoXjP9ejcD0K1+M/KVyPwvUo5D97FK5H4XrkP83MzMzMzOQ/H4XrUbge5T9xPQrXo3DlP8P1KFyPwuU/FK5H4XoU5j9mZmZmZmbmP7gehetRuOY/CtejcD0K5z9cj8L1KFznP65H4XoUruc/AAAAAAAA6D9SuB6F61HoP6RwPQrXo+g/9ihcj8L16D9I4XoUrkfpP5qZmZmZmek/7FG4HoXr6T89CtejcD3qP4/C9Shcj+o/4XoUrkfh6j8zMzMzMzPrP4XrUbgehes/16NwPQrX6z8pXI/C9SjsP3sUrkfheuw/zczMzMzM7D8fhetRuB7tP3E9CtejcO0/w/UoXI/C7T8UrkfhehTuP2ZmZmZmZu4/uB6F61G47j8K16NwPQrvP1yPwvUoXO8/rkfhehSu7z8AAAAAAADwPylcj8L1KPA/UrgehetR8D97FK5H4XrwP6RwPQrXo/A/zczMzMzM8D/2KFyPwvXwPx+F61G4HvE/SOF6FK5H8T9xPQrXo3DxP5qZmZmZmfE/w/UoXI/C8T/sUbgehevxPxSuR+F6FPI/PQrXo3A98j9mZmZmZmbyP4/C9Shcj/I/uB6F61G48j/hehSuR+HyPwrXo3A9CvM/MzMzMzMz8z9cj8L1KFzzP4XrUbgehfM/rkfhehSu8z/Xo3A9CtfzPwAAAAAAAPQ/KVyPwvUo9D9SuB6F61H0P3sUrkfhevQ/pHA9Ctej9D/NzMzMzMz0P/YoXI/C9fQ/H4XrUbge9T9I4XoUrkf1P3E9CtejcPU/mpmZmZmZ9T/D9Shcj8L1P+xRuB6F6/U/FK5H4XoU9j89CtejcD32P2ZmZmZmZvY/j8L1KFyP9j+4HoXrUbj2P+F6FK5H4fY/CtejcD0K9z8zMzMzMzP3P1yPwvUoXPc/hetRuB6F9z+uR+F6FK73P9ejcD0K1/c/AAAAAAAA+D8pXI/C9Sj4P1K4HoXrUfg/exSuR+F6+D+kcD0K16P4P83MzMzMzPg/9ihcj8L1+D8fhetRuB75P0jhehSuR/k/cT0K16Nw+T+amZmZmZn5P8P1KFyPwvk/7FG4HoXr+T8UrkfhehT6Pz0K16NwPfo/ZmZmZmZm+j+PwvUoXI/6P7gehetRuPo/4XoUrkfh+j8K16NwPQr7PzMzMzMzM/s/\",\"dtype\":\"float64\",\"shape\":[171]}},\"selected\":{\"id\":\"1036\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"1037\",\"type\":\"UnionRenderers\"}},\"id\":\"1026\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"callback\":null,\"tooltips\":[[\"OD, cells/ml\",\"$y, $x\"]]},\"id\":\"1002\",\"type\":\"HoverTool\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1028\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1012\",\"type\":\"LinearScale\"},{\"attributes\":{\"data_source\":{\"id\":\"1026\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"1027\",\"type\":\"Line\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1028\",\"type\":\"Line\"},\"selection_glyph\":null,\"view\":{\"id\":\"1030\",\"type\":\"CDSView\"}},\"id\":\"1029\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1034\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1010\",\"type\":\"LinearScale\"},{\"attributes\":{\"source\":{\"id\":\"1026\",\"type\":\"ColumnDataSource\"}},\"id\":\"1030\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1032\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"axis_label\":\"cells per ml (x 10^7)\",\"formatter\":{\"id\":\"1034\",\"type\":\"BasicTickFormatter\"},\"ticker\":{\"id\":\"1015\",\"type\":\"BasicTicker\"}},\"id\":\"1014\",\"type\":\"LinearAxis\"}],\"root_ids\":[\"1003\"]},\"title\":\"Bokeh Application\",\"version\":\"1.4.0\"}};\n", " var render_items = [{\"docid\":\"d92349ed-8d5a-4579-a7ca-0f8c920c4b32\",\"roots\":{\"1003\":\"03757900-57bb-46ae-beba-dc34136bf357\"}}];\n", " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", "\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " var attempts = 0;\n", " var timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " clearInterval(timer);\n", " embed_document(root);\n", " } else {\n", " attempts++;\n", " if (attempts > 100) {\n", " clearInterval(timer);\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " }\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "1003" } }, "output_type": "display_data" } ], "source": [ "import bokeh\n", "from bokeh.plotting import figure, output_file, show, ColumnDataSource\n", "from bokeh.io import output_notebook, show\n", "output_notebook() # tells Bokeh to plot inline in the Jupyter notebook\n", "from bokeh.models import HoverTool\n", "\n", "import pandas as pd\n", "od660_values_list, cells_per_ml_values_list = unzip(yeast_cell_density_by_OD660_tuples)\n", "cells_per_ml_values_list = [(x/1.0e7) for x in cells_per_ml_values_list] # trying to get them in scale, see http://stackoverflow.com/questions/32542957/control-tick-labels-in-python-seaborn-package\n", "data_dict = {'od':od660_values_list, 'cells_per_ml':cells_per_ml_values_list} # see http://www.gregreda.com/2013/10/26/intro-to-pandas-data-structures/data_dict = {'od':od660_values_list, 'cells_per_ml':cells_per_ml_values_list} # see http://www.gregreda.com/2013/10/26/intro-to-pandas-data-structures/\n", "data_df = pd.DataFrame(data_dict,columns=['od','cells_per_ml']) # see http://www.gregreda.com/2013/10/26/intro-to-pandas-data-structures/\n", "\n", "hover = HoverTool(\n", " tooltips=[\n", " (\"OD, cells/ml\", \"$y, $x\"),\n", " ]\n", " )\n", "\n", "# plot = figure(tools=[hover], title=\"Optical Density vs. Cell Density\", x_axis_label=\"cells per ml ($\\\\times 10^7$)\", y_axis_label=\"OD$_{660}$\")\n", "# Seems still working on latex support in Bokeh, and so for now:\n", "plot = figure(tools=[hover], title=\"Optical Density vs. Cell Density\", x_axis_label=\"cells per ml (x 10^7)\", y_axis_label=\"OD_660\")\n", "#plot.xaxis.axis_label_text_font_size = \"40pt\" #just an example of how size can be controlled\n", "\n", "\n", "#plot.scatter(data_df['cells_per_ml'],data_df['od'],fill_color=None, fill_alpha=0.6,line_color=None) # Causes hover issues it seems in crowded areas, if leave both.\n", "plot.line(data_df['cells_per_ml'],data_df['od'], line_width = 3)\n", "\n", "show(plot); # for the semi-colon at end, see https://groups.google.com/forum/#!msg/jupyter/SMBUkOWPetA/nIVztypABQAJ and http://stackoverflow.com/questions/14506583/suppress-output-of-object-when-plotting-in-ipython" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "# Performing the actual calculations\n", "cells_per_ml, factor_error_detected = cells_per_ml_calc (absorbance, dilution_factor)\n", "# TO DO: ADD HANDLING OF ERROR\n", "\n", "# adjust if diploid --> \" Cell densities for diploids are half those for\n", "# halploids as diploids and some mutants which are abnormally large will\n", "# scatter more light than the wildtype haploids at the same cell density.\"\n", "if haploid == False:\n", " cells_per_ml = cells_per_ml/2\n", "\n", "volume_to_inoculate_for_transformation = transformation_inoculation_volume_calc (cells_per_ml)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Formatting of the output:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### IF YOU JUST WANT THE RESULT BASED ON WHAT YOU ENTERED ABOVE, SKIP TO BOTTOM OF THIS NOTEBOOK." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### (The first part is just more behind the scenes stuff.)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "33579999.99999999" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cells_per_ml" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Better formatting based on [here](http://stackoverflow.com/questions/27883510/convert-to-scientific-notation-python-2-7) and [here](http://stackoverflow.com/questions/6913532/display-a-decimal-in-scientific-notation) is below" ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "cells_per_ml_formatted = \"{:.2E}\".format(cells_per_ml)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "data": { "text/plain": [ "'3.36E+07'" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "cells_per_ml_formatted" ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.36E+07\n" ] } ], "source": [ "print (cells_per_ml_formatted)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "(I don't know why print command and just calling variable give different results, i.e., one has the single-quotes and the one involving `print` doesn't. I guess it is because one is a string and the other is printed string?)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "3.36E+07\n" ] } ], "source": [ "print (\"{:.2E}\".format(cells_per_ml))" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "# adjust if diploid\n", "if haploid == False:\n", " print (\"You indicated your strain is a diploid.\")" ] }, { "cell_type": "code", "execution_count": 15, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "The sample density is 3.36E+07 yeast cells per ml.\n" ] } ], "source": [ "print (\"The sample density is \"+ \"{:.2E}\".format(cells_per_ml) +\" yeast cells per ml.\")" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "If using this sample for inoculating a 50 mL culture for growing to density 2.0E+07 cells per mL for use in a transformation, use 7.4 mL of the culture with 42.6 mL YPD media.\n" ] } ], "source": [ "# Formatting output of transformation advice\n", "# Formatting correct decimal place for Python 2.7 based on Daren Thomas's answer\n", "# http://stackoverflow.com/questions/6149006/display-a-float-with-two-decimal-places-in-python\n", "print (\"If using this sample for inoculating a 50 mL culture for growing to density 2.0E+07 cells per mL for use in a transformation, use \" + \"{:.1f}\".format(\n", " volume_to_inoculate_for_transformation) + \" mL of the culture with \" + \"{:.1f}\".format(\n", " 50.0 - volume_to_inoculate_for_transformation ) + \" mL YPD media.\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "-------" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.6" }, "widgets": { "state": {}, "version": "1.1.2" } }, "nbformat": 4, "nbformat_minor": 4 }