# cif2robotex

This jupyter notebook can be used to obtain publication ready latex tables from cif files. Furthermore in the future this notebook can also use [robocrys](https://github.com/hackingmaterials/robocrystallographer) to return a first description of the structure.

```
!git clone https://github.com/openbabel/openbabel --depth 1 && cd openbabel
!mkdir build && cd build
!cmake ../openbabel -DPYTHON_BINDINGS=ON
!make && make install
!pip install pymatgen

```

    Requirement already satisfied: pymatgen in /usr/local/lib/python3.6/dist-packages (2020.7.14)
    Requirement already satisfied: scipy>=1.5.0 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (1.5.1)
    Requirement already satisfied: tabulate in /usr/local/lib/python3.6/dist-packages (from pymatgen) (0.8.7)
    Requirement already satisfied: pandas in /usr/local/lib/python3.6/dist-packages (from pymatgen) (1.0.5)
    Requirement already satisfied: plotly>=4.5.0 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (4.8.2)
    Requirement already satisfied: sympy in /usr/local/lib/python3.6/dist-packages (from pymatgen) (1.1.1)
    Requirement already satisfied: monty>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (3.0.4)
    Requirement already satisfied: networkx>=2.2 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (2.4)
    Requirement already satisfied: numpy>=1.14.3 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (1.18.5)
    Requirement already satisfied: palettable>=3.1.1 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (3.3.0)
    Requirement already satisfied: dataclasses>=0.6; python_version < "3.7" in /usr/local/lib/python3.6/dist-packages (from pymatgen) (0.7)
    Requirement already satisfied: requests in /usr/local/lib/python3.6/dist-packages (from pymatgen) (2.23.0)
    Requirement already satisfied: spglib>=1.9.9.44 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (1.15.1)
    Requirement already satisfied: ruamel.yaml>=0.15.6 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (0.16.10)
    Requirement already satisfied: matplotlib>=1.5 in /usr/local/lib/python3.6/dist-packages (from pymatgen) (3.2.2)
    Requirement already satisfied: python-dateutil>=2.6.1 in /usr/local/lib/python3.6/dist-packages (from pandas->pymatgen) (2.8.1)
    Requirement already satisfied: pytz>=2017.2 in /usr/local/lib/python3.6/dist-packages (from pandas->pymatgen) (2018.9)
    Requirement already satisfied: six in /usr/local/lib/python3.6/dist-packages (from plotly>=4.5.0->pymatgen) (1.12.0)
    Requirement already satisfied: retrying>=1.3.3 in /usr/local/lib/python3.6/dist-packages (from plotly>=4.5.0->pymatgen) (1.3.3)
    Requirement already satisfied: mpmath>=0.19 in /usr/local/lib/python3.6/dist-packages (from sympy->pymatgen) (1.1.0)
    Requirement already satisfied: decorator>=4.3.0 in /usr/local/lib/python3.6/dist-packages (from networkx>=2.2->pymatgen) (4.4.2)
    Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.6/dist-packages (from requests->pymatgen) (2020.6.20)
    Requirement already satisfied: idna<3,>=2.5 in /usr/local/lib/python3.6/dist-packages (from requests->pymatgen) (2.10)
    Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in /usr/local/lib/python3.6/dist-packages (from requests->pymatgen) (1.24.3)
    Requirement already satisfied: chardet<4,>=3.0.2 in /usr/local/lib/python3.6/dist-packages (from requests->pymatgen) (3.0.4)
    Requirement already satisfied: ruamel.yaml.clib>=0.1.2; platform_python_implementation == "CPython" and python_version < "3.9" in /usr/local/lib/python3.6/dist-packages (from ruamel.yaml>=0.15.6->pymatgen) (0.2.0)
    Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib>=1.5->pymatgen) (1.2.0)
    Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib>=1.5->pymatgen) (2.4.7)
    Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib>=1.5->pymatgen) (0.10.0)

```
from pymatgen.io.cif import CifParser
from pymatgen import Structure
```

The following function *cif_import* imports the cif file and returns it as a structure file which can later be used to acces the informations of the cif file.

```
def cif_import(filename):
  parser = CifParser(filename + ".cif")
  structure = parser.as_dict()
  structure = structure[list(structure.keys())[0]]
  return structure
# To import the cif just call the function with the filenmae without extension
#structure = cif_import("BLJ223_DABCO_SB_Cu_Br")
#print(structure["_diffrn_radiation_type"][:-2])
```

# Cif Table

Write .tex file with information from cif file.
Add items here using keys of dictionary from cif file.
The output will be a latex table

```
def ciftable_tex(filename, structure):
  # Open the file with writing permission
  with open(filename +".tex", "w") as myfile:

    # Write a line to the file
    myfile.write("\\begin{table} \n \\caption{Crystallographic data for compound}\n \\label{tab:cryst_data} \n")
    myfile.write("\\begin{tabular}{@{}ll@{}} \n")
    myfile.write("\\toprule\n"+ structure["_chemical_formula_sum"] +"& \\ce{} \\\ \\midrule \n")
    myfile.write("Formula weight & "+ structure["_chemical_formula_weight"] +"    \\\ \n")
    myfile.write("Temperature/K & "+ structure["_cell_measurement_temperature"] +"  \\\ \n")
    myfile.write("Crystal system  & "+ structure["_space_group_crystal_system"]     +"                           \\\ \n")
    myfile.write("Space group & "+ structure["_space_group_name_H-M_alt"].replace(" ", "")+ "  \\\ \n")
    myfile.write("a/\\AA\\ & "+ structure["_cell_length_a"] +" \\\ \n")
    myfile.write("b/\\AA\\ & "+ structure["_cell_length_b"] +"  \\\ \n")
    myfile.write("c/\\AA\\ & "+ structure["_cell_length_c"] +" \\\ \n")
    myfile.write("$\\alpha$/\\textdegree  & "+ structure["_cell_angle_alpha"] +"   \\\ \n")
    myfile.write("$\\beta$/\\textdegree  & "+ structure["_cell_angle_beta"] +" \\\ \n")
    myfile.write("$\\gamma$/\\textdegree  & "+ structure["_cell_angle_gamma"] +" \\\ \n")
    myfile.write("Volume/\\AA$^3$   & "+ structure["_cell_volume"] +" \\\ \n")
    myfile.write("Z & "+ structure["_cell_formula_units_Z"] +" \\\ \n")
    myfile.write("$\\rho$calcg/cm$^3$  & "+ structure["_exptl_crystal_density_meas"]+ "\\\ \n")
    myfile.write("F(000)  & "+ structure["_exptl_crystal_F_000"] +" \\\ \n")
    myfile.write("Crystal size/mm$^3$ & "+ structure["_exptl_crystal_size_max"] +" x" + structure["_exptl_crystal_size_mid"] +" x" + structure["_exptl_crystal_size_min"] +"\\\ \n")
    myfile.write("Radiation  & "+ structure["_diffrn_radiation_type"][:-2]+ "$\\alpha$ ($\\lambda$ = " + structure["_diffrn_radiation_wavelength"] +") \\\ \n")
    myfile.write("2$\\theta$ range for data collection/\textdegree                 & "+ structure["_diffrn_reflns_theta_min"]+ " to " + structure["_diffrn_reflns_theta_max"] +" \\\ \n")
    myfile.write("Index ranges & " +structure["_diffrn_reflns_limit_h_min"]+" $\leq$ h $\leq$ "+structure["_diffrn_reflns_limit_h_max"]+","+structure["_diffrn_reflns_limit_k_min"]+"  $\leq$ k $\leq$"+ structure["_diffrn_reflns_limit_k_max"]+"," + structure["_diffrn_reflns_limit_l_min"]+" $\leq$ l $\leq$"+ structure["_diffrn_reflns_limit_h_min"]+"  \\\ \n")
    myfile.write("Reflections collected & "+ structure["_diffrn_reflns_number"]+" \\\ \n")
    myfile.write("Independent reflections & " + structure["_reflns_number_total"] + "{[}R$_{int}$ =" + structure["_diffrn_reflns_av_R_equivalents"]+ ", R$_\sigma$ =" + structure["_diffrn_reflns_av_unetI/netI"]+"{]} \\\ \n")
    myfile.write("Data/restraints/parameters &"+ structure["_refine_ls_number_reflns"]+"/"+ structure["_refine_ls_number_restraints"]+ "/"+ structure["_refine_ls_number_parameters"]  +" \\\ \n")
    myfile.write("Goodness-of-fit & "+ structure["_refine_ls_restrained_S_all"] + " \\\ \n")
    myfile.write("Final R indexes {[}I$\\geq$2$\\sigma$ (I){]} & R$_1$ = "+ structure["_refine_ls_R_factor_gt"]+ ", wR$_2$ = "+ structure["_refine_ls_wR_factor_gt"] + "\\\ \n")
    myfile.write("Final R indexes {[}all data{]}               & R$_1$ = "+ structure["_refine_ls_R_factor_all"]+ ", wR$_2$ = "+ structure["_refine_ls_wR_factor_ref"] + " \\\ \n")
    myfile.write("Largest diff. peak/hole / e \AA$^-3$  & "+ structure["_refine_diff_density_max"] + "/ "+ structure["_refine_diff_density_min"] +" \\\* \\bottomrule \n")
    myfile.write("\\end{tabular} \n")
    myfile.write("\\end{table}")

ciftable_tex("filename", cif_import("structure_name"))

```

