<jupyter_start><jupyter_text>Introduction to using Python for Biochem 6765 - SP21; Foster_2021-01-04 MPF_This Jupyter notebook is intended to serve as a tutorial guide for introducing students to data plotting and fitting in Python. It is by no means a complete description of capabilities or possibilities for data analysis in Python, but hopefully provides some useful guides and examples. Although you may wish to install JupyterLab on your computer (See [jupyter.org](https://jupyter.org/)), for starters you can create your first Jupyter notebooks using [Google Colab](https://colab.research.google.com/); this does require that you have a GMail. Your work will be automatically saved to your Google Drive space.  If you are viewing this document on the [GitHub page](https://github.com/mpfoster/Biochem6765/blob/master/Intro_plotting_python_6765_SP21.ipynb), you should be able to open the notebook in Colab by simply clicking on the Open in Colab link at the top of the page. Alternatively, you can download the jupyter notebook, with the `.ipynb` extension (click on `Raw`, then _File-save_), then drag-drop into the file browser of a running Jupyter server.Jupyter notebooks have three components: (1) Markdown Text cells, (2) Code cells, and (3) Output cells. We can enter styled text in the Markdown cells, Python code in the code cells, and the result of executing the code is shown in the output cells. Students should use the code cells as a guide, and feel free to edit them and/or copy-paste into their own notebooks. The effect of editing the code can be seen by re-running the selected cell. Note that some cells will depend on execution of other cells, in which case the have to be executed in the right order. For best use of the tutorial, if you are going to made edits to this Notebook, it is helpful to clear the output fields when starting so that you can progress through it sequentially. This can be done at any time in Colab, via Tools > Command Palette > Clear all outputs.---  MarkdownThis is a Markdown cell in a [Jupyter](https://jupyterlab.readthedocs.io/) notebook. [Markdown](https://guides.github.com/features/mastering-markdown/) is an easy-to-type formatting language that is interpreted into HTML to generate nice formatting withought having to learn and type html code: like `for italics`.We can easliy format headings like this:``` This is a heading This is a subheading``` This is a heading This is a subheadingText can be **bold**, __bolded__, *italics*, _italicized_, and formatted to look like `code`, rendered as a $\frac{Latex}{equation}$, as well as other options.Check out the [markdown cheat-sheet](https://www.markdownguide.org/cheat-sheet) for formatting tips.  Code CellsWe can perform mathematical operations using the Python language in "code" cells. Code cells can have commands to be interpreted by the Python engine, or comments (commenting code is very good practice!). Coments begin with "", or are breacketed by triple quotes.<jupyter_code># This is a comment in code cell; it's preceded by "#"
'''
This is also a comment; note the triple quotes
Code cells can be *run* by typing Ctrl/Cmd-Enter, or by clicking on the 
"Play" icon in the top-left corner
The following, is a mathematical operation that results in a simple output upon
executing the code by running the cell.
'''
5+3<jupyter_output><empty_output><jupyter_text>In Python, we can declare and assign values to them as we need them:<jupyter_code>a = 5+3   # this assigns to the variable a, the sum of 5 and 3
a # a variable by itself as the last line of a code cell prints its value:<jupyter_output><empty_output><jupyter_text>Then perform operations with the declared variable:<jupyter_code>a**2  # this how we raise a number to an exponent in Python<jupyter_output><empty_output><jupyter_text>Some operations you might want to perform are not included in "standard" python, but can be _imported_ from add-on _packages_, or code _libraries_. For example, we could take the square root by raising $a$ to the 1/2 power: `a**0.5`<jupyter_code>a**0.5<jupyter_output><empty_output><jupyter_text>Or, by calling a function that someone else has written, called `sqrt`. We will gain access to this function by importing it from a library. We call the function by name, and provide the function with the necessary input in parentheses:<jupyter_code>from numpy import sqrt
sqrt(a)<jupyter_output><empty_output><jupyter_text>We can also import an entire library, a couple of different ways: (1) `from numpy import *` will import all code in the library and be directly callable; or, (2) `import numpy` or `import numpy as np`, will import the library, but accessing the functions requires the use of a prefix, in the second case `np`. The advantage of the second option is that we might inadvertently import from two libraries, functions that have the same name.<jupyter_code>import numpy as np
np.sqrt(a)<jupyter_output><empty_output><jupyter_text>Formatted printing Taking `sqrt(8)` generates a value with a lot of decimal places! Let's say we only care about the first two (hundred's) we can format the output using a formatted print statement:<jupyter_code># formatted printing
print("The square root of %.f is: %5.2f" % (a,sqrt(a)))<jupyter_output>The square root of 8 is:  2.83<jupyter_text>In the formatted print statement the two instances of `%` indicate we are expecting two variables, which are passed as a list `% (a, sqrt(a))`. The text `%5.2f` says to represent a number as a floating point decimal with 5 characters, including the point and two digits to the right of the decimal; rounding happens after the 2nd decimal.<jupyter_code># C-like formatting statements:
print("The volume of a sphere with a radius r = %d is 4/3πr^3 = %5.2f" % (a, 4*np.pi*a**3/3))<jupyter_output>The volume of a sphere with a radius r = 8 is 4/3πr^3 = 2144.66<jupyter_text>There's a second ("Pythonic") way to format printed text; use whichever form is easiest for you:<jupyter_code># Python way of formatting text:
print("The volume of a sphere with a radius r = {0:d} is 4/3πr^3 = {1:5.2f}".format(a, 4*np.pi*a**3/3))<jupyter_output>The volume of a sphere with a radius r = 8 is 4/3πr^3 = 2144.66<jupyter_text>Lists and ArraysIn Python, list elements are indexed from 0, not 1. So the third element of a list would be 2, and we access it using the list name and square brackets: `name[i]`<jupyter_code>my_list = 'first', 'second', 'third', 'fourth'
my_list[2]<jupyter_output><empty_output><jupyter_text>Plotting a function using Numpy and MatplotlibSeveral plotting and graphics libraries are available in Python, but [Matplotlib](https://matplotlib.org/) is powerful and the most common.<jupyter_code>import matplotlib.pyplot as plt
import numpy as np<jupyter_output><empty_output><jupyter_text>We can plot a function by generating synthetic $x$ values and computing corresponding $y$ values. Numpy's `linspace` [(docs)](https://numpy.org/doc/stable/reference/generated/numpy.linspace.html) will generate (by default 50) evenly spaced values between the two indicated bounds, inclusive).<jupyter_code>x = np.linspace(0,2) # generates an array of x values between 0 and 2pi
plt.plot(x,np.cos(x*np.pi), label='$cos(\Theta)$') 
plt.plot(x,np.sin(x*np.pi),'.-.', label='$sin(\Theta)$')
phi = 0.3 # phase shift in pi radians
A = 1 # amplitude
freq = 1 # frequency multiple
y = A*np.sin(freq*x*np.pi + phi*np.pi)
plt.plot(x,y,'-.', label='%.g$sin(%g\Theta+$%.g)' % (A,freq,phi))
plt.xlabel('$\pi$ radians')
plt.grid(); plt.legend(); plt.show()<jupyter_output><empty_output><jupyter_text>Try changing the values `phi`, `A` and `freq` in the code cell above (and re-running) to see the effect on the third curve.  Simple plotting and fitting with Python, using matplotlib and pandasWe will start with a cooperative isotherm of oxygen binding to hemoglobin. The data as follows, in which the first column is oxygen partial pressure (in mmHg), and the second is fractional saturation:|$P(O_2)$ | Y || --- | --- ||0.499	|0.000||1.341	|0.015||2.106	|0.030||5.345	|0.146||7.934	|0.316||11.132	|0.505||14.761	|0.644||18.499	|0.760||25.233	|0.919||64.028	|0.995|We plot the data using `matplotlib` https://matplotlib.org/ (a library with functionality similar to that of MATLAB), we define _x_ and _y_ data. This can be done manually, as ...<jupyter_code># the x and y data: 
x = [0.499,  1.341,  2.106,  5.345,  7.934,  11.132,  14.761,  18.499, 
     25.233, 64.028]
y = [0.0, 0.015, 0.03, 0.146, 0.316, 0.505, 0.644, 0.76, 0.919, 0.995]
plt.plot(x,y, 'bo--') # 'bo--' means *b*lue 'o's and dashes
plt.xlabel('Oxygen Pressure (mm)'); plt.ylabel('Saturation')
plt.grid(); plt.show()<jupyter_output><empty_output><jupyter_text>Loading tabular data with PandasAbove, we specified the _x_ and _y_ data as two lists. Usually, our data is tabulated in some file which we could read in to Python, instead of entering the list of values. We can most easily read in the data using the [Pandas package](https://pandas.pydata.org/). Pandas simplifies loading tabular data into a "data frame"; basically a table with rows and columns. For this example, the data are available on the web as a space-separated text file, at [this link]( https://github.com/mpfoster/Biochem6765/blob/master/data/hb+o2.txt). The first line of the file is a comment, so we need to tell pandas to ignore lines that start with `comment=''`, that the separator between fields is blank space `sep='\s+'`, and that the file does not have a reader row with properly formatted column names, `header=None`.(In addition to space, or tab-delimited files, pandas has utilites for reading `.csv` files (comma-separated-values; probably the most common), and can diretly read data from _Excel_ spreadsheets, or even on-line Google spreadsheets. See [here](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_table.html))<jupyter_code># use pandas to load the data from a url
import pandas as pd
df = pd.read_table(
    "https://www.asc.ohio-state.edu/foster.281/gnuplot/gnuplot_tutorial1_files/hb+o2.txt",
    sep='\s+', header=None, comment='#')
df.columns = ['PO2','Ys']  # rename columns; 0: oxygen pressure; 1: saturation
df  # print out the data frame<jupyter_output><empty_output><jupyter_text>and... easily plot the data using either (1) the pyplot funtions of matplotlib, or (2) built-in plotting functions of a pandas data frame [(docs)](https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.plot.htmlpandas.DataFrame.plot):<jupyter_code># (1) using pyplot; x and y by column name
plt.plot(df['PO2'], df['Ys'], 'o-'); plt.grid()
# (2) using built-in pandas plot functions:
df.plot('PO2', 'Ys', style='o-', figsize=(4,3))
plt.grid() # plot the data using a scatter plot<jupyter_output><empty_output><jupyter_text>NB: we can convert a column in a data frame to a list:<jupyter_code>df['Ys'].tolist() # print a column as a list<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.10116873630387144, 'fraction_numerical': 0.02675310445580716, 'mean_word_length': 4.959194776931447, 'pattern_counts': {'":': 0, '<': 62, '<?xml version=': 0, '>': 64, 'https://': 14, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '16', 'dir': 'jupyter-structured-clean-dedup', 'id': '630486', 'license': 'MIT', 'n_tokens_mistral': 3593, 'n_tokens_neox': 3336, 'n_words': 1449, 'path': 'Intro_plotting_python_6765_SP21.ipynb', 'repo_name': 'mpfoster/Biochem6765', 'size': '10952'}