## Here the table for atom coordinates etc will be written to "name_tables.tex"

```
import pandas as pd
def atom_tables(filename, structure):
  atom_label = structure["_atom_site_label"]
  atom_x = structure["_atom_site_fract_x"]
  atom_y = structure["_atom_site_fract_y"]
  atom_z = structure["_atom_site_fract_z"]
  atom_U = structure["_atom_site_U_iso_or_equiv"]
  data_iso = pd.DataFrame({"Atom": atom_label, "x": atom_x , "y": atom_y, "z": atom_z, "U": atom_U})

  with open(filename+"_atom_coordinates_iso.tex", "w") as myfile:
    myfile.write(data_iso.to_latex(index=False, caption="Test"))

  atom_anis = structure["_atom_site_aniso_label"]
  atom_u11 = structure["_atom_site_aniso_U_11"]
  atom_u22 = structure["_atom_site_aniso_U_22"]
  atom_u33 = structure["_atom_site_aniso_U_33"]
  atom_u23 = structure["_atom_site_aniso_U_23"]
  atom_u13 = structure["_atom_site_aniso_U_13"]
  atom_u12 = structure["_atom_site_aniso_U_12"]
  data_anis = pd.DataFrame({"Atom": atom_anis, "U_{11}": atom_u11 , "U_{22}": atom_u22 , "U_{33}": atom_u33 , "U_{23}": atom_u23 , "U_{13}": atom_u13, "U_{12}": atom_u12})

  with open(filename+"_atom_anis.tex", "w") as myfile:
    myfile.write(data_anis.to_latex(index=False))

atom_tables("filename", cif_import("structure_name"))
```

# Robocrystallographer

Here [robocrys](https://hackingmaterials.lbl.gov/robocrystallographer/modules.html) will be used to desccribe the structure.

```
!pip install robocrys
```

```

from robocrys import StructureCondenser, StructureDescriber
filename = "filename"
structure_cif = Structure.from_file(filename+ ".cif") # other file formats also supported

# alternatively, uncomment the lines below to use the MPRester object
# to fetch structures from the Materials Project database
# from pymatgen import MPRester
# structure = MPRester(API_KEY=None).get_structure_by_material_id("mp-856")

condenser = StructureCondenser()
describer = StructureDescriber()

condensed_structure = condenser.condense_structure(structure_cif)
description = describer.describe(condensed_structure)

with open(filename +"_description.tex", "w") as robotext:
  robotext.write(description)
print(description)
```

```

```


```python
! pip install qeds
import random
import numpy as np
import pandas as pd
import qeds
import matplotlib.pyplot as plt
%matplotlib inline
import qeds
qeds.themes.mpl_style();
```

    Requirement already satisfied: qeds in c:\users\asus\anaconda3\lib\site-packages (0.6.2)
    Requirement already satisfied: pandas in c:\users\asus\anaconda3\lib\site-packages (from qeds) (0.25.1)
    Requirement already satisfied: numpy in c:\users\asus\anaconda3\lib\site-packages (from qeds) (1.16.5)
    Requirement already satisfied: quantecon in c:\users\asus\anaconda3\lib\site-packages (from qeds) (0.4.6)
    Requirement already satisfied: matplotlib in c:\users\asus\anaconda3\lib\site-packages (from qeds) (3.1.1)
    Requirement already satisfied: scipy in c:\users\asus\anaconda3\lib\site-packages (from qeds) (1.3.1)
    Requirement already satisfied: scikit-learn in c:\users\asus\anaconda3\lib\site-packages (from qeds) (0.21.3)
    Requirement already satisfied: seaborn in c:\users\asus\anaconda3\lib\site-packages (from qeds) (0.9.0)
    Requirement already satisfied: statsmodels in c:\users\asus\anaconda3\lib\site-packages (from qeds) (0.10.1)
    Requirement already satisfied: pandas-datareader in c:\users\asus\anaconda3\lib\site-packages (from qeds) (0.8.1)
    Requirement already satisfied: plotly in c:\users\asus\anaconda3\lib\site-packages (from qeds) (4.5.4)
    Requirement already satisfied: pyarrow in c:\users\asus\anaconda3\lib\site-packages (from qeds) (0.16.0)
    Requirement already satisfied: quandl in c:\users\asus\anaconda3\lib\site-packages (from qeds) (3.5.0)
    Requirement already satisfied: openpyxl in c:\users\asus\anaconda3\lib\site-packages (from qeds) (3.0.0)
    Requirement already satisfied: requests in c:\users\asus\anaconda3\lib\site-packages (from qeds) (2.22.0)
    Requirement already satisfied: pytz>=2017.2 in c:\users\asus\anaconda3\lib\site-packages (from pandas->qeds) (2019.3)
    Requirement already satisfied: python-dateutil>=2.6.1 in c:\users\asus\anaconda3\lib\site-packages (from pandas->qeds) (2.8.0)
    Requirement already satisfied: numba>=0.38 in c:\users\asus\anaconda3\lib\site-packages (from quantecon->qeds) (0.45.1)
    Requirement already satisfied: sympy in c:\users\asus\anaconda3\lib\site-packages (from quantecon->qeds) (1.4)
    Requirement already satisfied: cycler>=0.10 in c:\users\asus\anaconda3\lib\site-packages (from matplotlib->qeds) (0.10.0)
    Requirement already satisfied: kiwisolver>=1.0.1 in c:\users\asus\anaconda3\lib\site-packages (from matplotlib->qeds) (1.1.0)
    Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in c:\users\asus\anaconda3\lib\site-packages (from matplotlib->qeds) (2.4.2)
    Requirement already satisfied: joblib>=0.11 in c:\users\asus\anaconda3\lib\site-packages (from scikit-learn->qeds) (0.13.2)
    Requirement already satisfied: patsy>=0.4.0 in c:\users\asus\anaconda3\lib\site-packages (from statsmodels->qeds) (0.5.1)
    Requirement already satisfied: lxml in c:\users\asus\anaconda3\lib\site-packages (from pandas-datareader->qeds) (4.4.1)
    Requirement already satisfied: six in c:\users\asus\anaconda3\lib\site-packages (from plotly->qeds) (1.12.0)
    Requirement already satisfied: retrying>=1.3.3 in c:\users\asus\anaconda3\lib\site-packages (from plotly->qeds) (1.3.3)
    Requirement already satisfied: more-itertools in c:\users\asus\anaconda3\lib\site-packages (from quandl->qeds) (7.2.0)
    Requirement already satisfied: inflection>=0.3.1 in c:\users\asus\anaconda3\lib\site-packages (from quandl->qeds) (0.3.1)
    Requirement already satisfied: et-xmlfile in c:\users\asus\anaconda3\lib\site-packages (from openpyxl->qeds) (1.0.1)
    Requirement already satisfied: jdcal in c:\users\asus\anaconda3\lib\site-packages (from openpyxl->qeds) (1.4.1)
    Requirement already satisfied: certifi>=2017.4.17 in c:\users\asus\anaconda3\lib\site-packages (from requests->qeds) (2019.9.11)
    Requirement already satisfied: urllib3!=1.25.0,!=1.25.1,<1.26,>=1.21.1 in c:\users\asus\anaconda3\lib\site-packages (from requests->qeds) (1.24.2)
    Requirement already satisfied: chardet<3.1.0,>=3.0.2 in c:\users\asus\anaconda3\lib\site-packages (from requests->qeds) (3.0.4)
    Requirement already satisfied: idna<2.9,>=2.5 in c:\users\asus\anaconda3\lib\site-packages (from requests->qeds) (2.8)
    Requirement already satisfied: llvmlite>=0.29.0dev0 in c:\users\asus\anaconda3\lib\site-packages (from numba>=0.38->quantecon->qeds) (0.29.0)
    Requirement already satisfied: mpmath>=0.19 in c:\users\asus\anaconda3\lib\site-packages (from sympy->quantecon->qeds) (1.1.0)
    Requirement already satisfied: setuptools in c:\users\asus\anaconda3\lib\site-packages (from kiwisolver>=1.0.1->matplotlib->qeds) (41.4.0)

# GroupBy - Exercises

**We will begin with a simple made-up dataset to discuss the concepts and then work through extended example and exercises with real data.**

```python
C = np.arange(1, 7, dtype=float)
C[[3, 5]] = np.nan
df = pd.DataFrame({
    "A" : [1, 1, 1, 2, 2, 2],
    "B" : [1, 1, 2, 2, 1, 1],
    "C": C,
})
df
```

      A
      B
      C

      0
      1
      1
      1.0

      1
      1
      1
      2.0

      2
      1
      2
      3.0

      3
      2
      2
      NaN

      4
      2
      1
      5.0

      5
      2
      1
      NaN

**We create a DataFrameGroupBy to use in what follows.**

```python
gbA = df.groupby("A")
gbA.head()
```

      A
      B
      C

      0
      1
      1
      1.0

      1
      1
      1
      2.0

      2
      1
      2
      3.0

      3
      2
      2
      NaN

      4
      2
      1
      5.0

      5
      2
      1
      NaN

## Exercise 1

**Try the following operations: gbA.sum(), gbA.mean(), gbA.count(). How did pandas compute the sum of `gbA`? What happened to the `NaN` entries in column `C`? Write your thoughts.**

```python
# the NaN entries in column C are disregarded in the analysis, regardless of the operation we use
    # for A = 2: the sum is 5, the mean is also 5 (computed with one element), the count gives us 1 element

print("This is gbA.sum()")
display(gbA.sum())
print("This is gbA.mean()")
display(gbA.mean())
print("This is gbA.count()")
display(gbA.count())
```

    This is gbA.sum()

      B
      C

      A

      1
      4
      6.0

      2
      4
      5.0

    This is gbA.mean()

      B
      C

      A

      1
      1.333333
      2.0

      2
      1.333333
      5.0

    This is gbA.count()

      B
      C

      A

      1
      3
      3

      2
      3
      1

## Exercise 2

1. **Use introspection (tab completion) to see what other aggregations are defined for GroupBy objects. Pick three and evaluate them in the cells below.**

```python
print("This is gbA.max()")
display(gbA.max())
print("This is gbA.median()")
display(gbA.median())
print("This is gbA.diff()")
display(gbA.diff())
```

    This is gbA.max()

      B
      C

      A

      1
      2
      3.0

      2
      2
      5.0

    This is gbA.median()

      B
      C

      A

      1
      1
      2.0

      2
      1
      5.0

    This is gbA.diff()

      B
      C

      0
      NaN
      NaN

      1
      0.0
      1.0

      2
      1.0
      1.0

      3
      NaN
      NaN

      4
      -1.0
      NaN

      5
      0.0
      NaN

2. **Does the output of each of these commands have the same features as the output of `gbA.sum()` from above? If not, what is different?**

```python
#the three commands chosen seem to have the same features, excet for the last one where the key disappears
```

## Exercise 3

1. **Write a function that, given a DataFrame, computes each entry's deviation from the mean of its column and apply the function to `gbA`.**

```python
# write function here
def mean_deviation(x):
    avg = x.mean()

    return x - avg

# apply function here
mean_deviation = gbA.apply(mean_deviation)
mean_deviation
```

      B
      C

      0
      -0.333333
      -1.0

      1
      -0.333333
      0.0

      2
      0.666667
      1.0

      3
      0.666667
      NaN

      4
      -0.333333
      0.0

      5
      -0.333333
      NaN

2. **Describe what the index and and columns are? Where are the group keys (the `A` column)?**

```python
mean_deviation.info()
#the index contains 6 entries, from 0 to 5
#the columns are B and C
#the group keys no longer appear
    #gbA.groups.keys()
```

    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 6 entries, 0 to 5
    Data columns (total 2 columns):
    B    6 non-null float64
    C    4 non-null float64
    dtypes: float64(2)
    memory usage: 224.0 bytes

3. **Determine the correct way to add these results back into `df` as new columns.**
    - Hint: remember the merge lecture

```python
# add output of function as new columns to df here...
mean_deviation_tu = mean_deviation.rename(columns={"B":"B_dev", "C":"C_dev"},inplace=True)

merged=pd.concat([df, mean_deviation], axis=1)
merged

```

      A
      B
      C
      B_dev
      C_dev

      0
      1
      1
      1.0
      -0.333333
      -1.0

      1
      1
      1
      2.0
      -0.333333
      0.0

      2
      1
      2
      3.0
      0.666667
      1.0

      3
      2
      2
      NaN
      0.666667
      NaN

      4
      2
      1
      5.0
      -0.333333
      0.0

      5
      2
      1
      NaN
      -0.333333
      NaN

Note that if the group keys

remained in the index as the `.apply`'s output, the merge/join step would have been complicated.

## Exercise 4

**We use an airline DataFrame:**

```python
air_dec = qeds.load("airline_performance_dec16")
air_dec.head()
```

      Carrier
      TailNum
      FlightNum
      OriginCityMarketID
      Origin
      OriginCityName
      OriginStateName
      DestCityMarketID
      Dest
      DestCityName
      ...
      AirTime
      Distance
      CarrierDelay
      WeatherDelay
      NASDelay
      SecurityDelay
      LateAircraftDelay
      FirstDepTime
      TotalAddGTime
      Date

      0
      AA
      N3JHAA
      46
      31650
      MSP
      Minneapolis, MN
      Minnesota
      30977
      ORD
      Chicago, IL
      ...
      58.0
      334.0
      0.0
      0.0
      20.0
      0.0
      0.0
      NaN
      NaN
      2016-12-18

      1
      AA
      N3DPAA
      46
      31650
      MSP
      Minneapolis, MN
      Minnesota
      30977
      ORD
      Chicago, IL
      ...
      57.0
      334.0
      0.0
      0.0
      20.0
      0.0
      0.0
      NaN
      NaN
      2016-12-19

      2
      AA
      N3KUAA
      46
      31650
      MSP
      Minneapolis, MN
      Minnesota
      30977
      ORD
      Chicago, IL
      ...
      49.0
      334.0
      0.0
      0.0
      0.0
      0.0
      0.0
      NaN
      NaN
      2016-12-20

      3
      AA
      N3FBAA
      46
      31650
      MSP
      Minneapolis, MN
      Minnesota
      30977
      ORD
      Chicago, IL
      ...
      51.0
      334.0
      0.0
      0.0
      0.0
      0.0
      0.0
      NaN
      NaN
      2016-12-21

      4
      AA
      N3BLAA
      46
      31650
      MSP
      Minneapolis, MN
      Minnesota
      30977
      ORD
      Chicago, IL
      ...
      51.0
      334.0
      0.0
      0.0
      0.0
      0.0
      0.0
      NaN
      NaN
      2016-12-22

5 rows × 36 columns

1. **Which type of delay was the most common?**

```python
#The air_dec DataFrame has information on the minutes of delay attributed to 5 different categories:
delay_cols = [
    'CarrierDelay',
    'WeatherDelay',
    'NASDelay',
    'SecurityDelay',
    'LateAircraftDelay'
]

air_dec[delay_cols]=(air_dec[delay_cols] > 0)
air_dec[delay_cols][air_dec[delay_cols]==True].count().sort_values()
#CarrierDelay was the most frequent one
```

    SecurityDelay          356
    WeatherDelay          5946
    NASDelay             55765
    LateAircraftDelay    56377
    CarrierDelay         57189
    dtype: int64

2. **Which one caused the largest average delay?**

```python
air_dec[delay_cols].mean().sort_values()
#CarrierDelay caused the largest average delay
```

    SecurityDelay        0.000772
    WeatherDelay         0.012899
    NASDelay             0.120979
    LateAircraftDelay    0.122306
    CarrierDelay         0.124068
    dtype: float64

3. **Does that vary by airline?**

```python
air_dec.groupby("Carrier")[delay_cols].mean()
#it does:
    #AA - LateAircraftDelay
    #EV - CarrierDelay
```

      CarrierDelay
      WeatherDelay
      NASDelay
      SecurityDelay
      LateAircraftDelay

      Carrier

      AA
      0.112612
      0.012317
      0.118127
      0.001233
      0.089361

      AS
      0.067172
      0.016121
      0.154461
      0.002067
      0.078333

      B6
      0.197797
      0.005878
      0.149540
      0.002918
      0.158089

      DL
      0.104186
      0.020499
      0.099187
      0.000168
      0.076663

      EV
      0.113454
      0.004558
      0.124010
      0.000000
      0.122304

      F9
      0.180027
      0.010525
      0.181006
      0.000000
      0.154693

      HA
      0.115488
      0.027730
      0.002363
      0.000945
      0.077517

      NK
      0.117898
      0.007484
      0.203283
      0.001449
      0.089731

      OO
      0.090251
      0.016382
      0.149895
      0.000484
      0.150500

      UA
      0.129314
      0.018658
      0.119668
      0.000175
      0.100901

      VX
      0.113102
      0.049975
      0.120500
      0.003123
      0.142693

      WN
      0.150046
      0.006281
      0.106032
      0.000695
      0.170568


Copyright 2020 DeepMind Technologies Limited

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

     https://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

## Clone repo and import dependencies

```python
!pip install tensorflow==1.15 dm-sonnet==1.36 tensor2tensor==1.14 pyntcloud

import os
import numpy as np
import tensorflow.compat.v1 as tf
tf.logging.set_verbosity(tf.logging.ERROR)  # Hide TF deprecation messages
import matplotlib.pyplot as plt

%cd /tmp
%rm -rf /tmp/deepmind_research
!git clone https://github.com/davidharrod/PengLai.git
%cd /tmp/PengLai
import modules
import data_utils
import train
from pre_process import point_cloud_2_voxel as p2v
```

    Requirement already satisfied: tensorflow==1.15 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (1.15.0)
    Requirement already satisfied: dm-sonnet==1.36 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (1.36)
    Requirement already satisfied: tensor2tensor==1.14 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (1.14.0)
    Requirement already satisfied: pyntcloud in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (0.1.5)
    Requirement already satisfied: protobuf>=3.6.1 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (3.19.1)
    Requirement already satisfied: numpy<2.0,>=1.16.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.18.5)
    Requirement already satisfied: gast==0.2.2 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (0.2.2)
    Requirement already satisfied: google-pasta>=0.1.6 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (0.2.0)
    Requirement already satisfied: tensorflow-estimator==1.15.1 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.15.1)
    Requirement already satisfied: six>=1.10.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.16.0)
    Requirement already satisfied: termcolor>=1.1.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.1.0)
    Requirement already satisfied: grpcio>=1.8.6 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.43.0)
    Requirement already satisfied: wheel>=0.26 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (0.37.0)
    Requirement already satisfied: absl-py>=0.7.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (0.12.0)
    Requirement already satisfied: keras-preprocessing>=1.0.5 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.1.2)
    Requirement already satisfied: tensorboard<1.16.0,>=1.15.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.15.0)
    Requirement already satisfied: astor>=0.6.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (0.8.1)
    Requirement already satisfied: opt-einsum>=2.3.2 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (3.3.0)
    Requirement already satisfied: wrapt>=1.11.1 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.13.3)
    Requirement already satisfied: keras-applications>=1.0.8 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow==1.15) (1.0.8)
    Requirement already satisfied: semantic-version in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from dm-sonnet==1.36) (2.8.5)
    Requirement already satisfied: contextlib2 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from dm-sonnet==1.36) (21.6.0)
    Requirement already satisfied: tensorflow-probability<0.9.0,>=0.8.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from dm-sonnet==1.36) (0.8.0)
    Requirement already satisfied: opencv-python in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (4.5.4.60)
    Requirement already satisfied: gym in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (0.12.5)
    Requirement already satisfied: kfac in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (0.2.3)
    Requirement already satisfied: tqdm in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (4.62.3)
    Requirement already satisfied: mesh-tensorflow in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (0.1.19)
    Requirement already satisfied: requests in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (2.26.0)
    Requirement already satisfied: pypng in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (0.0.21)
    Requirement already satisfied: gevent in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (21.12.0)
    Requirement already satisfied: dopamine-rl in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (3.0.1)
    Requirement already satisfied: flask in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (2.0.2)
    Requirement already satisfied: gunicorn in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (20.1.0)
    Requirement already satisfied: Pillow in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (8.4.0)
    Requirement already satisfied: scipy in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (1.7.3)
    Requirement already satisfied: tensorflow-datasets in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (4.4.0)
    Requirement already satisfied: oauth2client in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (4.1.3)
    Requirement already satisfied: google-api-python-client in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (2.33.0)
    Requirement already satisfied: h5py in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (3.6.0)
    Requirement already satisfied: gin-config in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (0.5.0)
    Requirement already satisfied: bz2file in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (0.98)
    Requirement already satisfied: sympy in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (1.9)
    Requirement already satisfied: future in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (0.18.2)
    Requirement already satisfied: tensorflow-gan in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensor2tensor==1.14) (2.1.0)
    Requirement already satisfied: pandas in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from pyntcloud) (1.3.5)
    Requirement already satisfied: setuptools>=41.0.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorboard<1.16.0,>=1.15.0->tensorflow==1.15) (58.0.4)
    Requirement already satisfied: werkzeug>=0.11.15 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorboard<1.16.0,>=1.15.0->tensorflow==1.15) (2.0.2)
    Requirement already satisfied: markdown>=2.6.8 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorboard<1.16.0,>=1.15.0->tensorflow==1.15) (3.3.6)
    Requirement already satisfied: importlib-metadata>=4.4 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from markdown>=2.6.8->tensorboard<1.16.0,>=1.15.0->tensorflow==1.15) (4.10.0)
    Requirement already satisfied: typing-extensions>=3.6.4 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from importlib-metadata>=4.4->markdown>=2.6.8->tensorboard<1.16.0,>=1.15.0->tensorflow==1.15) (4.0.1)
    Requirement already satisfied: zipp>=0.5 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from importlib-metadata>=4.4->markdown>=2.6.8->tensorboard<1.16.0,>=1.15.0->tensorflow==1.15) (3.6.0)
    Requirement already satisfied: decorator in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-probability<0.9.0,>=0.8.0->dm-sonnet==1.36) (5.1.0)
    Requirement already satisfied: cloudpickle==1.1.1 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-probability<0.9.0,>=0.8.0->dm-sonnet==1.36) (1.1.1)
    Requirement already satisfied: pyglet>=1.2.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from gym->tensor2tensor==1.14) (1.5.21)
    Requirement already satisfied: itsdangerous>=2.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from flask->tensor2tensor==1.14) (2.0.1)
    Requirement already satisfied: click>=7.1.2 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from flask->tensor2tensor==1.14) (8.0.3)
    Requirement already satisfied: Jinja2>=3.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from flask->tensor2tensor==1.14) (3.0.3)
    Requirement already satisfied: MarkupSafe>=2.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from Jinja2>=3.0->flask->tensor2tensor==1.14) (2.0.1)
    Requirement already satisfied: zope.interface in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from gevent->tensor2tensor==1.14) (5.4.0)
    Requirement already satisfied: greenlet<2.0,>=1.1.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from gevent->tensor2tensor==1.14) (1.1.2)
    Requirement already satisfied: zope.event in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from gevent->tensor2tensor==1.14) (4.5.0)
    Requirement already satisfied: uritemplate<5,>=3.0.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-api-python-client->tensor2tensor==1.14) (4.1.1)
    Requirement already satisfied: google-api-core<3.0.0dev,>=1.21.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-api-python-client->tensor2tensor==1.14) (2.3.2)
    Requirement already satisfied: google-auth<3.0.0dev,>=1.16.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-api-python-client->tensor2tensor==1.14) (2.3.3)
    Requirement already satisfied: google-auth-httplib2>=0.1.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-api-python-client->tensor2tensor==1.14) (0.1.0)
    Requirement already satisfied: httplib2<1dev,>=0.15.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-api-python-client->tensor2tensor==1.14) (0.20.2)
    Requirement already satisfied: googleapis-common-protos<2.0dev,>=1.52.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-api-core<3.0.0dev,>=1.21.0->google-api-python-client->tensor2tensor==1.14) (1.54.0)
    Requirement already satisfied: cachetools<5.0,>=2.0.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-auth<3.0.0dev,>=1.16.0->google-api-python-client->tensor2tensor==1.14) (4.2.4)
    Requirement already satisfied: rsa<5,>=3.1.4 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-auth<3.0.0dev,>=1.16.0->google-api-python-client->tensor2tensor==1.14) (4.8)
    Requirement already satisfied: pyasn1-modules>=0.2.1 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from google-auth<3.0.0dev,>=1.16.0->google-api-python-client->tensor2tensor==1.14) (0.2.8)
    Requirement already satisfied: pyparsing!=3.0.0,!=3.0.1,!=3.0.2,!=3.0.3,<4,>=2.4.2 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from httplib2<1dev,>=0.15.0->google-api-python-client->tensor2tensor==1.14) (3.0.6)
    Requirement already satisfied: pyasn1<0.5.0,>=0.4.6 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from pyasn1-modules>=0.2.1->google-auth<3.0.0dev,>=1.16.0->google-api-python-client->tensor2tensor==1.14) (0.4.8)
    Requirement already satisfied: certifi>=2017.4.17 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from requests->tensor2tensor==1.14) (2021.10.8)
    Requirement already satisfied: urllib3<1.27,>=1.21.1 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from requests->tensor2tensor==1.14) (1.26.7)
    Requirement already satisfied: charset-normalizer~=2.0.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from requests->tensor2tensor==1.14) (2.0.9)
    Requirement already satisfied: idna<4,>=2.5 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from requests->tensor2tensor==1.14) (3.3)
    Requirement already satisfied: cached-property in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from h5py->tensor2tensor==1.14) (1.5.2)
    Requirement already satisfied: python-dateutil>=2.7.3 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from pandas->pyntcloud) (2.8.2)
    Requirement already satisfied: pytz>=2017.3 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from pandas->pyntcloud) (2021.3)
    Requirement already satisfied: mpmath>=0.19 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from sympy->tensor2tensor==1.14) (1.2.1)
    Requirement already satisfied: attrs>=18.1.0 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-datasets->tensor2tensor==1.14) (21.2.0)
    Requirement already satisfied: tensorflow-metadata in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-datasets->tensor2tensor==1.14) (1.5.0)
    Requirement already satisfied: importlib-resources in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-datasets->tensor2tensor==1.14) (5.4.0)
    Requirement already satisfied: dill in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-datasets->tensor2tensor==1.14) (0.3.4)
    Requirement already satisfied: promise in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-datasets->tensor2tensor==1.14) (2.3)
    Requirement already satisfied: tensorflow-hub>=0.2 in /home/yqs/anaconda3/envs/poly/lib/python3.7/site-packages (from tensorflow-gan->tensor2tensor==1.14) (0.12.0)
    /tmp
    正克隆到 'PMGen'...
    remote: Enumerating objects: 39, done.
    remote: Counting objects: 100% (39/39), done.
    remote: Compressing objects: 100% (37/37), done.
    remote: Total 39 (delta 5), reused 0 (delta 0), pack-reused 0
    展开对象中: 100% (39/39), 完成.
    [Errno 2] No such file or directory: '/tmp/PolyGen'
    /tmp

## Prepare dataset

```python
batch_size = 1
buffer_size =20
obj_path = "./dataset/obj/"
binvox_path = "./dataset/binvox"
vertex_dataset, face_dataset = train.load_dataset(obj_path, binvox_path,batch_size,buffer_size)
```

## Set configuration

```python
VERTICES = "VERTICES_FLAT"
FACES = "FACES"
EPOCH = 10000
CHECK_POINT = 5000

# Set tensorflow gpu configuration.
tf_gpu_config = tf.ConfigProto(allow_soft_placement=True)
tf_gpu_config.gpu_options.allow_growth = True

# Set encoders and decoders' configuration.
vertex_model_encoder_config = {
    "hidden_sizes": (64, 256),
    "num_blocks": (1, 2),
    "dropout_rate": 0.1
}
vertex_model_decoder_config = {
    "hidden_size": 256,
    "fc_size": 1024,
    "num_heads": 4,
    "dropout_rate": 0.2,
}
face_model_encoder_config = {
    'hidden_size': 128,
    'fc_size': 512,
    'num_layers': 3,
    'dropout_rate': 0.
}
face_model_decoder_config = {
    'hidden_size': 128,
    'fc_size': 512,
    'num_layers': 3,
    'dropout_rate': 0.
}
```

## Create models

```python
# Set training parameters.
target_dir = "./log/"
learning_rate = 5e-4
training_step = 20
check_step = 2

# Prepare for training.
vertex_batch = vertex_dataset.make_one_shot_iterator().get_next()
face_batch = face_dataset.make_one_shot_iterator().get_next()
_, vertex_loss, vertex_samples = train._create_model(
    vertex_batch,
    model_type=VERTICES,
    encoder_config=vertex_model_encoder_config,
    decoder_config=vertex_model_decoder_config)
_, face_loss, _=train._create_model(face_batch,
                                model_type=FACES,
                                encoder_config=face_model_encoder_config,
                                decoder_config=face_model_decoder_config,
                                vertex_samples=vertex_samples)
optimizer = tf.train.AdamOptimizer(learning_rate)
vertex_model_optim_op = optimizer.minimize(vertex_loss)
face_model_optim_op = optimizer.minimize(face_loss)
# Set saver and summary.
tf.summary.scalar("vertex loss", vertex_loss)
tf.summary.scalar("face loss", face_loss)
merged = tf.summary.merge_all()
```

## Start training

```python
with tf.Session(config=tf_gpu_config) as sess:
    writer = tf.summary.FileWriter(os.getcwd(), sess.graph)
    sess.run(tf.global_variables_initializer())
    for epoch in range(EPOCH):
        for n in range(training_step):
            if n % check_step == 0:
                summary = sess.run(merged)
                writer.add_summary(summary, n + epoch * training_step)
            sess.run((vertex_model_optim_op, face_model_optim_op))
```

## Check out logging with tensorboard

```python
%load_ext tensorboard
%tensorboard --logdir ./
```


# Orders of Magnitude
The simulation examples in the previous chapters are conceptual. As we begin to build simulation models of realistic biological processes, the need to obtain information such as the numerical values of the parameters that appear in the dynamic mass balances. We thus go through a process of estimating the approximate numerical values of various quantities and parameters. Size, mass, chemical composition, metabolic complexity, and genetic makeup represent characteristics for which we now have extensive data available. Based on typical values for these quantities we show how one can make useful estimates of concentrations and the dynamic features of the intracellular environment.

## Cellular Composition and Ultra-structure
It is often stated that all biologists have two favorite organisms, _E. coli_ and another one. Fortunately, much data exists for _E. coli,_ and we can go through parameter and variable estimation procedures using it as an example. These estimation procedures can be performed for other target organisms, cell types, and cellular processes in an analogous manner if the appropriate data is available. We organize the discussion around key questions.

### The interior of a cell
The typical bacterial cell, like _E. coli,_ is on the order of microns in size (Figure 7.1a). The _E. coli_ cell is a short cylinder, about 2-4 micron in length with a 0.5 to 1.5 micron diameter, Figure 7.1b. The size of the _E. coli_ cell is growth rate dependent; the faster the cell grows, the larger it is.

It has a complex intra-cellular environment. One can isolate and crystallize macromolecules and obtain their individual structure. However, this approach gives limited information about the configuration and location of a protein in a living functional cell. The intracellular milieu can to be reconstructed from available data to yield an indirect picture of the interior of an cell. Such a reconstruction has been carried out Goodsell93. Based on well known chemical composition data, this image provides us with about a million-fold magnification of the interior of an _E. coli_ cell, see Figure 7.1c. Examination of this picture of the interior of the _E. coli_ cell is instructive:

* The intracellular environment is very crowded and represents a dense solution. Protein density in some sub-cellular structures can approach that found in protein crystals, and the intracellular environment is sometimes referred to as 'soft glass,' suggesting that it is close to a crystalline state.

* The chemical composition of this dense mixture is very complex. The majority of cellular mass are macromolecules with metabolites, the small molecular weight molecules interspersed among the macromolecules.

* In this crowded solution, the motion of the macromolecules is estimated to be one hundred to even one thousand-fold slower than in a dilute solution. The time it takes a 160 kDa protein to move 10 nm - a distance that corresponds approximately to the size of the protein molecule - is estimated to be 0.2 to 2 milliseconds. Moving one cellular diameter of approximately 0.64 $\mu m$, or 640 nm, would then require 1-10 min. The motion of metabolites is expected to be significantly faster due to their smaller size.

**Figure 7.1:** (a) An electron micrograph of the _E. coli_ cell, from Ingraham83. (b) Characteristic features of an _E. coli_ cell. (c) The interior of an _E. coli_ cell, © David S. Goodsell 1999.

### The overall chemical composition of a cell
With these initial observations, let's take a closer look at the chemical composition of the cell. Most cells are about 70% water. It is likely that cellular functions and evolutionary design is constrained by the solvent capacity of water, and the fact that most cells are approximately 70% water suggests that all cells are close to these constraints.

The 'biomass' is about 30% of cell weight. It is sometimes referred to as the dry weight of a cell, and is denoted by gDW. The 30% of the weight that is biomass is comprised of 26% macromolecules, 1% inorganic ions, and 3% low molecular weight metabolites. The basic chemical makeup of prokaryotic cells is shown in Table 7.1, and contrasted to that of a typical animal cell. The gross chemical composition is similar except that animal cells, and eukaryotic cells in general, have a higher lipid content because of the membrane requirement for cellular compartmentalization. Approximate cellular composition is available or relatively easy to get for other cell types.

**Table 7.1:** Approximate composition of cells, from (Alberts, 1983). The numbers given are weight percent.

### The detailed composition of _E. coli_
The total weight of a bacterial cell is about 1 picogram. The density of cells barely exceeds that of water, and cellular density is typically around 1.04 to 1.08 $gm/cm^3$. Since the density of cells is close to unity, a cellular concentration of about $10^12$ cells per milliliter represents packing density of _E. coli_ cells. Detailed and recent data is found later in Figure 7.2.

This information provides the basis for estimating the numerical values for a number of important quantities that relate to dynamic network modeling. Having such order of magnitude information provides a frame of reference, allows one to develop a conceptual model of cells, evaluate the numerical outputs from models, and perform any approximation or simplification that is useful and justified based on the numbers. "Numbers count," even in biology.

### Order of magnitude estimates
It is relatively easy to estimate the approximate order of magnitude of the numerical values of key quantities. Enrico Fermi the famous physicist was well-known for his skills with such calculations and they thus know as Fermi problems. We give a couple examples to illustrate the order of magnitude estimation process.

#### 1. How many piano tuners are in Chicago?
This question represents a classical Fermi problem. First we state assumptions or key numbers:

**1.** There are approximately 5,000,000 people living in Chicago.

**2.** On average, there are two persons in each household in Chicago.

**3.** Roughly one household in twenty has a piano that is tuned regularly.

**4.** Pianos that are tuned regularly are tuned on average about once per year.

**5.** It takes a piano tuner about two hours to tune a piano, including travel time.

**6.** Each piano tuner works eight hours in a day, five days in a week, and 50 weeks in a year.

From these assumptions we can compute:

* that the number of piano tunings in a single year in Chicago is:
(5,000,000 persons in Chicago)/(2 persons/household) $*$ (1 piano/20 households) $*$ (1 piano tuning per piano per year) = 125,000 piano tunings per year in Chicago.

* that the average piano tuner performs (50 weeks/year) $*$ (5 days/week) $*$ (8 hours/day)/(1 piano tuning per 2 hours per piano tuner) = 1000 piano tunings per year per piano tuner.

* then dividing gives (125,000 piano tuning per year in Chicago) / (1000 piano tunings per year per piano tuner) = 125 piano tuners in Chicago, which is the answer that we sought.

#### 2. How far can a retrovirus diffuse before it falls apart?
A similar procedure that relies more on scientific principles can be used to answer this question. The half-live of retroviruses, $t_{0.5}$, are measured to be about 5 to 6 hours. The time constant for diffusion is:

$$\begin{equation} t_{diff} = t^2 / D \tag{7.1} \end{equation}$$

where l is the diffusion distance and $D$ is the diffusion constant. Then the distance $l_{0.5}$ that a virus can travel over a half life is

$$\begin{equation} l_{0.5} = \sqrt{D\ t_{0.5}} \tag{7.2} \end{equation}$$

Using a numerical value for $D$ of $6.5*10^{-8}\ cm^2/sec$ that is computed from the Stokes-Einstein equation for a 100 nm particle (approximately the diameter of the retrovirus) the estimate is about 500 $\mu m$ (Chuck, 1996). A fairly short distance that limits how far a virus can go to infect a target cell.

### A multi-scale view
The cellular composition of cells is complex. More complex yet is the intricate and coordinated web of complex functions that underlie the physiological state of a cell. We can view this as a multi-scale relationship, Figure 7.2. Based on cellular composition and other data we can estimate the overall parameters that are associated with cellular functions. Here we will focus on metabolism, macro-molecular synthesis and overall cellular states.

**Figure 7.2:** A multi-scale view of metabolism, macromolecular synthesis, and cellular functions. Prokaryotic cell (Synechocytis image from W. Vermaas, Arizona State University). Prokaryotic cell structures (purified carboxysomes) image from T. Yates, M. Yeager, and K. Dryden. Macromolecular complexes image © 2000, David S. Goodsell.

## Metabolism
Biomass composition allows the estimation of important overall features of metabolic processes. These quantities are basically concentrations (abundance), rates of change (fluxes), and time constants (response times, sensitivities, etc). For metabolism, we can readily estimate reasonable values for these quantities, and we again organize the discussion around key questions.

### What are typical concentrations?
#### Estimation
The approximate number of different metabolites present in a given cell is on the order of 1000 (Feist, 2007). By assuming that metabolite has a median molecular weight of about 312 gm/mol (Figure 7.3a) and that the fraction of metabolites of the wet weight is 0.01, we can estimate a typical metabolite concentration of:

$$\begin{equation} x_{avg} \approx \frac{1 gm/cm^3 * 0.01}{1000*312\ gm/mol} \approx 32 \mu M \tag{7.3} \end{equation}$$

The volume of a bacterial cell is about one cubic micron, or about one femto-liter $(=(10^-15)$ liter). Since a cubic micron is a logical reference volume, we convert the concentration unit as follows:

$$\begin{align} 1 \mu M &= \frac{10^{-6} mole}{1\ L} * \frac{10^{-15}\ L}{1\ \mu m^3} * \frac{6 * 10^{23}\ molecules}{mol} \tag{7.4} \\ &= 600\ molecules/\ \mu m^3 \tag{7.5} \end{align}$$

This number is remarkably small. A typical metabolite concentration of $32 \mu M$ then translates into mere $19,000$ molecules per cubic micron. One would expect that such low concentrations would lead to slow reaction rates. However, metabolic reaction rates are fairly rapid. As discussed in Chapter 5, cells have evolved highly efficient enzymes to achieve high reaction rates that occur even in the presence of low metabolite concentrations.

**Figure 7.3:** Details of _E. coli_ K12 MG1655 composition and properties. (a) The average molecular weight of metabolites is 500 gm/mol and the median is 312 gm/mol. Molecular weight distribution. (b) Thermodynamic properties of the reactions in the iAF1260 reconstruction the metabolic network. (c) Size distribution of ORF lengths or protein sizes: protein size distribution. The average protein length is 316 amino acids, the median is 281. Average molecular weight of _E. coli's_ proteins (monomers): 34.7 kDa Median: 30.828 kDa (d) distribution of protein concentrations: relative protein abundance distribution. See (Feist, 2007) and (Riley, 2006) for details. Prepared by Vasiliy Portnoy.

#### Measurement
Experimentally determined ranges of metabolite concentrations fall around the estimated range; an example is provided in Table 7.2. Surprisingly, glutamate is at a concentration that falls within the 100 millimolar range in _E. coli_. Other important metabolites such as ATP tend to fall in the millimolar range. Intermediates of pathways are often in the micromolar range. Several on-line resources are now available for metabolic concentration data, Table 7.3.

**Table 7.2:** Measured and predicted parameters for _E. coli_ growing on minimal media. Taken from (Yuan, 2006).

**Table 7.3:** Publicly available metabolic resources (above the dashed line) and proteomic resources (below the dashed line). Assembled by Vasiliy Portnoy.

### What are typical metabolic fluxes?
#### Rates of diffusion
In estimating reaction rates we first need to know if they are diffusion limited. Typical cellular dimensions are on the order of microns, or less. The diffusion constants for metabolites is on the order of $10^{-5}\ cm^2/sec$  and $10^{-6}\ cm^2/sec$. These figures translate into diffusional response times that are on the order of:

$$\begin{equation} t_{diff} = \frac{t^2}{D} = \frac{(10^{-4} cm)^2}{10^{-5}\ \text{to}\ 10^{-6} cm^2 / sec} \approx 1-10 msec \tag{7.6} \end{equation}$$

or faster. The metabolic dynamics of interest are much slower than milliseconds. Although more detail about the cell's finer spatial structure is becoming increasingly available, it is unlikely, from a dynamic modeling standpoint, that spatial concentration gradients will be a key concern for dynamic modeling of metabolic states in bacterial cells (Weisz, 1973).

#### Estimating maximal reaction rates
Reaction rates in cells are limited by the achievable kinetics. Few collections of enzyme kinetic parameters are available in the literature, see Table 7.3. One observation from such collections is that the biomolecular association rate constant, $k_1$, for a substrate $(S)$ to an enzyme $(E)$;

$$\begin{equation} S + E \stackrel{k_1}{\longrightarrow} \tag{7.7} \end{equation}$$

is on the order of $10^8 M^{-1} sec^{-1}$. This numerical value corresponds to the estimated theoretical limit, due to diffusional constraints (Gutfreund, 1972). The corresponding number for macromolecules is about three orders of magnitude lower.

Using the order of magnitude values for concentrations of metabolites given above and for enzymes in the next section, we find the representative association rate of substrate to enzymes to be on the order of

$$\begin{equation} k_1 s e = 10^8 (M*sec)^{-1} * 10^{-4}M * 10^{-6}M = 0.01\ M/sec \tag{7.8} \end{equation}$$

that translates into about

$$\begin{equation} k_1 s e = 10^6\ molecules / \mu m^3 sec \tag{7.9} \end{equation}$$

that is only one million molecules per cubic micron per second. However, the binding of the substrate to the enzyme is typically reversible and a better order of magnitude estimate for _net_ reaction rates is obtained by considering the release rate of the product from the substrate-enzyme complex, $X$. This release step tends to be the slowest step in enzyme catalysis (Albery 1976, Albery 1977, Cleland 1975). Typical values for the release rate constant, $k_2$,

$$\begin{equation} X \stackrel{k_2}{\rightarrow} P + E \tag{7.10} \end{equation}$$

are $100-1000\ sec^{-1}$. If the concentration of the intermediate substrate-enzyme complex, $X$, is on the order of 1 $\mu M$ we get a release rate of about

$$\begin{equation} k_2x = 10^4\ \text{to}\ 10^5 molecules/\mu m^3 sec \tag{7.11} \end{equation}$$

We can compare the estimate in Eq. (7.9) to observed metabolic fluxes, see Table 7.4. Uptake and secretion rates of major metabolites during bacterial growth represent high flux pathways.

**Table 7.4:** Typical metabolic fluxes measured in _E. coli_ K12 MG1655 grown under oxic and anoxic conditions.

#### Measured kinetic constants
There are now several accessible sources of information that contain kinetic data for enzymes and the chemical transformation that they catalyze. For kinetic information, both BRENDA and SABIO-RK (Wittig, 2006) are resources of literature curated constants, including rates and saturation levels, Table 7.2.2. Unlike stoichiometric information which is universal, kinetic parameters are highly condition-dependent. _In vitro_ kinetic assays typically do not represent in vivo conditions. Factors such as cofactor binding, pH, and unknown interactions with metabolites and proteins are likely causes.

#### Thermodynamics
While computational prediction of enzyme kinetic rates is difficult, obtaining thermodynamic values is more feasible. Estimates of metabolite standard transformed Gibbs energy of formation can be derived using an approach called _group contribution method_ (Mavrovouniotis 1991). This method considers a single compound as being made up of smaller structural subgroups. The metabolite standard Gibbs energy of formation associated with structural subgroups commonly found in metabolites are available in the literature and in the NIST database urlnist. To estimate the metabolite standard Gibbs energy of formation of the entire compound, the contributions from each of the subgroups are summed along with an origin term. The group contribution approach has been used to estimate standard transformed Gibbs energy of formation for 84% of the metabolites in the genome scale model of _E. coli_ (Feist 2007, Henry 2006, Henry 2007).

Thermodynamic values can also be obtained by integrating experimentally measured parameters and algorithms which implement sophisticated theory from biophysical chemistry (Alberty 2003, Alberty 2006). Combining this information with the results from group contribution method provides standard transformed Gibbs energy of formation for 96% of the reactions in the genome-scale _E. coli_ model (Feist 2007), see Figure 7.3b.

### What are typical turnover times?
As outlined in Chapter 2, turnover times can be estimated by taking that ratio of the concentration relative to the flux of degradation. Both concentrations and fluxes have been estimated above. Some specific examples of estimated turnover times are now provided.

#### Glucose turnover in rapidly growing E. coli cells
With an intracellular concentration of glucose of 1 to 5 mM, the estimate of the internal glucose turnover time is

$$\begin{equation} \tau_{glu} = \frac{6-30*10^5\ molecules/cell}{4.2 * 10^5\ \text{to}\ 8.4*10^5\ molecules/ \mu m^3 /sec} = 1\ \text{to} \ 8\  sec \tag{7.12} \end{equation}$$

#### Response of red cell glycolytic intermediates
A typical glycolytic flux in the red cell is about 1.25 mM/hr. By using this number and measured concentrations, we can estimate the turnover times for the intermediates of glycolysis by simply using:

$$\begin{equation} t_R = \frac{x_{avg}}{1.25 \ mM/hr} \tag{7.13} \end{equation}$$

The results are shown in Table 7.5. We see the sharp distribution of turnover times that appears. Note that the turnover times are set by the relative concentrations since the flux through the pathway is the same. Thus the least abundant metabolites will have the fastest turnover. At a constant flux, the relative concentrations are set by the kinetic constants.

**Table 7.5:** Turnover times for the glycolytic intermediates in the red blood cell. The glycolytic flux is assumed to be 1.25 mM/hr = 0.35 $\mu M/sec$ and the Rapoport-Luebering shunt flux is about 0.5 mM/hr. Table adapted from (Joshi, 1990).

#### Response of the energy charge
Exchange of high energy bonds between the various carriers is on the order of minutes. The dynamics of this energy pool occur on the middle time scale of minutes as described earlier, see Figure 7.4.

**Figure 7.4:** Responses in energy transduction processes in cells. (a) Effect of addition of glucose on the energy charge of Ehrlich ascites tumor cells. Redrawn based on (Atkinson, 1977). (b) Transient response of the transmembrane gradient, from (Konings, 1983). Generation of a proton motive force in energy starved _S. cremoris_ upon addition of lactose (indicated by arrows) at different times after the start of starvation (t=0).

#### Response of transmembrane charge gradients
Cells store energy by extruding protons across membranes. The consequence is the formation of an osmotic and charge gradient that results in the so-called _proton motive force,_ denoted as $\Delta \mu_{H^+}$. It is defined by:

$$\begin{equation} \Delta \mu_{H^+} = \Delta \Psi - Z\Delta pH \tag{7.14} \end{equation}$$

where $\Delta \Psi$ is the charge gradient and $\Delta pH$ is the hydrogen ion gradient. The parameter $Z$ takes a value of about 60 mV under physiological conditions. The transient response of gradient establishment is very rapid, Figure 7.4.

(Konings, 1983)

#### Conversion between different forms of energy
If energy is to be readily exchanged between transmembrane gradients and the high energy phosphate bond system, their displacement from equilibrium should be about the same. Based on typical ATP, ADP, and $P_i$ concentrations, one can calculate the transmembrane gradient to be about -180mV. Table 7.6 shows that observed values for the transmembrane gradient, $\Delta \widetilde{\mu}$, are on the order of -180 to -220 mV. It is interesting to note that the maximum gradient that a bi-lipid layer can withstand is on the order of -280mV (Konings, 1983), based on electrostatic considerations.

**Table 7.6:** Typical values (mV) for the transmembrane electrochemical potential gradient, reproduced from (Konings, 1983).

#### What are typical power densities?
The metabolic rates estimated above come with energy transmission through key cofactors. The highest energy production and dissipation rates are associated with energy transducing membranes. The ATP molecule is considered to be an energy currency of the cell, allowing one to estimate the power density in the cell/organelle based on the ATP production rate.

#### Power density in mitochondria
The rate of ATP production in mitochondria can be measured. Since we know the energy in each phosphate bond and the volume of the mitochondria, we can estimate the volumetric rate of energy production in the mitochondria.

Reported rates of ATP production in rat mitochondria from succinate are on the order of $6*10^{-19}$ mol ATP/mitochondria/sec  Schwerzmann86, taking place in a volume of about 0.27 $\mu m^3$. The energy in the phosphate bond about is -52kJ/mol ATP at physiological conditions. These numbers lead to the computation of a per unit volume energy production rate of $2.2*10^{-18}$ mol ATP/$\mu m^3/sec$, or $10^{-13}W/\mu m^3\ (0.1 pW/\mu m^3)$.

#### Power density in chloroplast of green algae
In _Chlamydomonas reinhardtii_, the rate of ATP production of chloroplast varies between $9.0*10^{-17}\ \text{to}\ 1.4*10^{-16}$ mol ATP/chloroplast/sec depending on the light intensity (Baroli 2003, Burns 1990, Melis 2000, Ross 1995) in the volume of 17.4 $\mu m^3$ (Harris 1989a). Thus, the volumetric energy production rate of chloroplast is on the order of $5*10^{-18}$ mol ATP/$\mu m^3/sec$, or $3*10^{-13}W/\mu m^3\ (0.3 pW/\mu m^3)$.

#### Power density in rapidly growing E. coli cells:
A similar estimate of energy production rates can be performed for microorganisms. The aerobic glucose consumption of _E. coli_ is about 10 mmol/gDW/hr. The weight of a cell is about $2.8*10^{-13}$ gDW/cell. The ATP yield on glucose is about 17.5 ATP/glucose. These numbers allow us to compute the energy generation density from the ATP production rate of $1.4*10^{-17}$ mol ATP/cell/sec. These numbers lead to the computation of the power density of or $7.3*10^{-13}W/\mu m^3 O_2\ (0.7 pW/\mu m^3)$., that is a similar numbers computed for the mitochondria and chloroplast above.

## Macromolecules
We now look at the abundance, concentration and turnover rates of macromolecules in the bacterial cell. We are interested in the genome, RNA and protein molecules.

### What are typical characteristics of a genome?
Sizes of genomes vary significantly amongst different organisms, see Table 7.7. For bacteria, they vary from about 0.5 to 9 million base pairs. The key features of the _E. coli_ K-12 MG1655 genome are summarized in Table 7.8. There are about 4500 ORFs on the genome of an average length of about 1kb. This means that the average protein size is 316 amino acids, see Figure 7.3c.

**Table 7.7:** Genome sizes. A selection of representative genome sizes from the rapidly growing list of organisms whose genomes have been sequenced. Adapted from Kimball's Biology Pages.

**Table 7.8:** Some features of the _E. coli_ genome. From (Blattner 1997).

The number of RNA polymerase binding sites is estimated to be about 2800, leading to a estimate of about 1.6 ORFs $(\approx 4.4*10^6/2400)$ per transcription unit. There are roughly 3000 copies of the RNA polymerase present in an _E. coli_ cell (Wagner 2000). Thus if 1000 of the transcription units are active at any given time, there are only 2-3 RNA polymerase molecules available for each transcription unit. The promoters have different binding strength and thus recruit a different number of RNA polymerase molecules each. ChIP-chip data can be used to estimate this distribution.

### What are typical protein concentrations?
Cells represent a fairly dense solution of protein. One can estimate the concentration ranges for individual enzymes in cells. If we assume that the cell has about 1000 proteins with an average molecular weight of 34.7kD, as is typical for an _E. coli_ cell, see Figure 7.3c, and given the fact that the cellular biomass is about 15% protein, we get:

$$\begin{equation} e_{tot} \approx \frac{1\ gm/cm^3 * 0.15}{1000 * 34700 gm/mole} = 4.32 \mu M \tag{7.15} \end{equation}$$

This estimate is, indeed, the range into which the _in vivo_ concentration of most proteins fall. It corresponds to about 2500 molecules of a particular protein molecule per cubic micron. As with metabolites there is a significant distribution around the estimate of Eq. (7.15). Important proteins such as the enzymes catalyzing major catabolic reactions tend to be present in higher concentrations, and pathways with smaller fluxes have their enzymes in lower concentrations. It should be noted that we are not assuming that all these proteins are in solution; the above number should be viewed more as a molar density.

The distribution about this mean is significant, Figure 7.3d. Many of the proteins in _E. coli_ are in concentrations as low as a few dozen per cell. The _E. coli_ cell is believed to have about 200 major proteins which brings our estimate for the abundant ones to about 12,000 copies per cell. The _E. coli_ cell has a capacity to carry about 2.0-2.3 million protein molecules.

### What are typical fluxes?
The rates of synthesis of the major classes of macromolecules in _E. coli_ are summarized in Table 7.9. The genome can be replicated in 40 min with two replication forks. This means that the speed of DNA polymerase is estimated to be

$$\begin{equation} \text{rate of DNA polymerase} = \frac{4.4*10^6\ \text{bp}}{2*40*60} \approx 900\ \text{bp/sec/fork} \tag{7.16} \end{equation}$$

RNA polymerase is much slower at 40-50 bp/sec and the ribosomes operate at about 12-21 peptide bonds per ribosome per second.

#### Protein synthesis capacity in _E. coli_
We can estimate the number of peptide bonds (pb) produced by _E. coli_ per second. To do so we will need the rate of peptide bond formation by the ribosome (12 to 21 bp/ribosome/sec (Bremer 1996, Dennis 1974, Young 1976)); and number of ribosomes present in the _E. coli_ cell $(7*10^3\ \text{to} \ 7*10^4$ ribosomes/cell depending on the growth rate (Bremer 1996)). So the total number of the peptide bonds that _E. coli_ can make per second is on the order of: $8*10^4\ \text{to}\ 1.5*10^6$ pb/cell/sec

The average size of a protein in _E. coli_ is about 320 amino acids. At about 45 to 60 min doubling time, the total amount of protein produced by _E. coli_ per second is ~300 to 900 protein molecules/cell/sec. This is equivalent to $1\ \text{to}\ 3*10^6$ molecules/cell/h as a function of growth rate, about the total number of protein per cell given above.

#### Maximum protein production rate from a single gene in murine cells
The total amount of the protein formed from a single gene in the mammalian cell can be estimated based on the total amount of mRNA present in the cytoplasm from a single gene, the rate of translation of the mRNA molecule by ribosomes, and the ribosomal spacing (Savinell 1989). Additional factors needed include gene dosage (here taken as 1), rate of mRNA degradation, velocity of the RNA polymerase II molecule, and the growth rate (Savinell 1989).

Murine hybridoma cell lines are commonly used for antibody production. For this cell type, the total amount of mRNA from a single antibody encoding gene in the cytoplasm is on the order of 40,000 mRNA molecules/cell (Gilmore 1979, Schibler 1978) the ribosomal synthesis rate is on the order of 20 nucleotides/sec [Potter72], and the ribosomal spacing on the mRNA is between 90-100 nucleotides (Christensen 1987, Potter 1972). Multiplying these numbers, we can estimate the protein production rate in a hybridoma cell line to be approximately 3000 - 6000 protein molecules/cell/sec.

### What are the typical turnover times?
The assembly of new macromolecules such as RNA and proteins requires the source of nucleotides and amino acids. These building blocks are generated by the degradation of existing RNA molecules and proteins. Many cellular components are constantly degraded and synthesized. This process is commonly characterized by the turnover rates and half-lives. Intracellular protein turnover is experimentally assessed by an addition of an isotope-labeled amino acid mixture to the normally growing or non-growing cells (Levine 1965, Pratt 2002). It has been shown that the rate of breakdown of an individual proteins is on the order of 2-20% per hour in _E. coli_ culture (Levine 1965, Neidhardt 1996).

## Cell Growth and Phenotypic Functions
### What are typical cell-specific production rates?
The estimated rates of metabolism and macromolecular synthesis can be used to compute various cellular functions and their limitations. Such computations can in turn be used for bioengineering design purposes, environmental roles and impacts of microorganisms, and for other purposes. We provide a couple of simple examples.

#### Limits on volumetric productivity
_E. coli_ is one of the most commonly used host organisms for metabolic engineering and overproduction of metabolites. In many cases, the glycolytic flux acts as a carbon entry point to the pathway for metabolite overproduction (Eiteman 2008, Jantama 2008, Yomano 2008, Zhu 2008). Thus, the substrate uptake rate (SUR) is one of the critical characteristics of the productive capabilities of the engineered cell.

Let us examine the wild-type _E. coli_ grown on glucose under anoxic conditions. As shown in Table 7.4, the (SUR) is on the order of 15-20 mmol glucose/gDW/h which translates into 1.5 gm glucose/L/h at cell densities of (VP has number). Theoretically, if all the carbon source (glucose) is converted to the desired metabolite the volumetric productivity will be approximately 3 g/L/h.

The amount of cells present in the culture, play a significant role in production potential. In the industrial settings, the cell density is usually higher which increases the volumetric productivity. Some metabolic engineered strain designs demonstrate higher SUR (Portnoy 2008) that also leads to the increase in volumetric productivity.

#### Photoautotrophic growth
_Chlorella vulgaris_ is a single-celled green algae that uses light to generate energy necessary for growth. At the top rate of photosynthesis, the specific oxygen production rate (SOPR) can be estimated to be between 20-400 fmol $O_2$/cell/h (Lee 1994a). Algae biotechnology is drawing increasing interest due to its potential for production of biofuels and fine chemicals (Lee 1994a). However, a lack of suitable photobioreactors (PBR) makes the cost of algally-derived compounds high. One of the key limiting factors for PBR is the light source; however, light-emitting diodes (LED) can be employed for these purposes.

Let us now use order of magnitude calculations to estimate the light requirement for an algae photobioreactor using _C. vulgaris_ as a model organism. Given the fact that maximum photosynthetic efficiency of _C. vulgaris_ is below 50%  (Kok 1960, Myers 1980, Pirt 1980) and one mole of photons (680 nm) is equivalent to 50W, we can estimate that in order to sustain the SOPR of 100 fmol $\text{O}_2$/cell/h each cell must receive 40pW equivalent of photons (Lee1994a). A conventional LED can provide $0.3\ \text{mW/cm}^2$ or $0.1\ \text{mW}$ per LED. With a cell density close to $10^9\ \text{cells/ml}$ and $80\ \text{cm}^3$ volume of the reactor (Lee 1994a), the photobioreactor must include close to a 100 LED to sustain the growth of algae and oxygen production.

### Balancing the fluxes and composition in an entire cell
The approximate calculation procedures presented can be used to estimate the overall flows of mass and energy in a bacterial cell. Proteins are 55% of the dry weight of cells and their most energetically costly component, so let's begin such computation with the assumption that there are about $10^9$ amino acids found in the proteins of a single cell. With this starting point and the various data given in this chapter, we can roughly estimate all the major flows using a 60 min doubling time:

* With approximately 316 amino acids found in a protein, we have to make about 3 million protein molecules.

* If we take the ribosome to make 20 pb/sec = 72,000 pb/hr, (pb=peptide bond) the we require

    $$\begin{equation} \frac{1,000,000,000}{72,000} = 14,000\ \text{ribosomes} \tag{7.17} \end{equation}$$

    to carry out this protein synthesis.

* To make 14,000 ribosomes with each having 4,500 nt length RNA molecules (nt = nucleotide), we need

    $$\begin{equation} 14,000*4,500 = 63,000,000\ \text{nt}\ \tag{7.18} \end{equation}$$

    assembled. In addition, there are 10 tRNAs of 80 nt in length per ribosome leading to an additional nucleotide requirement of

    $$\begin{equation} 10*80*14,000 = 11,200,000\ \text{nt}\ \tag{7.19} \end{equation}$$

    for a grand total of approximately 75,000,000 for stable RNA molecule synthesis.

* The total nucleotide synthesis for RNA will be 3000 RNA polymerase molecules synthesizing at the rate of 50 nt/sec or

    $$\begin{equation} 3000*50*3600 = 540,000,000\ \text{nt/hour}\ \tag{7.20} \end{equation}$$

* The fraction of RNA that is mRNA is 0.03 to 0.05 Rosenow01 or,

    $$\begin{equation} 540,000,000*(0.03\ \text{to}\ 0.05) \approx (16\ \text{to}\ 25.0)*10^6\ \text{nt/cell/hr}\ \tag{7.21} \end{equation}$$

    If the average mRNA length is 1100 nt then the cell needs to make on average 20,000 transcripts in one hour.

* We have to make 3,000,000 proteins from 20,000 transcripts, or about 150 protein molecules per transcript.

* The transcripts have a finite half live. On average, each transcript has a 5 min lifetime, or 300 sec. Due to structural constraints a ribosome can only bind every 50 nt to the mRNA, producing a maximum ribosomal loading of about 20 ribosomes per transcript. The rate of translation is 20 pb/sec. With the average length of the peptide being 316 amino acids, we can produce 1.25 protein/sec. This calculation estimated the maximum protein production from one transcript on the order of 375 protein molecules per transcript.

* To synthesize the genome, we need $2*4,500,000 = 9,000,000\ \text{nt}$ to make the double stranded DNA.

* Thus, the total metabolic requirement of amino acids and nucleotides in _E. coli_ per doubling is $1*10^9$ amino acids/cell/h and $5*10^8$ nt/cell/h.

These are the approximate overall material requirements. We also need energy to drive the process. Using Table 7.4 we can estimate energy requirements for _E. coli_ under oxic and anoxic conditions.

* Aerobically, at a doubling time of 1 hour, the glucose uptake rate is about 10 mmol/gDW/h, that is equivalent to $1.5*10^9$ molecules of glucose per cell per doubling. At 17.5 ATP produced per glucose he corresponding energy production is: $3*10^{10}$ ATP per cell per doubling.

* Anaerobically, at a doubling time of 1.5 hours, the glucose uptake rate is about 18 mmol/gDW/h, which is equivalent to $4.5*10^9$ molecules of glucose/ cell/doubling. At 3 ATP per glucose the corresponding energy production is $1.4*10^{10}$ molecules ATP/cell/doubling.

## Summary
* Data on cellular composition and over all rates are available.

* Order of magnitude estimation procedures exist through which one can obtain the approximate values for key quantities.

* In this fashion, typical concentrations, fluxes and turnover times can be estimated.

* An approximate quantitative overall multi-scale framework can be obtained for the function of complex biological processes.

$\tiny{\text{© B. Ø. Palsson 2011;}\ \text{This publication is in copyright.}\\ \text{Subject to statutory exception and to the provisions of relevant collective licensing agreements,}\\ \text{no reproduction of any part may take place without the written permission of Cambridge University Press.}}$