[med-svn] [emperor] 01/01: modified for new version

Kerim Ölçer kerimlcr-guest at moszumanska.debian.org
Fri Oct 28 17:54:05 UTC 2016


This is an automated email from the git hooks/post-receive script.

kerimlcr-guest pushed a commit to branch master
in repository emperor.

commit c80c5f5da10d29da918200827f2c09375ed2038c
Author: Kerim Ölçer <kerimlcr at gmail.com>
Date:   Fri Oct 28 20:53:08 2016 +0300

    modified for new version
---
 ChangeLog.md                                       |  105 +-
 INSTALL.md                                         |   56 +-
 LICENSE.md                                         |  312 +++--
 README.md                                          |   16 +-
 debian/changelog                                   |   16 +-
 debian/compat                                      |    2 +-
 debian/control                                     |   44 +-
 debian/patches/series                              |    2 +-
 debian/rules                                       |   52 +-
 debian/watch                                       |    2 +-
 doc/description_index.html                         |  112 +-
 doc/index.html                                     |  134 +-
 doc/tutorial_index.html                            |  107 +-
 emperor/__init__.py                                |   54 +-
 emperor/biplots.py                                 |  147 +-
 emperor/filter.py                                  |   84 +-
 emperor/format.py                                  |  717 +---------
 emperor/qiime_backports/__init__.py                |    4 +-
 emperor/qiime_backports/biplots.py                 |    6 +-
 emperor/qiime_backports/filter.py                  |   10 +-
 emperor/qiime_backports/make_3d_plots.py           |   10 +-
 emperor/qiime_backports/parse.py                   |   46 +-
 emperor/qiime_backports/util.py                    |    9 +-
 emperor/sort.py                                    |   84 +-
 emperor/util.py                                    |  648 ++++++---
 scripts/make_emperor.py                            |  633 +--------
 setup.py                                           |   86 +-
 tests/all_tests.py                                 |  220 ++-
 .../make_emperor/Fasting_Map_modified.txt          |   22 +-
 tests/scripts_test_data/make_emperor/biplot.txt    |    2 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_0.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_1.txt  |   14 +-
 .../make_emperor/otu_table_L3.txt                  |    2 +-
 .../make_emperor/unweighted_unifrac_pc.txt         |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_0.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_1.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_2.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_3.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_4.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_5.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_6.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_7.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_8.txt  |   14 +-
 .../pcoa_unweighted_unifrac_rarefaction_110_9.txt  |   14 +-
 tests/test_biplots.py                              |  490 ++++---
 tests/test_filter.py                               |  114 +-
 tests/test_format.py                               | 1467 +-------------------
 tests/test_qiime_backports/test_biplots.py         |   33 +-
 tests/test_qiime_backports/test_filter.py          |    5 +-
 tests/test_qiime_backports/test_make_3d_plots.py   |   20 +-
 tests/test_qiime_backports/test_parse.py           |    5 +-
 tests/test_qiime_backports/test_util.py            |   12 +-
 tests/test_sort.py                                 |  178 ++-
 tests/test_util.py                                 |  877 ++++++++----
 54 files changed, 2672 insertions(+), 4455 deletions(-)

diff --git a/ChangeLog.md b/ChangeLog.md
index 0bd9d1d..2b49544 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,5 +1,98 @@
-Emperor 0.9.3
-=============
+Emperor ChangeLog
+=================
+
+# Emperor 1.0
+
+Introducing Emperor 1.0, an improved and new version of Emperor. Including
+a stable Python API and JavaScript API.
+
+Emperor 0.9.51-dev
+------------------
+
+### Bug Fixes
+* Fix problem where the taxonomic vectors weren't scaled properly when the scale coordinates button was toggled  ([#386](https://github.com/biocore/emperor/issues/373).
+* Fix problem where `make_emperor.py` would attempt to parse `Icon?` files when a directory was passed via the `-i` option ([#323](https://github.com/biocore/emperor/issues/323)).
+* Fix bug where Emperor would try to animate trajectories with a single timepoint i.e. a single unique value in the gradient category.
+* Fix bug where the output saved to `--biplot_fp` would list the principal coordinate axes starting at zero instead of one ([#389](https://github.com/biocore/emperor/issues/389)).
+* Remove misleading "QIIME version" from `index.html` ([#447](https://github.com/biocore/emperor/issues/447)).
+
+### Miscellaneous
+
+* Reorganized `emperor/support_files/` to separate Emperor's source code from third-party packages.
+* Add code coverage support through [Coveralls](https://coveralls.io/r/biocore/emperor).
+* Add [flake8](http://flake8.readthedocs.org/en/2.3.0/) to enforce the PEP-8 coding guidelines in every Travis build ([#342](https://github.com/biocore/emperor/issues/342)).
+* Add an `all` target to get all the needed dependencies for emperor development (`pip install emperor[all]`).
+* Update FileSaver.js to the latest development version and fixes a bug with large file downloads.
+* Emperor's website can now be found by going to [http://emperor.microbio.me](http://emperor.microbio.me)
+
+### New features
+
+* Add a slider bar under the `Labels` tab to select different taxonomies for display.
+* Biplots now include arrows, which represent taxa variances. These can be turned off using the `Taxa arrow visibility` checkbox.
+
+Emperor 0.9.51 (5 Feb 2015)
+---------------------------
+
+* Improved error message when none of the samples match between coordinates and mapping file.
+* Removed warning due to NumPy 1.9.x.
+* Added support for NumPy 1.9.x.
+
+Emperor 0.9.5 (14 Nov 2014)
+---------------------------
+
+* Add `make_emperor.py` script auto-generated documentation.
+* Add numpydoc generated documentation setup.
+* Emperor's documentation requires `sphinx-boostrap-theme` and `sphinx`.
+* Add documentation about file formats.
+* Updated to three.js revision 68.
+* Fixed problem that removed unique/single-valued categories in the mapping file even if these were selected with `--color_by`.
+* Added [chosen](http://harvesthq.github.io/chosen/) v1.1.0 for drop down menu.
+* Replace MeshLambertMaterial for MeshPhongMaterial to get nicer coloring.
+* Add options to select among different [colorbrewer](http://colorbrewer2.org) colormaps for continuous coloring.
+* Discrete colors are provided by [colorbrewer](http://colorbrewer2.org).
+* The rainbow colormap has disappeared from emperor, see [this paper](http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=4118486) if you want to use that colormap.
+* Remove discrete/continuous coloring checkbox and replace for the color-scheme drop down menu.
+* Add option to select QIIME colors from the color-scheme drop down menu.
+* Emperor now depends on scikit-bio 0.2.1.
+
+Emperor 0.9.4 (10 Sept 2014)
+----------------------------
+
+* Category names are no longer trimmed to 25 characters in the user interface.
+* Change the minimum percent required to display a plot to be greater than 0.01 instead of 0.5.
+* The percent explained by each of the axes is now formatted as a floating point number with two digits in the mantissa.
+* The `Key` tab now uses all the available space on screen.
+* Improve mouse sensitivity to rotate, pan, zoom-in and zoom out in the 3D plot.
+* Emperor is now hosted under the biocore GitHub organization.
+* Add toggle visible button (`Invert Selected`) under the `Visibility` tab, this button will change hidden categories to visible and vice-versa.
+* Supports both NumPy 1.7 and 1.8.
+* Depends on scikit-bio 0.1.4.
+* Emperor provides a Python object that is IPython aware (emperor.Emperor) that will display a usable plot from within the IPython notebook.
+* Each of the categories in the Colors tab displays the # of samples. Also, the labels svg has this information.
+* Emperor will multiply by 100 the percentages explained in the input file if PC1 is lower than 1. This behavior can be stopped using --pct_variation_below_one.
+
+*Bug Fixes*
+
+* Fixed problem where coordinate files with large values (greater than 100) would not be displayed on screen.
+* Fixed problem that prevented the user from scrolling through the categories in the user interface.
+* Clean-up the layout of the user interface so it's cleaner and consistent.
+* Fix problem where long category names would alter the layout of the interface.
+* Fix inability to write an 'E' character in the Filename field when exporting an svg.
+* Fix problem where Emperor would generate invalid SVG files for the labels and the plot.
+* Fix inability to reset an animation using the rewind button.
+* Fix one-sample trajectories to not fail during rendering of the animation (these will get ignored).
+* Fix sample identifiers that would fail when the animation started.
+* Fix failure due to passing --missing_custom_axes_values and having a value for all rows in the column of interest. Now is ignored.
+
+*New Features*
+
+* Add animations tab to the main user interface.
+* Add unit tests for the JavaScript library code.
+* Support both classic and [scikit-bio](http://scikit-bio.org)'s coordinate formats.
+* The legends file that emperor generates now has a non-monospace font and a line surrounding each colored square.
+
+Emperor 0.9.3 (5 Dec 2013)
+--------------------------
 
 * `Use gradient colors` checkbox is now found under the `Colors` tab.
 * Merge the `Options` and `View` tabs; additionally the global opacity slider and global scale slider were moved to their respective tabs.
@@ -13,7 +106,7 @@ Emperor 0.9.3
 * Add more meaningful error message for biplots when the contingency table passed included only one row.
 
 Emperor 0.9.2 (24 Oct 2013)
-===========================
+---------------------------
 
 *Bug Fixes*
 
@@ -21,7 +114,7 @@ Emperor 0.9.2 (24 Oct 2013)
 
 
 Emperor 0.9.1 (21 Oct 2013)
-===========================
+---------------------------
 
 *New features*
 
@@ -43,7 +136,7 @@ Emperor 0.9.1 (21 Oct 2013)
 * Labels for biplots now have a color picker.
 * Add color pickers for connecting bars in coordinate comparison plots.
 * Add option to select a master set of coordinates when making a comparison plot.
-* Adds a feature to negate axes. With this feature you can negate the coordinates of each data point. As a result, the spheres and/or edges will be adjusted appropriately. 
+* Adds a feature to negate axes. With this feature you can negate the coordinates of each data point. As a result, the spheres and/or edges will be adjusted appropriately.
 * Minor additions to the separator controller for the side bar.
 * As of 308629f550ff3e108903d3bcf1ce76ce85f4cb96 Emperor is now released under a BSD license.
 
@@ -63,7 +156,7 @@ Emperor 0.9.1 (21 Oct 2013)
 
 
 Emperor 0.9.0 (14 May 2013)
-===========================
+---------------------------
 
 *New features*:
 
diff --git a/INSTALL.md b/INSTALL.md
index 2603830..83a726c 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -1,28 +1,56 @@
 Emperor Installation Notes
 ==========================
 
-Emperor is a python package that relies in [QIIME](http://www.qiime.org), [NumPy](http://www.numpy.org) and [PyCogent](http://www.pycogent.org). These packages must be installed prior running the `setup.py` script.
+Emperor is a Python package that powers a JavaScript-based user interface. The
+Python library relies on several packages from the scientific Python stack.
 
-To download Emperor, use [this link](https://github.com/qiime/emperor/archive/master.zip) or use git to get the latest version of the repository:
+To install the latest release version of Emperor, you can use `pip` or
+`conda`:
 
-    git clone git://github.com/qiime/emperor.git
+```bash
+    # with pip
+    pip install emperor
 
-Installation
-============
+    # with conda
+    conda install -c bioconda emperor
+```
 
-To perform a global installation of Emperor, execute the following command from a terminal session:
 
-    python setup.py install
+Pre-releases
+============
 
-If you do not want to do a global installation, you will have to add the Emperor scripts and libraries to the `PATH` and `PYTHONPATH` environment variables. To add these variables to your `.bash_profile` issue the following terminal commands:
+If you are interested in using a pre-release version (for example `1.0.0beta`)
+you can use `pip` or `conda`:
 
-``` bash
-echo "export PATH=$HOME/emperor_bin/:$PATH" >> ~/.bash_profile
-echo "export PYTHONPATH=$HOME/emperor_lib/:$PYTHONPATH" >> ~/.bash_profile
-python setup.py install --install-scripts=~/emperor_bin/ --install-purelib=~/emperor_lib/ --install-lib=~/emperor_lib/
+```bash
+    # with pip
+    pip install emperor --pre
+
+    # with conda
+    conda install -c biocore emperor
 ```
 
-To test for a correct installation, open a new terminal window and issue the following command to see the help of `make_emperor.py`:
+Note that we will update these pre-releases as often as it makes sense.
+
+Developers
+==========
 
-    make_emperor.py -h
+If you are planning to do development, we recommend that you clone the git
+repository, create a new environment (using `conda` or `virtualenvs`) and then
+use `pip install -e` to work on the source code without having to reinstall
+when you make editions:
 
+```bash
+    # fork
+    git clone git://github.com/YOUR-USERNAME/emperor.git
+
+    # if you are using conda
+    conda create -n emperor-dev scipy numpy pandas matplotlib jupyter
+
+    # if you are using virtualenvs
+    mkvirtualenv emperor-dev && workon emperor-dev
+
+    # now install the repository
+    cd emperor
+    pip install -e '.[all]'
+```
diff --git a/LICENSE.md b/LICENSE.md
index e0a947e..64b0003 100644
--- a/LICENSE.md
+++ b/LICENSE.md
@@ -5,7 +5,141 @@ Emperor makes usage of all of the following copyrighted packages; their licenses
 
 --------------------------------------------------------------------------------
 
-### THREE.js ([r58](https://github.com/mrdoob/three.js/tree/r58)) is released under the MIT License
+#### RequireJS (v2.1.22)
+[require.js](https://github.com/jrburke/requirejs) - A file and module loader for JavaScript
+
+Copyright (c) 2010-2015, The Dojo Foundation
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  * Redistributions of source code must retain the above copyright notice, this
+    list of conditions and the following disclaimer.
+  * Redistributions in binary form must reproduce the above copyright notice,
+    this list of conditions and the following disclaimer in the documentation
+    and/or other materials provided with the distribution.
+  * Neither the name of the Dojo Foundation nor the names of its contributors
+    may be used to endorse or promote products derived from this software
+    without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#### SlickGrid (v2.1.0-dev)
+[SlickGrid](https://github.com/6pac/SlickGrid) - A lightning fast JavaScript grid/spreadsheet (d05dcd5b9369cae4b61df895ef7f51e8248e11c2)
+
+Copyright (c) 2010 Michael Leibman, http://github.com/mleibman/slickgrid
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+
+#### Chroma (v1.1.1)
+[chroma.js](https://github.com/gka/chroma.js) - JavaScript library for color conversions
+
+Copyright (c) 2011-2013, Gregor Aisch
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this
+   list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. The name Gregor Aisch may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL GREGOR AISCH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+chroma.js includes colors from colorbrewer2.org,
+which are released under the following license:
+
+
+Copyright (c) 2002 Cynthia Brewer, Mark Harrower,
+and The Pennsylvania State University.
+
+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
+http://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.
+
+
+Named colors are taken from X11 Color Names.
+http://www.w3.org/TR/css3-color/#svg-color
+
+--------------------------------------------------------------------------------
+
+#### Chosen (v1.4.2)
+- by Patrick Filler for [Harvest](http://getharvest.com)
+- Copyright (c) 2011-2014 by Harvest
+
+Available for use under the [MIT License](http://en.wikipedia.org/wiki/MIT_License)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+--------------------------------------------------------------------------------
+
+### THREE.js ([r73](https://github.com/mrdoob/three.js/tree/r73) is released under the MIT License
 
 The MIT License
 
@@ -31,7 +165,7 @@ THE SOFTWARE.
 
 --------------------------------------------------------------------------------
 
-### jQuery ([1.8](https://github.com/jquery/jquery/tree/1.8.0), [1.7.1](https://github.com/jquery/jquery/tree/1.7.1) & [1.6.2](https://github.com/jquery/jquery/tree/1.6.2)) is released under the MIT License
+### jQuery ([2.1.4](https://github.com/jquery/jquery/tree/2.1.4)) is released under the MIT License
 
 Copyright 2013 jQuery Foundation and other contributors
 http://jquery.com/
@@ -57,7 +191,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 --------------------------------------------------------------------------------
 
-### Spectrum ([1.0.2](https://github.com/bgrins/spectrum/tree/1.0.2)) is released under the MIT License
+### Spectrum ([1.8.0](https://github.com/bgrins/spectrum/tree/1.8.0)) is released under the MIT License
 
 Copyright (c) 2013, Brian Grinstead, http://briangrinstead.com
 
@@ -82,9 +216,10 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 --------------------------------------------------------------------------------
 
-### [ColorPicker](https://github.com/laktek/really-simple-color-picker/) is released under the MIT License
+### Underscore.js [1.8.3](https://github.com/jashkenas/underscore)
 
-Copyright (c) 2012 Lakshan Perera
+Copyright (c) 2009-2013 Jeremy Ashkenas, DocumentCloud and Investigative
+Reporters & Editors
 
 Permission is hereby granted, free of charge, to any person
 obtaining a copy of this software and associated documentation
@@ -107,74 +242,10 @@ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 OTHER DEALINGS IN THE SOFTWARE.
 
---------------------------------------------------------------------------------
-
-### Parallel Coordinates [v0.1.7](http://syntagmatic.github.io/parallel-coordinates/)
-
-Copyright (c) 2012, Kai Chang
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
+### QUnit [1.12.0](https://github.com/jquery/qunit)
 
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-* The name Kai Chang may not be used to endorse or promote products
-  derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
---------------------------------------------------------------------------------
-
-### d3 [v3](https://github.com/mbostock/d3) is released under the
-
-Copyright (c) 2013, Michael Bostock
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice, this
-  list of conditions and the following disclaimer.
-
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-
-* The name Michael Bostock may not be used to endorse or promote products
-  derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL MICHAEL BOSTOCK BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
-BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
-OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
-EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
---------------------------------------------------------------------------------
-
-### THREEx.screenshot [v1](http://learningthreejs.com/data/THREEx/docs/THREEx.screenshot.html) 
-[repository](https://github.com/jeromeetienne/threex)
-
-Copyright (c) 2011 Jerome Etienne, http://jetienne.com
+Copyright 2013 jQuery Foundation and other contributors
+http://jquery.com/
 
 Permission is hereby granted, free of charge, to any person obtaining
 a copy of this software and associated documentation files (the
@@ -197,27 +268,84 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
 --------------------------------------------------------------------------------
 
-### FileSaver.js [283e78fd3c](https://github.com/eligrey/FileSaver.js/) 
+### contextMenu [2.1.1](https://github.com/swisnl/jQuery-contextMenu)
+MIT licensed
 
-Copyright (c) 2011 [Eli Grey](http://eligrey.com).
+--------------------------------------------------------------------------------
 
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use,
-copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the
-Software is furnished to do so, subject to the following
-conditions:
+### FileSaver [1.1.20160328](https://github.com/eligrey/FileSaver.js/)
 
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
+Copyright © 2015 Eli Grey.
 
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
-OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
-HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
-WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
-FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
-OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+--------------------------------------------------------------------------------
+
+### Blob [079824b] (https://github.com/eligrey/Blob.js/tree/079824b6c118fbcd0b99c561d57ad192d2c6619b)
+
+Copyright © 2015 Eli Grey.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+--------------------------------------------------------------------------------
+
+### D3.js [3.5.17](https://github.com/d3/d3/releases/tag/v3.5.17)
+
+
+Copyright 2010-2016 Mike Bostock
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+* Neither the name of the author nor the names of contributors may be used to
+  endorse or promote products derived from this software without specific prior
+  written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README.md b/README.md
index 5afb06a..ec1d432 100644
--- a/README.md
+++ b/README.md
@@ -1,12 +1,16 @@
 Emperor
 =======
 
-[![Build Status](https://travis-ci.org/qiime/emperor.png?branch=master)](https://travis-ci.org/qiime/emperor)
+[![Join the chat at https://gitter.im/biocore/emperor](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/biocore/emperor?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+[![Build Status](https://travis-ci.org/biocore/emperor.png?branch=master)](https://travis-ci.org/biocore/emperor) [![Coverage Status](https://coveralls.io/repos/biocore/emperor/badge.svg)](https://coveralls.io/r/biocore/emperor)
 
 Emperor is a next-generation tool for the analysis and visualization of large microbial ecology datasets; amongst many features Emperor provides a modern user interface that will rapidly adjust to your daily workflow.
 
 To start using Emperor, please refer to the [installation notes](INSTALL.md).
 
+Before contributing code to Emperor, please familiarize yourself with the [contributing guidelines](CONTRIBUTING.md).
+
 ## Usage examples
 
 The main interface to create Emperor visualizations is the `make_emperor.py` script, inputing a mapping file and a PCoA data file, will generate an Emperor graphical user interface to analyze and visualize your data.
@@ -27,8 +31,8 @@ make_emperor.py -i unweighted_unifrac_pc_time.txt -m mapping_with_time.txt -a TI
 
 Some build examples are bundled with every Emperor repository, you can begin exploring some sample data using **Google Chrome**:
 
-- To see an example of a simple PCoA plot, see this [link](http://emperor.colorado.edu/master/make_emperor/emperor_output/index.html).
-- To see an example of a Jackknifed plot, see this [link](http://emperor.colorado.edu/master/make_emperor/jackknifed_pcoa/index.html).
-- To see an example of a PCoA Biplot, see this [link](http://emperor.colorado.edu/master/make_emperor/biplot/index.html).
-- To see an example of a PCoA plot with connecting lines between samples, see this [link](http://emperor.colorado.edu/master/make_emperor/vectors/index.html).
-- To see an example of a PCoA plot with connecting lines between samples and an explicit axis, see this [link](http://emperor.colorado.edu/master/make_emperor/sorted_by_DOB/index.html).
+- To see an example of a simple PCoA plot, see this [link](http://emperor.microbio.me/master/make_emperor/emperor_output/index.html).
+- To see an example of a Jackknifed plot, see this [link](http://emperor.microbio.me/master/make_emperor/jackknifed_pcoa/index.html).
+- To see an example of a PCoA Biplot, see this [link](http://emperor.microbio.me/master/make_emperor/biplot/index.html).
+- To see an example of a PCoA plot with connecting lines between samples, see this [link](http://emperor.microbio.me/master/make_emperor/vectors/index.html).
+- To see an example of a PCoA plot with connecting lines between samples and an explicit axis, see this [link](http://emperor.microbio.me/master/make_emperor/sorted_by_DOB/index.html).
diff --git a/debian/changelog b/debian/changelog
index 726bc26..2ef4edb 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,14 +1,8 @@
-emperor (0.9.3+dfsg-1) UNRELEASED; urgency=medium
+emperor (1.0.0beta5) UNRELEASED; urgency=medium
 
-  * Initial upload to Debian (Closes: #???)
+  * Team upload.
+  * Packaged software
+  * Setup.py fixed
 
- -- Andreas Tille <tille at debian.org>  Tue, 25 Feb 2014 15:17:10 +0100
-
-python-emperor (0.9.3-0biolinux1) precise; urgency=low
-
-  * New package as required by QIIME 1.8
-  * Move support_files to /usr/share
-  * Make manpage for make_emperor
-
- -- Tim Booth <tbooth at ceh.ac.uk>  Mon, 24 Feb 2014 17:47:51 +0000
+ -- Kerim ÖLÇER <lcr at debian>  Wed, 19 Oct 2016 22:19:34 +0300
 
diff --git a/debian/compat b/debian/compat
index ec63514..7f8f011 100644
--- a/debian/compat
+++ b/debian/compat
@@ -1 +1 @@
-9
+7
diff --git a/debian/control b/debian/control
index 4ec6cbb..2cb8a79 100644
--- a/debian/control
+++ b/debian/control
@@ -1,34 +1,22 @@
 Source: emperor
-Maintainer: Debian Med Packaging Team <debian-med-packaging at lists.alioth.debian.org>
-Uploaders: Steffen Moeller <moeller at debian.org>,
-           Andreas Tille <tille at debian.org>,
-           Tim Booth <tbooth at ceh.ac.uk>
-Section: science
+Maintainer: Emperor development team <yoshiki89 at gmail.com>
+Section: python
 Priority: optional
-Build-Depends: debhelper (>= 9),
-               python,
-               dh-linktree,
-               libjs-twitter-bootstrap,
-               libjs-jquery-ui,
-               libjs-jquery,
-               libjs-d3
-Standards-Version: 3.9.5
-Vcs-Browser: https://anonscm.debian.org/cgit/debian-med/emperor.git
-Vcs-Git: https://anonscm.debian.org/git/debian-med/emperor.git
-Homepage: http://biocore.github.io/emperor/
+Build-Depends: python-all (>= 2.6.6-3), debhelper (>= 7.4.3)
+Standards-Version: 3.9.1
 
-Package: emperor
+
+
+Package: python-emperor
 Architecture: all
-Depends: ${misc:Depends},
-         ${python:Depends}
-Description: tool for visualizing high-throughput microbial community data
- Emperor is an interactive next generation tool for the analysis, visualization
- and understanding of high throughput microbial ecology datasets.
+Depends: ${misc:Depends}, ${python:Depends}
+Description: Emperor
+ Emperor: a tool for visualizing high-throughput microbial community data
+ .
+ EMPeror: a tool for visualizing high-throughput microbial community data.
+ Vazquez-Baeza Y, Pirrung M, Gonzalez A, Knight R.
+ Gigascience. 2013 Nov 26;2(1):16.
  .
- Due to its tailor-made graphical user interface, delving into a new dataset to
- elucidate the patterns hidden in the data has never been easier. Emperor brings
- a rich set of customizations and modifications that can be integrated into any
- QIIME compliant dataset; with lightweight data files and hardware accelerated
- graphics, constitutes itself as the state of the art for analyzing
- N-dimensional data using principal coordinates analysis.
+
+
 
diff --git a/debian/patches/series b/debian/patches/series
index 458e8ae..3da8193 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1 +1 @@
-fetch_examples_from_web.patch
+setup-fix
diff --git a/debian/rules b/debian/rules
index 0551f48..595f0a0 100755
--- a/debian/rules
+++ b/debian/rules
@@ -1,33 +1,31 @@
 #!/usr/bin/make -f
-# -*- makefile -*-
 
-# Uncomment this to turn on verbose mode.
-#export DH_VERBOSE=1
-
-#Allowing this to be overridden by environemnt helps with backports
-DEB_PYTHON_SUPPORT?=python2
+# This file was automatically generated by stdeb 0.8.5 at
+# Wed, 19 Oct 2016 22:16:02 +0300
 
 %:
-	dh $@ --with $(DEB_PYTHON_SUPPORT) --with linktree
+	dh $@ --with python2 --buildsystem=python_distutils
+
+
+override_dh_auto_clean:
+	python setup.py clean -a
+	find . -name \*.pyc -exec rm {} \;
+
+
+
+override_dh_auto_build:
+	python setup.py build --force
+
+
 
 override_dh_auto_install:
-	dh_auto_install
-	#Shunt support_files to /usr/share
-	( cd debian/emperor/usr/lib/python*/dist-packages/emperor && \
-	  mkdir -p ../../../../share/emperor ; \
-	  mv support_files ../../../../share/emperor ; \
-	  ln -s ../../../../share/emperor/support_files )
-	( cd debian/emperor/usr/bin ; \
-	  mv make_emperor.py make_emperor )
-
-override_dh_installdocs:
-	cp -rp doc html
-	dh_installdocs
-
-override_dh_clean:
-	dh_clean
-	rm -rf html
-
-#Don't compress .js files
-override_dh_compress:
-	dh_compress -X.js
+	python setup.py install --force --root=debian/python-emperor --no-compile -O0 --install-layout=deb  
+
+
+
+override_dh_python2:
+	dh_python2 --no-guessing-versions
+
+
+
+
diff --git a/debian/watch b/debian/watch
index b9e10c7..292465d 100644
--- a/debian/watch
+++ b/debian/watch
@@ -1,3 +1,3 @@
 version=3
 opts=dversionmangle=s/\+dfsg// \
-   https://pypi.python.org/pypi/emperor/ .*/emperor-([.0-9]+)\.(?:tgz|tar.gz|tar.bz2)
+   https://github.com/biocore/emperor/tags .*/v?(\d\S+)\.tar\.gz
diff --git a/doc/description_index.html b/doc/description_index.html
index 801de03..15616ba 100644
--- a/doc/description_index.html
+++ b/doc/description_index.html
@@ -6,7 +6,9 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="description" content="">
     <meta name="author" content="">
-    <link href="bootstrap/css/bootstrap.css" rel="stylesheet">
+    <script type="text/javascript" src="bootstrap/js/jquery-2.2.3.min.js"></script>
+    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
+    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <style type="text/css">
       body {
         padding-top: 20px;
@@ -21,67 +23,10 @@
       .container > hr {
         margin: 60px 0;
       }
-
-      /* Main marketing message and sign up button */
-      .jumbotron {
-        margin: 80px 0;
-        text-align: center;
-      }
-      .jumbotron h1 {
-        font-size: 100px;
-        line-height: 1;
-      }
-      .jumbotron .lead {
-        font-size: 24px;
-        line-height: 1.25;
-      }
-      .jumbotron .btn {
-        font-size: 21px;
-        padding: 14px 24px;
-      }
-
-      /* Supporting marketing content */
-      .marketing {
-        margin: 60px 0;
-      }
-      .marketing p + h4 {
-        margin-top: 28px;
-      }
-
-
-      /* Customize the navbar links to be fill the entire space of the .navbar */
-      .navbar .navbar-inner {
-        padding: 0;
-      }
-      .navbar .nav {
-        margin: 0;
-        display: table;
-        width: 100%;
-      }
-      .navbar .nav li {
-        display: table-cell;
-        width: 1%;
-        float: none;
-      }
-      .navbar .nav li a {
-        font-weight: bold;
-        text-align: center;
-        border-left: 1px solid rgba(255,255,255,.75);
-        border-right: 1px solid rgba(0,0,0,.1);
-      }
-      .navbar .nav li:first-child a {
-        border-left: 0;
-        border-radius: 3px 0 0 3px;
-      }
-      .navbar .nav li:last-child a {
-        border-right: 0;
-        border-radius: 0 3px 3px 0;
-      }
     </style>
-    <link href="bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
 
     <!-- GitHub ribbon -->
-    <a href="https://github.com/qiime/emperor"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
+    <a href="https://github.com/biocore/emperor"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
     <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
     <!--[if lt IE 9]>
       <script src="bootstrap/js/html5shiv.js"></script>
@@ -97,25 +42,28 @@
 
       <div class="masthead">
         <a href="index.html"><p align="center"><img src="img/emperor_heading.png" alt="Emperor Logo"></p></a>
-        <div class="navbar">
-          <div class="navbar-inner">
-            <div class="container">
-              <ul class="nav">
+        <nav class="nabvar navbar-default">
+          <div class="container-fluid">
+            <div class="navbar-collapse collapse">
+              <ul class="nav navbar-nav">
                 <li><a href="index.html">Home</a></li>
-                <li class="active"><a href="description_index.html">Description</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Documentation<span class="caret"></span></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="build/html/index.html">User Documentation</a></li>
+                    <li><a href="build/jsdoc/index.html">Javascript Documentation</a></li>
+                  </ul>
+                </li>
+                <li class="active"><a href="#">Description</a></li>
                 <li><a href="tutorial_index.html">Tutorial</a></li>
-                <li><a href="installation_index.html">Installation</a></li>
-                <li><a href="https://github.com/qiime/emperor/issues">Support</a></li>
+                <li><a href="https://github.com/biocore/emperor/blob/new-api/INSTALL.md#emperor-installation-notes">Installation</a></li>
+                <li><a href="https://github.com/biocore/emperor/issues">Support</a></li>
               </ul>
             </div>
           </div>
-        </div><!-- /.navbar -->
+        </nav><!-- /.navbar -->
       </div>
 
-      <!-- Jumbotron -->
-      <div class="jumbotron">
-
-      </div>
         <h2>Overview</h2>
         <p class="lead" align="justify">
           Emperor is a local full-browser enabled scatter plots visual tool. Its modern user interface, allows you to customize the appearance of your plot by controlling things like: opacity, sphere scaling, coloring, dimensions being presented among many others.
@@ -148,7 +96,7 @@
             Shows a list of the categories listed under the mapping file column selected in the menu of this tab (for this example DOB). Each category has a color box where you can modify the current color of the samples that belong to this category.
           </p>
           <p align="center"><img src="img/colors_menu.png" alt="Coloring Menu Example"></p>
-        <h3 class="muted">Vsibility</h3>
+        <h3 class="muted">Visibility</h3>
           <p class="lead" align="justify">
             Shows a list of the categories listed under the mapping file column selected in the menu of this tab, for each of these categories a checkbox and a slider is presented. The checkbox will allow you to hide (unchecked) or show (checked) samples that belong to each category. The slider controls the opacity of the samples defined under this category.
           </p>
@@ -181,29 +129,11 @@
       <hr>
 
       <div class="footer">
-        <a href="https://github.com/qiime/emperor/network/members">
+        <a href="https://github.com/biocore/emperor/network/members">
           <p align="center">© The Emperor Development Team</p>
         </a>
       </div>
 
     </div> <!-- /container -->
-
-    <!-- Le javascript
-    ================================================== -->
-    <!-- Placed at the end of the document so the pages load faster -->
-    <script src="bootstrap/js/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap-transition.js"></script>
-    <script src="bootstrap/js/bootstrap-alert.js"></script>
-    <script src="bootstrap/js/bootstrap-modal.js"></script>
-    <script src="bootstrap/js/bootstrap-dropdown.js"></script>
-    <script src="bootstrap/js/bootstrap-scrollspy.js"></script>
-    <script src="bootstrap/js/bootstrap-tab.js"></script>
-    <script src="bootstrap/js/bootstrap-tooltip.js"></script>
-    <script src="bootstrap/js/bootstrap-popover.js"></script>
-    <script src="bootstrap/js/bootstrap-button.js"></script>
-    <script src="bootstrap/js/bootstrap-collapse.js"></script>
-    <script src="bootstrap/js/bootstrap-carousel.js"></script>
-    <script src="bootstrap/js/bootstrap-typeahead.js"></script>
-
   </body>
 </html>
diff --git a/doc/index.html b/doc/index.html
index 47d027f..9eec1f0 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -4,9 +4,11 @@
     <meta charset="utf-8">
     <title>Emperor</title>
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <script type="text/javascript" src="bootstrap/js/jquery-2.2.3.min.js"></script>
+    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
     <meta name="description" content="">
     <meta name="author" content="">
-    <link href="bootstrap/css/bootstrap.css" rel="stylesheet">
+    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <style type="text/css">
       body {
         padding-top: 20px;
@@ -22,66 +24,20 @@
         margin: 60px 0;
       }
 
-      /* Main marketing message and sign up button */
-      .jumbotron {
-        margin: 80px 0;
-        text-align: center;
-      }
-      .jumbotron h1 {
-        font-size: 100px;
-        line-height: 1;
-      }
-      .jumbotron .lead {
-        font-size: 24px;
-        line-height: 1.25;
-      }
-      .jumbotron .btn {
-        font-size: 21px;
-        padding: 14px 24px;
-      }
-
-      /* Supporting marketing content */
-      .marketing {
-        margin: 60px 0;
-      }
-      .marketing p + h4 {
-        margin-top: 28px;
-      }
-
-
-      /* Customize the navbar links to be fill the entire space of the .navbar */
-      .navbar .navbar-inner {
-        padding: 0;
-      }
-      .navbar .nav {
-        margin: 0;
-        display: table;
-        width: 100%;
-      }
-      .navbar .nav li {
-        display: table-cell;
-        width: 1%;
-        float: none;
-      }
-      .navbar .nav li a {
-        font-weight: bold;
-        text-align: center;
-        border-left: 1px solid rgba(255,255,255,.75);
-        border-right: 1px solid rgba(0,0,0,.1);
-      }
-      .navbar .nav li:first-child a {
-        border-left: 0;
-        border-radius: 3px 0 0 3px;
-      }
-      .navbar .nav li:last-child a {
-        border-right: 0;
-        border-radius: 0 3px 3px 0;
+      @media (min-width: 768px) {
+        .navbar .navbar-nav {
+            display: inline-block;
+            float: none;
+        }
+        
+        .navbar .navbar-collapse {
+            text-align: center;
+        }
       }
     </style>
-    <link href="bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
 
     <!-- GitHub ribbon -->
-    <a href="https://github.com/qiime/emperor"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
+    <a href="https://github.com/biocore/emperor"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
     <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
     <!--[if lt IE 9]>
       <script src="bootstrap/js/html5shiv.js"></script>
@@ -97,19 +53,26 @@
 
       <div class="masthead">
         <a href="index.html"><p align="center"><img src="img/emperor_heading.png" alt="Emperor Logo"></p></a>
-        <div class="navbar">
-          <div class="navbar-inner">
-            <div class="container">
-              <ul class="nav">
+        <nav class="nabvar navbar-default" role="navigation">
+          <div class="container-fluid">
+            <div class="collapse navbar-collapse navbar-ex1-collapse">
+              <ul class="nav navbar-nav">
                 <li class="active"><a href="#">Home</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Documentation<span class="caret"></span></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="build/html/index.html">Python Documentation</a></li>
+                    <li><a href="build/jsdoc/index.html">Javascript Documentation</a></li>
+                  </ul>
+                </li>
                 <li><a href="description_index.html">Description</a></li>
                 <li><a href="tutorial_index.html">Tutorial</a></li>
-                <li><a href="installation_index.html">Installation</a></li>
-                <li><a href="https://github.com/qiime/emperor/issues">Support</a></li>
+                <li><a href="https://github.com/biocore/emperor/blob/new-api/INSTALL.md#emperor-installation-notes">Installation</a></li>
+                <li><a href="https://github.com/biocore/emperor/issues">Support</a></li>
               </ul>
             </div>
           </div>
-        </div><!-- /.navbar -->
+        </nav><!-- /.navbar -->
       </div>
 
       <!-- Jumbotron -->
@@ -118,12 +81,24 @@
         <br><br><br><br> -->
         <p class="lead" align="justify">Emperor is an interactive next generation tool for the analysis, visualization and understanding of high throughput microbial ecology datasets.
         </p>
-        <img src="img/sample_1.png" alt="Emperor">
         <p class="lead" align="justify">
-          Due to it’s tailor-made graphical user interface, delving into a new dataset to elucidate the patterns hidden in the data, has never been easier. Emperor brings a rich set of customizations and modifications that can be integrated into any <a href="http://qiime.org">QIIME</a> compliant dataset; with lightweight data files and hardware accelerated graphics, constitutes itself as the state of the art for analyzing N-dimensional data using principal coordinates analysis.
+        Due to its tailor-made graphical user interface, delving into a new dataset to elucidate the patterns hidden in the data, has never been easier. Emperor brings a rich set of customizations and modifications that can be integrated into any <a href="http://qiime.org">QIIME</a> or <a href="http://scikit-bio.org">scikit-bio</a> compliant dataset; with lightweight data files and hardware accelerated graphics, constitutes itself as the state of the art for analyzing N-dimensional data  [...]
         </p>
+        <p class="lead" align="justify">
+          If you use Emperor for any published research, please include the following citation:<br>
+          <blockquote>
+            <div align="left">
+              <b>EMPeror: a tool for visualizing high-throughput microbial community data</b><br>
+              Vazquez-Baeza Y, Pirrung M, Gonzalez A, Knight R.<br>
+              Gigascience. 2013 Nov 26;2(1):16.<br>
+            </div>
+          </blockquote>
+        </p>
+        <p class="lead" align="justify">
+        You can find the <a href="http://www.gigasciencejournal.com/content/2/1/16/">Emperor paper here</a>.
+        </p>
+        <img src="img/sample_1.png" alt="Emperor">
         <br>
-        <strong><p class="text-error lead" align="justify">We've encountered that for large studies (more than five thousand samples) a 64-bit browser is needed. Even though we recommend Google Chrome, there are no official 64-bit binaries for OS X or Windows (Linux builds are 64-bit by default, see <a href="https://code.google.com/p/chromium/issues/detail?id=18323">issue #18323</a> and <a href="https://code.google.com/p/chromium/issues/detail?id=312958">issue #312958</a>), if you encoun [...]
       </div>
 
       <hr>
@@ -133,46 +108,29 @@
         <div class="span4">
           <h2>Biplots</h2>
           <p>To visualize the taxa  driving the differences in a PCoA plot we can use biplots.</p>
-          <p><a class="btn" href="http://emperor.colorado.edu/master/make_emperor/biplot/index.html">Biplots Example »</a></p>
+          <p><a class="btn" href="http://emperor.microbio.me/master/make_emperor/biplot/index.html">Biplots Example »</a></p>
         </div>
         <div class="span4">
           <h2>Jackknifing</h2>
           <p>A jackknifed PCoA plot (with confidence intervals for each sample) helps to assure that our rarefaction selection is not the cause of the clustering patterns we are looking in beta diversity.</p>
-          <p><a class="btn" href="http://emperor.colorado.edu/master/make_emperor/jackknifed_pcoa/index.html">Jackknifing Example »</a></p>
+          <p><a class="btn" href="http://emperor.microbio.me/master/make_emperor/jackknifed_pcoa/index.html">Jackknifing Example »</a></p>
        </div>
         <div class="span4">
           <h2>Gradients</h2>
           <p>Integrating gradient information to our coloring scheme, such as pH, time, or geographical location can be done in multiple ways with Emperor. One of them, is to add an explicit axis to the plot, from the mapping file.</p>
-          <p><a class="btn" href="http://emperor.colorado.edu/master/make_emperor/vectors/index.html">Gradient Example »</a></p>
+          <p><a class="btn" href="http://emperor.microbio.me/master/make_emperor/vectors/index.html">Gradient Example »</a></p>
         </div>
       </div>
 
       <hr>
 
       <div class="footer">
-        <a href="https://github.com/qiime/emperor/network/members">
+        <a href="https://github.com/biocore/emperor/network/members">
           <p align="center">© The Emperor Development Team</p>
         </a>
       </div>
 
     </div> <!-- /container -->
 
-    <!-- Le javascript
-    ================================================== -->
-    <!-- Placed at the end of the document so the pages load faster -->
-    <script src="bootstrap/js/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap-transition.js"></script>
-    <script src="bootstrap/js/bootstrap-alert.js"></script>
-    <script src="bootstrap/js/bootstrap-modal.js"></script>
-    <script src="bootstrap/js/bootstrap-dropdown.js"></script>
-    <script src="bootstrap/js/bootstrap-scrollspy.js"></script>
-    <script src="bootstrap/js/bootstrap-tab.js"></script>
-    <script src="bootstrap/js/bootstrap-tooltip.js"></script>
-    <script src="bootstrap/js/bootstrap-popover.js"></script>
-    <script src="bootstrap/js/bootstrap-button.js"></script>
-    <script src="bootstrap/js/bootstrap-collapse.js"></script>
-    <script src="bootstrap/js/bootstrap-carousel.js"></script>
-    <script src="bootstrap/js/bootstrap-typeahead.js"></script>
-
   </body>
 </html>
diff --git a/doc/tutorial_index.html b/doc/tutorial_index.html
index 2586827..91fd5ee 100644
--- a/doc/tutorial_index.html
+++ b/doc/tutorial_index.html
@@ -6,7 +6,9 @@
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="description" content="">
     <meta name="author" content="">
-    <link href="bootstrap/css/bootstrap.css" rel="stylesheet">
+    <script type="text/javascript" src="bootstrap/js/jquery-2.2.3.min.js"></script>
+    <script type="text/javascript" src="bootstrap/js/bootstrap.min.js"></script>
+    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
     <style type="text/css">
       body {
         padding-top: 20px;
@@ -21,67 +23,10 @@
       .container > hr {
         margin: 60px 0;
       }
-
-      /* Main marketing message and sign up button */
-      .jumbotron {
-        margin: 80px 0;
-        text-align: center;
-      }
-      .jumbotron h1 {
-        font-size: 100px;
-        line-height: 1;
-      }
-      .jumbotron .lead {
-        font-size: 24px;
-        line-height: 1.25;
-      }
-      .jumbotron .btn {
-        font-size: 21px;
-        padding: 14px 24px;
-      }
-
-      /* Supporting marketing content */
-      .marketing {
-        margin: 60px 0;
-      }
-      .marketing p + h4 {
-        margin-top: 28px;
-      }
-
-
-      /* Customize the navbar links to be fill the entire space of the .navbar */
-      .navbar .navbar-inner {
-        padding: 0;
-      }
-      .navbar .nav {
-        margin: 0;
-        display: table;
-        width: 100%;
-      }
-      .navbar .nav li {
-        display: table-cell;
-        width: 1%;
-        float: none;
-      }
-      .navbar .nav li a {
-        font-weight: bold;
-        text-align: center;
-        border-left: 1px solid rgba(255,255,255,.75);
-        border-right: 1px solid rgba(0,0,0,.1);
-      }
-      .navbar .nav li:first-child a {
-        border-left: 0;
-        border-radius: 3px 0 0 3px;
-      }
-      .navbar .nav li:last-child a {
-        border-right: 0;
-        border-radius: 0 3px 3px 0;
-      }
     </style>
-    <link href="bootstrap/css/bootstrap-responsive.css" rel="stylesheet">
 
     <!-- GitHub ribbon -->
-    <a href="https://github.com/qiime/emperor"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://s3.amazonaws.com/github/ribbons/forkme_right_orange_ff7600.png" alt="Fork me on GitHub"></a>
+    <a href="https://github.com/biocore/emperor"><img style="position: absolute; top: 0; right: 0; border: 0;" src="https://camo.githubusercontent.com/38ef81f8aca64bb9a64448d0d70f1308ef5341ab/68747470733a2f2f73332e616d617a6f6e6177732e636f6d2f6769746875622f726962626f6e732f666f726b6d655f72696768745f6461726b626c75655f3132313632312e706e67" alt="Fork me on GitHub" data-canonical-src="https://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png"></a>
     <!-- HTML5 shim, for IE6-8 support of HTML5 elements -->
     <!--[if lt IE 9]>
       <script src="bootstrap/js/html5shiv.js"></script>
@@ -97,20 +42,28 @@
 
       <div class="masthead">
         <a href="index.html"><p align="center"><img src="img/emperor_heading.png" alt="Emperor Logo"></p></a>
-        <div class="navbar">
-          <div class="navbar-inner">
-            <div class="container">
-              <ul class="nav">
+        <nav class="nabvar navbar-default">
+          <div class="container-fluid">
+            <div class="navbar-collapse collapse">
+              <ul class="nav navbar-nav">
                 <li><a href="index.html">Home</a></li>
+                <li class="dropdown">
+                  <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Documentation<span class="caret"></span></a>
+                  <ul class="dropdown-menu">
+                    <li><a href="build/html/index.html">User Documentation</a></li>
+                    <li><a href="build/jsdoc/index.html">Javascript Documentation</a></li>
+                  </ul>
+                </li>
                 <li><a href="description_index.html">Description</a></li>
-                <li class="active"><a href="tutorial_index.html">Tutorial</a></li>
-                <li><a href="installation_index.html">Installation</a></li>
-                <li><a href="https://github.com/qiime/emperor/issues">Support</a></li>
+                <li class="active"><a href="#">Tutorial</a></li>
+                <li><a href="https://github.com/biocore/emperor/blob/new-api/INSTALL.md#emperor-installation-notes">Installation</a></li>
+                <li><a href="https://github.com/biocore/emperor/issues">Support</a></li>
               </ul>
             </div>
           </div>
-        </div><!-- /.navbar -->
+        </nav><!-- /.navbar -->
       </div>
+
         <h2>Tutorial</h2>
         <h3 class="muted">Introduction</h3>
           <p class="lead" align="justify">
@@ -217,29 +170,11 @@
 
       <hr>
       <div class="footer">
-        <a href="https://github.com/qiime/emperor/network/members">
+        <a href="https://github.com/biocore/emperor/network/members">
           <p align="center">© The Emperor Development Team</p>
         </a>
       </div>
 
     </div> <!-- /container -->
-
-    <!-- Le javascript
-    ================================================== -->
-    <!-- Placed at the end of the document so the pages load faster -->
-    <script src="bootstrap/js/jquery.js"></script>
-    <script src="bootstrap/js/bootstrap-transition.js"></script>
-    <script src="bootstrap/js/bootstrap-alert.js"></script>
-    <script src="bootstrap/js/bootstrap-modal.js"></script>
-    <script src="bootstrap/js/bootstrap-dropdown.js"></script>
-    <script src="bootstrap/js/bootstrap-scrollspy.js"></script>
-    <script src="bootstrap/js/bootstrap-tab.js"></script>
-    <script src="bootstrap/js/bootstrap-tooltip.js"></script>
-    <script src="bootstrap/js/bootstrap-popover.js"></script>
-    <script src="bootstrap/js/bootstrap-button.js"></script>
-    <script src="bootstrap/js/bootstrap-collapse.js"></script>
-    <script src="bootstrap/js/bootstrap-carousel.js"></script>
-    <script src="bootstrap/js/bootstrap-typeahead.js"></script>
-
   </body>
 </html>
diff --git a/emperor/__init__.py b/emperor/__init__.py
index 593e9b9..8a41053 100644
--- a/emperor/__init__.py
+++ b/emperor/__init__.py
@@ -1,13 +1,41 @@
-#!/usr/bin/env python
-# File created on 24 Jan 2013
-
-__author__ = "Emperor Development Team"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Antonio Gonzalez Pena", "Meg Pirrung", "Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Antonio Gonzalez Pena"
-__email__ = "antgonza at gmail.com"
-__status__ = "Release"
-
-__all__ = ['biplots', 'format', 'filter', 'sort', 'util']
+r"""
+Emperor 3D PCoA viewer (:mod:`emperor`)
+============================================
+
+This module provides objects and functions to interact and visualize a set of
+coordinates using the Emperor interface user interface. The `Emperor` class,
+and the functions present here are all intended to be compatible with the
+Jupyter notebook.
+
+.. currentmodule:: emperor
+
+Classes
+-------
+.. autosummary::
+    :toctree: generated/
+
+    Emperor
+
+Functions
+---------
+.. autosummary::
+    :toctree: generated/
+
+    nbinstall
+    scatterplot
+"""
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
+__version__ = "1.0.0beta5"  # noqa
+
+from emperor.core import Emperor
+from emperor._pandas import scatterplot
+from emperor.util import nbinstall
+
+__all__ = ['Emperor', 'scatterplot', 'biplots', 'format', 'filter', 'parse',
+           'sort', 'util', 'nbinstall']
diff --git a/emperor/biplots.py b/emperor/biplots.py
index 3dceb90..6d84719 100644
--- a/emperor/biplots.py
+++ b/emperor/biplots.py
@@ -1,47 +1,57 @@
-#!/usr/bin/env python
-# File created on 14 Apr 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
-
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
 from numpy import argsort, array
 
 from emperor.util import EmperorUnsupportedComputation
 from emperor.sort import sort_taxa_table_by_pcoa_coords
 from emperor.qiime_backports.biplots import (get_taxa_prevalence,
-    get_taxa_coords, make_biplot_scores_output)
+                                             get_taxa_coords,
+                                             make_biplot_scores_output)
 
-def extract_taxa_data(otu_coords, otu_table, lineages, prevalence, N=0):
-    """Extrac the N most prevalent elements according to a prevalence vector
-
-    Inputs:
-    otu_coords: coordinates where specific taxa is centered
-    otu_table: contingency table
-    lineages: taxonomic assignments for each row in the otu_table
-    prevalence: vector with prevalnce from 0 to 1 for each row of the otu_table
-    as returned from qiime.biplots.get_taxa_prevalence
-    N: number of most prevalent elements to retain, if zero is passed, will
-    reatain all available
-
-    Outputs:
-    otu_coords: N most prevalent coords
-    out_otu_table: N most prevalent rows of the otu_table
-    out_otu_lineages: N most prevalent taxonomic assignments for each row of the
-    otu_table
-    out_prevalence: first N values of prevalence
 
+def extract_taxa_data(otu_coords, otu_table, lineages, prevalence, N=0):
+    """Extract the N most prevalent elements according to a prevalence vector
+
+    Parameters
+    ----------
+    otu_coords : array_like
+         coordinates where specific taxa is centered
+    otu_table : array_like
+         contingency table
+    lineages : list, str
+         taxonomic assignments for each row in the otu_table
+    prevalence : list, float
+         vector with prevalnce from 0 to 1 for each row of the otu_table
+         as returned from qiime.biplots.get_taxa_prevalence
+    N : int, optional
+         number of most prevalent elements to retain, if zero is passed, will
+         retain all available
+
+    Returns
+    -------
+    otu_coords : np.ndarray
+         N most prevalent coords
+    out_otu_table : np.ndarray
+         N most prevalent rows of the otu_table
+    out_otu_lineages : np.ndarray
+         N most prevalent taxonomic assignments for each row of the
+         otu_table
+    out_prevalence : np.ndarray
+         first N values of prevalence
+
+    Notes
+    -----
     Based on qiime.biplots.remove_rare_taxa; though this function opperates on
     generic data that's not in dict forma and returns the appropriate result.
     """
     # If less than zero or greater than length of taxa, N = fix to max
-    if N<=0 or N>len(prevalence):
+    if N <= 0 or N > len(prevalence):
         N = len(prevalence)
 
     # get the first N indices to keep from all of the taxa data
@@ -56,25 +66,45 @@ def extract_taxa_data(otu_coords, otu_table, lineages, prevalence, N=0):
 
     return out_otu_coords, out_otu_table, out_otu_lineages, out_prevalence
 
+
 def preprocess_otu_table(otu_sample_ids, otu_table, lineages,
-                        coords_data, coords_headers, N=0):
+                         coords_data, coords_headers, N=0):
     """Preprocess the OTU table to to generate the required data for the biplots
 
-    Input:
-    otu_sample_ids: sample identifiers for the otu_table
-    otu_table: contingency table
-    lineages: taxonomic assignments for the OTUs in the otu_table
-    coords_data: principal coordinates data where the taxa will be mapped
-    N: number of most prevalent taxa to keep, by default will use all
-
-    Output:
-    otu_coords: coordinates representing the N most prevalent taxa in otu_table
-    otu_table: N most prevalent OTUs from the input otu_table
-    otu_lineages: taxonomic assignments corresponding to the N most prevalent
-    OTUs
-    otu_prevalence: vector with the prevalence scores of the N highest values
-    lines: coords where the N most prevalent taxa will be positioned in the
-    biplot
+    Parameters
+    ----------
+    otu_sample_ids : array_like
+         sample identifiers for the otu_table
+    otu_table : array_like
+         contingency table
+    lineages : list, str
+         taxonomic assignments for the OTUs in the otu_table
+    coords_data : array_like
+         principal coordinates data where the taxa will be mapped
+    coords_data : array_like
+         principal coordinates data where the taxa will be mapped
+    N : int, optional
+         number of most prevalent taxa to keep, by default will use all
+
+    Returns
+    -------
+    otu_coords : np.ndarray
+         coordinates representing the N most prevalent taxa in otu_table
+    otu_table : np.ndarray
+         N most prevalent OTUs from the input otu_table
+    otu_lineages : np.ndarray
+         taxonomic assignments corresponding to the N most prevalent
+         OTUs
+    otu_prevalence : np.ndarray
+         vector with the prevalence scores of the N highest values
+    lines : np.ndarray
+         coords where the N most prevalent taxa will be positioned in the
+         biplot
+
+    Raises
+    ------
+    EmperorUnsupportedComputation
+        If the contingency table contains one or fewer rows.
     """
 
     # return empty values if any of the taxa data is empty
@@ -83,18 +113,23 @@ def preprocess_otu_table(otu_sample_ids, otu_table, lineages,
 
     # this means there's only one or fewer rows in the contingency table
     if len(otu_table) <= 1 or len(lineages) <= 1:
-        raise EmperorUnsupportedComputation, "Biplots are not supported for "+\
-            "contingency tables with one or fewer rows"
+        raise EmperorUnsupportedComputation(
+            "Biplots are not supported for "
+            "contingency tables with one or fewer rows")
 
     # if this element is a list take the first headers and coordinates
-    # both of these will be the master coordinates, i. e. where data is centered
+    # both of these will be the master coordinates,
+    # i. e. where data is centered
     if type(coords_data) == list and type(coords_headers) == list:
         coords_data = coords_data[0]
         coords_headers = coords_headers[0]
 
-    # re-arrange the otu table so it matches the order of the samples in the
-    # coordinates data & remove any sample that is not in the coordinates header
-    otu_sample_ids, otu_table = sort_taxa_table_by_pcoa_coords(coords_headers,
+    # re-arrange the otu table so it matches the
+    # order of the samples in the coordinates
+    # data & remove any sample that is not in the
+    # coordinates header
+    otu_sample_ids, otu_table = sort_taxa_table_by_pcoa_coords(
+        coords_headers,
         otu_table, otu_sample_ids)
 
     # retrieve the prevalence and the coords prior the filtering
@@ -104,7 +139,7 @@ def preprocess_otu_table(otu_sample_ids, otu_table, lineages,
     o_otu_coords, o_otu_table, o_otu_lineages, o_prevalence =\
         extract_taxa_data(bi_plot_coords, otu_table, lineages, prevalence, N)
 
-    lines = '\n'.join(make_biplot_scores_output({'coord': o_otu_coords,
-        'lineages': o_otu_lineages}))
+    lines = '\n'.join(make_biplot_scores_output(
+        {'coord': o_otu_coords, 'lineages': o_otu_lineages}))
 
     return o_otu_coords, o_otu_table, o_otu_lineages, o_prevalence, lines
diff --git a/emperor/filter.py b/emperor/filter.py
index 96f766d..4801e77 100644
--- a/emperor/filter.py
+++ b/emperor/filter.py
@@ -1,29 +1,41 @@
-#!/usr/bin/env python
-# File created on 12 May 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
-
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
 from numpy import array
 
-def filter_samples_from_coords(headers, coords, valid_sample_ids, negate=False):
+
+def filter_samples_from_coords(headers, coords,
+                               valid_sample_ids, negate=False):
     """Filter samples from a pair of headers and coordinates
 
-    headers: list of sample ids corresponding to the coordinates data
-    coords: numpy array of float values
-    valid_sample_ids: list of sample ids to keep
-    negate: False means keep the samples in valid_sample_ids, True means remove
-    the samples in valid_sample_ids
+    Parameters
+    ----------
+    headers : array_like
+         list of sample ids corresponding to the coordinates data
+    coords : numpy.ndarray
+         numpy array of float values
+    valid_sample_ids : list, str
+         list of sample ids to keep
+    negate: bool, optional
+         False means keep the samples in valid_sample_ids,
+         True means remove the samples in valid_sample_ids
+
+    Returns
+    -------
+    out_coord_ids : list, str
+         Filtered list headers
+    out_coords : list, np.array
+         Filtered list of coordinates
 
-    Notes:
-    Raises ValueError when all the samples are filtered out
+    Raises
+    ------
+    ValueError
+        If all the samples are filtered out
     """
     out_coord_ids, out_coords = [], []
 
@@ -42,18 +54,31 @@ def filter_samples_from_coords(headers, coords, valid_sample_ids, negate=False):
 
     # do not allow empty sets as return values, raise an exception
     if len(out_coord_ids) < 1:
-        raise ValueError, "All samples have been filtered out"
+        raise ValueError("All samples have been filtered out")
 
     return out_coord_ids, array(out_coords)
 
+
 def keep_samples_from_pcoa_data(headers, coords, sample_ids):
     """Controller function to filter coordinates data according to a list
 
-    headers: list of sample identifiers, if used for jackknifed data, this
-    should be a list of lists containing the sample identifiers
-    coords: 2-D numpy array with the float data in the coordinates, if used for
-    jackknifed data, coords should be a list of 2-D numpy arrays
-    sample_ids: list of sample ids that should be kept
+    Parameters
+    ----------
+    headers : list, str
+        list of sample identifiers, if used for jackknifed data, this
+        should be a list of lists containing the sample identifiers
+    coords : numpy.ndarray
+        2-D numpy array with the float data in the coordinates, if used for
+        jackknifed data, coords should be a list of 2-D numpy arrays
+    sample_ids : list, str
+        list of sample ids that should be kept
+
+    Returns
+    -------
+    out_headers : list, str
+        list of headers
+    out_coords : list, np.array
+        list of coordinates
     """
 
     # if the coords are a list then it means that the input jackknifed
@@ -62,11 +87,14 @@ def keep_samples_from_pcoa_data(headers, coords, sample_ids):
 
         for single_headers, single_coords in zip(headers, coords):
             a, b = filter_samples_from_coords(single_headers, single_coords,
-                sample_ids)
+                                              sample_ids)
 
             out_headers.append(a)
             out_coords.append(b)
 
         return out_headers, out_coords
     else:
-        return filter_samples_from_coords(headers, coords, sample_ids)
+        out_headers, out_coords = filter_samples_from_coords(headers,
+                                                             coords,
+                                                             sample_ids)
+        return out_headers, out_coords
diff --git a/emperor/format.py b/emperor/format.py
old mode 100755
new mode 100644
index 0a097ac..d6babef
--- a/emperor/format.py
+++ b/emperor/format.py
@@ -1,428 +1,51 @@
-#!/usr/bin/env python
-# File created on 24 Jan 2013
-from __future__ import division
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file COPYING.txt, distributed with this software.
+# ----------------------------------------------------------------------------
 
-__author__ = "Antonio Gonzalez Pena"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Meg Pirrung", "Antonio Gonzalez Pena", "Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
+from __future__ import division
 
 
 from sys import argv
-from copy import deepcopy
 from os.path import abspath
 from datetime import datetime
-from StringIO import StringIO
 from socket import gethostname
 
-from numpy import max, min, abs, argsort, array
-
-from emperor.util import (keep_columns_from_mapping_file,
-    get_emperor_library_version)
-
-from emperor.qiime_backports.format import format_mapping_file
-from emperor.qiime_backports.parse import (mapping_file_to_dict,
-    parse_mapping_file)
-from emperor.qiime_backports.filter import (
-    filter_mapping_file_by_metadata_states,sample_ids_from_metadata_description)
-from emperor.qiime_backports import __version__ as qiime_backports_version
-
-class EmperorLogicError(ValueError):
-    """Exception raised when a requirement for the Emperor GUI is not met"""
-    pass
-
-def format_pcoa_to_js(header, coords, eigvals, pct_var, custom_axes=[],
-                    coords_low=None, coords_high=None, number_of_axes=10, 
-                    number_of_segments=8):
-    """Write the javascript necessary to represent a pcoa file in emperor
-
-    Inputs:
-    header: sample names for the pcoa file 1-D array
-    coords: coordinates of the PCoA file, 2-D array
-    eigvals: eigen-values of the PCoA file, 1-D array
-    pct_var: percentage of variation of the PCoA file, 1-D array
-    custom_axes: list of category names for the custom axes
-    coords_low: coordinates representing the lower edges of an ellipse
-    coords_high: coordinates representing the highere edges of an ellipse
-    number_of_axes: number of axes to be returned
-    number_of_segments: number of segments and rings for each sphere 
-
-    Output:
-    string: javascript representation of the PCoA data inputed, contains a list
-    of spheres, list of ellipses (if coords_low and coords_high are present) and
-    several setup variables.
-
-    Formats the output of qiime.parse.parse_coords_file into javascript variable
-    declarations.
-    """
-    js_pcoa_string = ''
-    
-    # validating that the number of coords in coords
-    if number_of_axes>len(coords[0]):
-        number_of_axes = len(coords[0])
-    # validating that all the axes are above 0.51%, this accounts for really
-    # small variations explained in some axes that end up being not practical
-    # the GUI has some problems when presenting those values on screen
-    valid_pcoalabels = len([i for i in pct_var if i>0.51])
-    if number_of_axes>valid_pcoalabels:
-        number_of_axes = valid_pcoalabels
-    if number_of_axes<3:
-        raise EmperorLogicError, "Due to the variation explained, Emperor "+\
-            "could not plot at least 3 axes, check the input files to ensure"+\
-            " that the percent explained is greater than 0.5 in at least "+\
-            "three axes."
-
-    # ranges for the PCoA space
-    max_x = max(coords[:,0:1])
-    max_y = max(coords[:,1:2])
-    max_z = max(coords[:,2:3])
-    min_x = min(coords[:,0:1])
-    min_y = min(coords[:,1:2])
-    min_z = min(coords[:,2:3])
-    maximum = max(abs(coords[:,:number_of_axes]))
-    pcoalabels = pct_var[:number_of_axes]
-    
-    radius = (max_x-min_x)*.012
-
-    # write the values for all the spheres
-    js_pcoa_string += '\nvar g_spherePositions = new Array();\n'
-    for point, coord in zip(header, coords):
-        all_coords = ', '.join(["'P%d': %f" % (i+1,coord[i]) for i in range(number_of_axes)])
-        js_pcoa_string += ("g_spherePositions['%s'] = { 'name': '%s', 'color': "
-            "0, 'x': %f, 'y': %f, 'z': %f, %s };\n" % (point, point, coord[0],
-            coord[1],coord[2], all_coords))
-
-    # write the values for all the ellipses
-    js_pcoa_string += '\nvar g_ellipsesDimensions = new Array();\n'
-    if coords_low != None and coords_high != None:
-        for s_header, s_coord, s_low, s_high in zip(header, coords, coords_low,
-            coords_high):
-            delta = abs(s_high-s_low)
-            all_coords = ', '.join(["'P%d': %f" % (i+1,s_coord[i]) for i in range(number_of_axes)])
-            js_pcoa_string += ("g_ellipsesDimensions['%s'] = { 'name': '%s', "
-                "'color': 0, 'width': %f, 'height': %f, 'length': %f , 'x': %f,"
-                " 'y': %f, 'z': %f, %s }\n" % (s_header, s_header,delta[0], delta[1],
-                delta[2], s_coord[0], s_coord[1], s_coord[2], all_coords))
-    
-    js_pcoa_string += 'var g_segments = %d, g_rings = %d, g_radius = %f;\n' % (number_of_segments, 
-        number_of_segments, radius)
-    js_pcoa_string += 'var g_xAxisLength = %f;\n' % (abs(max_x)+abs(min_x))
-    js_pcoa_string += 'var g_yAxisLength = %f;\n' % (abs(max_y)+abs(min_y))
-    js_pcoa_string += 'var g_zAxisLength = %f;\n' % (abs(max_z)+abs(min_z))
-    js_pcoa_string += 'var g_xMaximumValue = %f;\n' % (max_x)
-    js_pcoa_string += 'var g_yMaximumValue = %f;\n' % (max_y)
-    js_pcoa_string += 'var g_zMaximumValue = %f;\n' % (max_z)
-    js_pcoa_string += 'var g_xMinimumValue = %f;\n' % (min_x)
-    js_pcoa_string += 'var g_yMinimumValue = %f;\n' % (min_y)
-    js_pcoa_string += 'var g_zMinimumValue = %f;\n' % (min_z)
-    js_pcoa_string += 'var g_maximum = %f;\n' % maximum
-
-    offset = 0
-
-    # create three vars, pc1, pc2 and pc3 if no custom_axes are passed, then use
-    # the values of the percent explained by the PCoA; if custom_axes are passed
-    # use as many as you can (since customs axes can be either [0, 1, 2, 3])
-    for i in range(0, 3):
-        try:
-            js_pcoa_string += 'var g_pc%dLabel = \"%s\";\n' % (i+1,
-                custom_axes[i])
-            offset+=1 # offset will help us retrieve the correct pcoalabels val
-        except:
-            # if there are custom axes then subtract the number of custom axes
-            js_pcoa_string += 'var g_pc%dLabel = \"PC%d (%.0f %%)\";\n' %\
-                (i+1, i+1-offset, pcoalabels[i-offset])
-    js_pcoa_string += 'var g_number_of_custom_axes = %d;\n' % offset
-    
-    js_pcts = []
-    js_pcts_round = []
-    if custom_axes == None: custom_axes = []
-    for element in custom_axes + list(pct_var[:number_of_axes]):
-        try:
-            # scale the percent so it's a number from 0 to 1
-            js_pcts.append('%f' % (float(element)/100))
-            js_pcts_round.append('%d' % (round(element)))
-        except ValueError:
-            js_pcts.append('%f' % (float(pct_var[0]/100)))
-            js_pcts_round.append('%d' % (round(pct_var[0])))
-    js_pcoa_string += 'var g_fractionExplained = [%s];\n' % ', '.join(js_pcts)
-    js_pcoa_string += 'var g_fractionExplainedRounded = [%s];\n' % ', '.join(js_pcts_round)
-    
-    return js_pcoa_string
-
-def format_mapping_file_to_js(mapping_file_data, mapping_file_headers, columns):
-    """Write a javascript representation of the mapping file
-
-    Inputs:
-    mapping_file_data: contents of the mapping file
-    mapping_file_headers: headers of the mapping file
-    columns: valid columns to use, usually a subset of mapping_file_headers
-
-    Outputs:
-    string: javascript representation of the mapping file
-    """
-    js_mapping_file_string = ''
-
-    mapping_file_dict = mapping_file_to_dict(mapping_file_data,
-        mapping_file_headers)
-
-    map_values = []
-    for k,v in mapping_file_dict.items():
-        if 'SampleID' in columns:
-            vals = ["'%s'" % k] + ["'%s'" % v[col]\
-                for col in mapping_file_headers[1:]]
-        else:
-            vals = ["'%s'" % v[col] for col in mapping_file_headers[1:]]
-        map_values.append("'%s': [%s]" % (k, ','.join(vals)))
-
-    if 'SampleID' not in columns:
-        mapping_file_headers = mapping_file_headers[1:]
-
-    # format the mapping file as javascript objects
-    js_mapping_file_string += 'var g_mappingFileHeaders = [%s];\n' % ','.join(
-        ["'%s'" % col for col in mapping_file_headers])
-    js_mapping_file_string += 'var g_mappingFileData = { %s };\n' % ','.join(
-        map_values)
-
-    return js_mapping_file_string
-
-def format_taxa_to_js(otu_coords, lineages, prevalence, min_taxon_radius=0.5,
-                    max_taxon_radius=5, radius=1.0):
-    """Write a string representing the taxa in a PCoA plot as javascript
-    
-    Inputs:
-    otu_coords: numpy array where the taxa is positioned
-    lineages: label for each of these lineages
-    prevalence: score of prevalence for each of the taxa that is drawn
-
-    *These parameters should work more as constants and once we find out that
-    there's a value that is too big to be presented, the proper checks should
-    be put into place. Currently we haven't found such cases in any study*
-    min_taxon_radius: minimum value for the radius of the spheres on the plot
-    max_taxon_radious: maximum value for the radius of the spheres on the plot
-    radius: default value size
-
-    Outputs:
-    js_biplots_string: javascript string where the taxa information is written
-    to create the spheres representing each of these, will return only the
-    variable declaration if the inputs are empty.
-    """
-    js_biplots_string = []
-    js_biplots_string.append('\nvar g_taxaPositions = new Array();\n')
-
-    # if we have prevalence scores, calculate the taxa radii values
-    if len(prevalence):
-        taxa_radii = radius*(min_taxon_radius+(max_taxon_radius-
-            min_taxon_radius)*prevalence)
-    else:
-        taxa_radii = []
-
-    index = 0
-
-    # write the data in the form of a dictionary
-    for taxa_label, taxa_coord, t_radius in zip(lineages,otu_coords,taxa_radii):
-        js_biplots_string.append(("g_taxaPositions['%d'] = { 'lineage': '%s', "
-            "'x': %f, 'y': %f, 'z': %f, 'radius': %f};\n") % (index,
-            taxa_label, taxa_coord[0], taxa_coord[1], taxa_coord[2], t_radius))
-        index += 1
-    js_biplots_string.append('\n')
-    # join the array of strings as a single string
-    return ''.join(js_biplots_string)
-
-def format_vectors_to_js(mapping_file_data, mapping_file_headers, coords_data,
-                        coords_headers, connected_by_header,
-                        sorted_by_header=None):
-    """Write a string representing the vectors in a PCoA plot as javascript
-
-    Inputs:
-    mapping_file_data: contents of the mapping file
-    mapping_file_headers: headers of the mapping file
-    coords_data: coordinates of the PCoA plot in a numpy 2-D array or a list of
-    numpy 2-D arrays for jackknifed input
-    coords_headers: headers of the coords in the PCoA plot or a list of lists
-    with the headers for jackknifed input
-    connected_by_header: header of the mapping file that represents how the
-    lines will be connected
-    sorted_by_header: numeric-only header name to sort the samples in the
-    vectors
-
-    Output:
-    js_vectors_string: string that represents the vectors in the shape of a
-    javascript object
-
-    Notes:
-    If using jackknifed input, the coordinates and headers that will be used are
-    the ones belonging to the master coords i. e. the first element.
-    """
-
-    js_vectors_string = []
-    js_vectors_string.append('\nvar g_vectorPositions = new Array();\n')
-
-    if connected_by_header != None:
-        # check if we are processing jackknifed input, if so just get the master
-        if type(coords_data) == list:
-            coords_data = coords_data[0]
-            coords_headers = coords_headers[0]
-
-        columns_to_keep = ['SampleID', connected_by_header]
-
-        # do not ad None if sorted_by_header is None or empty
-        if sorted_by_header:
-            columns_to_keep.append(sorted_by_header)
-
-        # reduce the amount of data by keeping the required fields only
-        mapping_file_data, mapping_file_headers =\
-            keep_columns_from_mapping_file(mapping_file_data,
-            mapping_file_headers, columns_to_keep)
-
-        # format the mapping file to use this with the filtering function
-        mf_string = format_mapping_file(mapping_file_headers, mapping_file_data)
-
-        index = mapping_file_headers.index(connected_by_header)
-        connected_by = list(set([line[index] for line in mapping_file_data]))
-
-        for category in connected_by:
-            # convert to StringIO to for each iteration; else the object
-            # won't be usable after the first iteration & you'll get an error
-            sample_ids = sample_ids_from_metadata_description(
-                StringIO(mf_string),'%s:%s' % (connected_by_header,category))
-
-            # if there is a sorting header, sort the coords using these values
-            if sorted_by_header:
-                sorting_index = mapping_file_headers.index(sorted_by_header)
-                to_sort = [line for line in mapping_file_data if line[0] in\
-                    sample_ids]
-
-                # get the sorted sample ids from the sorted-reduced mapping file
-                sample_ids = zip(*sorted(to_sort,
-                    key=lambda x: float(x[sorting_index])))[0]
-
-            # each category value is a new vector
-            js_vectors_string.append("g_vectorPositions['%s'] = new Array();\n"
-                % (category))
-
-            for s in sample_ids:
-                index = coords_headers.index(s)
-
-                # print the first three elements of each coord for each sample
-                js_vectors_string.append("g_vectorPositions['%s']['%s'] = %s;\n"
-                    % (category, s, coords_data[index, :3].tolist()))
+from emperor import __version__ as emperor_library_version
 
-    return ''.join(js_vectors_string)
-
-def format_comparison_bars_to_js(coords_data, coords_headers, clones,
-                                is_serial_comparison=True):
-    """Format coordinates data to create a comparison plot
-
-    Inputs:
-    coords_data: numpy array with the replicated coordinates
-    cooreds_headers: list with the headers for each of replicated coordinates
-    clones: number of replicates in the coords_data and coords_headers
-    is_serial_comparison: whether the samples will be connected one after the
-    other (True) or all will originate in the first set of coordinates.
-
-    Outputs:
-    Javascript object that contains the data for the comparison plot
-
-    Raises:
-    AssertionError if the coords_data and coords_headers don't have the same
-    length.
-    AssertionError if the number of clones doesn't concord with the samples
-    being presented.
-
-    Unless the value of clones is > 0 this function will return an empty
-    javascript object initialization.
-    """
-
-    js_comparison_string = []
-    js_comparison_string.append('\nvar g_comparisonPositions = new Array();\n')
-
-    if is_serial_comparison:
-        js_comparison_string.append('var g_isSerialComparisonPlot = true;\n')
-    else:
-        js_comparison_string.append('var g_isSerialComparisonPlot = false;\n')
-
-    if clones:
-        headers_length = len(coords_headers)
-
-        # assert some sanity checks
-        assert headers_length == len(coords_data), "The coords data and"+\
-            "the coords headers must have the same length"
-        assert headers_length%clones == 0, "There has to be an exact "+\
-            "number of clones of the data"
-
-        # get the indices that the sample names get sorted by, this will group
-        # all the samples with the same prefix together, and since the suffixes
-        # are numeric, the samples will be one after the other i. e. sample_0,
-        # sample_1, sample_2 and other_0, other_1, other_2 and so on. With these
-        # indices sort the coordinates and then the headers themselves, though
-        # convert to a numpy array first & back to a list to avoid sorting again
-        indices = argsort(coords_headers)
-        coords_data = coords_data[indices, :]
-        coords_headers = array(coords_headers)[indices, :].tolist()
-
-        # in steps of the number of clones iterate through the headers and the
-        # coords to create the javascript object with the coordinates
-        for index in xrange(0, headers_length, clones):
-            # 1st object must have _0 as a suffix, trim it reveal the sample id
-            assert coords_headers[index].endswith('_0'), "There's an internal"+\
-                " inconsistency with the sample ids"
-            sample_id = coords_headers[index][:-2]
-
-            # convert all elements in the numpy array into a string before
-            # formatting the elements into the javascript dictionary object
-            js_comparison_string.append("g_comparisonPositions['%s'] = [%s];\n"%
-                (sample_id, str(', '.join(map(str,
-                coords_data[index:(index+clones), 0:3].tolist())))))
-    return ''.join(js_comparison_string)
-
-
-def format_emperor_html_footer_string(has_biplots=False, has_ellipses=False,
-                                    has_vectors=False, has_edges=False):
-    """Create an HTML footer according to the things being presented in the plot
-
-    has_biplots: whether the plot has biplots or not
-    has_ellipses: whether the plot has ellipses or not
-    has_vectors: whether the plot has vectors or not
-    has_edges: whether the plot has edges between samples (comparison plot)
-
-
-    This function will remove unnecessary GUI elements from index.html to avoid
-    confusions i. e. showing an ellipse opacity slider when there are no
-    ellipses in the plot.
-    """
-    optional_strings = []
-
-    # the order of these statements matter, see _EMPEROR_FOOTER_HTML_STRING
-    # we use python's built-in ternary operator to add or not a string
-    optional_strings.append(_BIPLOT_SPHERES_COLOR_SELECTOR if has_biplots else
-        '')
-    optional_strings.append(_BIPLOT_VISIBILITY_SELECTOR if has_biplots else '')
-    optional_strings.append(_TAXA_LABELS_SELECTOR if has_biplots else '')
-    optional_strings.append(_TAXA_LABELS_COLOR_SELECTOR if has_biplots else '')
-    optional_strings.append(_EDGES_COLOR_SELECTOR if has_edges else '')
-    optional_strings.append(_ELLIPSE_OPACITY_SLIDER if has_ellipses else '')
-    optional_strings.append(_VECTORS_OPACITY_SLIDER if has_vectors else '')
-    optional_strings.append(_EDGES_VISIBILITY_SELECTOR if has_edges else '')
-
-    return _EMPEROR_FOOTER_HTML_STRING % tuple(optional_strings)
 
 def format_emperor_autograph(metadata_fp, coords_fp, language='HTML'):
     """Create a signature with some meta-data of the Emperor package
 
-    language: language to which it will be formatted as a multi-line comment
-
+    Parameters
+    ----------
+    metadata_fp : str
+        Absolute file path to the metadata mapping file
+    coords_fp : str
+        Absolute file path to the coordinates file
+    language : {'HTML', 'Python', 'C', 'Bash'}, optional
+        Language to which it will be formatted as a multi-line comment
+
+    Returns
+    -------
+    str
+        String with information about the executed command
+
+    Raises
+    ------
+    AssertionError
+        If the file is not allowed.
     """
 
     # supported open and closing of multi-line comments for different languages
-    _languages = {'HTML':('<!--', '-->'), 'Python':('"""', '"""'), 'C':('/*',
-        '*/'), 'Bash':('<<COMMENT', 'COMMENT')}
+    _languages = {'HTML': ('<!--', '-->'), 'Python': ('"""', '"""'),
+                  'C': ('/*', '*/'), 'Bash': ('<<COMMENT', 'COMMENT')}
 
-    assert language in _languages.keys(), '%s is not a supported language' %\
-        language
+    assert language in list(_languages.keys()), ('%s is not a supported '
+                                                 'language' % language)
 
     autograph = []
     autograph.append(_languages[language][0])
@@ -430,11 +53,10 @@ def format_emperor_autograph(metadata_fp, coords_fp, language='HTML'):
 
     # add the day and time at which the command was called
     autograph.append(datetime.now().strftime('Command executed on %B %d, %Y at'
-        ' %H:%M:%S'))
+                                             ' %H:%M:%S'))
 
     # add library version and SHA-1 if available
-    autograph.append('Emperor Version: %s' %  get_emperor_library_version())
-    autograph.append('QIIME Version: %s' % qiime_backports_version)
+    autograph.append('Emperor Version: %s' % emperor_library_version)
     autograph.append('HostName: %s' % gethostname())
 
     # full path to input files
@@ -448,276 +70,3 @@ def format_emperor_autograph(metadata_fp, coords_fp, language='HTML'):
     autograph.append(_languages[language][1])
 
     return '%s' % '\n'.join(autograph)
-
-
-EMPEROR_HEADER_HTML_STRING =\
-"""<!doctype html>
-<html lang="en">
-
-<head>
-    <title>Emperor</title>
-    <meta charset="utf-8">
-    <link rel="shortcut icon" href="emperor_required_resources/img/favicon.ico" />
-    <meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
-    <link rel="stylesheet" type="text/css" href="emperor_required_resources/emperor/css/emperor.css">
-    <link rel="stylesheet" type="text/css" href="emperor_required_resources/css/jquery-ui2.css">
-    <link rel="stylesheet" type="text/css" href="emperor_required_resources/css/colorPicker.css">
-    <link rel="stylesheet" type="text/css" href="emperor_required_resources/css/spectrum.css">
-    <link rel="stylesheet" type="text/css" href="emperor_required_resources/css/d3.parcoords.css">
-    <table id="logotable" style="vertical-align:middle;text-align:center;height:100%;width:100%;margin:0;padding:0;border:0;">
-        <tr><td><img src="emperor_required_resources/img/emperor.png" alt="Emperor" id="logo"/></td></tr>
-    </table>
-    <script type="text/javascript" src="emperor_required_resources/js/d3.v3.min.js"></script>
-    <script type="text/javascript" src="emperor_required_resources/js/d3.parcoords.js"></script>
-    <script type="text/javascript" src="emperor_required_resources/js/jquery-1.7.1.min.js"></script>
-    <script type="text/javascript" src="emperor_required_resources/js/jquery-ui-1.8.17.custom.min.js"></script>
-    <script src="emperor_required_resources/js/jquery.colorPicker.js"></script>
-    <script src="emperor_required_resources/js/spectrum.js"></script>
-
-    <script src="emperor_required_resources/js/Three.js"></script>
-    <script src="emperor_required_resources/js/js/Detector.js"></script>
-    <script src="emperor_required_resources/js/js/RequestAnimationFrame.js"></script>
-    <script src="emperor_required_resources/emperor/js/emperor.js"></script>
-    <script type="text/javascript" src="emperor_required_resources/js/THREEx.screenshot.js"></script>
-    <script type="text/javascript" src="emperor_required_resources/js/FileSaver.min.js"></script>
-    
-    <script type="text/javascript">
-    
-"""
-
-_ELLIPSE_OPACITY_SLIDER = """
-            <br>
-            <label for="ellipseopacity" class="text">Ellipse Opacity</label>
-            <label id="ellipseopacity" class="slidervalue"></label>
-            <div id="eopacityslider" class="slider-range-max"></div>"""
-
-_VECTORS_OPACITY_SLIDER = """
-            <br>
-            <label for="vectorsopacity" class="text">Vectors Opacity</label>
-            <label id="vectorsopacity" class="slidervalue"></label>
-            <div id="vopacityslider" class="slider-range-max"></div>"""
-
-_TAXA_LABELS_SELECTOR = """
-            <form name="biplotoptions">
-            <input type="checkbox" onClick="toggleTaxaLabels()">Biplots Label Visibility</input>
-            </form>"""
-
-_TAXA_LABELS_COLOR_SELECTOR = """
-            <tr><td><div id="taxalabelcolor" class="colorbox"></div></td><td><label>Taxa Label Color</label></td></tr>
-"""
-
-_BIPLOT_VISIBILITY_SELECTOR = """
-            <br>
-            <form name="biplotsvisibility">
-            <input type="checkbox" onClick="toggleBiplotVisibility()" checked>Biplots Visibility</input>
-            </form>
-            <br>"""
-
-_BIPLOT_SPHERES_COLOR_SELECTOR ="""
-            <br>
-            <table>
-                <tr><td><div id="taxaspherescolor" class="colorbox" name="taxaspherescolor"></div></td><td title="taxacolor">Taxa Spheres Color</td></tr>
-            </table>
-            <br>"""
-
-_EDGES_VISIBILITY_SELECTOR = """
-            <br>
-            <form name="edgesvisibility">
-            <input type="checkbox" onClick="toggleEdgesVisibility()" checked>Edges Visibility</input>
-            </form>
-            <br>"""
-
-_EDGES_COLOR_SELECTOR = """
-            <tr><td><div id="edgecolorselector_a" class="colorbox" name="edgecolorselector_a"></div></td><td title="edgecolor_a">Edge Color Selector A</td></tr>
-            <tr><td><div id="edgecolorselector_b" class="colorbox" name="edgecolorselector_b"></div></td><td title="edgecolor_b">Edge Color Selector B</td></tr>
-"""
-
-_EMPEROR_FOOTER_HTML_STRING ="""document.getElementById("logo").style.display = 'none';
-document.getElementById("logotable").style.display = 'none';
-
- </script>
-</head>
-
-<body>
-
-<div id="overlay">
-    <div>
-    <img src="emperor_required_resources/img/emperor.png" alt="Emperor" id="smalllogo"/>
-        <h1>WebGL is not enabled!</h1>
-        <p>Emperor's visualization framework is WebGL based, it seems that your system doesn't have this resource available. Here is what you can do:</p>
-        <p id="explanation"><strong>Chrome:</strong> Type "chrome://flags/" into the address bar, then search for "Disable WebGL". Disable this option if you haven't already. <em>Note:</em> If you follow these steps and still don't see an image, go to "chrome://flags/" and then search for "Override software rendering list" and enable this option.</p>
-        <p id="explanation"><strong>Safari:</strong> Open Safari's menu and select Preferences. Click on the advanced tab, and then check "Show Developer" menu. Then open the "Developer" menu and select "Enable WebGL".</p>
-        <p id="explanation"><strong>Firefox:</strong> Go to Options through Firefox > Options or Tools > Options. Go to Advanced, then General. Check "Use hardware acceleration when available" and restart Firefox.</p>
-        <p id="explanation"><strong>Other browsers:</strong> The only browsers that support WebGL are Chrome, Safari, and Firefox. Please switch to these browsers when using Emperor.</p>
-        <p id="explanation"><em>Note:</em> Once you went through these changes, reload the page and it should work!</p>
-        <p id="source">Sources: Instructions for <a href="https://www.biodigitalhuman.com/home/enabling-webgl.html">Chrome and Safari</a>, and <a href="http://www.infewbytes.com/?p=144">Firefox</a></p>
-    </div>
-</div>
-
-<div id="plotToggle">
-    <form>
-      <div id="plottype">
-        <input id="pcoa" type="radio" id="pcoa" name="plottype" checked="checked" /><label for="pcoa">PCoA</label>
-        <input id="parallel" type="radio" id="parallel" name="plottype" /><label for="parallel">Parallel</label>
-      </div>
-    </form>
-</div>
-<div id="pcoaPlotWrapper" class="plotWrapper">
-    <label id="pointCount" class="ontop">
-    </label>
-
-    <div id="finder" class="arrow-right">
-    </div>
-
-    <div id="labels" class="unselectable">
-    </div>
-
-    <div id="taxalabels" class="unselectable">
-    </div>
-
-    <div id="axislabels" class="axislabels">
-    </div>
-
-    <div id="main_plot">
-    </div>
-</div>
-
-<div id="parallelPlotWrapper" class="plotWrapper">
-</div>
-
-<div class="separator" ondblclick="separatorDoubleClick()"></div>
-
-<div id="menu">
-    <div id="menutabs">
-        <ul>
-            <li><a href="#keytab">Key</a></li>
-            <li><a href="#colorby">Colors</a></li>
-            <li><a href="#showby">Visibility</a></li>
-            <li><a href="#scalingby">Scaling</a></li>
-            <li><a href="#labelby">Labels</a></li>
-            <li><a href="#axes">Axes</a></li>
-            <li><a href="#options">Options</a></li>
-        </ul>
-        <div id="keytab">
-            <form name="keyFilter">
-            <label>Filter  </label><input name="filterBox" id="searchBox" type="text" onkeyup="filterKey()"></input>
-            </form>
-            <div id="key">
-            </div>
-        </div>
-        <div id="colorby">
-            <br>%s
-            <input type="checkbox" onchange="toggleContinuousAndDiscreteColors(this)" id="discreteorcontinuouscolors" name="discreteorcontinuouscolors">  Use gradient colors</input>
-            <br><br>
-            <select id="colorbycombo" onchange="colorByMenuChanged()" size="3">
-            </select>
-            <div class="list" id="colorbylist">
-            </div>
-        </div>
-        <div id="showby" align="center">%s
-            <table width="100%%">
-                <tr>
-                    <td align="center">
-                        <select id="showbycombo" onchange="showByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="showbylist" style="height:100%%;width:100%%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereopacity" class="text">Global Sphere Opacity</label>
-                        <label id="sphereopacity" class="slidervalue"></label>
-                        <div id="sopacityslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="scalingby" align="center">
-            <table width="100%%">
-                <tr>
-                    <td align="center">
-                        <select id="scalingbycombo" onchange="scalingByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="scalingbylist" style="height:100%%;width:100%%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereradius" class="text">Global Sphere Scale</label>
-                        <label id="sphereradius" class="slidervalue"></label>
-                        <div id="sradiusslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="labelby">
-        <div id="labelsTop">
-            <form name="plotoptions">
-            <input type="checkbox" onClick="toggleLabels()">Samples Label Visibility</input>
-            </form>%s
-            <br>
-            <label for="labelopacity" class="text">Label Opacity</label>
-            <label id="labelopacity" class="slidervalue"></label>
-            <div id="lopacityslider" class="slider-range-max"></div>
-            <div id="labelColorHolder clearfix">
-            <table>
-                <tr><td><div id="labelColor" class="colorbox"></div></td><td><label>Master Label Color</label></td></tr>%s
-            </table></div>
-        </div>
-            <br>
-            <select id="labelcombo" onchange="labelMenuChanged()">
-            </select>
-            <div class="list" id="labellist">
-            </div>
-        </div>
-        <div id="axes">
-            <div id="pcoaaxes">
-                <div class="list" id="axeslist">
-                </div>
-            </div>
-        </div>
-        <div id="options">
-            <table>
-                <tr><td><div id="axeslabelscolor" class="colorbox" name="axeslabelscolor"></div></td><td title="Axes Labels Color">Axes Labels Color</td></tr>
-                <tr><td><div id="axescolor" class="colorbox" name="axescolor"></div></td><td title="Axes Color Title">Axes Color</td></tr>
-                <tr><td><div id="rendererbackgroundcolor" class="colorbox" name="rendererbackgroundcolor"></div></td><td title="Background Color Title">Background Color</td></tr>%s
-            </table>
-            <div id="pcoaviewoptions" class="">%s%s%s
-                <form name="settingsoptionscolor">
-                </form>
-                <div id="pcoaoptions" class="">
-                    <form name="settingsoptions">
-                        <input type="checkbox" onchange="toggleScaleCoordinates(this)" id="scale_checkbox" name="scale_checkbox">Scale coords by percent explained</input>
-                    </form>
-                </div>
-                <br><input id="reset" class="button" type="submit" value="Recenter Camera" style="" onClick="resetCamera()">
-                <br><br>
-                <hr class='section-break'>
-                <br>Filename <small>(only letters, numbers, ., - and _)</small>:
-                <br><input name="saveas_name" id="saveas_name" value="screenshot" type="text"/>
-                <br><input id="saveas_legends" class="checkbox" type="checkbox" style=""> Create legend
-                <input id="saveas" class="button" type="submit" value="Save as SVG" style="" onClick="saveSVG()"/>
-                <br><br>For a PNG, simply press 'ctrl+p'.
-                <div id="paralleloptions" class="">
-                </div>
-            </div>
-            <br>
-        </div>
-    </div>  
-</div>
-</body>
-
-</html>
-"""
diff --git a/emperor/qiime_backports/__init__.py b/emperor/qiime_backports/__init__.py
index 6f85b3b..c4b3710 100644
--- a/emperor/qiime_backports/__init__.py
+++ b/emperor/qiime_backports/__init__.py
@@ -5,9 +5,9 @@ __author__ = "Emperor Development Team"
 __copyright__ = "Copyright 2013, The Emperor Project"
 __credits__ = ["Yoshiki Vazquez Baeza"]
 __license__ = "BSD"
-__version__ = "0.9.3"
+__version__ = "0.9.51-dev"
 __maintainer__ = "Yoshiki Vazquez Baeza"
 __email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
+__status__ = "Development"
 
 __all__ = ['biplots', 'filter', 'format', 'make_3d_plots', 'parse', 'util']
diff --git a/emperor/qiime_backports/biplots.py b/emperor/qiime_backports/biplots.py
index c6fda39..f310d66 100644
--- a/emperor/qiime_backports/biplots.py
+++ b/emperor/qiime_backports/biplots.py
@@ -39,14 +39,14 @@ def get_taxa_prevalence(tax_counts):
 
 def make_biplot_scores_output(taxa):
     """Create convenient output format of taxon biplot coordinates
-       
+
        taxa is a dict containing 'lineages' and a coord matrix 'coord'
-       
+
        output is a list of lines, each containing coords for one taxon
     """
     output = []
     ndims = len(taxa['coord'][1])
-    header = '#Taxon\t' + '\t'.join(['pc%d' %(i) for i in xrange(ndims)])
+    header = '#Taxon\t' + '\t'.join(['pc%d' %(i+1) for i in range(ndims)])
     output.append(header)
     for i, taxon in enumerate(taxa['lineages']):
         line = taxon + '\t'
diff --git a/emperor/qiime_backports/filter.py b/emperor/qiime_backports/filter.py
index b959f83..586b0cc 100644
--- a/emperor/qiime_backports/filter.py
+++ b/emperor/qiime_backports/filter.py
@@ -29,8 +29,8 @@ def sample_ids_from_metadata_description(mapping_f,valid_states_str):
     sample_ids = get_sample_ids(map_data, map_header, valid_states)
 
     if len(sample_ids)<1:
-        raise ValueError,"All samples have been filtered out for the criteria"+\
-            " described in the valid states"
+        raise ValueError("All samples have been filtered out for the criteria"
+                         " described in the valid states")
 
     return sample_ids
 
@@ -90,7 +90,7 @@ def filter_mapping_file(map_data, map_header, good_sample_ids,
     
     # keeping columns
     headers = []
-    to_keep = zip(*to_keep)
+    to_keep = list(zip(*to_keep))
     headers.append(map_header[0])
     result = [to_keep[0]]
     
@@ -100,7 +100,7 @@ def filter_mapping_file(map_data, map_header, good_sample_ids,
         for i,l in enumerate(to_keep[1:-1]):
             if i==column_rename_ids:
                 if len(set(l))!=len(result[0]):
-                     raise ValueError, "The column to rename the samples is not unique."
+                     raise ValueError("The column to rename the samples is not unique.")
                 result.append(result[0])
                 result[0] = l
                 headers.append('SampleID_was_' + map_header[i+1])
@@ -115,6 +115,6 @@ def filter_mapping_file(map_data, map_header, good_sample_ids,
     headers.append(map_header[-1])
     result.append(to_keep[-1])
     
-    result = map(list,zip(*result))
+    result = list(map(list, zip(*result)))
     
     return headers, result
diff --git a/emperor/qiime_backports/make_3d_plots.py b/emperor/qiime_backports/make_3d_plots.py
index 4b88632..50b985b 100644
--- a/emperor/qiime_backports/make_3d_plots.py
+++ b/emperor/qiime_backports/make_3d_plots.py
@@ -24,14 +24,14 @@ def get_custom_coords(axis_names,mapping, coords):
     """
     for i, axis in enumerate(reversed(axis_names)):
         if not axis in mapping[0]:
-            raise ValueError, 'Warning: could not find custom axis %s in map headers: %s' \
-                % (axis, mapping[0])
+            raise ValueError('Warning: could not find custom axis %s in map '
+                             'headers: %s' % (axis, mapping[0]))
         else:
             # get index of column in mapping file
             col_idx = mapping[0].index(axis)
             # extract column data
-            col = zip(*mapping[1:])[col_idx]
-            sample_IDs = zip(*mapping[1:])[0]
+            col = list(zip(*mapping[1:]))[col_idx]
+            sample_IDs = list(zip(*mapping[1:]))[0]
             new_coords = array([])
             # load custom coord for this axis for each sample ID 
             for id in coords[0]:
@@ -60,7 +60,7 @@ def scale_custom_coords(custom_axes,coords):
     to_mx = 2*max(coords[1][:,len(custom_axes)])
 
     # affine transformation for each custom axis
-    for i in xrange(len(custom_axes)):
+    for i in range(len(custom_axes)):
         from_mn = min(coords[1][:,i])
         from_mx = max(coords[1][:,i])
         coords[1][:,i] = (coords[1][:,i]  - from_mn) / (from_mx - from_mn)
diff --git a/emperor/qiime_backports/parse.py b/emperor/qiime_backports/parse.py
index 5297b07..b181e88 100644
--- a/emperor/qiime_backports/parse.py
+++ b/emperor/qiime_backports/parse.py
@@ -12,8 +12,6 @@ __email__ = "gregcaporaso at gmail.com"
 __status__ = "Development"
 
 
-from string import strip
-
 from numpy import asarray
 
 class QiimeParseError(Exception):
@@ -33,9 +31,8 @@ def parse_mapping_file(lines, strip_quotes=True, suppress_stripping=False):
         try:
             lines = open(lines,'U')
         except IOError:
-            raise QiimeParseError,\
-             ("A string was passed that doesn't refer "
-              "to an accessible filepath.")
+            raise QiimeParseError("A string was passed that doesn't refer "
+                                  "to an accessible filepath.")
         
     if strip_quotes:
         if suppress_stripping:
@@ -72,14 +69,14 @@ def parse_mapping_file(lines, strip_quotes=True, suppress_stripping=False):
                 comments.append(line)
         else:
             # Will add empty string to empty fields
-            tmp_line = map(strip_f, line.split('\t'))
+            tmp_line = list(map(strip_f, line.split('\t')))
             if len(tmp_line)<len(header):
                 tmp_line.extend(['']*(len(header)-len(tmp_line)))
             mapping_data.append(tmp_line)
     if not header:
-        raise QiimeParseError, "No header line was found in mapping file."
+        raise QiimeParseError("No header line was found in mapping file.")
     if not mapping_data:
-        raise QiimeParseError, "No data found in mapping file."
+        raise QiimeParseError("No data found in mapping file.")
     
     return mapping_data, header, comments
 
@@ -99,11 +96,12 @@ def parse_metadata_state_descriptions(state_string):
     result = {}
     state_string = state_string.strip()
     if state_string:
-        cols = map(strip, state_string.split(';'))
+        cols = [s.strip()  for s in state_string.split(';')]
         for c in cols:
             # split on the first colon to account for category names with colons
-            colname, vals = map(strip, c.split(':', 1))
-            vals = map(strip, vals.split(','))
+            colname, vals = [s.strip() for s in c.split(':', 1)]
+
+            vals = [v.strip() for v in vals.split(',')]
             result[colname] = set(vals)
     return result
 
@@ -126,9 +124,8 @@ def parse_mapping_file_to_dict(*args, **kwargs):
 def process_otu_table_sample_ids(sample_id_fields):
     """ process the sample IDs line of an OTU table """
     if len(sample_id_fields) == 0:
-            raise ValueError, \
-             'Error parsing sample ID line in OTU table. Fields are %s' \
-             % ' '.join(sample_id_fields)
+            raise ValueError('Error parsing sample ID line in OTU table. '
+                             'Fields are %s' % ' '.join(sample_id_fields))
             
     # Detect if a metadata column is included as the last column. This
     # field will be named either 'Consensus Lineage' or 'OTU Metadata',
@@ -166,9 +163,9 @@ def parse_classic_otu_table(lines,count_map_f=int, remove_empty_rows=False):
                     sample_ids, has_metadata = process_otu_table_sample_ids(
                      line.strip().split('\t')[1:])
                 except ValueError:
-                    raise ValueError, \
-                     "Error parsing sample IDs in OTU table. Appears to be a"+\
-                     " legacy OTU table. Sample ID line:\n %s" % line
+                    raise ValueError("Error parsing sample IDs in OTU table. "
+                                     "Appears to be a legacy OTU table. Sample"
+                                     " ID line:\n %s" % line)
             elif not line.startswith('#'):
                 if not sample_ids:
                     # current line is the first non-space, non-comment line 
@@ -177,9 +174,8 @@ def parse_classic_otu_table(lines,count_map_f=int, remove_empty_rows=False):
                         sample_ids, has_metadata = process_otu_table_sample_ids(
                          line.strip().split('\t')[1:])
                     except ValueError:
-                        raise ValueError,\
-                         "Error parsing sample IDs in OTU table."+\
-                         " Sample ID line:\n %s" % line
+                        raise ValueError("Error parsing sample IDs in OTU "
+                                         "table. Sample ID line:\n %s" % line)
                 else:
                     # current line is OTU line in OTU table
                     fields = line.split('\t')
@@ -197,7 +193,7 @@ def parse_classic_otu_table(lines,count_map_f=int, remove_empty_rows=False):
                         if remove_empty_rows and (valid_fields>=0).all() and \
                            sum(valid_fields)==0.0:
                             continue
-                        metadata.append(map(strip, fields[-1].split(';')))
+                        metadata.append([f.strip() for f in fields[-1].split(';')])
                     else:
                         # otherwise all columns are appended to otu_table
                         # added in a try/except to handle OTU tables containing
@@ -245,8 +241,8 @@ def parse_coords(lines):
         raise QiimeParseError("The line with the vector number was not found"
             ", this information is required in coordinates files")
 
-    lines = map(strip, lines[1:])   #discard first line, which is a label
-    lines = filter(None, lines) #remove any blank lines
+    lines = [l.strip() for l in lines[1:]] # discard first line, which is a label
+    lines = [_f for _f in lines if _f] # remove any blank lines
 
     # check on this information post removal of blank lines
     if not lines[-2].startswith('eigvals'):
@@ -263,8 +259,8 @@ def parse_coords(lines):
     #finally, dump the rest of the lines into a table
     header, result = [], []
     for line in lines[:-2]:
-        fields = map(strip, line.split('\t'))
+        fields = [f.strip() for f in line.split('\t')]
         header.append(fields[0])
-        result.append(map(float, fields[1:]))
+        result.append([float(f) for f in fields[1:]])
 
     return header, asarray(result), eigvals, pct_var
diff --git a/emperor/qiime_backports/util.py b/emperor/qiime_backports/util.py
index d7f08c1..29e4a78 100644
--- a/emperor/qiime_backports/util.py
+++ b/emperor/qiime_backports/util.py
@@ -9,8 +9,9 @@ __maintainer__ = "Yoshiki Vazquez Baeza"
 __email__ = "yoshik89 at gmail.com"
 __status__ = "Development"
 
+from scipy.spatial import procrustes
+
 from emperor.qiime_backports.parse import parse_mapping_file_to_dict
-from emperor.pycogent_backports.procrustes import procrustes
 
 from numpy.ma.extras import apply_along_axis
 from numpy.ma import MaskedArray
@@ -357,8 +358,8 @@ def _compute_jn_pcoa_avg_ranges(jn_flipped_matrices, method):
     elif method == "sdev":
         # calculate std error for each sample in each dimension
         sdevs = zeros(shape=[x,y])
-        for j in xrange(y):
-            for i in xrange(x):
+        for j in range(y):
+            for i in range(x):
                 vals = array([pcoa[i][j] for pcoa in jn_flipped_matrices])
                 sdevs[i,j] = vals.std(ddof=1)
         matrix_low = -sdevs/2
@@ -420,4 +421,4 @@ def idealfourths(data, axis=None):
     if (axis is None):
         return _idf(data)
     else:
-        return apply_along_axis(_idf, axis, data)
\ No newline at end of file
+        return apply_along_axis(_idf, axis, data)
diff --git a/emperor/sort.py b/emperor/sort.py
index c2ade34..ab0b9fe 100644
--- a/emperor/sort.py
+++ b/emperor/sort.py
@@ -1,41 +1,45 @@
-#!/usr/bin/env python
-# File created on 20 Apr 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
 from numpy import zeros
-from re import compile, search
+import re
+
 
 def sort_taxa_table_by_pcoa_coords(coords_header, otu_table, otu_header):
     """Sort and match the samples in the otu table and in the coordinates data
 
-    Inputs:
-    coords_header: sample ids that are present in principal coordinates data
-    otu_table: numpy array with the data for an otu table
-    otu_header: sample ids present in the otu table
-
-    Ouputs:
-    sorted_otu_headers: sample ids that were present in the coords_header list,
-    the order in this table matches the order of the coordinates data
-    sorted_otu_table: otu table data with columns belonging to the sample ids in
-    the sorted_otu_headers list
-
     This function will sort the columns of an otu table as suggested by the
     sample ids in the coords_header
+
+    Parameters
+    ----------
+    coords_header: list of str
+        sample ids that are present in principal coordinates data
+    otu_table: numpy array
+        numpy array with the data for an otu table
+    otu_header: list of str
+        sample ids present in the otu table
+
+    Returns
+    -------
+    sorted_otu_headers: list of str
+        sample ids that were present in the coords_header list, the order in
+        this table matches the order of the coordinates data
+    sorted_otu_table: numpy array
+        otu table data with columns belonging to the sample ids in the
+        sorted_otu_headers list
     """
 
     sorted_otu_headers = []
 
     # the size of the otu table can be pre-allocated for better memory usage
-    matching_headers = len(set(coords_header)&set(otu_header))
+    matching_headers = len(set(coords_header) & set(otu_header))
     sorted_otu_table = zeros([otu_table.shape[0], matching_headers])
 
     # iterate through the available sample ids in the coordinates file and work
@@ -44,22 +48,27 @@ def sort_taxa_table_by_pcoa_coords(coords_header, otu_table, otu_header):
     for i, element in enumerate(coords_header):
         if element in otu_header:
             current_index = otu_header.index(element)
-            sorted_otu_table[:,i] = otu_table[:,current_index]
+            sorted_otu_table[:, i] = otu_table[:, current_index]
             sorted_otu_headers.append(element)
 
     return sorted_otu_headers, sorted_otu_table
 
+
 def sort_comparison_filenames(coord_fps):
     """Pass in a list of file names and sort them using the suffix
 
-    Input:
-    coord_fps: list of filenames with the format something_something_qX.txt
-    where X is the index of the file.
-
-    Output:
-    Returns a sorted version of the list that was passed in where the strings
-    are sorted according to the suffix they have, if the string doesn't have
-    a suffix it will be added to the beginning of the list.
+    Parameters
+    ----------
+    coord_fps: list of str
+        The filenames with the format something_something_qX.txt where X is
+        the index of the file.
+
+    Returns
+    -------
+    list of str
+        A sorted version of the list that was passed in where the strings are
+        sorted according to the suffix they have, if the string doesn't have a
+        suffix it will be added to the beginning of the list.
     """
 
     if coord_fps == []:
@@ -67,11 +76,11 @@ def sort_comparison_filenames(coord_fps):
 
     def _get_suffix(fp):
         """Gets the number in the suffix for a string using a regex"""
-        # any alphanumeric set of characters proceeded by a 'q', a number, a dot
-        # & a txt extension at the end of the line. Take for example 
+        # any alphanumeric set of characters proceeded by a 'q', a number,
+        # a dot & a txt extension at the end of the line. Take for example
         # bray_curtis_q1.txt or unifrac_q11.txt
-        re = compile(r'(\w+)_q([0-9]+).txt$')
-        tmatch = search(re, fp)
+        regex = re.compile(r'(\w+)_q([0-9]+).txt$')
+        tmatch = re.search(regex, fp)
 
         try:
             number = tmatch.group(2)
@@ -84,4 +93,3 @@ def sort_comparison_filenames(coord_fps):
     # the key function retrieves the suffix number for the function to sort
     # according to it's floating point representation i. e. the cast to float
     return sorted(coord_fps, key=_get_suffix)
-
diff --git a/emperor/util.py b/emperor/util.py
index 3b776f5..64a1499 100644
--- a/emperor/util.py
+++ b/emperor/util.py
@@ -1,70 +1,40 @@
-#!/usr/bin/env python
-# File created on 25 Jan 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza", "Antonio Gonzalez Pena"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
+import pandas as pd
+import numpy as np
 
-
-from numpy import ndarray, array, ones, zeros, vstack
-from string import strip
-
-from os import makedirs
-from os.path import abspath, dirname, join, exists
+from os import listdir
+from os.path import abspath, dirname, join, isdir
 from copy import deepcopy
 
-from qcli.util import qcli_system_call
-
-from emperor.qiime_backports.format import format_mapping_file
-from emperor.qiime_backports.filter import filter_mapping_file
 from emperor.qiime_backports.make_3d_plots import (get_custom_coords,
-    remove_nans, scale_custom_coords)
-from emperor.qiime_backports.parse import (mapping_file_to_dict,
-    parse_metadata_state_descriptions)
-from emperor.qiime_backports.util import (MetadataMap, is_valid_git_refname,
-    is_valid_git_sha1, summarize_pcoas)
+                                                   remove_nans,
+                                                   scale_custom_coords)
+from emperor.qiime_backports.parse import mapping_file_to_dict
+from emperor.qiime_backports.util import MetadataMap, summarize_pcoas
 
-from emperor import __version__ as emperor_library_version
 
 class EmperorSupportFilesError(IOError):
     """Exception for missing support files"""
     pass
-    
+
+
 class EmperorInputFilesError(IOError):
     """Exception for missing support files"""
     pass
 
+
 class EmperorUnsupportedComputation(ValueError):
     """Exception for computations that lack a meaning"""
     pass
 
-# Based on qiime/qiime/util.py
-def get_emperor_library_version():
-    """Get Emperor version and the git SHA + current branch (if applicable)"""
-    emperor_dir = get_emperor_project_dir()
-    emperor_version = emperor_library_version
-
-    # more information could be retrieved following this pattern
-    sha_cmd = 'git --git-dir %s/.git rev-parse HEAD' % (emperor_dir)
-    sha_o, sha_e, sha_r = qcli_system_call(sha_cmd)
-    git_sha = sha_o.strip()
-
-    branch_cmd = 'git --git-dir %s/.git rev-parse --abbrev-ref HEAD' %\
-        (emperor_dir)
-    branch_o, branch_e, branch_r = qcli_system_call(branch_cmd)
-    git_branch = branch_o.strip()
-
-    # validate the output from both command calls
-    if is_valid_git_refname(git_branch) and is_valid_git_sha1(git_sha):
-        return '%s, %s@%s' % (emperor_version, git_branch, git_sha[0:7])
-    else:
-        return '%s' % emperor_version
 
 def get_emperor_project_dir():
     """ Returns the top-level Emperor directory
@@ -78,53 +48,92 @@ def get_emperor_project_dir():
     # Return the directory containing the directory containing util.py
     return dirname(current_dir_path)
 
+
 def get_emperor_support_files_dir():
     """Returns the path for the support files of the project """
     return join(get_emperor_project_dir(), 'emperor/support_files/')
 
-def copy_support_files(file_path):
-    """Copy the support files to a named destination 
 
-    file_path: path where you want the support files to be copied to
-
-    Will raise EmperorSupportFilesError if a problem is found whilst trying to
-    copy the files.
+def nbinstall(overwrite=False, user=True, prefix=None):
+    """Copies resources to the '/nbextensions' folder in your IPython directory
+
+    This function was taken from [1] and modified to match our usecase.
+
+    Parameters
+    ----------
+    overwrite : bool, optional
+        If True, always install the files, regardless of what may already be
+        installed. Defaults to False.
+    user : bool, optional
+        Whether to install to the user's .ipython/nbextensions directory.
+        Otherwise do a system-wide install
+        (e.g. /usr/local/share/jupyter/nbextensions/emperor). Defaults to
+        False.
+    prefix : str, optional
+        Where the files are copied to, by default they are copied to the
+        appropriate Jupyter/IPython folder, alternatively it can be a folder
+        where the resources are copied to. Note, that if this parameter is set
+        `user` has to be `None`.
+
+    Raises
+    ------
+    ArgumentConflict
+        When `prefix` and `user` are used together.
+
+    Notes
+    -----
+    After you install emperor, call this function once before attempting to
+    call ``Emperor`` in the Jupyter notebook.
+
+    References
+    ----------
+    .. [1] GitHub repository for qgrid https://github.com/quantopian/qgrid
     """
-    file_path = join(file_path, 'emperor_required_resources')
-
-    if not exists(file_path):
-        makedirs(file_path)
 
-    # shutil.copytree does not provide an easy way to copy the contents of a
-    # directory into another existing directory, hence the system call.
-    # use double quotes for the paths to escape any invalid chracter(s)/spaces
-    cmd = 'cp -R "%s/"* "%s"' % (get_emperor_support_files_dir(),
-        abspath(file_path))
-    cmd_o, cmd_e, cmd_r = qcli_system_call(cmd)
-
-    if cmd_e:
-        raise EmperorSupportFilesError, "Error found whilst trying to copy " +\
-            "the support files:\n%s\n Could not execute: %s" % (cmd_e, cmd)
+    # Lazy imports so we don't pollute the namespace.
+    try:
+        from notebook import install_nbextension
+    except ImportError:
+        from IPython.html.nbextensions import install_nbextension
+    from IPython import version_info
+
+    install_nbextension(
+        get_emperor_support_files_dir(),
+        overwrite=overwrite,
+        symlink=False,
+        prefix=prefix,
+        verbose=0,
+        destination='emperor/support_files',
+        **({'user': user} if version_info >= (3, 0, 0, '') else {})
+    )
 
-    return
 
 def preprocess_mapping_file(data, headers, columns, unique=False, single=False,
                             clones=0):
     """Process a mapping file to expand the data or remove unuseful fields
 
-    Inputs:
-    data: mapping file data
-    headers: mapping file headers
-    columns: list of headers to keep, if one of these headers includes two
-    ampersands, this function will create a new column by merging the delimited
-    columns.
-    unique: keep columns where all values are unique
-    single: keep columns where all values are the same
-    clones: number of times to replicate the metadata
-
-    Outputs:
-    data: processed mapping file data
-    headers: processed mapping file headers
+    Parameters
+    ----------
+    data: list of list of str
+        mapping file data
+    headers: list of str
+        mapping file headers
+    columns: list of str
+        headers to keep, if one of these headers includes two ampersands,
+        this function will create a new column by merging the delimited columns
+    unique: bool, optional
+        keep columns where all values are unique. Default: false.
+    single: bool, optional
+        keep columns where all values are the same. Default: false
+    clones: int, optional
+        number of times to replicate the metadata. Default: 0
+
+    Returns
+    -------
+    data: list of list of str
+        processed mapping file data
+    headers: list of str
+        processed mapping file headers
     """
 
     # The sample ID must always be there, else it's meaningless data
@@ -134,37 +143,71 @@ def preprocess_mapping_file(data, headers, columns, unique=False, single=False,
     # process concatenated columns if needed
     merge = []
     for column in columns:
-        if '&&' in column:
+        # the list can contain None so check "if column" before treating as str
+        if column and '&&' in column:
             merge.append(column)
     # each element needs several columns to be merged
     for new_column in merge:
         indices = [headers.index(header_name) for header_name in
-            new_column.split('&&')]
+                   new_column.split('&&')]
 
         # join all the fields of the metadata that are listed in indices
         for line in data:
             line.append(''.join([line[index] for index in indices]))
         headers.append(new_column)
 
-    # remove all unique or singled valued columns
+    # remove all unique or singled valued columns that are not included in
+    # the list of categories that should be kept i. e. columns
     if unique or single:
         columns_to_remove = []
         metadata = MetadataMap(mapping_file_to_dict(data, headers), [])
 
-        # find columns that have values that are all unique
-        if unique == True:
-            columns_to_remove += [column_name for column_name in headers[1::]
-                if metadata.hasUniqueCategoryValues(column_name)]
+        # the --coloy_by option in the script interface allows the user to
+        # specify the categories you want to use in the generated plot, this
+        # the default behaviour is to color by all categories that are not
+        # unique. If the user specifies a category with with the --color_by
+        # option and this category contains a unique values, this category must
+        # still be added thus the structure of the next few lines that
+        # form the structure for the two different routes. (1) where no value
+        # is specified in the CLI (the value of columns will be [None, x1, x2,
+        # x3] where x{1,2,3} are categories requested in other CLI options) and
+        # (2) where a value is specified in the CLI.
+        #
+        # TL;DR
+        # see https://github.com/biocore/emperor/issues/271
+        if None in columns:
+            columns = headers[:]
+            f_unique = metadata.hasUniqueCategoryValues
+            f_single = metadata.hasSingleCategoryValue
+        else:
+            def f_unique(x):
+                return metadata.hasUniqueCategoryValues(x) and x not in columns
+
+            def f_single(x):
+                return metadata.hasSingleCategoryValue(x) and x not in columns
 
+        # find columns that have values that are all unique
+        if unique:
+            for c in headers[1::]:
+                if f_unique(c):
+                    columns_to_remove.append(c)
         # remove categories where there is only one value
-        if single == True:
-            columns_to_remove += [column_name for column_name in headers[1::]
-                if metadata.hasSingleCategoryValue(column_name)]
+        if single:
+            for c in headers[1::]:
+                if f_single(c):
+                    columns_to_remove.append(c)
         columns_to_remove = list(set(columns_to_remove))
 
         # remove the single or unique columns
         data, headers = keep_columns_from_mapping_file(data, headers,
-            columns_to_remove, negate=True)
+                                                       columns_to_remove,
+                                                       negate=True)
+    else:
+        # when a None is contained in columns, we imply we want to use all the
+        # available categories in the mapping file, thus just overwrite the
+        # value
+        if None in columns:
+            columns = headers[:]
 
     # remove anything not specified in the input
     data, headers = keep_columns_from_mapping_file(data, headers, columns)
@@ -172,12 +215,13 @@ def preprocess_mapping_file(data, headers, columns, unique=False, single=False,
     # sanitize the mapping file data and headers
     data, headers = sanitize_mapping_file(data, headers)
 
-    # clones mean: replicate the metadata retagging the sample ids with a suffix
+    # clones mean: replicate the metadata retagging the sample ids with a
+    # suffix
     if clones:
         out_data = []
         for index in range(0, clones):
             out_data.extend([[element[0]+'_%d' % index]+element[1::]
-                for element in data])
+                             for element in data])
         data = out_data
 
     return data, headers
@@ -186,21 +230,30 @@ def preprocess_mapping_file(data, headers, columns, unique=False, single=False,
 def keep_columns_from_mapping_file(data, headers, columns, negate=False):
     """Select the header names to remove/keep from the mapping file
 
-    Inputs:
-    data: mapping file data
-    headers: mapping file headers names
-    columns: header names to keep/remove, see negate
-    negate: False will _keep_ the listed columns; True will _remove_ them
-
-    Outputs:
-    data: filtered mapping file data
-    headers: filtered mapping file headers
+    Parameters
+    ----------
+    data: list of list of str
+        mapping file data
+    headers: list of str
+        mapping file headers names
+    columns: list of str
+        header names to keep/remove, see negate
+    negate: bool, optional
+        False will _keep_ the listed columns; True will _remove_ them.
+        Default: False
+
+    Returns
+    -------
+    data: list of list of str
+        filtered mapping file data
+    headers: list of str
+        filtered mapping file headers
     """
     data = deepcopy(data)
     headers = deepcopy(headers)
 
     if negate:
-        indices_of_interest = range(0, len(headers))
+        indices_of_interest = list(range(0, len(headers)))
     else:
         indices_of_interest = []
 
@@ -217,67 +270,93 @@ def keep_columns_from_mapping_file(data, headers, columns, negate=False):
             continue
 
     # keep the elements at the positions indices
-    keep_elements = lambda elements, indices :[element for i, element in
-        enumerate(elements) if i in indices]
+    def keep_elements(elements, indices):
+        return [element for i, element in enumerate(elements) if i in indices]
 
     headers = keep_elements(headers, indices_of_interest)
     data = [keep_elements(row, indices_of_interest) for row in data]
 
     return data, headers
 
+
 def preprocess_coords_file(coords_header, coords_data, coords_eigenvals,
-                        coords_pct, mapping_header, mapping_data,
-                        custom_axes=None, jackknifing_method=None,
-                        is_comparison=False):
+                           coords_pct, mapping_header, mapping_data,
+                           custom_axes=None, jackknifing_method=None,
+                           is_comparison=False,
+                           pct_variation_below_one=False):
     """Process a PCoA data and handle customizations in the contents
 
-    Inputs:
-    coords_header: list of sample identifiers in the PCoA file _or_ list of
-    lists with sample identifiers for each coordinate file (if jackknifing or
-    comparing plots)
-    coords_data: matrix of coordinates in the PCoA file _or_ list of numpy
-    arrays with coordinates for each file (if jackknifing or comparing plots)
-    coords_eigenvals: numpy array with eigenvalues for the coordinates file _or_
-    list of numpy arrays with the eigenvalues (if jackknifing or comparing plots
-    )
-    coords_pct: numpy array with a the percent explained by each principal
-    coordinates axis _or_ a list of lists with numpy arrays (if jackknifing or
-    comparing plots)
-    mapping_header: mapping file headers names
-    mapping_data: mapping file data
-    custom_axes: name of the mapping data fields to add to coords_data
-    jackknifing_method: one of 'sdev' or 'IRQ', defaults to None, for more info
-    see qiime.util.summarize_pcoas
-    is_comparison: whether or not the inputs should be considered as the ones
-    for a comparison plot
-
-    Outputs:
-    coords_header: list of sample identifiers in the PCoA file
-    coords_data: matrix of coordinates in the PCoA file with custom_axes if
-    provided
-    coords_eigenvalues: either the eigenvalues of the input coordinates or the
-    average eigenvalues of the multiple coords that were passed in
-    coords_pct: list of percents explained by each axis as given by the master
-    coordinates i. e. the center around where the values revolve
-    coords_low: coordinates representing the lower edges of an ellipse; None if
-    no jackknifing is applied
-    coords_high: coordinates representing the highere edges of an ellipse; None
-    if no jackknifing is applied
-    clones: total number of input files
-
     This controller function handles any customization that has to be done to
     the PCoA data prior to the formatting. Note that the first element in each
-    list (coords, headers, eigenvalues & percents) will be considered the master
-    set of coordinates.
-
-    Raises: AssertionError if a comparison plot is requested but a list of data
-    is not passed as input
+    list (coords, headers, eigenvalues & percents) will be considered the
+    master set of coordinates.
+
+    Parameters
+    ----------
+    coords_header: 1d or 2d array of str
+        If 1d array of str, the sample identifiers in the PCoA file
+        If 2d array of str, the sample identifiers for each coordinate
+        file (if jackknifing or comparing plots)
+    coords_data: 2d array of float or list of 2d array of float
+        If 2d array of float, matrix of coordinates in the PCoA file
+        If list of 2d array of float,  with coordinates for each file
+        (if jackknifing or comparing plots)
+    coords_eigenvals: 1d or 2d array of float
+        If 1d array, eigenvalues for the coordinates file
+        If 2d array, list of  arrays with the eigenvalues
+        (if jackknifing or comparing plots)
+    coords_pct: 1d or 2d array of float
+        If 1d array, the percent explained by each principal coordinates axis
+        If 2d array, a list of lists with numpy arrays (if jackknifing or
+        comparing plots)
+    mapping_header: list of str
+        mapping file headers names
+    mapping_data: list of lists of str
+        mapping file data
+    custom_axes: str, optional
+        name of the mapping data fields to add to coords_data. Default: None
+    jackknifing_method: {'sdev', 'IRQ', None}, optional
+        For more info see qiime.util.summarize_pcoas. Default: None
+    is_comparison: bool, optional
+        whether or not the inputs should be considered as the ones for a
+        comparison plot. Default: false
+    pct_variation_below_one: bool, optional
+        boolean to allow percet variation of the axes be under one.
+        Default: false
+
+    Returns
+    -------
+    coords_header: list of str
+        Sample identifiers in the PCoA file
+    coords_data: 2d array of float
+        matrix of coordinates in the PCoA file with custom_axes if provided
+    coords_eigenvals: array of float
+        either the eigenvalues of the input coordinates or the average
+        eigenvalues of the multiple coords that were passed in
+    coords_pct: array of float
+        list of percents explained by each axis as given by the master
+        coordinates i. e. the center around where the values revolve
+    coords_low: 2d array of float
+        coordinates representing the lower edges of an ellipse; None if no
+        jackknifing is applied
+    coords_high: 2d array of float
+        coordinates representing the highere edges of an ellipse; None if no
+        jackknifing is applied
+    clones: int
+        total number of input files
+
+    Raises
+    ------
+    AssertionError
+        if a comparison plot is requested but a list of data is not passed
+        as input
     """
 
     # prevent obscure and obfuscated errors
     if is_comparison:
-        assert type(coords_data) == list, "Cannot process a comparison with "+\
-            "the data from a single coordinates file"
+        assert type(coords_data) == list, ("Cannot process a comparison with "
+                                           "the data from a single "
+                                           "coordinates file")
 
     mapping_file = [mapping_header] + mapping_data
     coords_file = [coords_header, coords_data]
@@ -285,25 +364,26 @@ def preprocess_coords_file(coords_header, coords_data, coords_eigenvals,
     # number PCoA files; zero for any case except for comparison plots
     clones = 0
 
-    if custom_axes and type(coords_data) == ndarray:
+    if custom_axes and type(coords_data) == np.ndarray:
             # sequence ported from qiime/scripts/make_3d_plots.py @ 9115351
             get_custom_coords(custom_axes, mapping_file, coords_file)
             remove_nans(coords_file)
             scale_custom_coords(custom_axes, coords_file)
-    elif type(coords_data) == list and is_comparison == False:
+    elif type(coords_data) == list and not is_comparison:
         # take the first pcoa file as the master set of coordinates
         master_pcoa = [coords_header[0], coords_data[0],
-            coords_eigenvals[0], coords_pct[0]]
+                       coords_eigenvals[0], coords_pct[0]]
 
         # support pcoas must be a list of lists where each list contain
         # all the elements that compose a coordinates file
         support_pcoas = [[h, d, e, p] for h, d, e, p in zip(coords_header,
-            coords_data, coords_eigenvals, coords_pct)]
+                         coords_data, coords_eigenvals, coords_pct)]
 
         # do not apply procrustes, at least not for now
         coords_data, coords_low, coords_high, eigenvalues_average,\
             identifiers = summarize_pcoas(master_pcoa, support_pcoas,
-                method=jackknifing_method, apply_procrustes=False)
+                                          method=jackknifing_method,
+                                          apply_procrustes=False)
 
         # custom axes and jackknifing is a tricky thing to do, you only have to
         # add the custom values to the master file which is represented as the
@@ -318,10 +398,14 @@ def preprocess_coords_file(coords_header, coords_data, coords_eigenvals,
 
             # this opens support for as many custom axes as needed
             axes = len(custom_axes)
-            coords_low[:, 0:axes] = zeros([coords_low.shape[0], axes])
-            coords_high[:, 0:axes] = ones([coords_high.shape[0], axes])*0.00001
+            coords_low[:, 0:axes] = np.zeros([coords_low.shape[0], axes])
+            coords_high[:, 0:axes] = np.full((coords_high.shape[0], axes),
+                                             fill_value=0.00001)
             coords_data = coords_file[1]
 
+        if master_pcoa[3][0] < 1.0 and not pct_variation_below_one:
+            master_pcoa[3] = master_pcoa[3]*100
+
         # return a value containing coords_low and coords_high
         return identifiers, coords_data, eigenvalues_average, master_pcoa[3],\
             coords_low, coords_high, clones
@@ -338,7 +422,8 @@ def preprocess_coords_file(coords_header, coords_data, coords_eigenvals,
             coords_i = coords_data[index]
 
             # tag each header with the the number in which those coords came in
-            out_headers.extend([element+'_%d' % index for element in headers_i])
+            out_headers.extend([element+'_%d' % index for element in
+                                headers_i])
 
             if index == 0:
                 # numpy can only stack things if they have the same shape
@@ -349,19 +434,19 @@ def preprocess_coords_file(coords_header, coords_data, coords_eigenvals,
                 coords_eigenvals = coords_eigenvals[index]
                 coords_pct = coords_pct[index]
             else:
-                out_coords = vstack((out_coords, coords_i))
+                out_coords = np.vstack((out_coords, coords_i))
 
         coords_file = [out_headers, out_coords]
 
         if custom_axes:
             # this condition deals with the fact that in order for the custom
-            # axes to be added into the original coordinates, we have to add the
-            # suffix for the sample identifiers that the coordinates have
+            # axes to be added into the original coordinates, we have to add
+            # the suffix for the sample identifiers that the coordinates have
             if clones:
                 out_data = []
                 for index in range(0, clones):
                     out_data.extend([[element[0]+'_%d' % index]+element[1::]
-                        for element in mapping_data])
+                                     for element in mapping_data])
                 mapping_file = [mapping_header] + out_data
 
             # sequence ported from qiime/scripts/make_3d_plots.py @ 9115351
@@ -369,16 +454,27 @@ def preprocess_coords_file(coords_header, coords_data, coords_eigenvals,
             remove_nans(coords_file)
             scale_custom_coords(custom_axes, coords_file)
 
+    if coords_pct[0] < 1.0 and not pct_variation_below_one:
+        coords_pct = coords_pct*100
+
     # if no coords summary is applied, return None in the corresponding values
     # note that the value of clones will be != 0 for a comparison plot
     return coords_file[0], coords_file[1], coords_eigenvals, coords_pct, None,\
         None, clones
 
+
 def _is_numeric(x):
     """Return true if x is a numeric value, return false else
 
-    Inputs:
-    x: string to test whether something is or not a number
+    Parameters
+    ----------
+    x : str
+        string to test whether something is or not a number
+
+    Returns
+    -------
+    bool
+        whether something is or not a number
     """
     try:
         float(x)
@@ -386,103 +482,225 @@ def _is_numeric(x):
         return False
     return True
 
+
 def fill_mapping_field_from_mapping_file(data, headers, values,
-                                        criteria=_is_numeric):
+                                         criteria=_is_numeric):
     """
-    Inputs:
-    data: mapping file data
-    headers: mapping file headers
-    values: string with the format a format of
-            Category:ValueToFill;Category:ValueToFill ...
-            or
-            Category:ColumnToSearch==ValueWithinTheColumnToSearch=ValueToFill
-    criteria: function that takes a value and returns true or false, default is
-    to check if the inputed value is numeric or not.
-
-    Output:
-    data: Filled in mapping file data
-
+    Parameters
+    ----------
+    data : list of list of str
+        mapping file data
+    headers : list of str
+        mapping file headers
+    values : str
+        string with the format a format of
+        Category:ValueToFill;Category:ValueToFill ...
+        or
+        Category:ColumnToSearch==ValueWithinTheColumnToSearch=ValueToFill
+    criteria : function, optional
+        function that takes a value and returns true or false, default is
+        to check if the inputed value is numeric or not (_is_numeric).
+
+    Returns
+    -------
+    data: list of list of str
+        Filled in mapping file data
+
+    Raises
+    ------
+    EmperorInputFilesError
+        If a header is not found in the mapping file or it wasn't used for
+        processing.
     """
     out_data = deepcopy(data)
 
     # parsing the input values
-    values = map(strip, values.split(';'))
+    values = [val.strip() for val in values.split(';')]
     values_dict = {}
     for v in values:
-        colname, vals = map(strip, v.split(':', 1))
-        vals = map(strip, vals.split(','))
-        assert len(vals)==1,  "You can only pass 1 replacement value: %s" % vals
+        colname, vals = [val for val in v.split(':', 1)]
+        vals = [val.strip() for val in vals.split(',')]
+        assert len(vals) == 1, ("You can only pass 1 replacement value:"
+                                " {}".format(vals))
         if colname not in values_dict:
             values_dict[colname] = []
         values_dict[colname].extend(vals)
-    
+
     for key, v in values_dict.items():
         for value in v:
-            # variable that is going to contain the name of the column for multiple 
-            # subtitutions 
+            # variable that is going to contain the name of the column for
+            # multiple subtitutions
             column = None
             # variable to control if the values with in a column exist
             used_column_index = False
-            
+
             try:
                 header_index = headers.index(key)
             except ValueError:
-                raise EmperorInputFilesError, ("The header %s does not exist in the "
-                    "mapping file" % key)
-            
-            # for the special case of multiple entries 
+                raise EmperorInputFilesError(
+                    "The header {} does not exist in the mapping "
+                    "file".format(key))
+
+            # for the special case of multiple entries
             if '==' in value and '=' in value:
                 arrow_index = value.index('==')
                 equal_index = value.rindex('=')
-                assert ((arrow_index+2)!=equal_index and (arrow_index+1)!=equal_index), \
-                    "Not properly formatted: %s" % value
-                
+                assert(arrow_index+2) != equal_index and\
+                      (arrow_index+1) != equal_index,\
+                    "Not properly formatted: {}".format(value)
+
                 column = value[:arrow_index]
                 column_value = value[arrow_index+2:equal_index]
                 new_value = value[equal_index+1:]
-                
+
                 try:
                     column_index = headers.index(column)
                 except ValueError:
-                    raise EmperorInputFilesError, ("The header %s does not exist in the "
-                        "mapping file" % column)
-            
+                    raise EmperorInputFilesError(
+                        "The header {} does not exist in the mapping "
+                        "file".format(column))
+
             # fill in the data
+            fill_the_data = False
             for line in out_data:
-                if criteria(line[header_index]) == False:
+                if criteria(line[header_index]) is False:
                     if not column:
                         line[header_index] = value
                         used_column_index = True
+                        fill_the_data = True
                     else:
-                        if line[column_index] == column_value:     
+                        if line[column_index] == column_value:
                             line[header_index] = new_value
                             used_column_index = True
-            
-            if not used_column_index:
-                raise EmperorInputFilesError, ("This value '%s' doesn't exist in '%s' or "
-                "it wasn't used in for processing" % (column_value, column))
-            
+                            fill_the_data = True
+
+            if not used_column_index and fill_the_data:
+                raise EmperorInputFilesError(
+                    "This value '{}' does not exist in '{}' or it wasn't used "
+                    "forprocessing".format(column_value, column))
+
     return out_data
 
+
 def sanitize_mapping_file(data, headers):
     """Clean the strings in the mapping file for use with javascript
 
-    Inputs:
-    data: list of lists with the mapping file data
-    headers: list of strings with the mapping file headers
-
-    Outputs:
-    s_data: sanitized version of the input mapping file data
-    s_headers: sanitized version of the input mapping file headers
-
     This function will remove all the ocurrences of characters like ' or ".
+
+    Parameters
+    ----------
+    data : list of lists of str
+        the mapping file data
+    headers : list of str
+        the mapping file headers
+
+    Returns
+    -------
+    s_data : list of lists of str
+        sanitized version of the input mapping file data
+    s_headers : list of str
+        sanitized version of the input mapping file headers
     """
     all_lines = [headers] + data
     out_lines = []
 
     # replace single and double quotes with escaped versions of them
     for line in all_lines:
-        out_lines.append([element.replace("'","").replace('"','')
-            for element in line])
+        out_lines.append([element.replace("'", "").replace('"', '')
+                          for element in line])
 
     return out_lines[1::], out_lines[0]
+
+
+def guess_coordinates_files(dir_path):
+    """Given a directory return the file paths that can contain coordinates
+
+    Parameters
+    ----------
+    dir_path : str
+        path to the directory where coordinate files are contained
+
+    Returns
+    -------
+    list of str
+        list of filepaths pointing to the coordinates files
+
+    Notes
+    -----
+    If a path inside dir_path meets any of the following criteria, it will be
+    ignored:
+    - Is a hidden file
+    - Is named `Icon?`.
+    - Is folder
+    - Is part of the procrustes results from QIIME, see
+      transform_coordinate_matrices.py
+    """
+    coord_fps = []
+
+    for filepath in listdir(dir_path):
+        if filepath.startswith('.'):
+            continue
+        if filepath.startswith('Icon?'):
+            continue
+
+        # we need the full path for the next check
+        filepath = join(abspath(dir_path), filepath)
+
+        if isdir(filepath):
+            continue
+        if filepath.endswith('procrustes_results.txt'):
+            continue
+
+        coord_fps.append(filepath)
+
+    return coord_fps
+
+
+def validate_and_process_custom_axes(mf, custom_axes):
+    """Validate and process mapping file for custom axes
+
+    Parameters
+    ----------
+    mf : pd.DataFrame
+        The sample metadata.
+    custom_axes : list of str
+        The custom axes to extract from the metadata.
+
+    Returns
+    -------
+    pd.DataFrame
+        A resulting DataFrame with the custom axes as numeric types.
+
+    Raises
+    ------
+    KeyError
+        When the category names in `custom_axes` are not present in `mf`.
+    ValueError
+        When there are non-numeric values in the categories selected by
+        `custom_axes`.
+    """
+    # avoid side-effects
+    mf = mf.copy()
+
+    headers = [mf.index.name] + mf.columns.tolist()
+    missing_headers = set(custom_axes).difference(set(headers))
+
+    if missing_headers:
+        raise KeyError("One or more custom axes headers are not present in the"
+                       " sample information: %s" % ', '.join(missing_headers))
+
+    for axis in custom_axes:
+        temp = pd.to_numeric(mf[axis], errors='coerce')
+        nans = np.isnan(temp)
+
+        if np.any(nans):
+            # summarize the values that were not converted into a float
+            summary = mf[nans][axis].value_counts(dropna=False).to_string()
+            raise ValueError("All values in a custom axis must be numeric, "
+                             "this summary shows the invalid values and the "
+                             "number of times they were found in column '%s':"
+                             "\n%s" % (axis, summary))
+
+        mf[axis] = temp
+
+    return mf
diff --git a/scripts/make_emperor.py b/scripts/make_emperor.py
index e9173ab..4f2ff1b 100755
--- a/scripts/make_emperor.py
+++ b/scripts/make_emperor.py
@@ -1,627 +1,12 @@
 #!/usr/bin/env python
-# File created on 06 Jul 2012
-from __future__ import division
-
-__author__ = "Antonio Gonzalez Pena"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Antonio Gonzalez Pena", "Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "antgonza at gmail.com"
-__status__ = "Release"
-
-from os import listdir, makedirs
-from os.path import join, exists, isdir, abspath
-
-from emperor.qiime_backports.filter import filter_mapping_file
-from emperor.qiime_backports.parse import (parse_mapping_file, parse_coords,
-    mapping_file_to_dict, parse_otu_table)
-from emperor.qiime_backports.util import MetadataMap
-
-from qcli.option_parsing import parse_command_line_parameters, make_option
-
-from emperor.biplots import preprocess_otu_table
-from emperor.sort import sort_comparison_filenames
-from emperor.filter import keep_samples_from_pcoa_data
-from emperor.util import (copy_support_files, preprocess_mapping_file,
-    preprocess_coords_file, fill_mapping_field_from_mapping_file, 
-    EmperorInputFilesError)
-from emperor.format import (format_pcoa_to_js, format_mapping_file_to_js,
-    format_taxa_to_js, format_vectors_to_js, format_emperor_html_footer_string,
-    format_comparison_bars_to_js, EMPEROR_HEADER_HTML_STRING, EmperorLogicError,
-    format_emperor_autograph)
-
-script_info = {}
-
-script_info['brief_description'] = "Create three dimensional PCoA plots"
-script_info['script_description'] = "This script automates the creation  of "+\
-    "three-dimensional PCoA plots to be visualized with Emperor using Google "+\
-    "Chrome."
-script_info['script_usage'] = [("Plot PCoA data","Visualize the a PCoA file "
-    "colored using a corresponding mapping file: ","%prog -i "
-    "unweighted_unifrac_pc.txt -m Fasting_Map.txt -o emperor_output"),
-    ("Coloring by metadata mapping file", "Additionally, using the supplied "
-    "mapping file and a specific category or any combination of the available "
-    "categories. When using the -b option, the user can specify "
-    "the coloring for multiple header names, where each header is separated by "
-    "a comma. The user can also combine mapping headers and color by the "
-    "combined headers that are created by inserting an '&&' between the input "
-    "header names. Color by 'Treatment' and by the result of concatenating "
-    "the 'DOB' category and the 'Treatment' category: ","%prog -i "
-    "unweighted_unifrac_pc.txt -m Fasting_Map.txt -b 'Treatment&&DOB,Treatment'"
-    " -o emperor_colored_by"),
-    ("PCoA plot with an explicit axis", "Create a PCoA plot with an axis of "
-    "the plot representing the 'DOB' of the samples. This option is useful when"
-    " presenting a gradient from your metadata e. g. 'Time' or 'pH': ", "%prog "
-    "-i unweighted_unifrac_pc.txt -m Fasting_Map.txt -a DOB -o pcoa_dob"),
-    ("PCoA plot with an explicit axis and using --missing_custom_axes_values",
-    "Create a PCoA plot with an axis of the plot representing the 'DOB' of the "
-    "samples and define the position over the gradient of those samples missing"
-    " a numeric value; in this case we are going to plot the samples in the "
-    "value 20060000. You can select for each explicit axis which value you want"
-    " to use for the missing values: ", "%prog -i unweighted_unifrac_pc.txt -m "
-    "Fasting_Map_modified.txt -a DOB -o pcoa_dob_with_missing_custom_axes_value"
-    "s -x 'DOB:20060000'"),
-    ("PCoA plot with an explicit axis and using --missing_custom_axes_values "
-    "but setting different values based on another column", "Create a PCoA plot"
-    " with an axis of the plot representing the 'DOB' of the samples and "
-    "defining the position over the gradient of those samples missing a numeric"
-    " value but using as reference another column of the mapping file. In this "
-    "case we are going to plot the samples that are Control on the Treatment "
-    "column on 20080220 and on 20080240 those that are Fast:", "%prog -i "
-    "unweighted_unifrac_pc.txt -m Fasting_Map_modified.txt -a DOB -o "
-    "pcoa_dob_with_missing_custom_axes_with_multiple_values -x "
-    "'DOB:Treatment==Control=20080220' -x 'DOB:Treatment==Fast=20080240'"),    
-    ("Jackknifed principal coordinates analysis plot", "Create a jackknifed "
-    "PCoA plot (with confidence intervals for each sample) passing as the input"
-    " a directory of coordinates files (where each file corresponds to a "
-    "different OTU table) and use the standard deviation method to compute the "
-    "dimensions of the ellipsoids surrounding each sample: ", "%prog -i "
-    "unweighted_unifrac_pc -m Fasting_Map.txt -o jackknifed_pcoa -e sdev"),
-    ("Jackknifed PCoA plot with a master coordinates file", "Passing a master "
-    "coordinates file (--master_pcoa) will display the ellipsoids centered by "
-    "the samples in this file: ", "%prog -i unweighted_unifrac_pc -s "
-    "unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_5.txt -m "
-    "Fasting_Map.txt -o jackknifed_with_master"),
-    ("BiPlots","To see which taxa are the ten more prevalent in the different "
-    "areas of the PCoA plot, you need to pass a summarized taxa file i. e. the "
-    "output of summarize_taxa.py. Note that if the the '--taxa_fp' has fewer "
-    "than 10 taxa, the script will default to use all.","%prog -i unweighted_un"
-    "ifrac_pc.txt -m Fasting_Map.txt -t otu_table_L3.txt -o biplot"),
-    ("BiPlots with extra options","To see which are the three most prevalent "
-    "taxa and save the coordinates where these taxa are centered, you can use "
-    "the -n (number of taxa to keep) and the --biplot_fp (output biplot file "
-    "path) options.", "%prog -i unweighted_unifrac_pc.txt -m Fasting_Map.txt -t"
-    " otu_table_L3.txt -o biplot_options -n 3 --biplot_fp biplot.txt"),
-    ("Drawing connecting lines between samples", "To draw lines betwen samples"
-    " within a category use the '--add_vectors' option. For example to connect "
-    "the lines by the 'Treatment' category.", "%prog -i unweighted_unifrac_pc."
-    "txt -m Fasting_Map.txt -o vectors --add_vectors Treatment"),
-    ("Drawing connecting lines between samples with an explicit axis", "To draw"
-    " lines between samples within a category of the mapping file and have them"
-    " sorted by a category that's explicitly represented in the 3D plot use the"
-    " '--add_vectors' and the '-a' option.", "%prog -i unweighted_unifrac_pc."
-    "txt -m Fasting_Map.txt --add_vectors Treatment,DOB -a DOB -o "
-    "sorted_by_DOB"),
-    ("Compare two coordinate files", "To draw replicates of the same samples "
-    "like for a procustes plot.", "%prog -i compare -m Fasting_Map.txt "
-    "--compare_plots -o comparison")
-    ]
-script_info['output_description']= "This script creates an output directory "+\
-    "with an HTML formated file named 'index.html' and a complementary "+\
-    "folder named 'emperor_required_resources'. Opening index.html with "+\
-    "Google's Chrome web browser will display a three dimensional "+\
-    "visualization of the processed PCoA data file and the corresponding "+\
-    "metadata mapping file."
-script_info['required_options'] = [
-    make_option('-i','--input_coords',type="existing_path",help='Depending on '
-    'the plot to be generated, can be one of the following: (1) Filepath of '
-    'a coordinates file to create a PCoA plot. (2) Directory path to a folder '
-    'containing coordinates files to create a jackknifed PCoA plot. (3) '
-    'Directory path to a folder containing coordinates files to compare the '
-    'coordinates there contained when --compare_plots is enabled (useful '
-    'for procustes analysis plots). For directories: hidden files, sub-'
-    'directories and files suffixed as \'_procrustes_results.txt\''),
-    make_option('-m','--map_fp',type="existing_filepath",help='path to a '
-    'metadata mapping file')
-]
-script_info['optional_options'] = [
-    make_option('--number_of_axes', type=int, help='Number of axes to be '
-    'incorporated in the plot. Only 3 will be displayed at any given time but '
-    'this option modifies how many axes you can use for your visualization. '
-    'Note that Emperor will only use the axes that explain more than 0.5% (this'
-    ' will be shown as 1% in the GUI)of the variability [default: %default]',
-    default=10),
-    make_option('-a', '--custom_axes', type='string', help='Comma-separated '
-    'list of metadata categories to use as custom axes in the plot. For '
-    'instance, if there is a time category and you would like to see the '
-    'samples plotted on that axis instead of PC1, PC2, etc., you would pass '
-    'time as the value of this option.  Note: if there is any non-numeric data '
-    'in the metadata column, an error will be presented [default: %default]',
-    default=None),
-    make_option('--add_unique_columns',action="store_true",help='Add to the '
-    'output categories of the mapping file the columns where all values are '
-    'different. Note: if the result of one of the concatenated fields in '
-    '--color_by is a column where all values are unique, the resulting column '
-    'will get removed as well [default: %default]', default=False),
-    make_option('--add_vectors', type='string', dest='add_vectors',
-    help='Comma-sparated category(ies) used to add connecting lines (vectors) '
-    'between samples. The first category specifies the samples that will be '
-    'connected by the vectors, whilst the second category (optionally) '
-    'determines the order in which the samples will be connected. [default: '
-    '%default]', default=[None, None]),
-    make_option('-b', '--color_by', dest='color_by', type='string', help=
-    'Comma-separated list of metadata categories (column headers) to color by'
-    ' in the plots. The categories must match the name of a column header in '
-    'the mapping file exactly. Multiple categories can be listed by comma '
-    'separating them without spaces. The user can also combine columns in'
-    ' the mapping file by separating the categories by "&&" without spaces. '
-    '[default=color by all categories except ones where all values are '
-    'different]', default=''),
-    make_option('--biplot_fp', help='Output filepath that will contain the '
-    'coordinates where each taxonomic sphere is centered. [default: %default]',
-    default=None, type='new_filepath'),
-    make_option('-c', '--compare_plots', dest='compare_plots',
-    action='store_true', default=False, help='Passing a directory with the -i '
-    '(--input_coords) option in combination with this flag results in a set of'
-    ' bars connecting the replicated samples across all the input files. '
-    '[default=%default]'),
-    make_option('-e', '--ellipsoid_method', help='Used only when plotting '
-    'ellipsoids for jackknifed beta diversity (i.e. using a directory of coord '
-    'files instead of a single coord file). Valid values are "IQR" (for '
-    'inter-quartile ranges) and "sdev" (for standard deviation). '
-    '[default=%default]', default='IQR', type='choice', choices=['IQR','sdev']),
-     make_option('--ignore_missing_samples', help='This will overpass the error'
-    ' raised when the coordinates file contains samples that are not present in'
-    ' the mapping file. Be aware that this is very misleading as the PCoA is '
-    'accounting for all the samples and removing some samples could lead to '
-    ' erroneous/skewed interpretations.', action='store_true', default=False),
-    make_option('-n', '--n_taxa_to_keep', help='Number of taxonomic groups from'
-    ' the "--taxa_fp" file to display. Passing "-1" will cause to display all '
-    'the taxonomic groups, this option is only used when creating BiPlots. '
-    '[default=%default]', default=10, type='int'),
-    make_option('-s', '--master_pcoa', help='Used only when the input is a '
-    'directory of coordinate files i. e. for jackknifed beta diversity plot or'
-    ' for a coordinate comparison plot (procrustes analysis). The coordinates '
-    'in this file will be the center of each ellipsoid in the case of a '
-    'jackknifed PCoA plot or the center where the connecting arrows originate '
-    'from for a comparison plot. [default: arbitrarily selected file from the '
-    'input directory for a jackknifed plot or None for a comparison plot in '
-    'this case one file will be connected to the next one and so on]',
-    default=None, type='existing_filepath'),
-    make_option('-t', '--taxa_fp', help='Path to a summarized taxa file (i. '
-    'e. the output of summarize_taxa.py). This option is only used when '
-    'creating BiPlots. [default=%default]', default=None, type=
-    'existing_filepath'),
-    make_option('-x', '--missing_custom_axes_values', help='Option to override '
-    'the error shown when the catergory used in \'--custom_axes\' has '
-    'non-numeric values in the mapping file. The basic format is '
-    'custom_axis:new_value. For example, if you want to plot in time 0 all the '
-    'samples that do not have a numeric value in the column Time. you would '
-    'pass -x "Time:0". Additionally, you can pass this format '
-    'custom_axis:other_column==value_in_other_column=new_value, with this '
-    'format you can specify different values (new_value) to use in the '
-    'substitution based on other column (other_column) value '
-    '(value_in_other_column); see example above. This option could be used in '
-    'all explicit axes.',action='append', default=None),
-    make_option('-o','--output_dir',type="new_dirpath", help='path to the '
-    'output directory that will contain the PCoA plot. [default: %default]',
-    default='emperor'),
-    make_option('--number_of_segments', type="int", help='the number of '
-    'segments to generate any spheres, this includes the samples, the taxa '
-    '(biplots), and the confidence intervals (jackknifing). Higher values will '
-    'result in better quality but can make the plots less responsive, also it '
-    'will make the resulting SVG images bigger. The value should be between 4 '
-    'and 14. [default: %default]', default=8),
-]
-script_info['version'] = __version__
-
-
-def main():
-    option_parser, opts, args = parse_command_line_parameters(**script_info)
-    input_coords = opts.input_coords
-    map_fp = opts.map_fp
-    output_dir = opts.output_dir
-    color_by_column_names = opts.color_by
-    add_unique_columns = opts.add_unique_columns
-    custom_axes = opts.custom_axes
-    ignore_missing_samples = opts.ignore_missing_samples
-    missing_custom_axes_values = opts.missing_custom_axes_values
-    jackknifing_method = opts.ellipsoid_method
-    master_pcoa = opts.master_pcoa
-    taxa_fp = opts.taxa_fp
-    n_taxa_to_keep = opts.n_taxa_to_keep
-    biplot_fp = opts.biplot_fp
-    add_vectors = opts.add_vectors
-    verbose_output = opts.verbose
-    number_of_axes = opts.number_of_axes
-    compare_plots = opts.compare_plots
-    number_of_segments = opts.number_of_segments
-
-    # add some metadata to the output
-    emperor_autograph = format_emperor_autograph(map_fp, input_coords, 'HTML')
-
-    # verifying that the number of axes requested is greater than 3
-    if number_of_axes<3:
-        option_parser.error(('You need to plot at least 3 axes.'))
-        
-    # verifying that the number of segments is between the desired range
-    if number_of_segments<4 or number_of_segments>14:
-        option_parser.error(('number_of_segments should be between 4 and 14.'))
-        
-    # append headernames that the script didn't find in the mapping file
-    # according to different criteria to the following variables
-    offending_fields = []
-    non_numeric_categories = []
-
-    serial_comparison = True
-
-    # can't do averaged pcoa plots _and_ custom axes in the same plot
-    if custom_axes!=None and len(custom_axes.split(','))>1 and\
-        isdir(input_coords):
-        option_parser.error(('Jackknifed plots are limited to one custom axis, '
-            'currently trying to use: %s. Make sure you use only one.' %
-            custom_axes))
-
-    # make sure the flag is not misunderstood from the command line interface
-    if isdir(input_coords) == False and compare_plots:
-        option_parser.error('Cannot use the \'--compare_plots\' flag unless the'
-            ' input path is a directory.')
-
-    # before creating any output, check correct parsing of the main input files
-    try:
-        mapping_data, header, comments = parse_mapping_file(open(map_fp,'U'))
-
-        # use this set variable to make presence/absensce checks faster
-        lookup_header = set(header)
-    except:
-        option_parser.error(('The metadata mapping file \'%s\' does not seem '
-            'to be formatted correctly, verify the formatting is QIIME '
-            'compliant by using check_id_map.py') % map_fp)
-
-    # dir means jackknifing or coordinate comparison type of processing
-    if isdir(input_coords):
-        offending_coords_fp = []
-        coords_headers, coords_data, coords_eigenvalues, coords_pct=[],[],[],[]
-
-        # iterate only over the non-hidden files and not folders and if anything
-        # ignore the procrustes results file that is generated by
-        # transform_coordinate_matrices.py suffixed in procrustes_results.txt
-        coord_fps = [join(input_coords, f) for f in listdir(input_coords) if
-            not f.startswith('.') and not isdir(join(abspath(input_coords),f))
-            and not f.endswith('procrustes_results.txt')]
-
-        # this could happen and we rather avoid this problem
-        if len(coord_fps) == 0:
-            option_parser.error('Could not use any of the files in the input '
-                'directory.')
-
-        # the master pcoa must be the first in the list of coordinates; however
-        # if the visualization is not a jackknifed plot this gets ignored
-        if master_pcoa and compare_plots == False:
-            if master_pcoa in coord_fps: # remove it if duplicated
-                coord_fps.remove(master_pcoa)
-            coord_fps = [master_pcoa] + coord_fps # prepend it to the list
-        # passing a master file means that the comparison is not serial
-        elif master_pcoa and compare_plots:
-            serial_comparison = False
-
-            # guarantee that the master is the first and is not repeated
-            if master_pcoa in  coord_fps:
-                coord_fps.remove(master_pcoa)
-                coord_fps = [master_pcoa] + sort_comparison_filenames(coord_fps)
-
-        # QIIME generates folders of transformed coordinates for the specific
-        # purpose of connecting all coordinates to a set of origin coordinates.
-        # The name of this file is suffixed as _transformed_reference.txt
-        elif master_pcoa == None and len([f for f in coord_fps if f.endswith(
-            '_transformed_reference.txt')]):
-            master_pcoa = [f for f in coord_fps if f.endswith(
-                '_transformed_reference.txt')][0]
-            serial_comparison = False
-
-            # Note: the following steps are to guarantee consistency.
-            # remove the master from the list and re-add it as a first element
-            # the rest of the files must be sorted alphabetically so the result
-            # will be: ['unifrac_transformed_reference.txt',
-            # 'unifrac_transformed_q1.txt', 'unifrac_transformed_q2.txt'] etc
-            coord_fps.remove(master_pcoa)
-            coord_fps = [master_pcoa] + sort_comparison_filenames(coord_fps)
-
-        for fp in coord_fps:
-            try:
-                _coords_headers, _coords_data, _coords_eigenvalues,_coords_pct=\
-                    parse_coords(open(fp,'U'))
-
-                # pack all the data correspondingly
-                coords_headers.append(_coords_headers)
-                coords_data.append(_coords_data)
-                coords_eigenvalues.append(_coords_eigenvalues)
-                coords_pct.append(_coords_pct)
-            except ValueError:
-                offending_coords_fp.append(fp)
-
-        # in case there were files that couldn't be parsed
-        if offending_coords_fp:
-            option_parser.error(('The following file(s): \'%s\' could not be '
-                'parsed properly. Make sure the input folder only contains '
-                'coordinates files.') % ', '.join(offending_coords_fp))
-
-        # check all files contain the same sample identifiers by flattening the
-        # list of available sample ids and returning the sample ids that are
-        # in one of the sets of sample ids but not in the globablly shared ids
-        non_shared_ids = set(sum([list(set(sum(coords_headers, []))^set(e))
-            for e in coords_headers],[]))
-        if non_shared_ids and len(coords_headers) > 1:
-            option_parser.error(('The following sample identifier(s): \'%s\''
-                'are not shared between all the files. The files used to '
-                'make a jackknifed PCoA plot or coordinate comparison plot ('
-                'procustes plot) must share all the same sample identifiers'
-                'between each other.')%', '.join(list(non_shared_ids)))
-
-        # flatten the list of lists into a 1-d list
-        _coords_headers = list(set(sum(coords_headers, [])))
-
-        # number of samples ids that are shared between coords and mapping files
-        sids_intersection=list(set(zip(*mapping_data)[0])&set(_coords_headers))
-
-        # sample ids that are not mapped but are in the coords
-        sids_difference=list(set(_coords_headers)-set(zip(*mapping_data)[0]))
-
-        # used to perform different validations in the script, very similar for
-        # the case where the input is not a directory
-        number_intersected_sids = len(sids_intersection)
-        required_number_of_sids = len(coords_headers[0])
-
-    else:
-        try:
-            coords_headers, coords_data, coords_eigenvalues, coords_pct =\
-                parse_coords(open(input_coords,'U'))
-        # this exception was noticed when there were letters in the coords file
-        # other exeptions should be catched here; code will be updated then
-        except ValueError:
-            option_parser.error(('The PCoA file \'%s\' does not seem to be a '
-                'coordinates formatted file, verify by manually inspecting '
-                'the contents.') % input_coords)
-
-        # number of samples ids that are shared between coords and mapping files
-        sids_intersection = list(set(zip(*mapping_data)[0])&set(coords_headers))
-        # sample ids that are not mapped but are in the coords
-        sids_difference = list(set(coords_headers)-set(zip(*mapping_data)[0]))
-        number_intersected_sids = len(sids_intersection)
-        required_number_of_sids = len(coords_headers)
-
-    if taxa_fp:
-        try:
-            # for summarized tables the "otu_ids" are really the "lineages"
-            otu_sample_ids, lineages, otu_table, _ = parse_otu_table(open(
-                taxa_fp, 'U'), count_map_f=float, remove_empty_rows=True)
-        except ValueError, e:
-            option_parser.error('There was a problem parsing the --taxa_fp: %s'%
-                e.message)
-
-        # make sure there are matching sample ids with the otu table
-        if not len(list(set(sids_intersection)&set(otu_sample_ids))):
-            option_parser.error('The sample identifiers in the OTU table must '
-                'have at least one match with the data in the mapping file and '
-                'with the coordinates file. Verify you are using input files '
-                'that belong to the same dataset.')
-        if len(lineages) <= 1:
-            option_parser.error('Contingency tables with one or fewer rows are '
-                'not supported, please try passing a contingency table with '
-                'more than one row.')
-    else:
-        # empty lists indicate that there was no taxa file passed in
-        otu_sample_ids, lineages, otu_table = [], [], []
-
-    # sample ids must be shared between files
-    if number_intersected_sids <= 0:
-        option_parser.error('The sample identifiers in the coordinates file '
-            'must have at least one match with the data contained in mapping '
-            'file. Verify you are using a coordinates file and a mapping file '
-            'that belong to the same dataset.')
-
-    # the intersection of the sample ids in the coords and the sample ids in the
-    # mapping file must at the very least include all ids in the coords file
-    # Otherwise it isn't valid; unless --ignore_missing_samples is set True
-    if number_intersected_sids != required_number_of_sids and\
-        not ignore_missing_samples:
-        message = 'The metadata mapping file has fewer sample identifiers '+\
-            'than the coordinates file. Verify you are using a mapping file '+\
-            'that contains at least all the samples contained in the '+\
-            'coordinates file(s). You can force the script to ignore these '+\
-            'samples by passing the \'--ignore_missing_samples\' flag.'
-
-        if verbose_output:
-            message += ' Offending sample identifier(s): %s.' %\
-                ', '.join(sids_difference)
-            print sids_difference
-
-        option_parser.error(message)
-
-    if number_intersected_sids != required_number_of_sids and\
-        ignore_missing_samples:
-        # keep only the samples that are mapped in the mapping file
-        coords_headers, coords_data = keep_samples_from_pcoa_data(
-            coords_headers, coords_data, sids_intersection)
-
-    # ignore samples that exist in the coords but not in the mapping file, note:
-    # we're using sids_intersection so if --ignore_missing_samples is enabled we
-    # account for unmapped coords, else the program will exit before this point
-    header, mapping_data = filter_mapping_file(mapping_data, header,
-        sids_intersection, include_repeat_cols=True)
-
-    # catch the errors that could occur when filling the mapping file values
-    if missing_custom_axes_values:
-        try:
-            # the fact that this uses parse_metadata_state_descriptions makes
-            # the following option '-x Category:7;PH:12' to work as well as the 
-            # script-interface-documented '-x Category:7 -x PH:12' option
-            for val in missing_custom_axes_values:
-                if ':' not in val:
-                    option_parser.error("Not valid missing value for custom "
-                        "axes: %s" % val)
-            mapping_data = fill_mapping_field_from_mapping_file(mapping_data,
-                header, ';'.join(missing_custom_axes_values))
-            
-        except AssertionError, e:
-            option_parser.error(e.message)
-        except EmperorInputFilesError, e:
-            option_parser.error(e.message)
-    
-    # check that all the required columns exist in the metadata mapping file
-    if color_by_column_names:
-        color_by_column_names = color_by_column_names.split(',')
-
-        # check for all the mapping fields
-        for col in color_by_column_names:
-            # for concatenated columns check each individual field
-            if '&&' in col:
-                for _col in col.split('&&'):
-                    if _col not in lookup_header:
-                        offending_fields.append(col)
-            elif col not in lookup_header:
-                offending_fields.append(col)
-    else:
-        # if the user didn't specify the header names display everything
-        color_by_column_names = header[:]
-
-    # extract a list of the custom axes provided and each element is numeric
-    if custom_axes:
-        custom_axes = custom_axes.strip().strip("'").strip('"').split(',')
-
-        # the MetadataMap object makes some checks easier
-        map_object = MetadataMap(mapping_file_to_dict(mapping_data, header), [])
-        for axis in custom_axes:
-            # append the field to the error queue that it belongs to
-            if axis not in lookup_header:
-                offending_fields.append(axis)
-                break
-            # make sure this value is in the mapping file
-            elif axis not in color_by_column_names:
-                color_by_column_names.append(axis)
-        # perform only if the for loop does not call break
-        else:
-            # make sure all these axes are numeric
-            for axis in custom_axes:
-                if map_object.isNumericCategory(axis) == False:
-                    non_numeric_categories.append(axis)
-
-    # make multiple checks for the add_vectors option
-    if add_vectors != [None, None]:
-        add_vectors = add_vectors.split(',')
-        # check there are at the most two categories specified for this option
-        if len(add_vectors) > 2:
-            option_parser.error("The '--add_vectors' option can accept up to "
-                "two different fields from the mapping file; currently trying "
-                "to use %d (%s)." % (len(add_vectors), ', '.join(add_vectors)))
-        # make sure the field(s) exist
-        for col in add_vectors:
-            # concatenated fields are allowed now so check for each field
-            if '&&' in col:
-                for _col in col.split('&&'):
-                    if _col not in lookup_header:
-                        offending_fields.append(col)
-                        break
-                # only execute this block of code if all checked fields exist
-                else:
-                    # make sure that if it's going to be used for vector
-                    # creation it gets used for coloring and map postprocessing
-                    if col not in color_by_column_names:
-                        color_by_column_names.append(col)
-            # if it's a column without concatenations
-            elif col not in lookup_header:
-                offending_fields.append(col)
-                break
-            else:
-                # check this vector value is in the color by category
-                if col not in color_by_column_names:
-                    color_by_column_names.append(col)
-        # perform only if the for loop does not call break
-        else:
-            # check that the second category is all with numeric values
-            if len(add_vectors) == 2:
-                map_object = MetadataMap(mapping_file_to_dict(mapping_data,
-                    header), [])
-                # if it has non-numeric values add it to the list of offenders
-                if map_object.isNumericCategory(add_vectors[1]) == False:
-                    non_numeric_categories.append(add_vectors[1]+' (used in '
-                        '--add_vectors)')
-            else:
-                add_vectors.append(None)
-
-    # terminate the program for the cases where a mapping field was not found
-    # or when a mapping field didn't meet the criteria of being numeric
-    if offending_fields:
-        option_parser.error("Invalid field(s) '%s'; the valid field(s) are:"
-            " '%s'" % (', '.join(offending_fields), ', '.join(header)))
-    if non_numeric_categories:
-        option_parser.error(('The following field(s): \'%s\' contain values '
-            'that are not numeric, hence not suitable for \'--custom_axes\' nor'
-            ' for \'--add_vectors\'. Try the \'--missing_custom_axes_values\' '
-            'option to fix these values.' % ', '.join(non_numeric_categories)))
-
-    # process the coordinates file first, preventing the case where the custom
-    # axes is not in the coloring categories i. e. in the --colory_by categories
-    coords_headers, coords_data, coords_eigenvalues, coords_pct, coords_low,\
-        coords_high, clones = preprocess_coords_file(coords_headers,coords_data,
-        coords_eigenvalues, coords_pct, header, mapping_data, custom_axes,
-        jackknifing_method=jackknifing_method, is_comparison=compare_plots)
-
-    # process the otu table after processing the coordinates to get custom axes
-    # (when available) or any other change that occurred to the coordinates
-    otu_coords, otu_table, otu_lineages, otu_prevalence, lines =\
-        preprocess_otu_table(otu_sample_ids, otu_table, lineages,
-        coords_data, coords_headers, n_taxa_to_keep)
-
-    # remove the columns in the mapping file that are not informative taking
-    # into account the header names that were already authorized to be used
-    # and take care of concatenating the fields for the && merged columns
-    mapping_data, header = preprocess_mapping_file(mapping_data, header,
-        color_by_column_names, unique=not add_unique_columns, clones=clones)
-
-    # create the output directory before creating any other output
-    if not isdir(opts.output_dir):
-        makedirs(opts.output_dir)
-
-    fp_out = open(join(output_dir, 'index.html'),'w')
-    fp_out.write(emperor_autograph+'\n')
-    fp_out.write(EMPEROR_HEADER_HTML_STRING)
-
-    # write the html file
-    fp_out.write(format_mapping_file_to_js(mapping_data, header, header))
-
-    # certain percents being explained cannot be displayed in the GUI
-    try:
-        fp_out.write(format_pcoa_to_js(coords_headers, coords_data,
-            coords_eigenvalues, coords_pct, custom_axes, coords_low,
-            coords_high, number_of_axes=number_of_axes, 
-            number_of_segments=number_of_segments))
-    except EmperorLogicError, e:
-        option_parser.error(e.message)
-
-    fp_out.write(format_taxa_to_js(otu_coords, otu_lineages, otu_prevalence))
-    fp_out.write(format_vectors_to_js(mapping_data, header, coords_data,
-        coords_headers, add_vectors[0], add_vectors[1]))
-    fp_out.write(format_comparison_bars_to_js(coords_data, coords_headers,
-        clones, is_serial_comparison=serial_comparison))
-    fp_out.write(format_emperor_html_footer_string(taxa_fp != None,
-        isdir(input_coords) and not compare_plots, add_vectors != [None, None],
-        clones>0))
-    fp_out.close()
-    copy_support_files(output_dir)
-
-    # write the biplot coords in the output file if a path is passed
-    if biplot_fp and taxa_fp:
-        # make sure this file can be created
-        try:
-            fd = open(biplot_fp, 'w')
-        except IOError:
-            option_parser.error('There was a problem creating the file with'
-                ' the coordinates for the biplots (%s).' % biplot_fp)
-        fd.writelines(lines)
-        fd.close()
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 
 if __name__ == "__main__":
-    main()
+    print("This script has been deprecated, please see the online "
+          "documentation for more help.")
diff --git a/setup.py b/setup.py
index b8c7648..1c6ab4a 100644
--- a/setup.py
+++ b/setup.py
@@ -1,16 +1,20 @@
 #!/usr/bin/env python
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
+
+import sys
 
 from distutils.core import setup
 from glob import glob
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Antonio Gonzalez Pena", "Meg Pirrung", "Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
+__version__ = "1.0.0beta5"
+__maintainer__ = "Emperor development team"
 __email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
 
 # based on the text found in github.com/qiime/pynast
 classes = """
@@ -20,6 +24,7 @@ classes = """
     Topic :: Software Development :: User Interfaces
     Programming Language :: Python
     Programming Language :: Python :: 2.7
+    Programming Language :: Python :: 3.4
     Programming Language :: Python :: Implementation :: CPython
     Operating System :: OS Independent
     Operating System :: POSIX
@@ -35,27 +40,48 @@ Vazquez-Baeza Y, Pirrung M, Gonzalez A, Knight R.
 Gigascience. 2013 Nov 26;2(1):16.
 """
 
-setup(name='emperor',
-        version=__version__,
-        description='Emperor',
-        author="Antonio Gonzalez Pena, Meg Pirrung & Yoshiki Vazquez Baeza",
-        author_email=__email__,
-        maintainer=__maintainer__,
-        maintainer_email=__email__,
-        url='http://github.com/qiime/emperor',
-        packages=['emperor', 'emperor/pycogent_backports',
-            'emperor/qiime_backports'],
-        scripts=glob('scripts/*py'),
-        package_data={'emperor':['support_files/js/*.js',
-            'support_files/js/js/*.js', 'support_files/js/js/ctm/*.js',
-            'support_files/js/js/ctm/license/*.txt',
-            'support_files/js/js/postprocessing/*.js',
-            'support_files/img/*.png', 'support_files/img/*.ico',
-            'support_files/css/*.css', 'support_files/css/images/*.png',
-            'support_files/emperor/css/*.css',
-            'support_files/emperor/js/*.js',]},
-        data_files={},
-        install_requires=["numpy >= 1.5.1, <=1.7.1", "qcli"],
-        long_description=long_description,
-        classifiers=classifiers)
+skbio_2 = "scikit-bio >= 0.4.1, < 0.5.0"
+skbio_3 = "scikit-bio >= 0.4.1"
+base = {"numpy >= 1.7", "scipy >= 0.17.0", "click", "pandas",
+        skbio_2, "jinja2", "future"}
+doc = {"Sphinx >= 1.2.2", "sphinx-bootstrap-theme"}
+test = {"nose >= 0.10.1", "pep8", "flake8"}
+all_deps = base | doc | test
+
+# prevent python2 from trying to install skbio >= 0.5.0 (which only works in
+# PY3K)
+if sys.version_info.major == 3:
+    base.remove(skbio_2)
+    base.add(skbio_3)
 
+setup(
+    name='emperor',
+    version=__version__,
+    description='Emperor',
+    author="Antonio Gonzalez Pena, Meg Pirrung & Yoshiki Vazquez Baeza",
+    author_email=__email__,
+    maintainer=__maintainer__,
+    maintainer_email=__email__,
+    url='http://github.com/biocore/emperor',
+    packages=['emperor', 'emperor.qiime_backports'],
+    scripts=glob('scripts/*py'),
+    package_data={
+        'emperor': ['support_files/vendor/js/three.js-plugins/*.js',
+                    'support_files/vendor/js/*.js',
+                    'support_files/vendor/css/*.css',
+                    'support_files/vendor/css/*.png',
+                    'support_files/vendor/css/images/*.png',
+                    'support_files/vendor/css/font/*.eot',
+                    'support_files/vendor/css/font/*.ttf',
+                    'support_files/vendor/css/font/*.woff',
+                    'support_files/vendor/css/font/*.woff2',
+                    'support_files/img/*.png',
+                    'support_files/img/*.ico',
+                    'support_files/css/*.css',
+                    'support_files/js/*.js',
+                    'support_files/templates/*.html']},
+    data_files={},
+    install_requires=base,
+    extras_require={'doc': doc, 'test': test, 'all': all_deps},
+    long_description=long_description,
+    classifiers=classifiers)
diff --git a/tests/all_tests.py b/tests/all_tests.py
index 20b1197..6d472a9 100755
--- a/tests/all_tests.py
+++ b/tests/all_tests.py
@@ -1,109 +1,82 @@
 #!/usr/bin/env python
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 """Run all tests.
+
+Originally based on the all_tests.py script from the QIIME project
+(http://github.com/qiime/qiime) project at svn revision 3290, now taken from
+the E-vident (http://github.com/qiime/evident) project master branch at git SHA
+dde2a06f2d990db8b09da65764cd27fc047db788
 """
-#Originally based on the all_tests.py script from the QIIME project
-#(http://github.com/qiime/qiime) project at svn revision 3290, now taken from
-#the E-vident (http://github.com/qiime/evident) project master branch at git SHA
-#dde2a06f2d990db8b09da65764cd27fc047db788
 
 import re
+import click
+import subprocess
 
 from os import walk
-from sys import exit
 from glob import glob
-from os.path import join, abspath, dirname, split, exists
-
-from emperor.util import get_emperor_project_dir
-
-from qcli.util import qcli_system_call
-from qcli.test import run_script_usage_tests
-from qcli.option_parsing import parse_command_line_parameters, make_option
-
-__author__ = "Rob Knight"
-__copyright__ = "Copyright 2013, The Emperor Project" #consider project name
-__credits__ = ["Rob Knight","Greg Caporaso", "Jai Ram Rideout",
-    "Yoshiki Vazquez-Baeza"] #remember to add yourself if you make changes
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez-Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
-
-script_info = {}
-script_info['brief_description'] = ""
-script_info['script_description'] = ""
-script_info['script_usage'] = [("","","")]
-script_info['output_description']= ""
-script_info['required_options'] = []
-script_info['optional_options'] = [
-    make_option('--suppress_unit_tests', action='store_true', help='suppress '
-    ' execution of Emperor\'s unit tests [default: %default]', default=False),
-    make_option('--suppress_script_usage_tests', action='store_true', help=
-    'suppress Emperor\'s script usage tests [default: %default]',default=False),
-    make_option('--unittest_glob', help='wildcard pattern to match the unit '
-    'tests to execute [default: %default]', default=None),
-    make_option('--script_usage_tests', help='comma-separated list of the '
-    'script usage tests to execute [default: run all]', default=None),
-    make_option('-p', '--temp_filepath', type='existing_path', help='temporary '
-    'directory where the script usage tests will be executed', default='/tmp/'),
-    make_option('--emperor_scripts_dir', help='filepath where the scripts are'
-    ' stored', type='existing_path', default=None)
-]
-script_info['version'] = __version__
-script_info['help_on_no_arguments'] = False
-
-
-def main():
-    option_parser, opts, args = parse_command_line_parameters(**script_info)
-
-    unittest_glob = opts.unittest_glob
-    temp_filepath = opts.temp_filepath
-    script_usage_tests = opts.script_usage_tests
-    suppress_unit_tests = opts.suppress_unit_tests
-    suppress_script_usage_tests = opts.suppress_script_usage_tests
-
-    # since the test data is in the tests folder just add scripts_test_data
-    emperor_test_data_dir = join(abspath(dirname(__file__)),
-        'scripts_test_data/')
-
-    # offer the option for the user to pass the scripts dir from the command
-    # line since there is no other way to get the scripts dir. If not provided
-    # the base structure of the repository will be assumed. Note that for both
-    # cases we are using absolute paths, to avoid unwanted failures.
-    if opts.emperor_scripts_dir is None:
-        emperor_scripts_dir = abspath(join(get_emperor_project_dir(),
-            'scripts/'))
-
-        # let's try to guess cases for qiime-deploy type of installs
-        if get_emperor_project_dir().endswith('/lib'):
-            emperor_scripts_dir = abspath(join(get_emperor_project_dir()[:-3],
-                'scripts/'))
+from os.path import join, abspath, dirname, split
 
-    else:
-        emperor_scripts_dir = abspath(opts.emperor_scripts_dir)
+from emperor import __version__
+
+
+def console(cmd):
+    """Small subprocess helper function
+
+    Originally based on this SO answer:
+    http://stackoverflow.com/a/33542403/379593
+    """
+    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
+                               stderr=subprocess.PIPE)
+    o, e = process.communicate()
+
+    return '' if o is None else o, '' if e is None else e, process.returncode
+
+
+ at click.command()
+ at click.option('--suppress_unit_tests', help="suppress execution of Emperor's "
+              "unit tests", default=False, is_flag=True, show_default=True)
+ at click.option('--suppress_javascript_unit_tests', help="suppress Emperor's "
+              "JavaScript unit tests.", default=False, is_flag=True,
+              show_default=True)
+ at click.option('--unittest_glob', help='wildcard pattern to match the unit '
+              'tests to execute.', default=None, is_flag=True,
+              show_default=True)
+ at click.version_option(__version__)
+def test(suppress_unit_tests, suppress_javascript_unit_tests, unittest_glob):
+    """Run Emperor's test suite.
+
+    Run the Python unit tests or the JavaScript unit tests (requires
+    phantomjs to be installed).
+    """
 
     # make a sanity check
-    if (suppress_unit_tests and suppress_script_usage_tests):
-        option_parser.error("All tests have been suppresed. Nothing to run.")
+    if suppress_unit_tests and suppress_javascript_unit_tests:
+        raise click.UsageError("All tests have been suppresed. Nothing to "
+                               "run.")
 
     test_dir = abspath(dirname(__file__))
 
-    unittest_good_pattern = re.compile('OK\s*$')
-    application_not_found_pattern = re.compile('ApplicationNotFoundError')
+    unittest_good_pattern = re.compile(b'OK\s*$')
+    application_not_found_pattern = re.compile(b'ApplicationNotFoundError')
     python_name = 'python'
     bad_tests = []
     missing_application_tests = []
 
-    # Run through all of Emperor's unit tests, and keep track of any files which
-    # fail unit tests, note that these are the unit tests only
+    # Run through all of Emperor's unit tests, and keep track of any files
+    # which fail unit tests, note that these are the unit tests only
     if not suppress_unit_tests:
         unittest_names = []
         if not unittest_glob:
             for root, dirs, files in walk(test_dir):
                 for name in files:
                     if name.startswith('test_') and name.endswith('.py'):
-                        unittest_names.append(join(root,name))
+                        unittest_names.append(join(root, name))
         else:
             for fp in glob(unittest_glob):
                 fn = split(fp)[1]
@@ -113,71 +86,64 @@ def main():
         unittest_names.sort()
 
         for unittest_name in unittest_names:
-            print "Testing %s:\n" % unittest_name
+            print("Testing %s:\n" % unittest_name)
             command = '%s %s -v' % (python_name, unittest_name)
-            stdout, stderr, return_value = qcli_system_call(command)
-            print stderr
+            stdout, stderr, return_value = console(command)
+            print(stderr.decode("utf-8"))
             if not unittest_good_pattern.search(stderr):
                 if application_not_found_pattern.search(stderr):
                     missing_application_tests.append(unittest_name)
                 else:
                     bad_tests.append(unittest_name)
 
-    script_usage_failures = 0
+    if not suppress_javascript_unit_tests:
+        runner = join(test_dir, 'javascript_tests', 'runner.js')
+        index = join(test_dir, 'javascript_tests', 'index.html')
 
-    # choose to run some of the script usage tests or all the available ones
-    if not suppress_script_usage_tests and exists(emperor_test_data_dir) and\
-        exists(emperor_scripts_dir):
-        if script_usage_tests != None:
-            script_tests = script_usage_tests.split(',')
-        else:
-            script_tests = None
-        # Run the script usage testing functionality; note that depending on the
-        # module where this was imported, the name of the arguments will change
-        # that's the reason why I added the name of the arguments in here
-        script_usage_result_summary, script_usage_failures = \
-            run_script_usage_tests( emperor_test_data_dir,  # test_data_dir
-                                    emperor_scripts_dir,    # scripts_dir
-                                    temp_filepath,          # working_dir
-                                    True,                   # verbose
-                                    script_tests,           # tests
-                                    None,                   # failure_log_fp
-                                    False)                  # force_overwrite
-
-    print "==============\nResult summary\n=============="
+        o, e, r = console('phantomjs %s %s' % (runner, index))
+
+        if o:
+            print(o.decode('utf-8'))
+        if e:
+            print(e.decode('utf-8'))
+
+        # if all the tests passed
+        javascript_tests_passed = True if r == 0 else False
+    else:
+        javascript_tests_passed = True
+
+    print("==============\nResult summary\n==============")
 
     if not suppress_unit_tests:
-        print "\nUnit test result summary\n------------------------\n"
+        print("\nUnit test result summary\n------------------------\n")
         if bad_tests:
-            print "\nFailed the following unit tests.\n%s" %'\n'.join(bad_tests)
-    
+            print("\nThe following unit tests failed.\n%s"
+                  % '\n'.join(bad_tests))
+
         if missing_application_tests:
-            print "\nFailed the following unit tests, in part or whole due "+\
-                "to missing external applications.\nDepending on the Emperor "+\
-                "features you plan to use, this may not be critical.\n%s"\
-                % '\n'.join(missing_application_tests)
-        
+            print("\nThe following unit tests failed, in part or whole due "
+                  "to missing external applications.\nDepending on the "
+                  "Emperor features you plan to use, this may not be "
+                  "critical.\n%s" % '\n'.join(missing_application_tests))
+
         if not(missing_application_tests or bad_tests):
-            print "\nAll unit tests passed.\n\n"
+            print("\nAll unit tests passed.\n")
 
-    if not suppress_script_usage_tests:
-        if exists(emperor_test_data_dir) and exists(emperor_scripts_dir):
-            print "\nScript usage test result summary"+\
-                "\n------------------------------------\n"
-            print script_usage_result_summary
+    if not suppress_javascript_unit_tests:
+        print('\nJavaScript unit tests result summary\n'
+              '------------------------------------\n')
+        if javascript_tests_passed:
+            print('All JavaScript unit tests passed.\n')
         else:
-            print ("\nCould not run script usage tests.\nThe Emperor scripts "
-                "directory could not be automatically located, try supplying "
-                " it manually using the --emperor_scripts_dir option.")
+            print('JavaScript unit tests failed, check the summary above.')
 
     # In case there were no failures of any type, exit with a return code of 0
     return_code = 1
     if (len(bad_tests) == 0 and len(missing_application_tests) == 0 and
-        script_usage_failures == 0):
+       javascript_tests_passed):
         return_code = 0
 
-    return return_code
-
+    exit(return_code)
 
 if __name__ == "__main__":
-    exit(main())
+    test()
diff --git a/tests/scripts_test_data/make_emperor/Fasting_Map_modified.txt b/tests/scripts_test_data/make_emperor/Fasting_Map_modified.txt
index aee6c01..2c48c06 100644
--- a/tests/scripts_test_data/make_emperor/Fasting_Map_modified.txt
+++ b/tests/scripts_test_data/make_emperor/Fasting_Map_modified.txt
@@ -1,11 +1,11 @@
-#SampleID	BarcodeSequence	LinkerPrimerSequence	Treatment	DOB	Description
-#Example mapping file for the QIIME analysis package.  These 9 samples are from a study of the effects of exercise and diet on mouse cardiac physiology (Crawford, et al, PNAS, 2009).
-PC.354	AGCACGAGCCTA	YATGCTGCCTCCCGTAGGAGT	Control	20061218	Control_mouse_I.D._354
-PC.355	AACTCGTCGATG	YATGCTGCCTCCCGTAGGAGT	Control	20061218	Control_mouse_I.D._355
-PC.356	ACAGACCACTCA	YATGCTGCCTCCCGTAGGAGT	Control	20061126	Control_mouse_I.D._356
-PC.481	ACCAGCGACTAG	YATGCTGCCTCCCGTAGGAGT	Control	20070314	Control_mouse_I.D._481
-PC.593	AGCAGCACTTGT	YATGCTGCCTCCCGTAGGAGT	Control	NA	Control_mouse_I.D._593
-PC.607	AACTGTGCGTAC	YATGCTGCCTCCCGTAGGAGT	Fast	20071112	Fasting_mouse_I.D._607
-PC.634	ACAGAGTCGGCT	YATGCTGCCTCCCGTAGGAGT	Fast	20080116	Fasting_mouse_I.D._634
-PC.635	ACCGCAGAGTCA	YATGCTGCCTCCCGTAGGAGT	Fast	20080116	Fasting_mouse_I.D._635
-PC.636	ACGGTGAGTGTC	YATGCTGCCTCCCGTAGGAGT	Fast	NA	Fasting_mouse_I.D._636
+#SampleID	BarcodeSequence	LinkerPrimerSequence	Categories of each sample in the study that was sequenced successfully	Treatment	DOB	Description
+"#Example mapping file for the QIIME analysis package.  These 9 samples are from a study of the effects of exercise and diet on mouse cardiac physiology (Crawford, et al, PNAS, 2009)."						
+PC.354	AGCACGAGCCTA	YATGCTGCCTCCCGTAGGAGT	A	Control	20061218	Control_mouse_I.D._354
+PC.355	AACTCGTCGATG	YATGCTGCCTCCCGTAGGAGT	A	Control	20061218	Control_mouse_I.D._355
+PC.356	ACAGACCACTCA	YATGCTGCCTCCCGTAGGAGT	B	Control	20061126	Control_mouse_I.D._356
+PC.481	ACCAGCGACTAG	YATGCTGCCTCCCGTAGGAGT	A	Control	20070314	Control_mouse_I.D._481
+PC.593	AGCAGCACTTGT	YATGCTGCCTCCCGTAGGAGT	B	Control	NA	Control_mouse_I.D._593
+PC.607	AACTGTGCGTAC	YATGCTGCCTCCCGTAGGAGT	C	Fast	20071112	Fasting_mouse_I.D._607
+PC.634	ACAGAGTCGGCT	YATGCTGCCTCCCGTAGGAGT	C	Fast	20080116	Fasting_mouse_I.D._634
+PC.635	ACCGCAGAGTCA	YATGCTGCCTCCCGTAGGAGT	A	Fast	20080116	Fasting_mouse_I.D._635
+PC.636	ACGGTGAGTGTC	YATGCTGCCTCCCGTAGGAGT	A	Fast	NA	Fasting_mouse_I.D._636
diff --git a/tests/scripts_test_data/make_emperor/biplot.txt b/tests/scripts_test_data/make_emperor/biplot.txt
index 9cda4b9..6ebe084 100644
--- a/tests/scripts_test_data/make_emperor/biplot.txt
+++ b/tests/scripts_test_data/make_emperor/biplot.txt
@@ -1,4 +1,4 @@
 #Taxon	pc0	pc1	pc2	pc3	pc4	pc5	pc6	pc7	pc8
 Root;k__Bacteria;p__Firmicutes	0.0840155767161	-0.00823816376882	-0.0237652607133	-0.0246683610503	-0.0161996992959	-0.00519164089553	0.00523283639012	-0.00419865957436	-4.84141986706e-09
 Root;k__Bacteria;p__Bacteroidetes	-0.111274634594	-0.0209166829829	0.0260589784114	0.0328465662311	0.0153651318051	0.00344370141059	-0.0108953599091	0.00392235426624	-4.84141986706e-09
-Root;k__Bacteria;p__Tenericutes	0.0286906406139	0.201636329198	0.0718385470146	0.0192870226318	0.0521872985074	0.0191261795707	0.0154613880758	0.0208652785029	-4.84141986706e-09
\ No newline at end of file
+Root;k__Bacteria;p__	0.0286906406139	0.201636329198	0.0718385470146	0.0192870226318	0.0521872985074	0.0191261795707	0.0154613880758	0.0208652785029	-4.84141986706e-09
\ No newline at end of file
diff --git a/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_0.txt b/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_0.txt
index 810e2b4..f0cdead 100644
--- a/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_0.txt
+++ b/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_0.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.461382484898	0.282586294059	0.259635090345	0.202508723789	0.192582035266	0.160350654061	0.138031252593	0.123015943185	7.5757356253e-17
+
+Proportion explained	9
+25.3493979248	15.5259305472	14.2649394718	11.1262876043	10.5808928707	8.81002784101	7.58374941088	6.75877432927	4.1622806072e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	0.281857587421	0.0507270541945	0.0374722443357	-0.0370074137223	0.15782793716	0.23359469867	0.174998809955	0.0219541318555	2.90129006273e-09
 PC.635	0.18215230676	0.132916775615	-0.100389688466	0.190011634826	-0.307283733566	0.00430749577241	0.0469580790424	-0.0617163043591	2.90129006273e-09
 PC.356	-0.239606359013	0.178116346653	-0.316300212034	-0.0116338896148	0.114589435481	0.0915396854904	-0.13794374686	-0.0311556901155	2.90129006273e-09
@@ -9,6 +17,6 @@ PC.355	-0.196195568243	0.169658119414	0.0424034255545	-0.0848245709891	0.0670053
 PC.607	0.133124236385	-0.378152288866	-0.239139015591	-0.103687426251	-0.0141771679839	-0.0969160055476	0.0312930958801	0.0232026349583	2.90129006273e-09
 PC.634	0.335092748334	0.0913419796777	0.112900504808	0.0836202835077	0.137259423818	-0.161059445277	-0.177049932906	0.0749552140687	2.90129006273e-09
 
+Biplot	0	0
 
-eigvals	0.461382484898	0.282586294059	0.259635090345	0.202508723789	0.192582035266	0.160350654061	0.138031252593	0.123015943185	7.5757356253e-17
-% variation explained	25.3493979248	15.5259305472	14.2649394718	11.1262876043	10.5808928707	8.81002784101	7.58374941088	6.75877432927	4.1622806072e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_1.txt b/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_1.txt
index 50b2e0b..af9a4d3 100644
--- a/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_1.txt
+++ b/tests/scripts_test_data/make_emperor/compare/pcoa_unweighted_unifrac_rarefaction_110_1.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.483314104562	0.306299367707	0.272267531543	0.192446818524	0.164885211801	0.155283759113	0.139844959373	0.112956103924	-1.4106073775e-16
+
+Proportion explained	9
+26.4496618781	16.7624214416	14.9000082591	10.5317706051	9.02344471155	8.49799930298	7.65310148381	6.18159231783	7.71963570387e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.288198422836	-0.0394400561594	0.155709945044	0.110165008813	-0.074622228146	-0.05065773954	-0.217629816961	0.138926064051	-3.95896644411e-09
 PC.635	-0.241287260869	-0.0113094708189	-0.0710427892223	-0.256796747044	0.221116161933	0.0148414610436	-0.086024926776	-0.0794987090308	-3.95896644411e-09
 PC.356	0.192207680814	-0.321726747298	-0.128718397379	-0.0122628266319	-0.0944977974365	0.230759463288	-0.0469763035028	0.00172079771458	-3.95896644411e-09
@@ -9,6 +17,6 @@ PC.355	0.133038027649	-0.233356301889	0.0324518672876	-0.00492825007504	-0.06539
 PC.607	-0.0622832861598	0.2368583004	-0.396154332152	0.0382634195983	-0.119360328521	-0.0594795163388	0.00817199024745	0.0213023627761	-3.95896644411e-09
 PC.634	-0.334922829033	0.0125244602096	0.152206619253	-0.0404571567605	-0.116846418379	0.0812801531067	0.246923498147	-0.0123561385027	-3.95896644411e-09
 
+Biplot	0	0
 
-eigvals	0.483314104562	0.306299367707	0.272267531543	0.192446818524	0.164885211801	0.155283759113	0.139844959373	0.112956103924	-1.4106073775e-16
-% variation explained	26.4496618781	16.7624214416	14.9000082591	10.5317706051	9.02344471155	8.49799930298	7.65310148381	6.18159231783	7.71963570387e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/otu_table_L3.txt b/tests/scripts_test_data/make_emperor/otu_table_L3.txt
index 2e40779..7b8e343 100644
--- a/tests/scripts_test_data/make_emperor/otu_table_L3.txt
+++ b/tests/scripts_test_data/make_emperor/otu_table_L3.txt
@@ -6,4 +6,4 @@ Root;k__Bacteria;p__Deferribacteres	0.0472972972973	0.0134228187919	0.0	0.0	0.0
 Root;k__Bacteria;p__Firmicutes	0.209459459459	0.395973154362	0.773333333333	0.787671232877	0.89932885906	0.41610738255	0.700680272109	0.456375838926	0.22
 Root;k__Bacteria;p__Proteobacteria	0.00675675675676	0.00671140939597	0.0	0.0	0.0	0.0335570469799	0.0	0.0201342281879	0.0133333333333
 Root;k__Bacteria;p__TM7	0.0	0.0	0.0	0.0	0.0	0.0	0.0	0.0	0.0133333333333
-Root;k__Bacteria;p__Tenericutes	0.0135135135135	0.00671140939597	0.00666666666667	0.0342465753425	0.0134228187919	0.147651006711	0.0	0.161073825503	0.0266666666667
+Root;k__Bacteria;p__	0.0135135135135	0.00671140939597	0.00666666666667	0.0342465753425	0.0134228187919	0.147651006711	0.0	0.161073825503	0.0266666666667
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc.txt
index ce07a51..c6460f0 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.479412119045	0.29201495623	0.247449246064	0.201496072404	0.180076127632	0.147806772727	0.135795927213	0.112259695609	2.10954116963e-16
+
+Proportion explained	9
+26.6887048633	16.2563704022	13.7754129161	11.217215823	10.024774995	8.22835130237	7.55971173665	6.24945796136	1.17437418531e-14
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.276542163845	-0.144964375408	0.0666467344429	-0.0677109454288	0.176070269506	0.072969390136	-0.229889463523	-0.0465989416581	-4.84141986706e-09
 PC.635	-0.237661393984	0.0460527772512	-0.138135814766	0.159061025229	-0.247484698646	-0.115211468101	-0.112864033263	0.0647940729676	-4.84141986706e-09
 PC.356	0.228820399536	-0.130142097093	-0.287149447883	0.0864498846421	0.0442951919304	0.20604260722	0.0310003571386	0.0719920436501	-4.84141986706e-09
@@ -9,6 +17,6 @@ PC.355	0.170517581885	-0.194113268955	-0.0308965283066	0.0198086158783	0.1551000
 PC.607	-0.0913299284215	0.424147148265	-0.135627421345	-0.057519480907	0.151363490722	-0.0253935675552	0.0517306152066	-0.038738217609	-4.84141986706e-09
 PC.634	-0.349339228244	-0.120787589539	0.115274502117	0.0694953933826	-0.0253722182853	0.067853201946	0.244447634756	-0.0598827706386	-4.84141986706e-09
 
+Biplot	0	0
 
-eigvals	0.479412119045	0.29201495623	0.247449246064	0.201496072404	0.180076127632	0.147806772727	0.135795927213	0.112259695609	2.10954116963e-16
-% variation explained	26.6887048633	16.2563704022	13.7754129161	11.217215823	10.024774995	8.22835130237	7.55971173665	6.24945796136	1.17437418531e-14
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_0.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_0.txt
index 810e2b4..f0cdead 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_0.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_0.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.461382484898	0.282586294059	0.259635090345	0.202508723789	0.192582035266	0.160350654061	0.138031252593	0.123015943185	7.5757356253e-17
+
+Proportion explained	9
+25.3493979248	15.5259305472	14.2649394718	11.1262876043	10.5808928707	8.81002784101	7.58374941088	6.75877432927	4.1622806072e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	0.281857587421	0.0507270541945	0.0374722443357	-0.0370074137223	0.15782793716	0.23359469867	0.174998809955	0.0219541318555	2.90129006273e-09
 PC.635	0.18215230676	0.132916775615	-0.100389688466	0.190011634826	-0.307283733566	0.00430749577241	0.0469580790424	-0.0617163043591	2.90129006273e-09
 PC.356	-0.239606359013	0.178116346653	-0.316300212034	-0.0116338896148	0.114589435481	0.0915396854904	-0.13794374686	-0.0311556901155	2.90129006273e-09
@@ -9,6 +17,6 @@ PC.355	-0.196195568243	0.169658119414	0.0424034255545	-0.0848245709891	0.0670053
 PC.607	0.133124236385	-0.378152288866	-0.239139015591	-0.103687426251	-0.0141771679839	-0.0969160055476	0.0312930958801	0.0232026349583	2.90129006273e-09
 PC.634	0.335092748334	0.0913419796777	0.112900504808	0.0836202835077	0.137259423818	-0.161059445277	-0.177049932906	0.0749552140687	2.90129006273e-09
 
+Biplot	0	0
 
-eigvals	0.461382484898	0.282586294059	0.259635090345	0.202508723789	0.192582035266	0.160350654061	0.138031252593	0.123015943185	7.5757356253e-17
-% variation explained	25.3493979248	15.5259305472	14.2649394718	11.1262876043	10.5808928707	8.81002784101	7.58374941088	6.75877432927	4.1622806072e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_1.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_1.txt
index 50b2e0b..af9a4d3 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_1.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_1.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.483314104562	0.306299367707	0.272267531543	0.192446818524	0.164885211801	0.155283759113	0.139844959373	0.112956103924	-1.4106073775e-16
+
+Proportion explained	9
+26.4496618781	16.7624214416	14.9000082591	10.5317706051	9.02344471155	8.49799930298	7.65310148381	6.18159231783	7.71963570387e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.288198422836	-0.0394400561594	0.155709945044	0.110165008813	-0.074622228146	-0.05065773954	-0.217629816961	0.138926064051	-3.95896644411e-09
 PC.635	-0.241287260869	-0.0113094708189	-0.0710427892223	-0.256796747044	0.221116161933	0.0148414610436	-0.086024926776	-0.0794987090308	-3.95896644411e-09
 PC.356	0.192207680814	-0.321726747298	-0.128718397379	-0.0122628266319	-0.0944977974365	0.230759463288	-0.0469763035028	0.00172079771458	-3.95896644411e-09
@@ -9,6 +17,6 @@ PC.355	0.133038027649	-0.233356301889	0.0324518672876	-0.00492825007504	-0.06539
 PC.607	-0.0622832861598	0.2368583004	-0.396154332152	0.0382634195983	-0.119360328521	-0.0594795163388	0.00817199024745	0.0213023627761	-3.95896644411e-09
 PC.634	-0.334922829033	0.0125244602096	0.152206619253	-0.0404571567605	-0.116846418379	0.0812801531067	0.246923498147	-0.0123561385027	-3.95896644411e-09
 
+Biplot	0	0
 
-eigvals	0.483314104562	0.306299367707	0.272267531543	0.192446818524	0.164885211801	0.155283759113	0.139844959373	0.112956103924	-1.4106073775e-16
-% variation explained	26.4496618781	16.7624214416	14.9000082591	10.5317706051	9.02344471155	8.49799930298	7.65310148381	6.18159231783	7.71963570387e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_2.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_2.txt
index c0f39ab..61a6770 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_2.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_2.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.467151269331	0.309553202359	0.227982661044	0.206249025551	0.181879322705	0.147537350405	0.129834142405	0.123424786986	-1.31113090173e-16
+
+Proportion explained	9
+26.045283575	17.2586514611	12.7108143484	11.4990897172	10.1403953008	8.22571270052	7.23869820902	6.88135468802	7.31000392838e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.291811048864	0.109699868326	-0.0858327621887	-0.0363345352382	-0.129522215769	0.0946765004148	0.18546581707	-0.161410801774	-3.81682081455e-09
 PC.635	-0.262457627274	-0.022626332813	0.0736327155898	0.099865206029	0.252989493775	0.194545268592	-0.0570948823666	0.0648783371866	-3.81682081455e-09
 PC.356	0.243530111276	0.18098079751	0.240516390145	0.111565470096	0.0291936951093	-0.0724851408509	0.180523264931	0.0791331945494	-3.81682081455e-09
@@ -9,6 +17,6 @@ PC.355	0.165602711122	0.258948926594	-0.0361519732043	0.0746828273727	-0.1879549
 PC.607	-0.0227688247286	-0.394436460907	0.198777377966	-0.00819196960445	-0.190306098497	0.0232182765318	-0.0299585405632	0.0151297883867	-3.81682081455e-09
 PC.634	-0.335961100144	0.0635958099611	-0.0181227466881	0.0545077293766	0.00708572727353	-0.283984621752	-0.0953762189457	0.0131558907721	-3.81682081455e-09
 
+Biplot	0	0
 
-eigvals	0.467151269331	0.309553202359	0.227982661044	0.206249025551	0.181879322705	0.147537350405	0.129834142405	0.123424786986	-1.31113090173e-16
-% variation explained	26.045283575	17.2586514611	12.7108143484	11.4990897172	10.1403953008	8.22571270052	7.23869820902	6.88135468802	7.31000392838e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_3.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_3.txt
index f17655b..54cb3f6 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_3.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_3.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.438193449813	0.303149574232	0.248737850995	0.208018516631	0.205845750596	0.155032935288	0.142263489179	0.129401808481	-2.36328968548e-16
+
+Proportion explained	9
+23.9365818458	16.5597285816	13.5874553374	11.3631371051	11.2444484482	8.46876772324	7.77122901735	7.06865194134	1.29096126393e-14
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.259617725178	-0.127034975645	-0.0666808280154	0.127224251991	0.0270017842986	-0.121258111474	0.227939491925	0.125932662581	-5.12433159378e-09
 PC.635	-0.230580732193	0.0290048715434	0.170223356474	-0.193514286497	0.2390531539	0.130626842785	-0.0540311448301	0.0881623374927	-5.12433159378e-09
 PC.356	0.18593872779	-0.179339928765	0.295255813109	0.251307747921	-0.023167290942	0.0651066216606	-0.0501858865665	-0.0167258121957	-5.12433159378e-09
@@ -9,6 +17,6 @@ PC.355	0.195650496999	-0.157765174624	0.0383077783424	-0.213856871786	-0.0475634
 PC.607	-0.109180192011	0.428093856324	0.14022111843	0.0317045158159	-0.154471859932	-0.0875356535256	0.00289973864488	-0.0319091564379	-5.12433159378e-09
 PC.634	-0.329885531917	-0.142498816231	-0.137315147392	0.0224068078709	-0.0494688354606	0.015370214314	-0.111272546766	-0.226053309339	-5.12433159378e-09
 
+Biplot	0	0
 
-eigvals	0.438193449813	0.303149574232	0.248737850995	0.208018516631	0.205845750596	0.155032935288	0.142263489179	0.129401808481	-2.36328968548e-16
-% variation explained	23.9365818458	16.5597285816	13.5874553374	11.3631371051	11.2444484482	8.46876772324	7.77122901735	7.06865194134	1.29096126393e-14
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_4.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_4.txt
index 03a2a1a..42bca1c 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_4.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_4.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.519914026682	0.30858919143	0.258164238227	0.202727303981	0.188511335665	0.148695541505	0.142995892141	0.109437810611	-5.48147077553e-17
+
+Proportion explained	9
+27.6691989526	16.4227454812	13.7391901418	10.7889032015	10.032346472	7.9133978122	7.6100693307	5.82414860791	2.91717279507e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.312618299505	-0.134917946942	-0.170972453493	0.0764753169825	0.0882699204763	0.0276567284685	-0.212890432382	0.122188819584	-2.46789851573e-09
 PC.635	-0.2132884209	-0.0740598897997	0.233675836919	-0.0721843071969	-0.294362560484	-0.0581637097257	-0.0768981998571	-0.0497853485604	-2.46789851573e-09
 PC.356	0.230640963532	-0.147797202059	0.188571605262	0.250626343249	0.0528628049705	0.184196793739	0.00488519962926	-0.0523484688119	-2.46789851573e-09
@@ -9,6 +17,6 @@ PC.355	0.167848130414	-0.213287333783	-0.0171692055242	0.00764992667748	0.128119
 PC.607	-0.185356415177	0.393132633935	0.182670419671	0.0719091507839	0.147767400013	-0.0733886145175	0.0310639380622	0.0303376984908	-2.46789851573e-09
 PC.634	-0.326921780126	-0.0888685283709	-0.149177855023	-0.0191813843756	-0.012979727269	0.0802228886509	0.270324429027	-0.0398440504794	-2.46789851573e-09
 
+Biplot	0	0
 
-eigvals	0.519914026682	0.30858919143	0.258164238227	0.202727303981	0.188511335665	0.148695541505	0.142995892141	0.109437810611	-5.48147077553e-17
-% variation explained	27.6691989526	16.4227454812	13.7391901418	10.7889032015	10.032346472	7.9133978122	7.6100693307	5.82414860791	2.91717279507e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_5.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_5.txt
index a77c412..8866dda 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_5.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_5.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.51444758364	0.286109243433	0.253677898271	0.20032493562	0.169189362502	0.153938151792	0.144775235712	0.101424794301	1.33437308462e-17
+
+Proportion explained	9
+28.2061073817	15.6867838431	13.9086396098	10.9834059388	9.2763062328	8.44011358528	7.93772966296	5.56091374554	7.31609433285e-16
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.297529982515	-0.134761736606	0.0797120449385	-0.0489692608121	0.132199783328	0.0629129889526	-0.261855324323	-0.0372661663609	-1.21763572578e-09
 PC.635	-0.269342929697	0.00823195555299	-0.170861487015	0.00676567224194	-0.272168045381	-0.166645022654	-0.0357138312685	-0.0231609609378	-1.21763572578e-09
 PC.356	0.252095110415	-0.154959217	-0.232952501924	0.124786056699	0.00548229006198	0.090696181001	-0.0498388124855	0.179875021982	-1.21763572578e-09
@@ -9,6 +17,6 @@ PC.355	0.165482455054	-0.218474333635	0.00746606813222	0.103635714451	0.14935208
 PC.607	-0.0852439993525	0.384049930101	-0.185136088675	-0.0121834684412	0.189264509901	-0.0199052838949	0.036082355067	-0.00323613962588	-1.21763572578e-09
 PC.634	-0.351656411877	-0.0734737225067	0.117789335936	0.0965749919843	-0.0119772368758	0.160619808588	0.225491958433	0.0297751994426	-1.21763572578e-09
 
+Biplot	0	0
 
-eigvals	0.51444758364	0.286109243433	0.253677898271	0.20032493562	0.169189362502	0.153938151792	0.144775235712	0.101424794301	1.33437308462e-17
-% variation explained	28.2061073817	15.6867838431	13.9086396098	10.9834059388	9.2763062328	8.44011358528	7.93772966296	5.56091374554	7.31609433285e-16
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_6.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_6.txt
index 52b5237..c69de22 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_6.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_6.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.493922499204	0.293653382897	0.236756355703	0.194338851936	0.1765267285	0.15233972193	0.119178511611	0.0983059248854	1.9172964533e-16
+
+Proportion explained	9
+27.9839291371	16.6373782751	13.4137908102	11.0105627298	10.0013898316	8.6310382502	6.75223952937	5.56967143667	1.08627341679e-14
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.306532758815	0.125055309543	-0.08615911958	0.00481923926582	0.12869850318	0.0884132334747	-0.234117775799	-0.0295337107367	-4.61554914669e-09
 PC.635	-0.2192577948	0.0255645834237	0.163426559207	-0.0175714515721	-0.33115744063	-0.0735011565247	-0.0452805641083	0.0100574762365	-4.61554914669e-09
 PC.356	0.225951027203	0.219515466953	0.204578542723	0.209761298578	0.119158634085	-0.135741439381	-0.00455873794414	0.0405033592303	-4.61554914669e-09
@@ -9,6 +17,6 @@ PC.355	0.223455475873	0.120414505692	-0.0253460016063	0.0158819262218	-0.0848105
 PC.607	-0.135408755395	-0.392685590709	0.203178560568	0.0595266484496	0.115365266737	0.0804627102484	0.0438872261002	0.000156925236315	-4.61554914669e-09
 PC.634	-0.340040096344	0.124973529437	-0.160277019095	0.0324611474211	0.0493087969997	-0.0502085288699	0.230120041624	-0.0357775806159	-4.61554914669e-09
 
+Biplot	0	0
 
-eigvals	0.493922499204	0.293653382897	0.236756355703	0.194338851936	0.1765267285	0.15233972193	0.119178511611	0.0983059248854	1.9172964533e-16
-% variation explained	27.9839291371	16.6373782751	13.4137908102	11.0105627298	10.0013898316	8.6310382502	6.75223952937	5.56967143667	1.08627341679e-14
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_7.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_7.txt
index eaf76d6..194c48d 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_7.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_7.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.543054102898	0.290991422552	0.254563261336	0.201903601877	0.175834268859	0.171080576396	0.143746820306	0.111200301257	1.53802566488e-16
+
+Proportion explained	9
+28.6969700961	15.3770537901	13.4520561748	10.6693266738	9.29172752472	9.04052498389	7.59610908326	5.87623167345	8.12749158443e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.247724703631	-0.110907880622	0.148515184061	-0.0697969019998	-0.0519451757417	-0.28129818774	0.129606852106	0.0559122384073	-4.13390542395e-09
 PC.635	-0.281592024147	-0.0935985957717	-0.156580222739	0.0751448471758	-0.00335363029797	0.202521202889	0.218028267769	-0.0447266204757	-4.13390542395e-09
 PC.356	0.277341318558	-0.217172335579	-0.240864189131	-0.0828846105057	0.124058716899	-0.113350088725	-0.0456150092711	-0.127477368313	-4.13390542395e-09
@@ -9,6 +17,6 @@ PC.355	0.163667410013	-0.101168902397	0.0976130732126	-0.0224543756361	-0.335618
 PC.607	-0.16847562339	0.30201471578	-0.283404571053	-0.0250931101611	-0.0911829156	-0.0670065802057	-0.103379559938	0.0793736811619	-4.13390542395e-09
 PC.634	-0.34147591421	-0.103625371722	0.14489891552	-0.0824125417707	0.145285782846	0.112132635255	-0.216869706054	0.00681758537734	-4.13390542395e-09
 
+Biplot	0	0
 
-eigvals	0.543054102898	0.290991422552	0.254563261336	0.201903601877	0.175834268859	0.171080576396	0.143746820306	0.111200301257	1.53802566488e-16
-% variation explained	28.6969700961	15.3770537901	13.4520561748	10.6693266738	9.29172752472	9.04052498389	7.59610908326	5.87623167345	8.12749158443e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_8.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_8.txt
index fe9a5bd..db7bf8d 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_8.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_8.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.464276362557	0.318290228223	0.279193241784	0.194898274087	0.18325656581	0.164542343712	0.136218302741	0.128149853582	-4.31017797408e-16
+
+Proportion explained	9
+24.8432207245	17.031567902	14.9395056259	10.428919567	9.80597695852	8.80458729546	7.28898051814	6.85724140855	2.3063569763e-14
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.297856558996	-0.118500137939	0.121887553385	0.00925175683482	-0.0629001611523	0.0235123286981	0.154183718038	0.226565441945	-6.9203227077e-09
 PC.635	-0.203966248031	0.00931969171391	-0.222791076921	-0.221486935693	0.101843830393	-0.144965640307	0.10888794931	-0.112159832411	-6.9203227077e-09
 PC.356	0.250075527075	-0.24138144942	-0.198173351288	0.12389753109	-0.236367962742	-0.0460108630286	0.0457784353988	-0.0488004347006	-6.9203227077e-09
@@ -9,6 +17,6 @@ PC.355	0.12865666755	-0.191614940238	-0.00298287271838	-0.111739184653	0.1376794
 PC.607	-0.0810236339757	0.352125113455	-0.254699322384	0.160902511543	0.0122565561358	0.115755383033	-0.0389182855819	0.0584163027965	-6.9203227077e-09
 PC.634	-0.355412335227	-0.0549047477064	0.139690678425	0.0253458401976	-0.113982885758	-0.008332475766	-0.218379835532	-0.12019762108	-6.9203227077e-09
 
+Biplot	0	0
 
-eigvals	0.464276362557	0.318290228223	0.279193241784	0.194898274087	0.18325656581	0.164542343712	0.136218302741	0.128149853582	-4.31017797408e-16
-% variation explained	24.8432207245	17.031567902	14.9395056259	10.428919567	9.80597695852	8.80458729546	7.28898051814	6.85724140855	2.3063569763e-14
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_9.txt b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_9.txt
index 66b8d7d..cc9aeaa 100644
--- a/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_9.txt
+++ b/tests/scripts_test_data/make_emperor/unweighted_unifrac_pc/pcoa_unweighted_unifrac_rarefaction_110_9.txt
@@ -1,4 +1,12 @@
-pc vector number	1	2	3	4	5	6	7	8	9
+Eigvals	9
+0.517202330691	0.30019150521	0.2650189	0.201057877124	0.192592716887	0.156750872809	0.13879823577	0.131494630884	1.08317974416e-16
+
+Proportion explained	9
+27.1767331967	15.7737580844	13.9255906441	10.5647170545	10.1199096985	8.23657666622	7.29324366474	6.90947099089	5.69163848736e-15
+
+Species	0	0
+
+Site	9	9
 PC.636	-0.276918773699	-0.109525428023	0.131430223502	-0.11422578396	-0.00807228907363	0.092749547669	0.247377186817	0.0989590042554	-3.46919738422e-09
 PC.635	-0.278181631362	-0.0264126317424	-0.107051242269	0.230883029394	-0.0423595235016	-0.253104608448	0.0377474156399	-0.00627296102413	-3.46919738422e-09
 PC.356	0.183414920533	-0.272502933338	-0.19359423824	-0.0219139076963	-0.155967607389	0.0537709485936	-0.107049426642	0.164325439223	-3.46919738422e-09
@@ -9,6 +17,6 @@ PC.355	0.19604841631	-0.158897863607	-0.0343705901915	-0.137803981217	-0.0531075
 PC.607	-0.101594937874	0.328567652216	-0.315877407021	-0.0481503686122	0.00758749286508	0.132203342143	0.016508139245	-0.0314390181072	-3.46919738422e-09
 PC.634	-0.340644502782	-0.0283195530314	0.198024463985	0.0257452386334	-0.0294215944475	0.121601942507	-0.222670727384	-0.0846875473443	-3.46919738422e-09
 
+Biplot	0	0
 
-eigvals	0.517202330691	0.30019150521	0.2650189	0.201057877124	0.192592716887	0.156750872809	0.13879823577	0.131494630884	1.08317974416e-16
-% variation explained	27.1767331967	15.7737580844	13.9255906441	10.5647170545	10.1199096985	8.23657666622	7.29324366474	6.90947099089	5.69163848736e-15
\ No newline at end of file
+Site constraints	0	0
diff --git a/tests/test_biplots.py b/tests/test_biplots.py
old mode 100755
new mode 100644
index 59efae5..a085241
--- a/tests/test_biplots.py
+++ b/tests/test_biplots.py
@@ -1,154 +1,190 @@
-#!/usr/bin/env python
-# File created on 16 Apr 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
 from unittest import TestCase, main
 
 from numpy import array
 from numpy.testing import assert_almost_equal
 
-from emperor.qiime_backports.parse import parse_classic_otu_table
 from emperor.util import EmperorUnsupportedComputation
 from emperor.biplots import extract_taxa_data, preprocess_otu_table
 
 
 class TopLevelTests(TestCase):
-    
+
     def setUp(self):
-        self.biplot_coords = array([[-0.0520990488006, -0.0108550868341,
-            0.00118513950438, -0.0195647012451, -0.0437589801599,
-            0.000848245309189, -0.0122035463608, 0.0288287964617,
-            -4.84141986706e-09], [-0.00406501716894, -0.0300693128299,
-            -0.090316974427, 0.0559730983008, -0.0597265944801, 0.0456519002902,
-            -0.054142291901, 0.0668355273511, -4.84141986706e-09],[
-            0.0965087039672, -0.0164113801126, 0.0168583314836, 0.0103732287638,
-            -0.0225710882818, 0.0283857610935, 3.22664794516e-05,
-            0.0290430321474, -4.84141986706e-09], [0.126316230269,
-            0.0263889076329, 0.0330227792131, 0.0885396607535, -0.0372547601153,
-            0.0638622448577, -0.0224927101495, 0.0902626098256,
-            -4.84141986706e-09], [-0.0672105325806, 0.0105941468738,
-            -0.00527647509456, -0.0131631383518, 0.0315560857565,
-            -0.0199787562498, 0.00815726904809, -0.0175931838803,
-            -4.84141986706e-09], [0.118424097634, -0.00197525147278,
-            -0.0399274159763, 0.0211233039391, -0.124633799325, 0.0133749785777,
-            -0.0384382665152, -0.0584384149046, -4.84141986706e-09],
-            [0.228820399536, -0.130142097093, -0.287149447883, 0.0864498846421,
-            0.0442951919304, 0.20604260722, 0.0310003571386, 0.0719920436501,
-            -4.84141986706e-09], [-0.000909430629502, 0.0116559690557,
-            -0.049810186364, 0.0452278786773, -0.12933257558, -0.0214449951683,
-            -0.0693407019638, -0.062534332665, -4.84141986706e-09]])
-
-        self.otu_table = array([[0.02739726, 0.04697987, 0.02, 0.04697987, 0.01,
-            0.02027027, 0.01360544, 0.01342282, 0.02666667], [0.00684932,
-            0.02013423, 0.02, 0.00671141,  0., 0.00675676, 0., 0., 0.], [
-            0.14383562, 0.27516779, 0.65333333, 0.52348993, 0.38926174,
-            0.69594595, 0.28571429, 0.0738255, 0.19333333], [0., 0.02013423,
-            0.03333333, 0.01342282, 0., 0.0472973, 0., 0., 0.], [0.78767123,
-            0.45637584, 0.22, 0.39597315, 0.41610738, 0.20945946, 0.70068027,
-            0.89932886, 0.77333333], [0.,0.02013423, 0.01333333, 0.00671141,
-            0.03355705, 0.00675676, 0., 0., 0.],[0., 0., 0.01333333, 0., 0., 0.,
-            0., 0., 0.], [0.03424658, 0.16107383, 0.02666667, 0.00671141,
-            0.14765101, 0.01351351, 0., 0.01342282, 0.00666667]])
+        self.biplot_coords = array(
+            [[-0.0520990488006, -0.0108550868341, 0.00118513950438,
+              -0.0195647012451, -0.0437589801599, 0.000848245309189,
+              -0.0122035463608, 0.0288287964617, -4.84141986706e-09],
+             [-0.00406501716894, -0.0300693128299, -0.090316974427,
+              0.0559730983008, -0.0597265944801, 0.0456519002902,
+             -0.054142291901, 0.0668355273511, -4.84141986706e-09],
+             [0.0965087039672, -0.0164113801126, 0.0168583314836,
+              0.0103732287638, -0.0225710882818, 0.0283857610935,
+             3.22664794516e-05, 0.0290430321474, -4.84141986706e-09],
+             [0.126316230269, 0.0263889076329, 0.0330227792131,
+              0.0885396607535, -0.0372547601153, 0.0638622448577,
+             -0.0224927101495, 0.0902626098256, -4.84141986706e-09],
+             [-0.0672105325806, 0.0105941468738, -0.00527647509456,
+              -0.0131631383518, 0.0315560857565, -0.0199787562498,
+             0.00815726904809, -0.0175931838803, -4.84141986706e-09],
+             [0.118424097634, -0.00197525147278, -0.0399274159763,
+              0.0211233039391, -0.124633799325, 0.0133749785777,
+             -0.0384382665152, -0.0584384149046, -4.84141986706e-09],
+             [0.228820399536, -0.130142097093, -0.287149447883,
+              0.0864498846421, 0.0442951919304, 0.20604260722,
+             0.0310003571386, 0.0719920436501, -4.84141986706e-09],
+             [-0.000909430629502, 0.0116559690557, -0.049810186364,
+              0.0452278786773, -0.12933257558, -0.0214449951683,
+             -0.0693407019638, -0.062534332665, -4.84141986706e-09]])
+
+        self.otu_table = array(
+            [[0.02739726, 0.04697987, 0.02, 0.04697987, 0.01,
+              0.02027027, 0.01360544, 0.01342282, 0.02666667],
+             [0.00684932, 0.02013423, 0.02, 0.00671141,
+              0., 0.00675676, 0., 0., 0.],
+             [0.14383562, 0.27516779, 0.65333333, 0.52348993,
+              0.38926174, 0.69594595, 0.28571429, 0.0738255, 0.19333333],
+             [0., 0.02013423, 0.03333333, 0.01342282, 0.,
+              0.0472973, 0., 0., 0.],
+             [0.78767123, 0.45637584, 0.22, 0.39597315, 0.41610738,
+              0.20945946, 0.70068027, 0.89932886, 0.77333333],
+             [0., 0.02013423, 0.01333333, 0.00671141, 0.03355705,
+              0.00675676, 0., 0., 0.],
+             [0., 0., 0.01333333, 0., 0., 0., 0., 0., 0.],
+             [0.03424658, 0.16107383, 0.02666667, 0.00671141,
+              0.14765101, 0.01351351, 0., 0.01342282, 0.00666667]])
 
         self.lineages = ['Root;k__Bacteria;Other',
-            'Root;k__Bacteria;p__Actinobacteria', 
-            'Root;k__Bacteria;p__Bacteroidetes',
-            'Root;k__Bacteria;p__Deferribacteres',
-            'Root;k__Bacteria;p__Firmicutes',
-            'Root;k__Bacteria;p__Proteobacteria','Root;k__Bacteria;p__TM7',
-            'Root;k__Bacteria;p__Tenericutes']
+                         'Root;k__Bacteria;p__Actinobacteria',
+                         'Root;k__Bacteria;p__Bacteroidetes',
+                         'Root;k__Bacteria;p__Deferribacteres',
+                         'Root;k__Bacteria;p__Firmicutes',
+                         'Root;k__Bacteria;p__Proteobacteria',
+                         'Root;k__Bacteria;p__TM7',
+                         'Root;k__Bacteria;p__Tenericutes']
 
-        self.prevalence = array([0.04445514, 0.00972396, 0.6646394, 0.02081361,
-            1., 0.01385989, 0., 0.08185147])
-        self.otu_sample_ids = ['PC.636', 'PC.635', 'PC.356', 'PC.481', 'PC.354',
-            'PC.593', 'PC.355', 'PC.607', 'PC.634']
+        self.prevalence = array(
+            [0.04445514, 0.00972396, 0.6646394, 0.02081361,
+             1., 0.01385989, 0., 0.08185147])
+        self.otu_sample_ids = ['PC.636', 'PC.635', 'PC.356',
+                               'PC.481', 'PC.354', 'PC.593',
+                               'PC.355', 'PC.607', 'PC.634']
         self.coords = COORDS
-        self.coords_header = ['PC.636', 'PC.635', 'PC.356', 'PC.481', 'PC.354',
-            'PC.593', 'PC.355', 'PC.607', 'PC.634']
+        self.coords_header = ['PC.636', 'PC.635', 'PC.356',
+                              'PC.481', 'PC.354', 'PC.593',
+                              'PC.355', 'PC.607', 'PC.634']
 
         # data used to test a case where an exception should be raised
-        self.otu_table_broken = array([[0.02739726, 0.04697987, 0.02,
-            0.04697987, 0.01, 0.02027027, 0.01360544, 0.01342282, 0.02666667]])
+        self.otu_table_broken = array(
+            [[0.02739726, 0.04697987, 0.02,
+              0.04697987, 0.01, 0.02027027,
+              0.01360544, 0.01342282, 0.02666667]])
         self.lineages_broken = ['Root;k__Bacteria']
 
     def test_filter_taxa(self):
         """Check the appropriate number of elements are extracted"""
         # test the simple case where you want to retain 5 taxonomic groups
         o_coords, o_table, o_lineages, o_prevalence = extract_taxa_data(
-            self.biplot_coords, self.otu_table, self.lineages,self.prevalence,3)
-
-        assert_almost_equal(o_coords, array([[-0.0672105325806, 0.0105941468738,
-            -0.00527647509456, -0.0131631383518, 0.0315560857565,
-            -0.0199787562498, 0.00815726904809, -0.0175931838803,
-            -4.84141986706e-09],[0.0965087039672, -0.0164113801126,
-            0.0168583314836, 0.0103732287638, -0.0225710882818, 0.0283857610935,
-            3.22664794516e-05, 0.0290430321474, -4.84141986706e-09], [
-            -0.000909430629502, 0.0116559690557, -0.049810186364,
-            0.0452278786773, -0.12933257558, -0.0214449951683,
-            -0.0693407019638, -0.062534332665, -4.84141986706e-09]]))
-        assert_almost_equal(o_table, array([[0.78767123, 0.45637584, 0.22,
-            0.39597315, 0.41610738, 0.20945946, 0.70068027, 0.89932886,
-            0.77333333], [0.14383562, 0.27516779, 0.65333333, 0.52348993,
-            0.38926174, 0.69594595, 0.28571429, 0.0738255, 0.19333333],
-            [0.03424658, 0.16107383, 0.02666667, 0.00671141, 0.14765101,
-            0.01351351, 0., 0.01342282, 0.00666667]]))
-        self.assertEquals(o_lineages, ['Root;k__Bacteria;p__Firmicutes',
-            'Root;k__Bacteria;p__Bacteroidetes',
-            'Root;k__Bacteria;p__Tenericutes'])
-        assert_almost_equal(o_prevalence,  array([ 1., 0.6646394, 0.08185147]))
+            self.biplot_coords, self.otu_table,
+            self.lineages, self.prevalence, 3)
+
+        assert_almost_equal(o_coords, array(
+            [[-0.0672105325806, 0.0105941468738, -0.00527647509456,
+              -0.0131631383518, 0.0315560857565, -0.0199787562498,
+              0.00815726904809, -0.0175931838803, -4.84141986706e-09],
+             [0.0965087039672, -0.0164113801126, 0.0168583314836,
+              0.0103732287638, -0.0225710882818, 0.0283857610935,
+              3.22664794516e-05, 0.0290430321474, -4.84141986706e-09],
+             [-0.000909430629502, 0.0116559690557, -0.049810186364,
+              0.0452278786773, -0.12933257558, -0.0214449951683,
+              -0.0693407019638, -0.062534332665, -4.84141986706e-09]]))
+
+        assert_almost_equal(o_table, array(
+            [[0.78767123, 0.45637584, 0.22,
+              0.39597315, 0.41610738, 0.20945946,
+              0.70068027, 0.89932886, 0.77333333],
+             [0.14383562, 0.27516779, 0.65333333,
+              0.52348993, 0.38926174, 0.69594595,
+              0.28571429, 0.0738255, 0.19333333],
+             [0.03424658, 0.16107383, 0.02666667,
+              0.00671141, 0.14765101, 0.01351351,
+              0., 0.01342282, 0.00666667]]))
+        self.assertEqual(o_lineages,
+                         ['Root;k__Bacteria;p__Firmicutes',
+                          'Root;k__Bacteria;p__Bacteroidetes',
+                          'Root;k__Bacteria;p__Tenericutes'])
+        assert_almost_equal(o_prevalence,
+                            array([1., 0.6646394, 0.08185147]))
 
         # test the case where all the elements are requested
         o_coords, o_table, o_lineages, o_prevalence = extract_taxa_data(
-            self.biplot_coords,self.otu_table,self.lineages,self.prevalence,-1)
-
-        assert_almost_equal(o_coords, array([[-6.72105326e-02, 1.05941469e-02,
-            -5.27647509e-03, -1.31631384e-02, 3.15560858e-02, -1.99787562e-02,
-            8.15726905e-03, -1.75931839e-02, -4.84141987e-09], [9.65087040e-02,
-            -1.64113801e-02, 1.68583315e-02, 1.03732288e-02, -2.25710883e-02,
-            2.83857611e-02, 3.22664795e-05, 2.90430321e-02, -4.84141987e-09],
-            [-9.09430630e-04, 1.16559691e-02, -4.98101864e-02, 4.52278787e-02,
-            -1.29332576e-01, -2.14449952e-02, -6.93407020e-02, -6.25343327e-02,
-            -4.84141987e-09], [-5.20990488e-02, -1.08550868e-02, 1.18513950e-03,
-            -1.95647012e-02, -4.37589802e-02, 8.48245309e-04, -1.22035464e-02,
-            2.88287965e-02, -4.84141987e-09], [1.26316230e-01, 2.63889076e-02,
-            3.30227792e-02, 8.85396608e-02, -3.72547601e-02, 6.38622449e-02,
-            -2.24927101e-02, 9.02626098e-02, -4.84141987e-09], [1.18424098e-01,
-            -1.97525147e-03, -3.99274160e-02, 2.11233039e-02, -1.24633799e-01,
-            1.33749786e-02, -3.84382665e-02, -5.84384149e-02, -4.84141987e-09],
-            [-4.06501717e-03, -3.00693128e-02, -9.03169744e-02, 5.59730983e-02,
-            -5.97265945e-02, 4.56519003e-02, -5.41422919e-02, 6.68355274e-02,
-            -4.84141987e-09], [2.28820400e-01, -1.30142097e-01, -2.87149448e-01,
-            8.64498846e-02, 4.42951919e-02, 2.06042607e-01, 3.10003571e-02,
-            7.19920437e-02, -4.84141987e-09]]))
-        assert_almost_equal(o_table, array([[ 0.78767123, 0.45637584, 0.22,
-            0.39597315, 0.41610738, 0.20945946, 0.70068027, 0.89932886,
-            0.77333333], [0.14383562, 0.27516779, 0.65333333, 0.52348993,
-            0.38926174, 0.69594595, 0.28571429, 0.0738255, 0.19333333],
-            [0.03424658, 0.16107383, 0.02666667, 0.00671141, 0.14765101,
-            0.01351351, 0., 0.01342282, 0.00666667], [0.02739726, 0.04697987,
-            0.02, 0.04697987, 0.01, 0.02027027, 0.01360544, 0.01342282,
-            0.02666667], [ 0., 0.02013423, 0.03333333, 0.01342282, 0.,
-            0.0472973, 0., 0., 0.], [ 0. , 0.02013423, 0.01333333, 0.00671141,
-            0.03355705, 0.00675676, 0., 0., 0.], [ 0.00684932, 0.02013423,
-            0.02, 0.00671141, 0., 0.00675676, 0., 0., 0.], [ 0., 0., 0.01333333,
-            0., 0., 0., 0., 0., 0.]]))
-        self.assertEquals(o_lineages, ['Root;k__Bacteria;p__Firmicutes',
+            self.biplot_coords, self.otu_table,
+            self.lineages, self.prevalence, -1)
+
+        assert_almost_equal(o_coords, array(
+            [[-6.72105326e-02, 1.05941469e-02, -5.27647509e-03,
+              -1.31631384e-02, 3.15560858e-02, -1.99787562e-02,
+              8.15726905e-03, -1.75931839e-02, -4.84141987e-09],
+             [9.65087040e-02, -1.64113801e-02, 1.68583315e-02,
+              1.03732288e-02, -2.25710883e-02, 2.83857611e-02,
+              3.22664795e-05, 2.90430321e-02, -4.84141987e-09],
+             [-9.09430630e-04, 1.16559691e-02, -4.98101864e-02,
+              4.52278787e-02, -1.29332576e-01, -2.14449952e-02,
+              -6.93407020e-02, -6.25343327e-02, -4.84141987e-09],
+             [-5.20990488e-02, -1.08550868e-02, 1.18513950e-03,
+              -1.95647012e-02, -4.37589802e-02, 8.48245309e-04,
+              -1.22035464e-02, 2.88287965e-02, -4.84141987e-09],
+             [1.26316230e-01, 2.63889076e-02, 3.30227792e-02,
+              8.85396608e-02, -3.72547601e-02, 6.38622449e-02,
+             -2.24927101e-02, 9.02626098e-02, -4.84141987e-09],
+             [1.18424098e-01, -1.97525147e-03, -3.99274160e-02,
+              2.11233039e-02, -1.24633799e-01, 1.33749786e-02,
+             -3.84382665e-02, -5.84384149e-02, -4.84141987e-09],
+             [-4.06501717e-03, -3.00693128e-02, -9.03169744e-02,
+              5.59730983e-02, -5.97265945e-02, 4.56519003e-02,
+              -5.41422919e-02, 6.68355274e-02, -4.84141987e-09],
+             [2.28820400e-01, -1.30142097e-01, -2.87149448e-01,
+              8.64498846e-02, 4.42951919e-02, 2.06042607e-01,
+              3.10003571e-02, 7.19920437e-02, -4.84141987e-09]]))
+        assert_almost_equal(o_table, array(
+            [[0.78767123, 0.45637584, 0.22,
+              0.39597315, 0.41610738, 0.20945946,
+              0.70068027, 0.89932886, 0.77333333],
+             [0.14383562, 0.27516779, 0.65333333, 0.52348993,
+              0.38926174, 0.69594595, 0.28571429,
+             0.0738255, 0.19333333],
+             [0.03424658, 0.16107383, 0.02666667, 0.00671141,
+              0.14765101, 0.01351351, 0., 0.01342282, 0.00666667],
+             [0.02739726, 0.04697987, 0.02, 0.04697987, 0.01,
+              0.02027027, 0.01360544, 0.01342282, 0.02666667],
+             [0., 0.02013423, 0.03333333, 0.01342282, 0.,
+              0.0472973, 0., 0., 0.],
+             [0., 0.02013423, 0.01333333, 0.00671141,
+              0.03355705, 0.00675676, 0., 0., 0.],
+             [0.00684932, 0.02013423, 0.02, 0.00671141,
+              0., 0.00675676, 0., 0., 0.],
+             [0., 0., 0.01333333, 0., 0., 0., 0., 0., 0.]]))
+
+        self.assertEqual(o_lineages, [
+            'Root;k__Bacteria;p__Firmicutes',
             'Root;k__Bacteria;p__Bacteroidetes',
             'Root;k__Bacteria;p__Tenericutes', 'Root;k__Bacteria;Other',
             'Root;k__Bacteria;p__Deferribacteres',
             'Root;k__Bacteria;p__Proteobacteria',
-            'Root;k__Bacteria;p__Actinobacteria','Root;k__Bacteria;p__TM7'])
-        assert_almost_equal(o_prevalence, array([ 1., 0.6646394, 0.08185147,
-            0.04445514, 0.02081361, 0.01385989, 0.00972396, 0.]))
+            'Root;k__Bacteria;p__Actinobacteria',
+            'Root;k__Bacteria;p__TM7'])
+        assert_almost_equal(o_prevalence,
+                            array([1., 0.6646394, 0.08185147,
+                                   0.04445514, 0.02081361,
+                                   0.01385989, 0.00972396, 0.]))
 
     def test_preprocess_otu_table(self):
         """Check the coords and otu table are processed correctly"""
@@ -156,88 +192,172 @@ class TopLevelTests(TestCase):
         # processing only the four most prevalent taxa
         o_otu_coords, o_otu_table, o_otu_lineages, o_prevalence, lines =\
             preprocess_otu_table(self.otu_sample_ids, self.otu_table,
-                self.lineages, self.coords, self.coords_header, 4)
-
-        assert_almost_equal(o_otu_coords, array([[ -6.71083200e-02,
-            1.05892642e-02, -5.26801821e-03, -1.31730322e-02, 3.15036935e-02,
-            -1.99712144e-02, 8.14445313e-03, -1.76632227e-02, -4.84141987e-09],
-            [ 9.65846961e-02, -1.64070839e-02, 1.68610695e-02, 1.03495979e-02,
-            -2.26223522e-02, 2.83763737e-02, 1.76116225e-05, 2.89253284e-02,
-            -4.84141987e-09], [-5.61881305e-04, 1.16341355e-02, -4.97196330e-02,
-            4.51141625e-02, -1.29353935e-01, -2.14114921e-02, -6.92988035e-02,
-            -6.27730937e-02, -4.84141987e-09], [-5.70985165e-02,
-            -1.09278921e-02, 8.49830390e-04, -1.91550282e-02, -4.22122952e-02,
-            7.75750297e-04, -1.18543093e-02, 3.31082777e-02, -4.84141987e-09]]))
-        assert_almost_equal(o_otu_table, array([[ 0.78767123, 0.45637584, 0.22,
-            0.39597315, 0.41610738, 0.20945946, 0.70068027, 0.89932886,
-            0.77333333], [0.14383562, 0.27516779, 0.65333333, 0.52348993,
-            0.38926174, 0.69594595, 0.28571429, 0.0738255, 0.19333333], [
-            0.03424658, 0.16107383, 0.02666667, 0.00671141, 0.14765101,
-            0.01351351, 0., 0.01342282, 0.00666667], [0.02739726, 0.04697987,
-            0.02, 0.04697987, 0.01, 0.02027027, 0.01360544, 0.01342282,
-            0.02666667]]))
-        self.assertEquals(o_otu_lineages, ['Root;k__Bacteria;p__Firmicutes',
-            'Root;k__Bacteria;p__Bacteroidetes',
-            'Root;k__Bacteria;p__Tenericutes', 'Root;k__Bacteria;Other'])
-        assert_almost_equal(o_prevalence, array([ 1., 0.66471926, 0.08193196,
-            0.04374296]))
-        self.assertEquals(lines, LINES)
+                                 self.lineages, self.coords,
+                                 self.coords_header, 4)
+
+        assert_almost_equal(o_otu_coords,
+                            array([[-6.71083200e-02, 1.05892642e-02,
+                                    -5.26801821e-03, -1.31730322e-02,
+                                    3.15036935e-02, -1.99712144e-02,
+                                    8.14445313e-03, -1.76632227e-02,
+                                    -4.84141987e-09],
+                                   [9.65846961e-02, -1.64070839e-02,
+                                    1.68610695e-02, 1.03495979e-02,
+                                    -2.26223522e-02, 2.83763737e-02,
+                                    1.76116225e-05, 2.89253284e-02,
+                                   -4.84141987e-09],
+                                   [-5.61881305e-04, 1.16341355e-02,
+                                    -4.97196330e-02, 4.51141625e-02,
+                                    -1.29353935e-01, -2.14114921e-02,
+                                    -6.92988035e-02, -6.27730937e-02,
+                                   -4.84141987e-09],
+                                   [-5.70985165e-02, -1.09278921e-02,
+                                    8.49830390e-04, -1.91550282e-02,
+                                    -4.22122952e-02, 7.75750297e-04,
+                                   -1.18543093e-02, 3.31082777e-02,
+                                   -4.84141987e-09]]))
+        assert_almost_equal(o_otu_table,
+                            array([[0.78767123, 0.45637584, 0.22, 0.39597315,
+                                    0.41610738, 0.20945946, 0.70068027,
+                                    0.89932886, 0.77333333],
+                                   [0.14383562, 0.27516779, 0.65333333,
+                                    0.52348993, 0.38926174, 0.69594595,
+                                    0.28571429, 0.0738255, 0.19333333],
+                                   [0.03424658, 0.16107383, 0.02666667,
+                                    0.00671141, 0.14765101, 0.01351351,
+                                    0., 0.01342282, 0.00666667],
+                                   [0.02739726, 0.04697987, 0.02, 0.04697987,
+                                    0.01, 0.02027027, 0.01360544, 0.01342282,
+                                    0.02666667]]))
+        self.assertEqual(o_otu_lineages,
+                         ['Root;k__Bacteria;p__Firmicutes',
+                          'Root;k__Bacteria;p__Bacteroidetes',
+                          'Root;k__Bacteria;p__Tenericutes',
+                          'Root;k__Bacteria;Other'])
+        assert_almost_equal(o_prevalence,
+                            array([1., 0.66471926, 0.08193196, 0.04374296]))
+        self.assertEqual(lines, LINES)
 
         # tests for correct outputs of empty inputs
         o_otu_coords, o_otu_table, o_otu_lineages, o_prevalence, lines =\
-            preprocess_otu_table([],[], [], self.coords, self.coords_header, 4)
-        self.assertEquals(o_otu_coords, [])
-        self.assertEquals(o_otu_table, [])
-        self.assertEquals(o_otu_lineages, [])
-        self.assertEquals(o_prevalence, [])
-        self.assertEquals(lines, '')
+            preprocess_otu_table([], [], [], self.coords,
+                                 self.coords_header, 4)
+        self.assertEqual(o_otu_coords, [])
+        self.assertEqual(o_otu_table, [])
+        self.assertEqual(o_otu_lineages, [])
+        self.assertEqual(o_prevalence, [])
+        self.assertEqual(lines, '')
 
     def test_preprocess_otu_table_exceptions(self):
         """Check the exceptions are raised appropriately"""
         # should raise an exception because the inputs contain a single row
         with self.assertRaises(EmperorUnsupportedComputation):
             o_otu_coords, o_otu_table, o_otu_lineages, o_prevalence, lines =\
-                preprocess_otu_table(self.otu_sample_ids, self.otu_table_broken,
-                self.lineages_broken, self.coords, self.coords_header, 4)
+                preprocess_otu_table(self.otu_sample_ids,
+                                     self.otu_table_broken,
+                                     self.lineages_broken,
+                                     self.coords, self.coords_header, 4)
 
         # some inputs are completely wrong but should still fail because the
         # contingency table has one row only, hence scores cannot be computed
         with self.assertRaises(EmperorUnsupportedComputation):
             o_otu_coords, o_otu_table, o_otu_lineages, o_prevalence, lines =\
-                preprocess_otu_table(self.otu_sample_ids, self.otu_table_broken,
-                [[]], self.coords, self.coords_header, 4)
+                preprocess_otu_table(
+                    self.otu_sample_ids, self.otu_table_broken,
+                    [[]], self.coords, self.coords_header, 4)
         with self.assertRaises(EmperorUnsupportedComputation):
             o_otu_coords, o_otu_table, o_otu_lineages, o_prevalence, lines =\
-                preprocess_otu_table(self.otu_sample_ids, array([]),
-                self.lineages_broken, self.coords, self.coords_header, 4)
-
-
-OTU_TABLE = """Taxon\tPC.636\tPC.635\tPC.356\tPC.481\tPC.354\tPC.593\tPC.355\tPC.607\tPC.634
-Root;k__Bacteria;Other\t0.0202702702703\t0.0469798657718\t0.0266666666667\t0.027397260274\t0.0134228187919\t0.0134228187919\t0.0136054421769\t0.0469798657718\t0.02
-Root;k__Bacteria;p__Actinobacteria\t0.00675675675676\t0.00671140939597\t0.0\t0.00684931506849\t0.0\t0.0\t0.0\t0.0201342281879\t0.02
-Root;k__Bacteria;p__Bacteroidetes\t0.695945945946\t0.523489932886\t0.193333333333\t0.143835616438\t0.0738255033557\t0.389261744966\t0.285714285714\t0.275167785235\t0.653333333333
-Root;k__Bacteria;p__Deferribacteres\t0.0472972972973\t0.0134228187919\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0201342281879\t0.0333333333333
-Root;k__Bacteria;p__Firmicutes\t0.209459459459\t0.395973154362\t0.773333333333\t0.787671232877\t0.89932885906\t0.41610738255\t0.700680272109\t0.456375838926\t0.22
-Root;k__Bacteria;p__Proteobacteria\t0.00675675675676\t0.00671140939597\t0.0\t0.0\t0.0\t0.0335570469799\t0.0\t0.0201342281879\t0.0133333333333
-Root;k__Bacteria;p__TM7\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0\t0.0133333333333
-Root;k__Bacteria;p__Tenericutes\t0.0135135135135\t0.00671140939597\t0.00666666666667\t0.0342465753425\t0.0134228187919\t0.147651006711\t0.0\t0.161073825503\t0.0266666666667
-"""
-
-COORDS = array([[-0.276542163845, -0.144964375408, 0.0666467344429, -0.0677109454288, 0.176070269506, 0.072969390136, -0.229889463523, -0.0465989416581, -4.84141986706e-09],
-[-0.237661393984, 0.0460527772512, -0.138135814766, 0.159061025229, -0.247484698646, -0.115211468101, -0.112864033263, 0.0647940729676, -4.84141986706e-09],
-[0.228820399536, -0.130142097093, -0.287149447883, 0.0864498846421, 0.0442951919304, 0.20604260722, 0.0310003571386, 0.0719920436501, -4.84141986706e-09],
-[0.0422628480532, -0.0139681511889, 0.0635314615517, -0.346120552134, -0.127813807608, 0.0139350721063, 0.0300206887328, 0.140147849223, -4.84141986706e-09],
-[0.280399117569, -0.0060128286014, 0.0234854344148, -0.0468109474823, -0.146624450094, 0.00566979124596, -0.0354299634191, -0.255785794275, -4.84141986706e-09],
-[0.232872767451, 0.139788385269, 0.322871079774, 0.18334700682, 0.0204661596818, 0.0540589147147, -0.0366250872041, 0.0998235721267, -4.84141986706e-09],
-[0.170517581885, -0.194113268955, -0.0308965283066, 0.0198086158783, 0.155100062794, -0.279923941712, 0.0576092515759, 0.0242481862127, -4.84141986706e-09],
-[-0.0913299284215, 0.424147148265, -0.135627421345, -0.057519480907, 0.151363490722, -0.0253935675552, 0.0517306152066, -0.038738217609, -4.84141986706e-09],
-[-0.349339228244, -0.120787589539, 0.115274502117, 0.0694953933826, -0.0253722182853, 0.067853201946, 0.244447634756, -0.0598827706386, -4.84141986706e-09]])
-
-LINES = """#Taxon\tpc0\tpc1\tpc2\tpc3\tpc4\tpc5\tpc6\tpc7\tpc8
-Root;k__Bacteria;p__Firmicutes\t-0.0671083199539\t0.010589264186\t-0.00526801821358\t-0.0131730321859\t0.0315036934893\t-0.0199712144464\t0.00814445312587\t-0.0176632227289\t-4.84141986706e-09
-Root;k__Bacteria;p__Bacteroidetes\t0.0965846961434\t-0.0164070839162\t0.0168610695358\t0.010349597944\t-0.0226223521782\t0.0283763736987\t1.76116225444e-05\t0.0289253284365\t-4.84141986706e-09
-Root;k__Bacteria;p__Tenericutes\t-0.000561881304886\t0.0116341354761\t-0.0497196329856\t0.0451141625418\t-0.129353934943\t-0.0214114921223\t-0.0692988035087\t-0.0627730937042\t-4.84141986706e-09
-Root;k__Bacteria;Other\t-0.0570985164756\t-0.0109278921351\t0.00084983039019\t-0.0191550282339\t-0.0422122952074\t0.000775750296682\t-0.0118543093074\t0.0331082776958\t-4.84141986706e-09"""
+                preprocess_otu_table(
+                    self.otu_sample_ids, array([]),
+                    self.lineages_broken, self.coords,
+                    self.coords_header, 4)
+
+OTU_TABLE = ''.join([
+    '\t'.join(['Taxon', 'PC.636', 'PC.635',
+               'PC.356', 'PC.481', 'PC.354',
+               'PC.593', 'PC.355', 'PC.607', 'PC.634']),
+    '\t'.join(['Root;k__Bacteria;Other', '0.0202702702703',
+               '0.0469798657718', '0.0266666666667',
+               '0.027397260274', '0.0134228187919',
+               '0.0134228187919', '0.0136054421769',
+              '0.0469798657718', '0.02']),
+    '\t'.join(['Root;k__Bacteria;p__Actinobacteria',
+               '0.00675675675676', '0.00671140939597',
+               '0.0', '0.00684931506849', '0.0', '0.0', '0.0',
+              '0.0201342281879', '0.02']),
+    '\t'.join(['Root;k__Bacteria;p__Bacteroidetes',
+               '0.695945945946',  '0.523489932886',
+               '0.193333333333',  '0.143835616438',
+               '0.0738255033557',  '0.389261744966',
+               '0.285714285714',  '0.275167785235',  '0.653333333333']),
+    '\t'.join(['Root;k__Bacteria;p__Deferribacteres',
+               '0.0472972972973', '0.0134228187919', '0.0',
+               '0.0', '0.0', '0.0', '0.0', '0.0201342281879',
+               '0.0333333333333']),
+    '\t'.join(['Root;k__Bacteria;p__Firmicutes', '0.209459459459',
+               '0.395973154362', '0.773333333333', '0.787671232877',
+               '0.89932885906', '0.41610738255', '0.700680272109',
+               '0.456375838926', '0.22']),
+    '\t'.join(['Root;k__Bacteria;p__Proteobacteria', '0.00675675675676',
+               '0.00671140939597', '0.0', '0.0', '0.0', '0.0335570469799',
+               '0.0', '0.0201342281879', '0.0133333333333']),
+    '\t'.join(['Root;k__Bacteria;p__TM7', '0.0', '0.0', '0.0', '0.0',
+               '0.0', '0.0', '0.0', '0.0', '0.0133333333333']),
+    '\t'.join(['Root;k__Bacteria;p__Tenericutes', '0.0135135135135',
+               '0.00671140939597', '0.00666666666667', '0.0342465753425',
+               '0.0134228187919', '0.147651006711', '0.0',
+               '0.161073825503', '0.0266666666667'])])
+
+
+COORDS = array([[-0.276542163845, -0.144964375408, 0.0666467344429,
+                 -0.0677109454288, 0.176070269506, 0.072969390136,
+                 -0.229889463523, -0.0465989416581, -4.84141986706e-09],
+                [-0.237661393984, 0.0460527772512, -0.138135814766,
+                 0.159061025229, -0.247484698646, -0.115211468101,
+                 -0.112864033263, 0.0647940729676, -4.84141986706e-09],
+                [0.228820399536, -0.130142097093, -0.287149447883,
+                 0.0864498846421, 0.0442951919304, 0.20604260722,
+                 0.0310003571386, 0.0719920436501, -4.84141986706e-09],
+                [0.0422628480532, -0.0139681511889, 0.0635314615517,
+                 -0.346120552134, -0.127813807608, 0.0139350721063,
+                 0.0300206887328, 0.140147849223, -4.84141986706e-09],
+                [0.280399117569, -0.0060128286014, 0.0234854344148,
+                 -0.0468109474823, -0.146624450094, 0.00566979124596,
+                 -0.0354299634191, -0.255785794275, -4.84141986706e-09],
+                [0.232872767451, 0.139788385269, 0.322871079774,
+                 0.18334700682, 0.0204661596818, 0.0540589147147,
+                 -0.0366250872041, 0.0998235721267, -4.84141986706e-09],
+                [0.170517581885, -0.194113268955, -0.0308965283066,
+                 0.0198086158783, 0.155100062794, -0.279923941712,
+                 0.0576092515759, 0.0242481862127, -4.84141986706e-09],
+                [-0.0913299284215, 0.424147148265, -0.135627421345,
+                 -0.057519480907, 0.151363490722, -0.0253935675552,
+                 0.0517306152066, -0.038738217609, -4.84141986706e-09],
+                [-0.349339228244, -0.120787589539, 0.115274502117,
+                 0.0694953933826, -0.0253722182853, 0.067853201946,
+                 0.244447634756, -0.0598827706386, -4.84141986706e-09]])
+
+LINES = '\n'.join([
+    '\t'.join(['#Taxon', 'pc1', 'pc2', 'pc3', 'pc4',
+               'pc5', 'pc6', 'pc7', 'pc8', 'pc9']),
+    '\t'.join(['Root;k__Bacteria;p__Firmicutes', '-0.0671083199539',
+               '0.010589264186', '-0.00526801821358',
+               '-0.0131730321859', '0.0315036934893',
+               '-0.0199712144464', '0.00814445312587',
+               '-0.0176632227289', '-4.84141986706e-09']),
+    '\t'.join(['Root;k__Bacteria;p__Bacteroidetes', '0.0965846961434',
+               '-0.0164070839162', '0.0168610695358',
+               '0.010349597944', '-0.0226223521782',
+               '0.0283763736987', '1.76116225444e-05',
+               '0.0289253284365', '-4.84141986706e-09']),
+    '\t'.join(['Root;k__Bacteria;p__Tenericutes', '-0.000561881304886',
+               '0.0116341354761', '-0.0497196329856', '0.0451141625418',
+               '-0.129353934943', '-0.0214114921223', '-0.0692988035087',
+               '-0.0627730937042', '-4.84141986706e-09']),
+    '\t'.join(['Root;k__Bacteria;Other', '-0.0570985164756',
+               '-0.0109278921351', '0.00084983039019', '-0.0191550282339',
+               '-0.0422122952074', '0.000775750296682', '-0.0118543093074',
+               '0.0331082776958', '-4.84141986706e-09'])])
 
 if __name__ == "__main__":
     main()
diff --git a/tests/test_filter.py b/tests/test_filter.py
old mode 100755
new mode 100644
index c3179c7..020fa93
--- a/tests/test_filter.py
+++ b/tests/test_filter.py
@@ -1,84 +1,106 @@
-#!/usr/bin/env python
-# File created on 12 May 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
 from numpy import array
 from emperor.filter import (filter_samples_from_coords,
-    keep_samples_from_pcoa_data)
+                            keep_samples_from_pcoa_data)
 from unittest import TestCase, main
 from numpy.testing import assert_almost_equal
 
+
 class TopLevelTests(TestCase):
-    
+
     def setUp(self):
         self.jk_coords_header = [['1', '2', '3'], ['1', '2', '3'],
-            ['1', '2', '3'], ['1', '2', '3']]
-        self.jk_coords_data = [array([[1.2, 0.1, -1.2],[-2.5, -4.0, 4.5],
-            [0.11, 5.33,-0.23]]),array([[-1.4, 0.05, 1.3],[2.6, 4.1, -4.7],
-            [0.14, 2.00, -1.11]]),array([[-1.5, 0.05, 1.6],[2.4, 4.0, -4.8],
-            [1.0, -0.8, 0.01]]),array([[-1.5, 0.05, 1.6],[2.4, 4.0, -4.8],
-            [2, 0, 1.11111]])]
+                                 ['1', '2', '3'], ['1', '2', '3']]
+        self.jk_coords_data = [array([[1.2, 0.1, -1.2], [-2.5, -4.0, 4.5],
+                                      [0.11, 5.33, -0.23]]),
+                               array([[-1.4, 0.05, 1.3], [2.6, 4.1, -4.7],
+                                      [0.14, 2.00, -1.11]]),
+                               array([[-1.5, 0.05, 1.6], [2.4, 4.0, -4.8],
+                                      [1.0, -0.8, 0.01]]),
+                               array([[-1.5, 0.05, 1.6], [2.4, 4.0, -4.8],
+                                      [2, 0, 1.11111]])]
 
         self.coords_header = ['PC.355', 'PC.635', 'PC.636', 'PC.354']
         self.coords_data = COORDS_DATA
 
-    def test_filter_Samples_from_coords(self):
+    def test_filter_samples_from_coords(self):
         """Check it filters samples from coords data as requested"""
         # check the function raises an exception on an empty set
         self.assertRaises(ValueError, filter_samples_from_coords,
-            self.coords_header, self.coords_data, ['foo','bar', 'PC.666'])
+                          self.coords_header, self.coords_data,
+                          ['foo', 'bar', 'PC.666'])
 
         # check it keeps the requested samples
-        out_headers, out_coords = filter_samples_from_coords(self.coords_header,
-            self.coords_data, ['PC.636', 'PC.355'])
-        self.assertEquals(out_headers, ['PC.355', 'PC.636'])
+        out_headers, out_coords = \
+            filter_samples_from_coords(self.coords_header,
+                                       self.coords_data,
+                                       ['PC.636', 'PC.355'])
+        self.assertEqual(out_headers, ['PC.355', 'PC.636'])
         assert_almost_equal(out_coords, array([[-0.2, -0.1, 0.06, -0.06],
-            [0.1, -0.1, -0.2, 0.08]]))
+                                               [0.1, -0.1, -0.2, 0.08]]))
 
         # check it removes the requested samples
-        out_headers, out_coords = filter_samples_from_coords(self.coords_header,
-            self.coords_data, ['PC.636', 'PC.355'], negate=True)
-        self.assertEquals(out_headers, ['PC.635', 'PC.354'])
+        out_headers, out_coords = \
+            filter_samples_from_coords(self.coords_header,
+                                       self.coords_data,
+                                       ['PC.636', 'PC.355'],
+                                       negate=True)
+
+        self.assertEqual(out_headers, ['PC.635', 'PC.354'])
         assert_almost_equal(out_coords, array([[-0.3, 0.04, -0.1, 0.15],
-            [0.04, -0.01, 0.06, -0.34]]))
+                                               [0.04, -0.01, 0.06, -0.34]]))
 
     def test_remove_samples_from_pcoa_data(self):
         """ """
         # check it keeps the requested samples
         out_headers, out_coords = keep_samples_from_pcoa_data(
             self.coords_header, self.coords_data, ['PC.636', 'PC.355'])
-        self.assertEquals(out_headers, ['PC.355', 'PC.636'])
+        self.assertEqual(out_headers, ['PC.355', 'PC.636'])
         assert_almost_equal(out_coords, array([[-0.2, -0.1, 0.06, -0.06],
-            [0.1, -0.1, -0.2, 0.08]]))
+                                               [0.1, -0.1, -0.2, 0.08]]))
 
-        # check it keeps the requested samples when the input is jackknifed data
-        out_headers, out_coords = keep_samples_from_pcoa_data(
-            self.jk_coords_header, self.jk_coords_data, ['1', '3'])
-        self.assertEqual(out_headers, [['1', '3'], ['1', '3'], ['1', '3'], ['1',
-            '3']])
-        assert_almost_equal(out_coords,[array([[1.2, 0.1, -1.2],
-            [0.11, 5.33,-0.23]]),array([[-1.4, 0.05, 1.3],[0.14, 2.00, -1.11]]),
-            array([[-1.5, 0.05, 1.6],[1.0, -0.8, 0.01]]),array([
-            [-1.5, 0.05, 1.6],[2, 0, 1.11111]])])
+        # check it keeps the requested samples when the input is jackknifed
+        # data
+        out_headers, out_coords = \
+            keep_samples_from_pcoa_data(self.jk_coords_header,
+                                        self.jk_coords_data,
+                                        ['1', '3'])
+        self.assertEqual(out_headers,
+                         [['1', '3'],
+                          ['1', '3'],
+                          ['1', '3'],
+                          ['1', '3']])
+
+        assert_almost_equal(out_coords, [array([[1.2, 0.1, -1.2],
+                                                [0.11, 5.33, -0.23]]),
+                                         array([[-1.4, 0.05, 1.3],
+                                                [0.14, 2.00, -1.11]]),
+                                         array([[-1.5, 0.05, 1.6],
+                                                [1.0, -0.8, 0.01]]),
+                                         array([[-1.5, 0.05, 1.6],
+                                                [2, 0, 1.11111]])])
 
         # flip the order of the samples to keep
         out_headers, out_coords = keep_samples_from_pcoa_data(
             self.jk_coords_header, self.jk_coords_data, ['3', '1'])
-        self.assertEqual(out_headers, [['1', '3'], ['1', '3'], ['1', '3'], ['1',
-            '3']])
-        assert_almost_equal(out_coords,[array([[1.2, 0.1, -1.2],
-            [0.11, 5.33,-0.23]]),array([[-1.4, 0.05, 1.3],[0.14, 2.00, -1.11]]),
-            array([[-1.5, 0.05, 1.6],[1.0, -0.8, 0.01]]),array([
-            [-1.5, 0.05, 1.6],[2, 0, 1.11111]])])
+        self.assertEqual(out_headers, [['1', '3'], ['1', '3'],
+                                       ['1', '3'], ['1', '3']])
+        assert_almost_equal(out_coords, [array([[1.2, 0.1, -1.2],
+                                                [0.11, 5.33, -0.23]]),
+                                         array([[-1.4, 0.05, 1.3],
+                                                [0.14, 2.00, -1.11]]),
+                                         array([[-1.5, 0.05, 1.6],
+                                                [1.0, -0.8, 0.01]]),
+                                         array([[-1.5, 0.05, 1.6],
+                                                [2, 0, 1.11111]])])
 
 
 COORDS_DATA = array([
diff --git a/tests/test_format.py b/tests/test_format.py
old mode 100755
new mode 100644
index 5512a46..b1525bd
--- a/tests/test_format.py
+++ b/tests/test_format.py
@@ -1,244 +1,23 @@
-#!/usr/bin/env python
-# File created on 25 Jan 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
-
-from numpy import array
-from emperor.format import (format_pcoa_to_js, format_mapping_file_to_js,
-    format_taxa_to_js, format_vectors_to_js, format_emperor_html_footer_string,
-    EmperorLogicError, format_comparison_bars_to_js, format_emperor_autograph)
+from emperor.format import format_emperor_autograph
 from unittest import TestCase, main
 
-class TopLevelTests(TestCase):
-
-    def setUp(self):
-        self.pcoa_pct_var = array([2.66887049e+01, 1.62563704e+01,
-            1.37754129e+01, 1.12172158e+01, 1.00247750e+01, 8.22835130e+00,
-            7.55971174e+00, 6.24945796e+00, 1.17437419e-14])
-        self.pcoa_pct_var_really_low = array([2.66887049e+01, 1.62563704e+01,
-            0.1, 0.2, 0.19, 0.18, 0.17, 0.16, 0.15])
-        self.pcoa_headers = ['PC.355','PC.607','PC.634','PC.635','PC.593',
-            'PC.636','PC.481','PC.354','PC.356']
-        self.pcoa_coords = PCOA_DATA
-        self.pcoa_eigen_values = array([4.79412119e-01, 2.92014956e-01,
-            2.47449246e-01, 2.01496072e-01, 1.80076128e-01, 1.47806773e-01,
-            1.35795927e-01, 1.12259696e-01, 2.10954117e-16])
-
-        # data specific for testing the jackknifing
-        self.pcoa_jk_headers = ['PC.355','PC.607','PC.634','PC.635']
-        self.pcoa_jk_coords = array([[0.3, 0.5, 0.1, 0.3],[1.1, 1.1, 1.0, 0.8],
-            [0.1, 3.3, 5.5, 0.1], [1.0, 2.0, 1.0, 1.0]])
-        self.pcoa_jk_eigen_values = array([0.45, 0.32, 0.21, 0.02])
-        self.pcoa_jk_pct_var = array([44, 40, 15, 1])
-        self.pcoa_jk_coords_low = array([[0.2, 0.3, 0.1, 0.3],[1.1, 0.1, 0.0, 0.3],
-            [0.6, 3.1, 1.5, 0.1], [0.023, 1.0, 0.01, 1.0]])
-        self.pcoa_jk_coords_high = array([[0.6, 0.8, 0.9, 0.31],[1, 2.1, 0.0, 0.8],
-            [0.9, 3.7, 5.5, 0.1111], [0.01222, 2.0, 0.033, 2.0]])
-
-        self.mapping_file_data = MAPPING_FILE_DATA
-        self.mapping_file_headers = ['SampleID', 'BarcodeSequence',
-            'LinkerPrimerSequence', 'Treatment', 'DOB', 'Description']
-        self.good_columns = ['Treatment', 'LinkerPrimerSequence']
-
-        self.otu_coords = array([[2.80399118e-01, -6.01282860e-03,
-            2.34854344e-02, -4.68109475e-02, -1.46624450e-01, 5.66979125e-03,
-            -3.54299634e-02, -2.55785794e-01, -4.84141987e-09], [2.28820400e-01,
-            -1.30142097e-01, -2.87149448e-01, 8.64498846e-02, 4.42951919e-02,
-            2.06042607e-01, 3.10003571e-02, 7.19920437e-02, -4.84141987e-09],
-            [-9.13299284e-02, 4.24147148e-01, -1.35627421e-01, -5.75194809e-02,
-            1.51363491e-01, -2.53935676e-02, 5.17306152e-02, -3.87382176e-02,
-            -4.84141987e-09], [-2.76542164e-01, -1.44964375e-01, 6.66467344e-02,
-            -6.77109454e-02, 1.76070270e-01, 7.29693901e-02, -2.29889464e-01,
-            -4.65989417e-02,-4.84141987e-09]])
-        self.lineages = ['Root;k__Bacteria;p__Firmicutes',
-            'Root;k__Bacteria;p__Bacteroidetes',
-            'Root;k__Bacteria;p__Tenericutes', 'Root;k__Bacteria;Other']
-        self.prevalence = array([ 1., 0.66471926, 0.08193196, 0.04374296])
-
-        # comparison test
-        self.comparison_coords_data = array([[-0.0677, -2.036, 0.2726, 1.051,
-            -0.180, -0.698], [-1.782, -0.972, 0.1582, -1.091, 0.531, 0.292],
-            [-0.659, -0.2566, 0.514, -2.698, -0.393, 0.420], [-1.179, -0.968,
-            2.525, 0.53, -0.529, 0.632],[-0.896, -1.765, 0.274, -0.3235, 0.4009,
-            -0.03497], [-0.0923, 1.414, -0.622, 0.298, 0.5, -0.4580], [-0.972,
-            0.551, 1.144, 0.3147, -0.476, -0.4279], [1.438, -2.603, -1.39,
-            1.300, -0.1606, 1.260], [-0.356, 0.0875, 0.772, 0.539, -0.586,
-            -1.431], [1.512, -1.239, -0.0365, -0.682, -0.971, 0.356],
-            [1.17, 1.31, -1.407, 1.6, 0.60, 2.26], [2.618, 0.739, -0.01295,
-            -0.937, 3.079, -2.534], [0.2339, -0.880, -1.753, 0.177, 0.3517,
-            -0.743], [0.436, 2.12, -0.935, -0.476, -0.805, 0.4164], [-0.880,
-            1.069, 1.069, -0.596, -0.199, 0.306], [0.294, 0.2988, 0.04670,
-            -0.3865, 0.460, -0.431], [1.640, 0.2485, -0.354, 1.43, 1.226,
-            1.095], [0.821, -1.13, -1.794, -1.171, -1.27, -0.842]])
-        self.comparison_coords_headers = ['sampa_0', 'sampb_0', 'sampc_0',
-            'sampd_0', 'sampe_0', 'sampf_0', 'sampa_1', 'sampb_1', 'sampc_1',
-            'sampd_1', 'sampe_1', 'sampf_1', 'sampa_2', 'sampb_2', 'sampc_2',
-            'sampd_2', 'sampe_2', 'sampf_2']
-        self.comparison_coords_headers_zero = ['sampa0_0', 'sampb0_0', 'sampc0_0',
-            'sampd00_0', 'sampe00_0', 'sampf00_0', 'sampa0_1', 'sampb0_1', 'sampc0_1',
-            'sampd00_1', 'sampe00_1', 'sampf00_1', 'sampa0_2', 'sampb0_2', 'sampc0_2',
-            'sampd00_2', 'sampe00_2', 'sampf00_2']
-
-    def test_format_pcoa_to_js(self):
-        """Test correct formatting of the PCoA file"""
-        # test the case with only points and nothing else
-        out_js_pcoa_string = format_pcoa_to_js(self.pcoa_headers,
-            self.pcoa_coords, self.pcoa_eigen_values, self.pcoa_pct_var)
-        self.assertEquals(out_js_pcoa_string, PCOA_JS)
-
-        # test custom axes and the labels
-        out_js_pcoa_string = format_pcoa_to_js(self.pcoa_headers,
-            self.pcoa_coords, self.pcoa_eigen_values,
-            self.pcoa_pct_var, custom_axes=['Instant'])
-        self.assertEquals(out_js_pcoa_string, PCOA_JS_CUSTOM_AXES)
-
-        # test jackknifed pcoa plots
-        out_js_pcoa_string = format_pcoa_to_js(self.pcoa_jk_headers,
-            self.pcoa_jk_coords, self.pcoa_jk_eigen_values,
-            self.pcoa_jk_pct_var, coords_low=self.pcoa_jk_coords_low,
-            coords_high=self.pcoa_jk_coords_high)
-        self.assertEquals(out_js_pcoa_string, PCOA_JS_JACKKNIFED)
-
-        # check it raises an exception when the variation explained on the
-        # axes is not greater than 0.51 for at least three of them
-        self.assertRaises(EmperorLogicError, format_pcoa_to_js,
-            self.pcoa_headers, self.pcoa_coords, self.pcoa_eigen_values,
-            self.pcoa_pct_var_really_low)
-            
-        # test segments
-        out_js_pcoa_string = format_pcoa_to_js(self.pcoa_jk_headers,
-            self.pcoa_jk_coords, self.pcoa_jk_eigen_values,
-            self.pcoa_jk_pct_var, coords_low=self.pcoa_jk_coords_low,
-            coords_high=self.pcoa_jk_coords_high, number_of_segments=14)
-        self.assertEquals(out_js_pcoa_string, PCOA_JS_SEGMENTS)
-
-
-    def test_format_mapping_file_to_js(self):
-        """Tests correct formatting of the metadata mapping file"""
-        out_js_mapping_file_string = format_mapping_file_to_js(
-            self.mapping_file_data, self.mapping_file_headers, self.good_columns)
-        self.assertEquals(out_js_mapping_file_string, MAPPING_FILE_JS)
-
-    def test_format_taxa_to_js(self):
-        """Tests correct formatting of the taxa"""
-        out_js_taxa_string = format_taxa_to_js(self.otu_coords, self.lineages,
-            self.prevalence)
-        self.assertEquals(out_js_taxa_string, TAXA_JS_STRING)
-
-        # case with empty data
-        out_js_taxa_string = format_taxa_to_js([], [], [])
-        self.assertEquals(out_js_taxa_string, "\nvar g_taxaPositions = "
-            "new Array();\n\n")
-
-    def test_format_vectors_to_js(self):
-        """Tests correct formatting of the vectors from the coords"""
-
-        # test that only the variable declaration gets returned
-        out_js_vector_string = format_vectors_to_js(self.mapping_file_data,
-            self.mapping_file_headers, self.pcoa_coords, self.pcoa_headers,
-            None, None)
-        self.assertEquals(out_js_vector_string, '\nvar g_vectorPositions = new '
-            'Array();\n')
-
-        # vector string without sorting for the coordinates
-        out_js_vector_string = format_vectors_to_js(self.mapping_file_data,
-            self.mapping_file_headers, self.pcoa_coords, self.pcoa_headers,
-            'Treatment', None)
-        self.assertEquals(out_js_vector_string, VECTOR_JS_STRING_NO_SORTING)
-
-        # vector string sorting by the DOB category
-        out_js_vector_string = format_vectors_to_js(self.mapping_file_data,
-            self.mapping_file_headers, self.pcoa_coords, self.pcoa_headers,
-            'Treatment', 'DOB')
-        self.assertEquals(out_js_vector_string, VECTOR_JS_STRING_SORTING)
-
-    def test_format_comparison_bars_to_js(self):
-        """Check the correct strings are created for the two types of inputs"""
-
-        # empty string generation for comparison i. e. no clones
-        out_js_comparison_string = format_comparison_bars_to_js(
-            self.comparison_coords_data, self.comparison_coords_headers, 0,
-            True)
-        self.assertEquals(out_js_comparison_string, '\nvar '
-            'g_comparisonPositions = new Array();\nvar g_isSerialComparisonPlot'
-            ' = true;\n')
-
-        out_js_comparison_string = format_comparison_bars_to_js(
-            self.comparison_coords_data, self.comparison_coords_headers, 3,
-            True)
-        self.assertEquals(out_js_comparison_string, COMPARISON_JS_STRING)
-
-        # empty string generation for comparison i. e. no clones
-        out_js_comparison_string = format_comparison_bars_to_js(
-            self.comparison_coords_data, self.comparison_coords_headers, 0,
-            False)
-        self.assertEquals(out_js_comparison_string, '\nvar '
-            'g_comparisonPositions = new Array();\nvar g_isSerialComparisonPlot'
-            ' = false;\n')
-
-        out_js_comparison_string = format_comparison_bars_to_js(
-            self.comparison_coords_data, self.comparison_coords_headers, 3,
-            False)
-        self.assertEquals(out_js_comparison_string,
-            COMPARISON_JS_STRING_NON_SERIAL)
-            
-        out_js_comparison_string = format_comparison_bars_to_js(
-            self.comparison_coords_data, self.comparison_coords_headers_zero, 3,
-            False)
-        self.assertEquals(out_js_comparison_string, COMPARISON_COORDS_HEADERS_ZERO)         
-
-    def test_format_comparison_bars_to_js_exceptions(self):
-        """Check the correct exceptions are raised for incorrect inputs"""
-
-        # assertion for wrong length in headers
-        self.assertRaises(AssertionError, format_comparison_bars_to_js, [],
-            self.comparison_coords_data, 3)
-
-        # assertion for wrong length in coords data
-        self.assertRaises(AssertionError, format_comparison_bars_to_js,
-            self.comparison_coords_headers, self.comparison_coords_data[1::], 3)
-
-        # assertion for wrong number of clones and elements
-        self.assertRaises(AssertionError, format_comparison_bars_to_js,
-            self.comparison_coords_headers, self.comparison_coords_data, 11)
-
-    def test_format_emperor_html_footer_string(self):
-        """Test correct formatting of the footer string"""
-        # footer for a jackknifed pcoa plot without biplots
-        out_string = format_emperor_html_footer_string(False, True)
-        self.assertEqual(out_string, EXPECTED_FOOTER_A)
-
-        # footer for biplots without jackknifing
-        out_string = format_emperor_html_footer_string(True, False)
-        self.assertEqual(out_string, EXPECTED_FOOTER_B)
-
-        # no biplots nor jackknifing
-        out_string = format_emperor_html_footer_string(False, False)
-        self.assertEqual(out_string, EXPECTED_FOOTER_C)
-
-        #  no biplots no jackknifing but with vectors
-        out_string = format_emperor_html_footer_string(False, False, True)
-        self.assertEqual(out_string, EXPECTED_FOOTER_D)
-
-        # comparison plot
-        out_string = format_emperor_html_footer_string(False, False, False,True)
-        self.assertEqual(out_string, EXPECTED_FOOTER_E)
 
+class TopLevelTests(TestCase):
 
     def test_format_emperor_autograph(self):
         """Test signatures are created correctly for each of language"""
 
         autograph = format_emperor_autograph('mapping_file.txt',
-            'pcoa_unweighted_unifrac.txt')
+                                             'pcoa_unweighted_unifrac.txt')
 
         # check for comment open and comment close
         self.assertTrue('<!--' in autograph)
@@ -250,11 +29,11 @@ class TopLevelTests(TestCase):
         self.assertTrue('HostName:' in autograph)
         self.assertTrue("Command:" in autograph)
         self.assertTrue("Emperor Version: " in autograph)
-        self.assertTrue("QIIME Version: " in autograph)
         self.assertTrue("Command executed on " in autograph)
 
         autograph = format_emperor_autograph('mapping_file.txt',
-            'pcoa_unweighted_unifrac.txt','Python')
+                                             'pcoa_unweighted_unifrac.txt',
+                                             'Python')
         # check for comment open and comment close
         self.assertTrue('"""' in autograph)
         self.assertTrue('"""' in autograph)
@@ -265,11 +44,11 @@ class TopLevelTests(TestCase):
         self.assertTrue('HostName:' in autograph)
         self.assertTrue("Command:" in autograph)
         self.assertTrue("Emperor Version: " in autograph)
-        self.assertTrue("QIIME Version: " in autograph)
         self.assertTrue("Command executed on " in autograph)
 
         autograph = format_emperor_autograph('mapping_file.txt',
-            'pcoa_unweighted_unifrac.txt','C')
+                                             'pcoa_unweighted_unifrac.txt',
+                                             'C')
         # check for comment open and comment close
         self.assertTrue('/*' in autograph)
         self.assertTrue('*/' in autograph)
@@ -280,11 +59,11 @@ class TopLevelTests(TestCase):
         self.assertTrue('HostName:' in autograph)
         self.assertTrue("Command:" in autograph)
         self.assertTrue("Emperor Version: " in autograph)
-        self.assertTrue("QIIME Version: " in autograph)
         self.assertTrue("Command executed on " in autograph)
 
         autograph = format_emperor_autograph('mapping_file.txt',
-            'pcoa_unweighted_unifrac.txt','Bash')
+                                             'pcoa_unweighted_unifrac.txt',
+                                             'Bash')
         # check for comment open and comment close
         self.assertTrue('<<COMMENT' in autograph)
         self.assertTrue('COMMENT' in autograph)
@@ -295,1222 +74,14 @@ class TopLevelTests(TestCase):
         self.assertTrue('HostName:' in autograph)
         self.assertTrue("Command:" in autograph)
         self.assertTrue("Emperor Version: " in autograph)
-        self.assertTrue("QIIME Version: " in autograph)
         self.assertTrue("Command executed on " in autograph)
 
         # haskell and cobol are ... not supported
         self.assertRaises(AssertionError, format_emperor_autograph,
-            'mapping_file.txt', 'pcoa.txt', 'Haskell')
+                          'mapping_file.txt', 'pcoa.txt', 'Haskell')
         self.assertRaises(AssertionError, format_emperor_autograph,
-            'mapping_file.txt', 'pcoa.txt', 'Cobol')
-        
-
-PCOA_DATA = array([[ -1.09166142e-01, 8.77774496e-02, 1.15866606e-02, -6.26863896e-02, 2.31533068e-02, 8.76934639e-02, 1.37400927e-03, -1.35496063e-05, 1.29849404e-09],
-[6.88959784e-02, -1.66234067e-01, -9.98300962e-02, -2.90522450e-02, 5.05569953e-02, -2.95200038e-03, -3.25863204e-02, -2.17218431e-02, 1.29849404e-09],
-[2.04684540e-01, 1.28911236e-01, -2.93614192e-02, 1.07657904e-01, 1.78480761e-02, 7.97778676e-03, -2.92003235e-02, -1.23468947e-03, 1.29849404e-09],
-[1.26131510e-01, -2.66030272e-03, -1.41717093e-01, -9.71089687e-03, -6.94272590e-02, 3.67235068e-03, 4.29867599e-02, 6.44276242e-03, 1.29849404e-09],
-[9.68466168e-02, -1.59388265e-01, 1.35271607e-01, 5.12015857e-02, -2.02552984e-02, 3.07034843e-02, 1.55159338e-02, 1.42426937e-02, 1.29849404e-09],
-[2.81534642e-01, 7.10660196e-02, 9.71542020e-02, -8.06472757e-02, 7.04245456e-03, -4.53133767e-02, 6.55825124e-03, -1.26412251e-02, 1.29849404e-09],
-[-1.92382819e-01, 1.47832029e-02, -1.47871039e-02, 1.90888050e-02, 7.26409669e-02, -3.73008815e-02, 3.94304860e-02, 3.25351917e-02, 1.29849404e-09],
-[-2.93353176e-01, 1.83956004e-02, 3.29884266e-02, 3.15360631e-02, -2.86943531e-02, -1.94225139e-02, 8.06272805e-03, -5.58094095e-02, 1.29849404e-09],
-[-1.83191151e-01, 34912621e-03, 8.69481594e-03, -2.73875510e-02, -5.28648893e-02, -2.50583131e-02, -5.21415245e-02, 3.82000689e-02, 1.29849404e-09]])
-
-PCOA_JS = """
-var g_spherePositions = new Array();
-g_spherePositions['PC.355'] = { 'name': 'PC.355', 'color': 0, 'x': -0.109166, 'y': 0.087777, 'z': 0.011587, 'P1': -0.109166, 'P2': 0.087777, 'P3': 0.011587, 'P4': -0.062686, 'P5': 0.023153, 'P6': 0.087693, 'P7': 0.001374, 'P8': -0.000014 };
-g_spherePositions['PC.607'] = { 'name': 'PC.607', 'color': 0, 'x': 0.068896, 'y': -0.166234, 'z': -0.099830, 'P1': 0.068896, 'P2': -0.166234, 'P3': -0.099830, 'P4': -0.029052, 'P5': 0.050557, 'P6': -0.002952, 'P7': -0.032586, 'P8': -0.021722 };
-g_spherePositions['PC.634'] = { 'name': 'PC.634', 'color': 0, 'x': 0.204685, 'y': 0.128911, 'z': -0.029361, 'P1': 0.204685, 'P2': 0.128911, 'P3': -0.029361, 'P4': 0.107658, 'P5': 0.017848, 'P6': 0.007978, 'P7': -0.029200, 'P8': -0.001235 };
-g_spherePositions['PC.635'] = { 'name': 'PC.635', 'color': 0, 'x': 0.126132, 'y': -0.002660, 'z': -0.141717, 'P1': 0.126132, 'P2': -0.002660, 'P3': -0.141717, 'P4': -0.009711, 'P5': -0.069427, 'P6': 0.003672, 'P7': 0.042987, 'P8': 0.006443 };
-g_spherePositions['PC.593'] = { 'name': 'PC.593', 'color': 0, 'x': 0.096847, 'y': -0.159388, 'z': 0.135272, 'P1': 0.096847, 'P2': -0.159388, 'P3': 0.135272, 'P4': 0.051202, 'P5': -0.020255, 'P6': 0.030703, 'P7': 0.015516, 'P8': 0.014243 };
-g_spherePositions['PC.636'] = { 'name': 'PC.636', 'color': 0, 'x': 0.281535, 'y': 0.071066, 'z': 0.097154, 'P1': 0.281535, 'P2': 0.071066, 'P3': 0.097154, 'P4': -0.080647, 'P5': 0.007042, 'P6': -0.045313, 'P7': 0.006558, 'P8': -0.012641 };
-g_spherePositions['PC.481'] = { 'name': 'PC.481', 'color': 0, 'x': -0.192383, 'y': 0.014783, 'z': -0.014787, 'P1': -0.192383, 'P2': 0.014783, 'P3': -0.014787, 'P4': 0.019089, 'P5': 0.072641, 'P6': -0.037301, 'P7': 0.039430, 'P8': 0.032535 };
-g_spherePositions['PC.354'] = { 'name': 'PC.354', 'color': 0, 'x': -0.293353, 'y': 0.018396, 'z': 0.032988, 'P1': -0.293353, 'P2': 0.018396, 'P3': 0.032988, 'P4': 0.031536, 'P5': -0.028694, 'P6': -0.019423, 'P7': 0.008063, 'P8': -0.055809 };
-g_spherePositions['PC.356'] = { 'name': 'PC.356', 'color': 0, 'x': -0.183191, 'y': 34912.621000, 'z': 0.008695, 'P1': -0.183191, 'P2': 34912.621000, 'P3': 0.008695, 'P4': -0.027388, 'P5': -0.052865, 'P6': -0.025058, 'P7': -0.052142, 'P8': 0.038200 };
-
-var g_ellipsesDimensions = new Array();
-var g_segments = 8, g_rings = 8, g_radius = 0.006899;
-var g_xAxisLength = 0.574888;
-var g_yAxisLength = 34912.787234;
-var g_zAxisLength = 0.276989;
-var g_xMaximumValue = 0.281535;
-var g_yMaximumValue = 34912.621000;
-var g_zMaximumValue = 0.135272;
-var g_xMinimumValue = -0.293353;
-var g_yMinimumValue = -0.166234;
-var g_zMinimumValue = -0.141717;
-var g_maximum = 34912.621000;
-var g_pc1Label = "PC1 (27 %)";
-var g_pc2Label = "PC2 (16 %)";
-var g_pc3Label = "PC3 (14 %)";
-var g_number_of_custom_axes = 0;
-var g_fractionExplained = [0.266887, 0.162564, 0.137754, 0.112172, 0.100248, 0.082284, 0.075597, 0.062495];
-var g_fractionExplainedRounded = [27, 16, 14, 11, 10, 8, 8, 6];
-"""
-
-PCOA_JS_CUSTOM_AXES = """
-var g_spherePositions = new Array();
-g_spherePositions['PC.355'] = { 'name': 'PC.355', 'color': 0, 'x': -0.109166, 'y': 0.087777, 'z': 0.011587, 'P1': -0.109166, 'P2': 0.087777, 'P3': 0.011587, 'P4': -0.062686, 'P5': 0.023153, 'P6': 0.087693, 'P7': 0.001374, 'P8': -0.000014 };
-g_spherePositions['PC.607'] = { 'name': 'PC.607', 'color': 0, 'x': 0.068896, 'y': -0.166234, 'z': -0.099830, 'P1': 0.068896, 'P2': -0.166234, 'P3': -0.099830, 'P4': -0.029052, 'P5': 0.050557, 'P6': -0.002952, 'P7': -0.032586, 'P8': -0.021722 };
-g_spherePositions['PC.634'] = { 'name': 'PC.634', 'color': 0, 'x': 0.204685, 'y': 0.128911, 'z': -0.029361, 'P1': 0.204685, 'P2': 0.128911, 'P3': -0.029361, 'P4': 0.107658, 'P5': 0.017848, 'P6': 0.007978, 'P7': -0.029200, 'P8': -0.001235 };
-g_spherePositions['PC.635'] = { 'name': 'PC.635', 'color': 0, 'x': 0.126132, 'y': -0.002660, 'z': -0.141717, 'P1': 0.126132, 'P2': -0.002660, 'P3': -0.141717, 'P4': -0.009711, 'P5': -0.069427, 'P6': 0.003672, 'P7': 0.042987, 'P8': 0.006443 };
-g_spherePositions['PC.593'] = { 'name': 'PC.593', 'color': 0, 'x': 0.096847, 'y': -0.159388, 'z': 0.135272, 'P1': 0.096847, 'P2': -0.159388, 'P3': 0.135272, 'P4': 0.051202, 'P5': -0.020255, 'P6': 0.030703, 'P7': 0.015516, 'P8': 0.014243 };
-g_spherePositions['PC.636'] = { 'name': 'PC.636', 'color': 0, 'x': 0.281535, 'y': 0.071066, 'z': 0.097154, 'P1': 0.281535, 'P2': 0.071066, 'P3': 0.097154, 'P4': -0.080647, 'P5': 0.007042, 'P6': -0.045313, 'P7': 0.006558, 'P8': -0.012641 };
-g_spherePositions['PC.481'] = { 'name': 'PC.481', 'color': 0, 'x': -0.192383, 'y': 0.014783, 'z': -0.014787, 'P1': -0.192383, 'P2': 0.014783, 'P3': -0.014787, 'P4': 0.019089, 'P5': 0.072641, 'P6': -0.037301, 'P7': 0.039430, 'P8': 0.032535 };
-g_spherePositions['PC.354'] = { 'name': 'PC.354', 'color': 0, 'x': -0.293353, 'y': 0.018396, 'z': 0.032988, 'P1': -0.293353, 'P2': 0.018396, 'P3': 0.032988, 'P4': 0.031536, 'P5': -0.028694, 'P6': -0.019423, 'P7': 0.008063, 'P8': -0.055809 };
-g_spherePositions['PC.356'] = { 'name': 'PC.356', 'color': 0, 'x': -0.183191, 'y': 34912.621000, 'z': 0.008695, 'P1': -0.183191, 'P2': 34912.621000, 'P3': 0.008695, 'P4': -0.027388, 'P5': -0.052865, 'P6': -0.025058, 'P7': -0.052142, 'P8': 0.038200 };
-
-var g_ellipsesDimensions = new Array();
-var g_segments = 8, g_rings = 8, g_radius = 0.006899;
-var g_xAxisLength = 0.574888;
-var g_yAxisLength = 34912.787234;
-var g_zAxisLength = 0.276989;
-var g_xMaximumValue = 0.281535;
-var g_yMaximumValue = 34912.621000;
-var g_zMaximumValue = 0.135272;
-var g_xMinimumValue = -0.293353;
-var g_yMinimumValue = -0.166234;
-var g_zMinimumValue = -0.141717;
-var g_maximum = 34912.621000;
-var g_pc1Label = "Instant";
-var g_pc2Label = "PC1 (27 %)";
-var g_pc3Label = "PC2 (16 %)";
-var g_number_of_custom_axes = 1;
-var g_fractionExplained = [0.266887, 0.266887, 0.162564, 0.137754, 0.112172, 0.100248, 0.082284, 0.075597, 0.062495];
-var g_fractionExplainedRounded = [27, 27, 16, 14, 11, 10, 8, 8, 6];
-"""
-
-PCOA_JS_JACKKNIFED = """
-var g_spherePositions = new Array();
-g_spherePositions[\'PC.355\'] = { \'name\': \'PC.355\', \'color\': 0, \'x\': 0.300000, \'y\': 0.500000, \'z\': 0.100000, \'P1\': 0.300000, \'P2\': 0.500000, \'P3\': 0.100000, \'P4\': 0.300000 };
-g_spherePositions[\'PC.607\'] = { \'name\': \'PC.607\', \'color\': 0, \'x\': 1.100000, \'y\': 1.100000, \'z\': 1.000000, \'P1\': 1.100000, \'P2\': 1.100000, \'P3\': 1.000000, \'P4\': 0.800000 };
-g_spherePositions[\'PC.634\'] = { \'name\': \'PC.634\', \'color\': 0, \'x\': 0.100000, \'y\': 3.300000, \'z\': 5.500000, \'P1\': 0.100000, \'P2\': 3.300000, \'P3\': 5.500000, \'P4\': 0.100000 };
-g_spherePositions[\'PC.635\'] = { \'name\': \'PC.635\', \'color\': 0, \'x\': 1.000000, \'y\': 2.000000, \'z\': 1.000000, \'P1\': 1.000000, \'P2\': 2.000000, \'P3\': 1.000000, \'P4\': 1.000000 };
-
-var g_ellipsesDimensions = new Array();
-g_ellipsesDimensions[\'PC.355\'] = { \'name\': \'PC.355\', \'color\': 0, \'width\': 0.400000, \'height\': 0.500000, \'length\': 0.800000 , \'x\': 0.300000, \'y\': 0.500000, \'z\': 0.100000, \'P1\': 0.300000, \'P2\': 0.500000, \'P3\': 0.100000, \'P4\': 0.300000 }
-g_ellipsesDimensions[\'PC.607\'] = { \'name\': \'PC.607\', \'color\': 0, \'width\': 0.100000, \'height\': 2.000000, \'length\': 0.000000 , \'x\': 1.100000, \'y\': 1.100000, \'z\': 1.000000, \'P1\': 1.100000, \'P2\': 1.100000, \'P3\': 1.000000, \'P4\': 0.800000 }
-g_ellipsesDimensions[\'PC.634\'] = { \'name\': \'PC.634\', \'color\': 0, \'width\': 0.300000, \'height\': 0.600000, \'length\': 4.000000 , \'x\': 0.100000, \'y\': 3.300000, \'z\': 5.500000, \'P1\': 0.100000, \'P2\': 3.300000, \'P3\': 5.500000, \'P4\': 0.100000 }
-g_ellipsesDimensions[\'PC.635\'] = { \'name\': \'PC.635\', \'color\': 0, \'width\': 0.010780, \'height\': 1.000000, \'length\': 0.023000 , \'x\': 1.000000, \'y\': 2.000000, \'z\': 1.000000, \'P1\': 1.000000, \'P2\': 2.000000, \'P3\': 1.000000, \'P4\': 1.000000 }
-var g_segments = 8, g_rings = 8, g_radius = 0.012000;
-var g_xAxisLength = 1.200000;
-var g_yAxisLength = 3.800000;
-var g_zAxisLength = 5.600000;
-var g_xMaximumValue = 1.100000;
-var g_yMaximumValue = 3.300000;
-var g_zMaximumValue = 5.500000;
-var g_xMinimumValue = 0.100000;
-var g_yMinimumValue = 0.500000;
-var g_zMinimumValue = 0.100000;
-var g_maximum = 5.500000;
-var g_pc1Label = "PC1 (44 %)";
-var g_pc2Label = "PC2 (40 %)";
-var g_pc3Label = "PC3 (15 %)";
-var g_number_of_custom_axes = 0;
-var g_fractionExplained = [0.440000, 0.400000, 0.150000, 0.010000];
-var g_fractionExplainedRounded = [44, 40, 15, 1];
-"""
-
-PCOA_JS_SEGMENTS = """
-var g_spherePositions = new Array();
-g_spherePositions[\'PC.355\'] = { \'name\': \'PC.355\', \'color\': 0, \'x\': 0.300000, \'y\': 0.500000, \'z\': 0.100000, \'P1\': 0.300000, \'P2\': 0.500000, \'P3\': 0.100000, \'P4\': 0.300000 };
-g_spherePositions[\'PC.607\'] = { \'name\': \'PC.607\', \'color\': 0, \'x\': 1.100000, \'y\': 1.100000, \'z\': 1.000000, \'P1\': 1.100000, \'P2\': 1.100000, \'P3\': 1.000000, \'P4\': 0.800000 };
-g_spherePositions[\'PC.634\'] = { \'name\': \'PC.634\', \'color\': 0, \'x\': 0.100000, \'y\': 3.300000, \'z\': 5.500000, \'P1\': 0.100000, \'P2\': 3.300000, \'P3\': 5.500000, \'P4\': 0.100000 };
-g_spherePositions[\'PC.635\'] = { \'name\': \'PC.635\', \'color\': 0, \'x\': 1.000000, \'y\': 2.000000, \'z\': 1.000000, \'P1\': 1.000000, \'P2\': 2.000000, \'P3\': 1.000000, \'P4\': 1.000000 };
-
-var g_ellipsesDimensions = new Array();
-g_ellipsesDimensions[\'PC.355\'] = { \'name\': \'PC.355\', \'color\': 0, \'width\': 0.400000, \'height\': 0.500000, \'length\': 0.800000 , \'x\': 0.300000, \'y\': 0.500000, \'z\': 0.100000, \'P1\': 0.300000, \'P2\': 0.500000, \'P3\': 0.100000, \'P4\': 0.300000 }
-g_ellipsesDimensions[\'PC.607\'] = { \'name\': \'PC.607\', \'color\': 0, \'width\': 0.100000, \'height\': 2.000000, \'length\': 0.000000 , \'x\': 1.100000, \'y\': 1.100000, \'z\': 1.000000, \'P1\': 1.100000, \'P2\': 1.100000, \'P3\': 1.000000, \'P4\': 0.800000 }
-g_ellipsesDimensions[\'PC.634\'] = { \'name\': \'PC.634\', \'color\': 0, \'width\': 0.300000, \'height\': 0.600000, \'length\': 4.000000 , \'x\': 0.100000, \'y\': 3.300000, \'z\': 5.500000, \'P1\': 0.100000, \'P2\': 3.300000, \'P3\': 5.500000, \'P4\': 0.100000 }
-g_ellipsesDimensions[\'PC.635\'] = { \'name\': \'PC.635\', \'color\': 0, \'width\': 0.010780, \'height\': 1.000000, \'length\': 0.023000 , \'x\': 1.000000, \'y\': 2.000000, \'z\': 1.000000, \'P1\': 1.000000, \'P2\': 2.000000, \'P3\': 1.000000, \'P4\': 1.000000 }
-var g_segments = 14, g_rings = 14, g_radius = 0.012000;
-var g_xAxisLength = 1.200000;
-var g_yAxisLength = 3.800000;
-var g_zAxisLength = 5.600000;
-var g_xMaximumValue = 1.100000;
-var g_yMaximumValue = 3.300000;
-var g_zMaximumValue = 5.500000;
-var g_xMinimumValue = 0.100000;
-var g_yMinimumValue = 0.500000;
-var g_zMinimumValue = 0.100000;
-var g_maximum = 5.500000;
-var g_pc1Label = "PC1 (44 %)";
-var g_pc2Label = "PC2 (40 %)";
-var g_pc3Label = "PC3 (15 %)";
-var g_number_of_custom_axes = 0;
-var g_fractionExplained = [0.440000, 0.400000, 0.150000, 0.010000];
-var g_fractionExplainedRounded = [44, 40, 15, 1];
-"""
-
-MAPPING_FILE_DATA = [\
-    ['PC.354','AGCACGAGCCTA','YATGCTGCCTCCCGTAGGAGT','Control','20061218','Control_mouse_I.D._354'],
-    ['PC.355','AACTCGTCGATG','YATGCTGCCTCCCGTAGGAGT','Control','20061218','Control_mouse_I.D._355'],
-    ['PC.356','ACAGACCACTCA','YATGCTGCCTCCCGTAGGAGT','Control','20061126','Control_mouse_I.D._356'],
-    ['PC.481','ACCAGCGACTAG','YATGCTGCCTCCCGTAGGAGT','Control','20070314','Control_mouse_I.D._481'],
-    ['PC.593','AGCAGCACTTGT','YATGCTGCCTCCCGTAGGAGT','Control','20071210','Control_mouse_I.D._593'],
-    ['PC.607','AACTGTGCGTAC','YATGCTGCCTCCCGTAGGAGT','Fast','20071112','Fasting_mouse_I.D._607'],
-    ['PC.634','ACAGAGTCGGCT','YATGCTGCCTCCCGTAGGAGT','Fast','20080116','Fasting_mouse_I.D._634'],
-    ['PC.635','ACCGCAGAGTCA','YATGCTGCCTCCCGTAGGAGT','Fast','20080116','Fasting_mouse_I.D._635'],
-    ['PC.636','ACGGTGAGTGTC','YATGCTGCCTCCCGTAGGAGT','Fast','20080116','Fasting_mouse_I.D._636']]
-
-
-MAPPING_FILE_JS = """var g_mappingFileHeaders = ['BarcodeSequence','LinkerPrimerSequence','Treatment','DOB','Description'];\nvar g_mappingFileData = { 'PC.636': ['ACGGTGAGTGTC','YATGCTGCCTCCCGTAGGAGT','Fast','20080116','Fasting_mouse_I.D._636'],'PC.355': ['AACTCGTCGATG','YATGCTGCCTCCCGTAGGAGT','Control','20061218','Control_mouse_I.D._355'],'PC.607': ['AACTGTGCGTAC','YATGCTGCCTCCCGTAGGAGT','Fast','20071112','Fasting_mouse_I.D._607'],'PC.634': ['ACAGAGTCGGCT','YATGCTGCCTCCCGTAGGAGT','Fast' [...]
-
-TAXA_JS_STRING = """
-var g_taxaPositions = new Array();
-g_taxaPositions['0'] = { 'lineage': 'Root;k__Bacteria;p__Firmicutes', 'x': 0.280399, 'y': -0.006013, 'z': 0.023485, 'radius': 5.000000};
-g_taxaPositions['1'] = { 'lineage': 'Root;k__Bacteria;p__Bacteroidetes', 'x': 0.228820, 'y': -0.130142, 'z': -0.287149, 'radius': 3.491237};
-g_taxaPositions['2'] = { 'lineage': 'Root;k__Bacteria;p__Tenericutes', 'x': -0.091330, 'y': 0.424147, 'z': -0.135627, 'radius': 0.868694};
-g_taxaPositions['3'] = { 'lineage': 'Root;k__Bacteria;Other', 'x': -0.276542, 'y': -0.144964, 'z': 0.066647, 'radius': 0.696843};
-
-"""
-
-VECTOR_JS_STRING_NO_SORTING = """
-var g_vectorPositions = new Array();
-g_vectorPositions['Control'] = new Array();
-g_vectorPositions['Control']['PC.354'] = [-0.293353176, 0.0183956004, 0.0329884266];
-g_vectorPositions['Control']['PC.355'] = [-0.109166142, 0.0877774496, 0.0115866606];
-g_vectorPositions['Control']['PC.356'] = [-0.183191151, 34912.621, 0.00869481594];
-g_vectorPositions['Control']['PC.481'] = [-0.192382819, 0.0147832029, -0.0147871039];
-g_vectorPositions['Control']['PC.593'] = [0.0968466168, -0.159388265, 0.135271607];
-g_vectorPositions['Fast'] = new Array();
-g_vectorPositions['Fast']['PC.607'] = [0.0688959784, -0.166234067, -0.0998300962];
-g_vectorPositions['Fast']['PC.634'] = [0.20468454, 0.128911236, -0.0293614192];
-g_vectorPositions['Fast']['PC.635'] = [0.12613151, -0.00266030272, -0.141717093];
-g_vectorPositions['Fast']['PC.636'] = [0.281534642, 0.0710660196, 0.097154202];
-"""
-
-VECTOR_JS_STRING_SORTING = """
-var g_vectorPositions = new Array();
-g_vectorPositions['Control'] = new Array();
-g_vectorPositions['Control']['PC.356'] = [-0.183191151, 34912.621, 0.00869481594];
-g_vectorPositions['Control']['PC.354'] = [-0.293353176, 0.0183956004, 0.0329884266];
-g_vectorPositions['Control']['PC.355'] = [-0.109166142, 0.0877774496, 0.0115866606];
-g_vectorPositions['Control']['PC.481'] = [-0.192382819, 0.0147832029, -0.0147871039];
-g_vectorPositions['Control']['PC.593'] = [0.0968466168, -0.159388265, 0.135271607];
-g_vectorPositions['Fast'] = new Array();
-g_vectorPositions['Fast']['PC.607'] = [0.0688959784, -0.166234067, -0.0998300962];
-g_vectorPositions['Fast']['PC.634'] = [0.20468454, 0.128911236, -0.0293614192];
-g_vectorPositions['Fast']['PC.635'] = [0.12613151, -0.00266030272, -0.141717093];
-g_vectorPositions['Fast']['PC.636'] = [0.281534642, 0.0710660196, 0.097154202];
-"""
-
-COMPARISON_JS_STRING = """
-var g_comparisonPositions = new Array();
-var g_isSerialComparisonPlot = true;
-g_comparisonPositions['sampa'] = [[-0.0677, -2.036, 0.2726], [-0.972, 0.551, 1.144], [0.2339, -0.88, -1.753]];
-g_comparisonPositions['sampb'] = [[-1.782, -0.972, 0.1582], [1.438, -2.603, -1.39], [0.436, 2.12, -0.935]];
-g_comparisonPositions['sampc'] = [[-0.659, -0.2566, 0.514], [-0.356, 0.0875, 0.772], [-0.88, 1.069, 1.069]];
-g_comparisonPositions['sampd'] = [[-1.179, -0.968, 2.525], [1.512, -1.239, -0.0365], [0.294, 0.2988, 0.0467]];
-g_comparisonPositions['sampe'] = [[-0.896, -1.765, 0.274], [1.17, 1.31, -1.407], [1.64, 0.2485, -0.354]];
-g_comparisonPositions['sampf'] = [[-0.0923, 1.414, -0.622], [2.618, 0.739, -0.01295], [0.821, -1.13, -1.794]];
-"""
-
-COMPARISON_JS_STRING_NON_SERIAL = """
-var g_comparisonPositions = new Array();
-var g_isSerialComparisonPlot = false;
-g_comparisonPositions['sampa'] = [[-0.0677, -2.036, 0.2726], [-0.972, 0.551, 1.144], [0.2339, -0.88, -1.753]];
-g_comparisonPositions['sampb'] = [[-1.782, -0.972, 0.1582], [1.438, -2.603, -1.39], [0.436, 2.12, -0.935]];
-g_comparisonPositions['sampc'] = [[-0.659, -0.2566, 0.514], [-0.356, 0.0875, 0.772], [-0.88, 1.069, 1.069]];
-g_comparisonPositions['sampd'] = [[-1.179, -0.968, 2.525], [1.512, -1.239, -0.0365], [0.294, 0.2988, 0.0467]];
-g_comparisonPositions['sampe'] = [[-0.896, -1.765, 0.274], [1.17, 1.31, -1.407], [1.64, 0.2485, -0.354]];
-g_comparisonPositions['sampf'] = [[-0.0923, 1.414, -0.622], [2.618, 0.739, -0.01295], [0.821, -1.13, -1.794]];
-"""
-
-COMPARISON_COORDS_HEADERS_ZERO = """
-var g_comparisonPositions = new Array();
-var g_isSerialComparisonPlot = false;
-g_comparisonPositions['sampa0'] = [[-0.0677, -2.036, 0.2726], [-0.972, 0.551, 1.144], [0.2339, -0.88, -1.753]];
-g_comparisonPositions['sampb0'] = [[-1.782, -0.972, 0.1582], [1.438, -2.603, -1.39], [0.436, 2.12, -0.935]];
-g_comparisonPositions['sampc0'] = [[-0.659, -0.2566, 0.514], [-0.356, 0.0875, 0.772], [-0.88, 1.069, 1.069]];
-g_comparisonPositions['sampd00'] = [[-1.179, -0.968, 2.525], [1.512, -1.239, -0.0365], [0.294, 0.2988, 0.0467]];
-g_comparisonPositions['sampe00'] = [[-0.896, -1.765, 0.274], [1.17, 1.31, -1.407], [1.64, 0.2485, -0.354]];
-g_comparisonPositions['sampf00'] = [[-0.0923, 1.414, -0.622], [2.618, 0.739, -0.01295], [0.821, -1.13, -1.794]];
-"""
-
-EXPECTED_FOOTER_A =\
-"""document.getElementById("logo").style.display = 'none';
-document.getElementById("logotable").style.display = 'none';
-
- </script>
-</head>
-
-<body>
-
-<div id="overlay">
-    <div>
-    <img src="emperor_required_resources/img/emperor.png" alt="Emperor" id="smalllogo"/>
-        <h1>WebGL is not enabled!</h1>
-        <p>Emperor's visualization framework is WebGL based, it seems that your system doesn't have this resource available. Here is what you can do:</p>
-        <p id="explanation"><strong>Chrome:</strong> Type "chrome://flags/" into the address bar, then search for "Disable WebGL". Disable this option if you haven't already. <em>Note:</em> If you follow these steps and still don't see an image, go to "chrome://flags/" and then search for "Override software rendering list" and enable this option.</p>
-        <p id="explanation"><strong>Safari:</strong> Open Safari's menu and select Preferences. Click on the advanced tab, and then check "Show Developer" menu. Then open the "Developer" menu and select "Enable WebGL".</p>
-        <p id="explanation"><strong>Firefox:</strong> Go to Options through Firefox > Options or Tools > Options. Go to Advanced, then General. Check "Use hardware acceleration when available" and restart Firefox.</p>
-        <p id="explanation"><strong>Other browsers:</strong> The only browsers that support WebGL are Chrome, Safari, and Firefox. Please switch to these browsers when using Emperor.</p>
-        <p id="explanation"><em>Note:</em> Once you went through these changes, reload the page and it should work!</p>
-        <p id="source">Sources: Instructions for <a href="https://www.biodigitalhuman.com/home/enabling-webgl.html">Chrome and Safari</a>, and <a href="http://www.infewbytes.com/?p=144">Firefox</a></p>
-    </div>
-</div>
-
-<div id="plotToggle">
-    <form>
-      <div id="plottype">
-        <input id="pcoa" type="radio" id="pcoa" name="plottype" checked="checked" /><label for="pcoa">PCoA</label>
-        <input id="parallel" type="radio" id="parallel" name="plottype" /><label for="parallel">Parallel</label>
-      </div>
-    </form>
-</div>
-<div id="pcoaPlotWrapper" class="plotWrapper">
-    <label id="pointCount" class="ontop">
-    </label>
-
-    <div id="finder" class="arrow-right">
-    </div>
-
-    <div id="labels" class="unselectable">
-    </div>
-
-    <div id="taxalabels" class="unselectable">
-    </div>
-
-    <div id="axislabels" class="axislabels">
-    </div>
-
-    <div id="main_plot">
-    </div>
-</div>
-
-<div id="parallelPlotWrapper" class="plotWrapper">
-</div>
-
-<div class="separator" ondblclick="separatorDoubleClick()"></div>
-
-<div id="menu">
-    <div id="menutabs">
-        <ul>
-            <li><a href="#keytab">Key</a></li>
-            <li><a href="#colorby">Colors</a></li>
-            <li><a href="#showby">Visibility</a></li>
-            <li><a href="#scalingby">Scaling</a></li>
-            <li><a href="#labelby">Labels</a></li>
-            <li><a href="#axes">Axes</a></li>
-            <li><a href="#options">Options</a></li>
-        </ul>
-        <div id="keytab">
-            <form name="keyFilter">
-            <label>Filter  </label><input name="filterBox" id="searchBox" type="text" onkeyup="filterKey()"></input>
-            </form>
-            <div id="key">
-            </div>
-        </div>
-        <div id="colorby">
-            <br>
-            <input type="checkbox" onchange="toggleContinuousAndDiscreteColors(this)" id="discreteorcontinuouscolors" name="discreteorcontinuouscolors">  Use gradient colors</input>
-            <br><br>
-            <select id="colorbycombo" onchange="colorByMenuChanged()" size="3">
-            </select>
-            <div class="list" id="colorbylist">
-            </div>
-        </div>
-        <div id="showby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="showbycombo" onchange="showByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="showbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereopacity" class="text">Global Sphere Opacity</label>
-                        <label id="sphereopacity" class="slidervalue"></label>
-                        <div id="sopacityslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="scalingby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="scalingbycombo" onchange="scalingByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="scalingbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereradius" class="text">Global Sphere Scale</label>
-                        <label id="sphereradius" class="slidervalue"></label>
-                        <div id="sradiusslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="labelby">
-        <div id="labelsTop">
-            <form name="plotoptions">
-            <input type="checkbox" onClick="toggleLabels()">Samples Label Visibility</input>
-            </form>
-            <br>
-            <label for="labelopacity" class="text">Label Opacity</label>
-            <label id="labelopacity" class="slidervalue"></label>
-            <div id="lopacityslider" class="slider-range-max"></div>
-            <div id="labelColorHolder clearfix">
-            <table>
-                <tr><td><div id="labelColor" class="colorbox"></div></td><td><label>Master Label Color</label></td></tr>
-            </table></div>
-        </div>
-            <br>
-            <select id="labelcombo" onchange="labelMenuChanged()">
-            </select>
-            <div class="list" id="labellist">
-            </div>
-        </div>
-        <div id="axes">
-            <div id="pcoaaxes">
-                <div class="list" id="axeslist">
-                </div>
-            </div>
-        </div>
-        <div id="options">
-            <table>
-                <tr><td><div id="axeslabelscolor" class="colorbox" name="axeslabelscolor"></div></td><td title="Axes Labels Color">Axes Labels Color</td></tr>
-                <tr><td><div id="axescolor" class="colorbox" name="axescolor"></div></td><td title="Axes Color Title">Axes Color</td></tr>
-                <tr><td><div id="rendererbackgroundcolor" class="colorbox" name="rendererbackgroundcolor"></div></td><td title="Background Color Title">Background Color</td></tr>
-            </table>
-            <div id="pcoaviewoptions" class="">
-            <br>
-            <label for="ellipseopacity" class="text">Ellipse Opacity</label>
-            <label id="ellipseopacity" class="slidervalue"></label>
-            <div id="eopacityslider" class="slider-range-max"></div>
-                <form name="settingsoptionscolor">
-                </form>
-                <div id="pcoaoptions" class="">
-                    <form name="settingsoptions">
-                        <input type="checkbox" onchange="toggleScaleCoordinates(this)" id="scale_checkbox" name="scale_checkbox">Scale coords by percent explained</input>
-                    </form>
-                </div>
-                <br><input id="reset" class="button" type="submit" value="Recenter Camera" style="" onClick="resetCamera()">
-                <br><br>
-                <hr class='section-break'>
-                <br>Filename <small>(only letters, numbers, ., - and _)</small>:
-                <br><input name="saveas_name" id="saveas_name" value="screenshot" type="text"/>
-                <br><input id="saveas_legends" class="checkbox" type="checkbox" style=""> Create legend
-                <input id="saveas" class="button" type="submit" value="Save as SVG" style="" onClick="saveSVG()"/>
-                <br><br>For a PNG, simply press 'ctrl+p'.
-                <div id="paralleloptions" class="">
-                </div>
-            </div>
-            <br>
-        </div>
-    </div>  
-</div>
-</body>
-
-</html>
-"""
-
-EXPECTED_FOOTER_B =\
-"""document.getElementById("logo").style.display = 'none';
-document.getElementById("logotable").style.display = 'none';
-
- </script>
-</head>
-
-<body>
-
-<div id="overlay">
-    <div>
-    <img src="emperor_required_resources/img/emperor.png" alt="Emperor" id="smalllogo"/>
-        <h1>WebGL is not enabled!</h1>
-        <p>Emperor's visualization framework is WebGL based, it seems that your system doesn't have this resource available. Here is what you can do:</p>
-        <p id="explanation"><strong>Chrome:</strong> Type "chrome://flags/" into the address bar, then search for "Disable WebGL". Disable this option if you haven't already. <em>Note:</em> If you follow these steps and still don't see an image, go to "chrome://flags/" and then search for "Override software rendering list" and enable this option.</p>
-        <p id="explanation"><strong>Safari:</strong> Open Safari's menu and select Preferences. Click on the advanced tab, and then check "Show Developer" menu. Then open the "Developer" menu and select "Enable WebGL".</p>
-        <p id="explanation"><strong>Firefox:</strong> Go to Options through Firefox > Options or Tools > Options. Go to Advanced, then General. Check "Use hardware acceleration when available" and restart Firefox.</p>
-        <p id="explanation"><strong>Other browsers:</strong> The only browsers that support WebGL are Chrome, Safari, and Firefox. Please switch to these browsers when using Emperor.</p>
-        <p id="explanation"><em>Note:</em> Once you went through these changes, reload the page and it should work!</p>
-        <p id="source">Sources: Instructions for <a href="https://www.biodigitalhuman.com/home/enabling-webgl.html">Chrome and Safari</a>, and <a href="http://www.infewbytes.com/?p=144">Firefox</a></p>
-    </div>
-</div>
-
-<div id="plotToggle">
-    <form>
-      <div id="plottype">
-        <input id="pcoa" type="radio" id="pcoa" name="plottype" checked="checked" /><label for="pcoa">PCoA</label>
-        <input id="parallel" type="radio" id="parallel" name="plottype" /><label for="parallel">Parallel</label>
-      </div>
-    </form>
-</div>
-<div id="pcoaPlotWrapper" class="plotWrapper">
-    <label id="pointCount" class="ontop">
-    </label>
-
-    <div id="finder" class="arrow-right">
-    </div>
-
-    <div id="labels" class="unselectable">
-    </div>
-
-    <div id="taxalabels" class="unselectable">
-    </div>
-
-    <div id="axislabels" class="axislabels">
-    </div>
-
-    <div id="main_plot">
-    </div>
-</div>
-
-<div id="parallelPlotWrapper" class="plotWrapper">
-</div>
-
-<div class="separator" ondblclick="separatorDoubleClick()"></div>
-
-<div id="menu">
-    <div id="menutabs">
-        <ul>
-            <li><a href="#keytab">Key</a></li>
-            <li><a href="#colorby">Colors</a></li>
-            <li><a href="#showby">Visibility</a></li>
-            <li><a href="#scalingby">Scaling</a></li>
-            <li><a href="#labelby">Labels</a></li>
-            <li><a href="#axes">Axes</a></li>
-            <li><a href="#options">Options</a></li>
-        </ul>
-        <div id="keytab">
-            <form name="keyFilter">
-            <label>Filter  </label><input name="filterBox" id="searchBox" type="text" onkeyup="filterKey()"></input>
-            </form>
-            <div id="key">
-            </div>
-        </div>
-        <div id="colorby">
-            <br>
-            <br>
-            <table>
-                <tr><td><div id="taxaspherescolor" class="colorbox" name="taxaspherescolor"></div></td><td title="taxacolor">Taxa Spheres Color</td></tr>
-            </table>
-            <br>
-            <input type="checkbox" onchange="toggleContinuousAndDiscreteColors(this)" id="discreteorcontinuouscolors" name="discreteorcontinuouscolors">  Use gradient colors</input>
-            <br><br>
-            <select id="colorbycombo" onchange="colorByMenuChanged()" size="3">
-            </select>
-            <div class="list" id="colorbylist">
-            </div>
-        </div>
-        <div id="showby" align="center">
-            <br>
-            <form name="biplotsvisibility">
-            <input type="checkbox" onClick="toggleBiplotVisibility()" checked>Biplots Visibility</input>
-            </form>
-            <br>
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="showbycombo" onchange="showByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="showbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereopacity" class="text">Global Sphere Opacity</label>
-                        <label id="sphereopacity" class="slidervalue"></label>
-                        <div id="sopacityslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="scalingby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="scalingbycombo" onchange="scalingByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="scalingbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereradius" class="text">Global Sphere Scale</label>
-                        <label id="sphereradius" class="slidervalue"></label>
-                        <div id="sradiusslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="labelby">
-        <div id="labelsTop">
-            <form name="plotoptions">
-            <input type="checkbox" onClick="toggleLabels()">Samples Label Visibility</input>
-            </form>
-            <form name="biplotoptions">
-            <input type="checkbox" onClick="toggleTaxaLabels()">Biplots Label Visibility</input>
-            </form>
-            <br>
-            <label for="labelopacity" class="text">Label Opacity</label>
-            <label id="labelopacity" class="slidervalue"></label>
-            <div id="lopacityslider" class="slider-range-max"></div>
-            <div id="labelColorHolder clearfix">
-            <table>
-                <tr><td><div id="labelColor" class="colorbox"></div></td><td><label>Master Label Color</label></td></tr>
-            <tr><td><div id="taxalabelcolor" class="colorbox"></div></td><td><label>Taxa Label Color</label></td></tr>
-
-            </table></div>
-        </div>
-            <br>
-            <select id="labelcombo" onchange="labelMenuChanged()">
-            </select>
-            <div class="list" id="labellist">
-            </div>
-        </div>
-        <div id="axes">
-            <div id="pcoaaxes">
-                <div class="list" id="axeslist">
-                </div>
-            </div>
-        </div>
-        <div id="options">
-            <table>
-                <tr><td><div id="axeslabelscolor" class="colorbox" name="axeslabelscolor"></div></td><td title="Axes Labels Color">Axes Labels Color</td></tr>
-                <tr><td><div id="axescolor" class="colorbox" name="axescolor"></div></td><td title="Axes Color Title">Axes Color</td></tr>
-                <tr><td><div id="rendererbackgroundcolor" class="colorbox" name="rendererbackgroundcolor"></div></td><td title="Background Color Title">Background Color</td></tr>
-            </table>
-            <div id="pcoaviewoptions" class="">
-                <form name="settingsoptionscolor">
-                </form>
-                <div id="pcoaoptions" class="">
-                    <form name="settingsoptions">
-                        <input type="checkbox" onchange="toggleScaleCoordinates(this)" id="scale_checkbox" name="scale_checkbox">Scale coords by percent explained</input>
-                    </form>
-                </div>
-                <br><input id="reset" class="button" type="submit" value="Recenter Camera" style="" onClick="resetCamera()">
-                <br><br>
-                <hr class='section-break'>
-                <br>Filename <small>(only letters, numbers, ., - and _)</small>:
-                <br><input name="saveas_name" id="saveas_name" value="screenshot" type="text"/>
-                <br><input id="saveas_legends" class="checkbox" type="checkbox" style=""> Create legend
-                <input id="saveas" class="button" type="submit" value="Save as SVG" style="" onClick="saveSVG()"/>
-                <br><br>For a PNG, simply press 'ctrl+p'.
-                <div id="paralleloptions" class="">
-                </div>
-            </div>
-            <br>
-        </div>
-    </div>  
-</div>
-</body>
-
-</html>
-"""
-
-EXPECTED_FOOTER_C =\
-"""document.getElementById("logo").style.display = 'none';
-document.getElementById("logotable").style.display = 'none';
-
- </script>
-</head>
-
-<body>
-
-<div id="overlay">
-    <div>
-    <img src="emperor_required_resources/img/emperor.png" alt="Emperor" id="smalllogo"/>
-        <h1>WebGL is not enabled!</h1>
-        <p>Emperor's visualization framework is WebGL based, it seems that your system doesn't have this resource available. Here is what you can do:</p>
-        <p id="explanation"><strong>Chrome:</strong> Type "chrome://flags/" into the address bar, then search for "Disable WebGL". Disable this option if you haven't already. <em>Note:</em> If you follow these steps and still don't see an image, go to "chrome://flags/" and then search for "Override software rendering list" and enable this option.</p>
-        <p id="explanation"><strong>Safari:</strong> Open Safari's menu and select Preferences. Click on the advanced tab, and then check "Show Developer" menu. Then open the "Developer" menu and select "Enable WebGL".</p>
-        <p id="explanation"><strong>Firefox:</strong> Go to Options through Firefox > Options or Tools > Options. Go to Advanced, then General. Check "Use hardware acceleration when available" and restart Firefox.</p>
-        <p id="explanation"><strong>Other browsers:</strong> The only browsers that support WebGL are Chrome, Safari, and Firefox. Please switch to these browsers when using Emperor.</p>
-        <p id="explanation"><em>Note:</em> Once you went through these changes, reload the page and it should work!</p>
-        <p id="source">Sources: Instructions for <a href="https://www.biodigitalhuman.com/home/enabling-webgl.html">Chrome and Safari</a>, and <a href="http://www.infewbytes.com/?p=144">Firefox</a></p>
-    </div>
-</div>
-
-<div id="plotToggle">
-    <form>
-      <div id="plottype">
-        <input id="pcoa" type="radio" id="pcoa" name="plottype" checked="checked" /><label for="pcoa">PCoA</label>
-        <input id="parallel" type="radio" id="parallel" name="plottype" /><label for="parallel">Parallel</label>
-      </div>
-    </form>
-</div>
-<div id="pcoaPlotWrapper" class="plotWrapper">
-    <label id="pointCount" class="ontop">
-    </label>
-
-    <div id="finder" class="arrow-right">
-    </div>
-
-    <div id="labels" class="unselectable">
-    </div>
-
-    <div id="taxalabels" class="unselectable">
-    </div>
-
-    <div id="axislabels" class="axislabels">
-    </div>
-
-    <div id="main_plot">
-    </div>
-</div>
-
-<div id="parallelPlotWrapper" class="plotWrapper">
-</div>
-
-<div class="separator" ondblclick="separatorDoubleClick()"></div>
-
-<div id="menu">
-    <div id="menutabs">
-        <ul>
-            <li><a href="#keytab">Key</a></li>
-            <li><a href="#colorby">Colors</a></li>
-            <li><a href="#showby">Visibility</a></li>
-            <li><a href="#scalingby">Scaling</a></li>
-            <li><a href="#labelby">Labels</a></li>
-            <li><a href="#axes">Axes</a></li>
-            <li><a href="#options">Options</a></li>
-        </ul>
-        <div id="keytab">
-            <form name="keyFilter">
-            <label>Filter  </label><input name="filterBox" id="searchBox" type="text" onkeyup="filterKey()"></input>
-            </form>
-            <div id="key">
-            </div>
-        </div>
-        <div id="colorby">
-            <br>
-            <input type="checkbox" onchange="toggleContinuousAndDiscreteColors(this)" id="discreteorcontinuouscolors" name="discreteorcontinuouscolors">  Use gradient colors</input>
-            <br><br>
-            <select id="colorbycombo" onchange="colorByMenuChanged()" size="3">
-            </select>
-            <div class="list" id="colorbylist">
-            </div>
-        </div>
-        <div id="showby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="showbycombo" onchange="showByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="showbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereopacity" class="text">Global Sphere Opacity</label>
-                        <label id="sphereopacity" class="slidervalue"></label>
-                        <div id="sopacityslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="scalingby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="scalingbycombo" onchange="scalingByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="scalingbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereradius" class="text">Global Sphere Scale</label>
-                        <label id="sphereradius" class="slidervalue"></label>
-                        <div id="sradiusslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="labelby">
-        <div id="labelsTop">
-            <form name="plotoptions">
-            <input type="checkbox" onClick="toggleLabels()">Samples Label Visibility</input>
-            </form>
-            <br>
-            <label for="labelopacity" class="text">Label Opacity</label>
-            <label id="labelopacity" class="slidervalue"></label>
-            <div id="lopacityslider" class="slider-range-max"></div>
-            <div id="labelColorHolder clearfix">
-            <table>
-                <tr><td><div id="labelColor" class="colorbox"></div></td><td><label>Master Label Color</label></td></tr>
-            </table></div>
-        </div>
-            <br>
-            <select id="labelcombo" onchange="labelMenuChanged()">
-            </select>
-            <div class="list" id="labellist">
-            </div>
-        </div>
-        <div id="axes">
-            <div id="pcoaaxes">
-                <div class="list" id="axeslist">
-                </div>
-            </div>
-        </div>
-        <div id="options">
-            <table>
-                <tr><td><div id="axeslabelscolor" class="colorbox" name="axeslabelscolor"></div></td><td title="Axes Labels Color">Axes Labels Color</td></tr>
-                <tr><td><div id="axescolor" class="colorbox" name="axescolor"></div></td><td title="Axes Color Title">Axes Color</td></tr>
-                <tr><td><div id="rendererbackgroundcolor" class="colorbox" name="rendererbackgroundcolor"></div></td><td title="Background Color Title">Background Color</td></tr>
-            </table>
-            <div id="pcoaviewoptions" class="">
-                <form name="settingsoptionscolor">
-                </form>
-                <div id="pcoaoptions" class="">
-                    <form name="settingsoptions">
-                        <input type="checkbox" onchange="toggleScaleCoordinates(this)" id="scale_checkbox" name="scale_checkbox">Scale coords by percent explained</input>
-                    </form>
-                </div>
-                <br><input id="reset" class="button" type="submit" value="Recenter Camera" style="" onClick="resetCamera()">
-                <br><br>
-                <hr class='section-break'>
-                <br>Filename <small>(only letters, numbers, ., - and _)</small>:
-                <br><input name="saveas_name" id="saveas_name" value="screenshot" type="text"/>
-                <br><input id="saveas_legends" class="checkbox" type="checkbox" style=""> Create legend
-                <input id="saveas" class="button" type="submit" value="Save as SVG" style="" onClick="saveSVG()"/>
-                <br><br>For a PNG, simply press 'ctrl+p'.
-                <div id="paralleloptions" class="">
-                </div>
-            </div>
-            <br>
-        </div>
-    </div>  
-</div>
-</body>
-
-</html>
-"""
-
-EXPECTED_FOOTER_D = """document.getElementById("logo").style.display = 'none';
-document.getElementById("logotable").style.display = 'none';
-
- </script>
-</head>
-
-<body>
-
-<div id="overlay">
-    <div>
-    <img src="emperor_required_resources/img/emperor.png" alt="Emperor" id="smalllogo"/>
-        <h1>WebGL is not enabled!</h1>
-        <p>Emperor's visualization framework is WebGL based, it seems that your system doesn't have this resource available. Here is what you can do:</p>
-        <p id="explanation"><strong>Chrome:</strong> Type "chrome://flags/" into the address bar, then search for "Disable WebGL". Disable this option if you haven't already. <em>Note:</em> If you follow these steps and still don't see an image, go to "chrome://flags/" and then search for "Override software rendering list" and enable this option.</p>
-        <p id="explanation"><strong>Safari:</strong> Open Safari's menu and select Preferences. Click on the advanced tab, and then check "Show Developer" menu. Then open the "Developer" menu and select "Enable WebGL".</p>
-        <p id="explanation"><strong>Firefox:</strong> Go to Options through Firefox > Options or Tools > Options. Go to Advanced, then General. Check "Use hardware acceleration when available" and restart Firefox.</p>
-        <p id="explanation"><strong>Other browsers:</strong> The only browsers that support WebGL are Chrome, Safari, and Firefox. Please switch to these browsers when using Emperor.</p>
-        <p id="explanation"><em>Note:</em> Once you went through these changes, reload the page and it should work!</p>
-        <p id="source">Sources: Instructions for <a href="https://www.biodigitalhuman.com/home/enabling-webgl.html">Chrome and Safari</a>, and <a href="http://www.infewbytes.com/?p=144">Firefox</a></p>
-    </div>
-</div>
-
-<div id="plotToggle">
-    <form>
-      <div id="plottype">
-        <input id="pcoa" type="radio" id="pcoa" name="plottype" checked="checked" /><label for="pcoa">PCoA</label>
-        <input id="parallel" type="radio" id="parallel" name="plottype" /><label for="parallel">Parallel</label>
-      </div>
-    </form>
-</div>
-<div id="pcoaPlotWrapper" class="plotWrapper">
-    <label id="pointCount" class="ontop">
-    </label>
-
-    <div id="finder" class="arrow-right">
-    </div>
-
-    <div id="labels" class="unselectable">
-    </div>
-
-    <div id="taxalabels" class="unselectable">
-    </div>
-
-    <div id="axislabels" class="axislabels">
-    </div>
-
-    <div id="main_plot">
-    </div>
-</div>
-
-<div id="parallelPlotWrapper" class="plotWrapper">
-</div>
-
-<div class="separator" ondblclick="separatorDoubleClick()"></div>
-
-<div id="menu">
-    <div id="menutabs">
-        <ul>
-            <li><a href="#keytab">Key</a></li>
-            <li><a href="#colorby">Colors</a></li>
-            <li><a href="#showby">Visibility</a></li>
-            <li><a href="#scalingby">Scaling</a></li>
-            <li><a href="#labelby">Labels</a></li>
-            <li><a href="#axes">Axes</a></li>
-            <li><a href="#options">Options</a></li>
-        </ul>
-        <div id="keytab">
-            <form name="keyFilter">
-            <label>Filter  </label><input name="filterBox" id="searchBox" type="text" onkeyup="filterKey()"></input>
-            </form>
-            <div id="key">
-            </div>
-        </div>
-        <div id="colorby">
-            <br>
-            <input type="checkbox" onchange="toggleContinuousAndDiscreteColors(this)" id="discreteorcontinuouscolors" name="discreteorcontinuouscolors">  Use gradient colors</input>
-            <br><br>
-            <select id="colorbycombo" onchange="colorByMenuChanged()" size="3">
-            </select>
-            <div class="list" id="colorbylist">
-            </div>
-        </div>
-        <div id="showby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="showbycombo" onchange="showByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="showbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereopacity" class="text">Global Sphere Opacity</label>
-                        <label id="sphereopacity" class="slidervalue"></label>
-                        <div id="sopacityslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="scalingby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="scalingbycombo" onchange="scalingByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="scalingbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereradius" class="text">Global Sphere Scale</label>
-                        <label id="sphereradius" class="slidervalue"></label>
-                        <div id="sradiusslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="labelby">
-        <div id="labelsTop">
-            <form name="plotoptions">
-            <input type="checkbox" onClick="toggleLabels()">Samples Label Visibility</input>
-            </form>
-            <br>
-            <label for="labelopacity" class="text">Label Opacity</label>
-            <label id="labelopacity" class="slidervalue"></label>
-            <div id="lopacityslider" class="slider-range-max"></div>
-            <div id="labelColorHolder clearfix">
-            <table>
-                <tr><td><div id="labelColor" class="colorbox"></div></td><td><label>Master Label Color</label></td></tr>
-            </table></div>
-        </div>
-            <br>
-            <select id="labelcombo" onchange="labelMenuChanged()">
-            </select>
-            <div class="list" id="labellist">
-            </div>
-        </div>
-        <div id="axes">
-            <div id="pcoaaxes">
-                <div class="list" id="axeslist">
-                </div>
-            </div>
-        </div>
-        <div id="options">
-            <table>
-                <tr><td><div id="axeslabelscolor" class="colorbox" name="axeslabelscolor"></div></td><td title="Axes Labels Color">Axes Labels Color</td></tr>
-                <tr><td><div id="axescolor" class="colorbox" name="axescolor"></div></td><td title="Axes Color Title">Axes Color</td></tr>
-                <tr><td><div id="rendererbackgroundcolor" class="colorbox" name="rendererbackgroundcolor"></div></td><td title="Background Color Title">Background Color</td></tr>
-            </table>
-            <div id="pcoaviewoptions" class="">
-            <br>
-            <label for="vectorsopacity" class="text">Vectors Opacity</label>
-            <label id="vectorsopacity" class="slidervalue"></label>
-            <div id="vopacityslider" class="slider-range-max"></div>
-                <form name="settingsoptionscolor">
-                </form>
-                <div id="pcoaoptions" class="">
-                    <form name="settingsoptions">
-                        <input type="checkbox" onchange="toggleScaleCoordinates(this)" id="scale_checkbox" name="scale_checkbox">Scale coords by percent explained</input>
-                    </form>
-                </div>
-                <br><input id="reset" class="button" type="submit" value="Recenter Camera" style="" onClick="resetCamera()">
-                <br><br>
-                <hr class='section-break'>
-                <br>Filename <small>(only letters, numbers, ., - and _)</small>:
-                <br><input name="saveas_name" id="saveas_name" value="screenshot" type="text"/>
-                <br><input id="saveas_legends" class="checkbox" type="checkbox" style=""> Create legend
-                <input id="saveas" class="button" type="submit" value="Save as SVG" style="" onClick="saveSVG()"/>
-                <br><br>For a PNG, simply press 'ctrl+p'.
-                <div id="paralleloptions" class="">
-                </div>
-            </div>
-            <br>
-        </div>
-    </div>  
-</div>
-</body>
-
-</html>
-"""
-
-EXPECTED_FOOTER_E = """document.getElementById("logo").style.display = 'none';
-document.getElementById("logotable").style.display = 'none';
-
- </script>
-</head>
-
-<body>
-
-<div id="overlay">
-    <div>
-    <img src="emperor_required_resources/img/emperor.png" alt="Emperor" id="smalllogo"/>
-        <h1>WebGL is not enabled!</h1>
-        <p>Emperor's visualization framework is WebGL based, it seems that your system doesn't have this resource available. Here is what you can do:</p>
-        <p id="explanation"><strong>Chrome:</strong> Type "chrome://flags/" into the address bar, then search for "Disable WebGL". Disable this option if you haven't already. <em>Note:</em> If you follow these steps and still don't see an image, go to "chrome://flags/" and then search for "Override software rendering list" and enable this option.</p>
-        <p id="explanation"><strong>Safari:</strong> Open Safari's menu and select Preferences. Click on the advanced tab, and then check "Show Developer" menu. Then open the "Developer" menu and select "Enable WebGL".</p>
-        <p id="explanation"><strong>Firefox:</strong> Go to Options through Firefox > Options or Tools > Options. Go to Advanced, then General. Check "Use hardware acceleration when available" and restart Firefox.</p>
-        <p id="explanation"><strong>Other browsers:</strong> The only browsers that support WebGL are Chrome, Safari, and Firefox. Please switch to these browsers when using Emperor.</p>
-        <p id="explanation"><em>Note:</em> Once you went through these changes, reload the page and it should work!</p>
-        <p id="source">Sources: Instructions for <a href="https://www.biodigitalhuman.com/home/enabling-webgl.html">Chrome and Safari</a>, and <a href="http://www.infewbytes.com/?p=144">Firefox</a></p>
-    </div>
-</div>
-
-<div id="plotToggle">
-    <form>
-      <div id="plottype">
-        <input id="pcoa" type="radio" id="pcoa" name="plottype" checked="checked" /><label for="pcoa">PCoA</label>
-        <input id="parallel" type="radio" id="parallel" name="plottype" /><label for="parallel">Parallel</label>
-      </div>
-    </form>
-</div>
-<div id="pcoaPlotWrapper" class="plotWrapper">
-    <label id="pointCount" class="ontop">
-    </label>
-
-    <div id="finder" class="arrow-right">
-    </div>
-
-    <div id="labels" class="unselectable">
-    </div>
-
-    <div id="taxalabels" class="unselectable">
-    </div>
-
-    <div id="axislabels" class="axislabels">
-    </div>
-
-    <div id="main_plot">
-    </div>
-</div>
-
-<div id="parallelPlotWrapper" class="plotWrapper">
-</div>
-
-<div class="separator" ondblclick="separatorDoubleClick()"></div>
-
-<div id="menu">
-    <div id="menutabs">
-        <ul>
-            <li><a href="#keytab">Key</a></li>
-            <li><a href="#colorby">Colors</a></li>
-            <li><a href="#showby">Visibility</a></li>
-            <li><a href="#scalingby">Scaling</a></li>
-            <li><a href="#labelby">Labels</a></li>
-            <li><a href="#axes">Axes</a></li>
-            <li><a href="#options">Options</a></li>
-        </ul>
-        <div id="keytab">
-            <form name="keyFilter">
-            <label>Filter  </label><input name="filterBox" id="searchBox" type="text" onkeyup="filterKey()"></input>
-            </form>
-            <div id="key">
-            </div>
-        </div>
-        <div id="colorby">
-            <br>
-            <input type="checkbox" onchange="toggleContinuousAndDiscreteColors(this)" id="discreteorcontinuouscolors" name="discreteorcontinuouscolors">  Use gradient colors</input>
-            <br><br>
-            <select id="colorbycombo" onchange="colorByMenuChanged()" size="3">
-            </select>
-            <div class="list" id="colorbylist">
-            </div>
-        </div>
-        <div id="showby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="showbycombo" onchange="showByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="showbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereopacity" class="text">Global Sphere Opacity</label>
-                        <label id="sphereopacity" class="slidervalue"></label>
-                        <div id="sopacityslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="scalingby" align="center">
-            <table width="100%">
-                <tr>
-                    <td align="center">
-                        <select id="scalingbycombo" onchange="scalingByMenuChanged()">
-                        </select>
-                    </td>
-                </tr>
-                <tr>
-                    <td>
-                        <div class="list" id="scalingbylist" style="height:100%;width:100%">
-                        </div>
-                    </td>
-                </tr>
-                <tr>
-                    <td style="padding-left: 12px; padding-right:12px;">
-                        <br>
-                        <label for="sphereradius" class="text">Global Sphere Scale</label>
-                        <label id="sphereradius" class="slidervalue"></label>
-                        <div id="sradiusslider" class="slider-range-max"></div>
-                    </td>
-                </tr>
-            </table>
-        </div>
-        <div id="labelby">
-        <div id="labelsTop">
-            <form name="plotoptions">
-            <input type="checkbox" onClick="toggleLabels()">Samples Label Visibility</input>
-            </form>
-            <br>
-            <label for="labelopacity" class="text">Label Opacity</label>
-            <label id="labelopacity" class="slidervalue"></label>
-            <div id="lopacityslider" class="slider-range-max"></div>
-            <div id="labelColorHolder clearfix">
-            <table>
-                <tr><td><div id="labelColor" class="colorbox"></div></td><td><label>Master Label Color</label></td></tr>
-            </table></div>
-        </div>
-            <br>
-            <select id="labelcombo" onchange="labelMenuChanged()">
-            </select>
-            <div class="list" id="labellist">
-            </div>
-        </div>
-        <div id="axes">
-            <div id="pcoaaxes">
-                <div class="list" id="axeslist">
-                </div>
-            </div>
-        </div>
-        <div id="options">
-            <table>
-                <tr><td><div id="axeslabelscolor" class="colorbox" name="axeslabelscolor"></div></td><td title="Axes Labels Color">Axes Labels Color</td></tr>
-                <tr><td><div id="axescolor" class="colorbox" name="axescolor"></div></td><td title="Axes Color Title">Axes Color</td></tr>
-                <tr><td><div id="rendererbackgroundcolor" class="colorbox" name="rendererbackgroundcolor"></div></td><td title="Background Color Title">Background Color</td></tr>
-            <tr><td><div id="edgecolorselector_a" class="colorbox" name="edgecolorselector_a"></div></td><td title="edgecolor_a">Edge Color Selector A</td></tr>
-            <tr><td><div id="edgecolorselector_b" class="colorbox" name="edgecolorselector_b"></div></td><td title="edgecolor_b">Edge Color Selector B</td></tr>
-
-            </table>
-            <div id="pcoaviewoptions" class="">
-            <br>
-            <form name="edgesvisibility">
-            <input type="checkbox" onClick="toggleEdgesVisibility()" checked>Edges Visibility</input>
-            </form>
-            <br>
-                <form name="settingsoptionscolor">
-                </form>
-                <div id="pcoaoptions" class="">
-                    <form name="settingsoptions">
-                        <input type="checkbox" onchange="toggleScaleCoordinates(this)" id="scale_checkbox" name="scale_checkbox">Scale coords by percent explained</input>
-                    </form>
-                </div>
-                <br><input id="reset" class="button" type="submit" value="Recenter Camera" style="" onClick="resetCamera()">
-                <br><br>
-                <hr class='section-break'>
-                <br>Filename <small>(only letters, numbers, ., - and _)</small>:
-                <br><input name="saveas_name" id="saveas_name" value="screenshot" type="text"/>
-                <br><input id="saveas_legends" class="checkbox" type="checkbox" style=""> Create legend
-                <input id="saveas" class="button" type="submit" value="Save as SVG" style="" onClick="saveSVG()"/>
-                <br><br>For a PNG, simply press 'ctrl+p'.
-                <div id="paralleloptions" class="">
-                </div>
-            </div>
-            <br>
-        </div>
-    </div>  
-</div>
-</body>
-
-</html>
-"""
+                          'mapping_file.txt', 'pcoa.txt', 'Cobol')
 
 
 if __name__ == "__main__":
-    main()
\ No newline at end of file
+    main()
diff --git a/tests/test_qiime_backports/test_biplots.py b/tests/test_qiime_backports/test_biplots.py
index 5afc319..a7aaafb 100755
--- a/tests/test_qiime_backports/test_biplots.py
+++ b/tests/test_qiime_backports/test_biplots.py
@@ -34,7 +34,7 @@ class BiplotTests(TestCase):
         otu_names = list('abc')
     
         res = bp.get_taxa_coords(otu_table, [.4,.2,.1,.9])
-        otu_coords= range(3)
+        otu_coords= list(range(3))
         otu_coords[0] = .4*2/3 + .9*1/3
         otu_coords[1] = .4*1/4 + .2*1/4 + .1*1/4 + .9*1/4
         otu_coords[2] = .4*0/5 + .2*2/5 + .1*2/5 + .9*1/5
@@ -67,42 +67,13 @@ class BiplotTests(TestCase):
                                  [1.1,1.2,1.3,1.5],
                                  [-.3,-2,2.5,1.9]],float)
         res = bp.make_biplot_scores_output(taxa)
-        exp = ['#Taxon\tpc0\tpc1\tpc2\tpc3',
+        exp = ['#Taxon\tpc1\tpc2\tpc3\tpc4',
                'A\t2.1\t0.2\t0.2\t1.4',
                'B\t1.1\t1.2\t1.3\t1.5',
                'C\t-0.3\t-2.0\t2.5\t1.9',
               ]
         self.assertEqual(res, exp)
-    
-taxa_mage_no_scale = [\
-'@group {Taxa (n=3)} collapsible', \
-'@balllist color=white radius=10.0 alpha=0.7 dimension=3 master={taxa_points} nobutton', \
-'{A} 1.0 4.0 7.0', \
-'@labellist color=white radius=10.0 alpha=0.7 dimension=3 master={taxa_labels} nobutton', \
-'{A} 1.0 4.0 7.0', \
-'@balllist color=white radius=15.0 alpha=0.7 dimension=3 master={taxa_points} nobutton', \
-'{B} 2.0 5.0 8.0', \
-'@labellist color=white radius=15.0 alpha=0.7 dimension=3 master={taxa_labels} nobutton', \
-'{B} 2.0 5.0 8.0', \
-'@balllist color=white radius=20.0 alpha=0.7 dimension=3 master={taxa_points} nobutton', \
-'{C} 3.0 6.0 9.0', \
-'@labellist color=white radius=20.0 alpha=0.7 dimension=3 master={taxa_labels} nobutton', \
-'{C} 3.0 6.0 9.0']
 
-taxa_mage_scale = [\
-'@group {Taxa (n=3)} collapsible', \
-'@balllist color=white radius=10.0 alpha=0.7 dimension=3 master={taxa_points} nobutton', \
-'{A} 1.0 0.4 0.07', \
-'@labellist color=white radius=10.0 alpha=0.7 dimension=3 master={taxa_labels} nobutton', \
-'{A} 1.0 0.4 0.07', \
-'@balllist color=white radius=15.0 alpha=0.7 dimension=3 master={taxa_points} nobutton', \
-'{B} 2.0 0.5 0.08', \
-'@labellist color=white radius=15.0 alpha=0.7 dimension=3 master={taxa_labels} nobutton', \
-'{B} 2.0 0.5 0.08', \
-'@balllist color=white radius=20.0 alpha=0.7 dimension=3 master={taxa_points} nobutton', \
-'{C} 3.0 0.6 0.09', \
-'@labellist color=white radius=20.0 alpha=0.7 dimension=3 master={taxa_labels} nobutton', \
-'{C} 3.0 0.6 0.09']
 
 if __name__ == "__main__":
     main()
diff --git a/tests/test_qiime_backports/test_filter.py b/tests/test_qiime_backports/test_filter.py
index 1074ff4..4bb732f 100755
--- a/tests/test_qiime_backports/test_filter.py
+++ b/tests/test_qiime_backports/test_filter.py
@@ -11,7 +11,10 @@ __maintainer__ = "Greg Caporaso"
 __email__ = "gregcaporaso at gmail.com"
 __status__ = "Development"
  
-from StringIO import StringIO
+try:
+    from StringIO import StringIO
+except ImportError:
+    from io import StringIO
 from unittest import TestCase, main
 
 from emperor.qiime_backports.parse import (parse_mapping_file,
diff --git a/tests/test_qiime_backports/test_make_3d_plots.py b/tests/test_qiime_backports/test_make_3d_plots.py
index 2a967c6..a134f5b 100755
--- a/tests/test_qiime_backports/test_make_3d_plots.py
+++ b/tests/test_qiime_backports/test_make_3d_plots.py
@@ -22,24 +22,24 @@ class TopLevelTests(TestCase):
     def setUp(self):
         """define some top-level data"""
         self.coord_header=["Sample1","Sample2","Sample3"]
-        self.coords=array([[-0.219044992,0.079674486,0.09233683],[-0.042258081,\
-                        0.000204041,0.024837603],[0.080504323,-0.212014503,\
+        self.coords=array([[-0.219044992,0.079674486,0.09233683],[-0.042258081,
+                        0.000204041,0.024837603],[0.080504323,-0.212014503,
                         -0.088353435]])
         self.pct_var=array([25.00,30.00,35.00])
-        self.mapping=[["Sample-ID","Day","Type"],["Sample1","Day1","Soil"],\
+        self.mapping=[["Sample-ID","Day","Type"],["Sample1","Day1","Soil"],
                     ["Sample2","Day1","Soil"],["Sample3","Day1","Soil"]]
-        self.mapping2=[["Sample-ID","Day","Type","Height","Weight"],\
-                        ["Sample1","Day1","Soil","10","60"],\
-                        ["Sample2","Day1","Soil","20","55"],\
+        self.mapping2=[["Sample-ID","Day","Type","Height","Weight"],
+                        ["Sample1","Day1","Soil","10","60"],
+                        ["Sample2","Day1","Soil","20","55"],
                         ["Sample3","Day1","Soil","30","50"]]
 
         self.prefs_vectors={}
         self.prefs_vectors['Sample']={}   
         self.prefs_vectors['Sample']['column']="Type"
-        self.coords2 = array([[0, -0.219044992,0.079674486,0.09233683], \
-                                [1, -0.042258081, 0.000204041, 0.024837603],\
-                                [2, 0.080504323, -0.212014503, -0.088353435],\
-                                [3, 0.012345551, -0.124512513, -01142356135]])
+        self.coords2 = array([[0, -0.219044992,0.079674486,0.09233683],
+                              [1, -0.042258081, 0.000204041, 0.024837603],
+                              [2, 0.080504323, -0.212014503, -0.088353435],
+                              [3, 0.012345551, -0.124512513, -1142356135]])
         self.custom_axes = ['Height']
         self.add_vectors = {'vectors_algorithm': 'trajectory', 'vectors_axes': 3,\
                                 'vectors': ['Height'], 'vectors_path': 'vectors_test',\
diff --git a/tests/test_qiime_backports/test_parse.py b/tests/test_qiime_backports/test_parse.py
index 5e07d5f..9e033aa 100755
--- a/tests/test_qiime_backports/test_parse.py
+++ b/tests/test_qiime_backports/test_parse.py
@@ -13,7 +13,10 @@ __status__ = "Development"
 
 from unittest import TestCase, main
 
-from StringIO import StringIO
+try:
+    from StringIO import StringIO
+except ImportError:
+    from io import StringIO
 
 from numpy import array
 from numpy.testing import assert_almost_equal
diff --git a/tests/test_qiime_backports/test_util.py b/tests/test_qiime_backports/test_util.py
index 3c67963..afc89e8 100755
--- a/tests/test_qiime_backports/test_util.py
+++ b/tests/test_qiime_backports/test_util.py
@@ -18,8 +18,10 @@ from unittest import TestCase, main
 
 from numpy.testing import assert_almost_equal
 from numpy import array, isnan, asarray, arange
+from builtins import chr as py_unichr
+
+from scipy.spatial import procrustes
 
-from emperor.pycogent_backports.procrustes import procrustes
 from emperor.qiime_backports.parse import (parse_mapping_file_to_dict,
     QiimeParseError)
 from emperor.qiime_backports.util import (MetadataMap, is_valid_git_sha1,
@@ -177,7 +179,7 @@ class TopLevelTests(TestCase):
                             test.repeat(2).reshape(-1,2))
         test = [0,0]
         _result = idealfourths(test)
-        assert_almost_equal(isnan(_result).all(),True)
+        self.assertEqual(isnan(_result).all(), True)
 
 
 class MetadataMapTests(TestCase):
@@ -466,7 +468,7 @@ class MetadataMapTests(TestCase):
         self.assertTrue(is_valid_git_refname('refname/bar'))
         self.assertTrue(is_valid_git_refname('ref.nameslu/_eggs_/spam'))
         self.assertTrue(is_valid_git_refname('valid{0}char'.format(
-            unichr(40))))
+            py_unichr(40))))
         self.assertTrue(is_valid_git_refname('master at head'))
         self.assertTrue(is_valid_git_refname('bar{thing}foo'))
 
@@ -484,9 +486,9 @@ class MetadataMapTests(TestCase):
         self.assertFalse(is_valid_git_refname('ref..name'))
 
         self.assertFalse(is_valid_git_refname(u'invalid{0}char'.format(
-            unichr(177))))
+            py_unichr(177))))
         self.assertFalse(is_valid_git_refname('invalid{0}char'.format(
-            unichr(39))))
+            py_unichr(39))))
         self.assertFalse(is_valid_git_refname('ref~name/bar'))
         self.assertFalse(is_valid_git_refname('refname spam'))
         self.assertFalse(is_valid_git_refname('bar/foo/eggs~spam'))
diff --git a/tests/test_sort.py b/tests/test_sort.py
old mode 100755
new mode 100644
index 242532f..ed146cb
--- a/tests/test_sort.py
+++ b/tests/test_sort.py
@@ -1,46 +1,49 @@
-#!/usr/bin/env python
-# File created on 20 Apr 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
 from unittest import TestCase, main
 
 from numpy import array
 from numpy.testing import assert_almost_equal
 
 from emperor.sort import (sort_taxa_table_by_pcoa_coords,
-    sort_comparison_filenames)
+                          sort_comparison_filenames)
+
 
 class TopLevelTests(TestCase):
     def setUp(self):
         self.otu_headers = ['PC.636', 'PC.635', 'PC.356', 'PC.481', 'PC.354',
-                'PC.593', 'PC.355', 'PC.607', 'PC.634']
-
-        self.otu_table = array([[0.02739726, 0.04697987, 0.02, 0.04697987, 0.01,
-            0.02027027, 0.01360544, 0.01342282, 0.02666667], [0.00684932,
-            0.02013423, 0.02, 0.00671141,  0., 0.00675676, 0., 0., 0.], [
-            0.14383562, 0.27516779, 0.65333333, 0.52348993, 0.38926174,
-            0.69594595, 0.28571429, 0.0738255, 0.19333333], [0., 0.02013423,
-            0.03333333, 0.01342282, 0., 0.0472973, 0., 0., 0.], [0.78767123,
-            0.45637584, 0.22, 0.39597315, 0.41610738, 0.20945946, 0.70068027,
-            0.89932886, 0.77333333], [0.,0.02013423, 0.01333333, 0.00671141,
-            0.03355705, 0.00675676, 0., 0., 0.],[0., 0., 0.01333333, 0., 0., 0.,
-            0., 0., 0.], [0.03424658, 0.16107383, 0.02666667, 0.00671141,
-            0.14765101, 0.01351351, 0., 0.01342282, 0.00666667]])
+                            'PC.593', 'PC.355', 'PC.607', 'PC.634']
+
+        self.otu_table = array(
+            [[0.02739726, 0.04697987, 0.02, 0.04697987, 0.01, 0.02027027,
+              0.01360544, 0.01342282, 0.02666667],
+             [0.00684932, 0.02013423, 0.02, 0.00671141,  0., 0.00675676, 0.,
+              0., 0.],
+             [0.14383562, 0.27516779, 0.65333333, 0.52348993, 0.38926174,
+              0.69594595, 0.28571429, 0.0738255, 0.19333333],
+             [0., 0.02013423, 0.03333333, 0.01342282, 0., 0.0472973, 0.,
+              0., 0.],
+             [0.78767123, 0.45637584, 0.22, 0.39597315, 0.41610738, 0.20945946,
+              0.70068027, 0.89932886, 0.77333333],
+             [0., 0.02013423, 0.01333333, 0.00671141, 0.03355705, 0.00675676,
+              0., 0., 0.],
+             [0., 0., 0.01333333, 0., 0., 0., 0., 0., 0.],
+             [0.03424658, 0.16107383, 0.02666667, 0.00671141, 0.14765101,
+              0.01351351, 0., 0.01342282, 0.00666667]])
 
         self.coords = COORDS
-        self.coords_header = ['PC.354','PC.356','PC.481','PC.593',
-            'PC.355','PC.607','PC.634', 'PC.636', 'PC.635']
+        self.coords_header = ['PC.354', 'PC.356', 'PC.481', 'PC.593', 'PC.355',
+                              'PC.607', 'PC.634', 'PC.636', 'PC.635']
 
-        self.coord_fps = ['output_data/emperor/bray_curtis_pc_transformed_q1.txt',
+        self.coord_fps = [
+            'output_data/emperor/bray_curtis_pc_transformed_q1.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q10.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q11.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q12.txt',
@@ -77,15 +80,18 @@ class TopLevelTests(TestCase):
             'output_data/emperor/bray_curtis_pc_transformed_q12.txt',
             'output_data/emperor/qqq2223_curtis_qc_transformed_q13.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q14.txt',
-            'output_data/emperor/bray_curtis_pc_transformed_reference.txtoutput_data/emperor/bray_curtis_pc_transformed_q15.txt',
+            'output_data/emperor/bray_curtis_pc_transformed_reference.'
+            'txtoutput_data/emperor/bray_curtis_pc_transformed_q15.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q16.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q17.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q18.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q19.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q2.txt',
             'output_data/emperor/boom.txt',
-            'output_data/emperor/another_file with some characters and stuff .txt',
-            'output_data/emperor/some_other_file_that_foo_wants_to_compare.txt',
+            'output_data/emperor/another_file with some characters '
+            'and stuff .txt',
+            'output_data/emperor/some_other_file_that_foo_wants_to_'
+            'compare.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q23.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q24.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q25.txt',
@@ -101,8 +107,6 @@ class TopLevelTests(TestCase):
             'output_data/emperor/bray_curtis_pc_transformed_q8.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q9.txt']
 
-
-
     def test_sort_taxa_table_by_pcoa_coords(self):
         """Make sure OTU table and coordinates are sorted equally"""
 
@@ -110,26 +114,31 @@ class TopLevelTests(TestCase):
         o_headers, o_otu_table = sort_taxa_table_by_pcoa_coords(
             self.coords_header, self.otu_table, self.otu_headers)
 
-        self.assertEquals(o_headers, ['PC.354','PC.356','PC.481','PC.593',
-            'PC.355','PC.607','PC.634', 'PC.636', 'PC.635'])
+        self.assertEqual(o_headers, ['PC.354', 'PC.356', 'PC.481', 'PC.593',
+                                     'PC.355', 'PC.607', 'PC.634', 'PC.636',
+                                     'PC.635'])
         assert_almost_equal(o_otu_table, OTU_TABLE_A)
 
         # case with shuffled inputs and fewer samples
-        o_headers, o_otu_table = sort_taxa_table_by_pcoa_coords(['PC.354',
-            'PC.356','PC.635'], self.otu_table, self.otu_headers)
-        self.assertEquals(o_headers, ['PC.354','PC.356','PC.635'])
-        assert_almost_equal(o_otu_table, array([[ 0.01, 0.02, 0.04697987],[0.,
-            0.02, 0.02013423], [0.38926174, 0.65333333, 0.27516779],[0.,
-            0.03333333, 0.02013423],[0.41610738, 0.22, 0.45637584],[0.03355705,
-            0.01333333, 0.02013423],[0., 0.01333333, 0.],[0.14765101,
-            0.02666667, 0.16107383]]))
+        o_headers, o_otu_table = sort_taxa_table_by_pcoa_coords(
+            ['PC.354', 'PC.356', 'PC.635'], self.otu_table, self.otu_headers)
+        self.assertEqual(o_headers, ['PC.354', 'PC.356', 'PC.635'])
+        assert_almost_equal(o_otu_table, array(
+            [[0.01, 0.02, 0.04697987],
+             [0., 0.02, 0.02013423],
+             [0.38926174, 0.65333333, 0.27516779],
+             [0., 0.03333333, 0.02013423],
+             [0.41610738, 0.22, 0.45637584],
+             [0.03355705, 0.01333333, 0.02013423],
+             [0., 0.01333333, 0.],
+             [0.14765101, 0.02666667, 0.16107383]]))
 
     def test_sort_comparison_filenames_regular(self):
         """Check filenames are sorted correctly"""
 
         # check it correctly sorts the files according to the suffix
         out_sorted = sort_comparison_filenames(self.coord_fps)
-        self.assertEquals(out_sorted, [
+        self.assertEqual(out_sorted, [
             'output_data/emperor/bray_curtis_pc_transformed_q1.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q2.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q3.txt',
@@ -163,10 +172,13 @@ class TopLevelTests(TestCase):
         # if files with garbage are passed in, the sorting should be still
         # consistent,putting the "garbaged" filenames at the beginning
         out_sorted = sort_comparison_filenames(self.coord_fps_garbage)
-        self.assertEquals(out_sorted, ['output_data/emperor/aaaaaaa.txt',
+        self.assertEqual(out_sorted, [
+            'output_data/emperor/aaaaaaa.txt',
             'output_data/emperor/boom.txt',
-            'output_data/emperor/another_file with some characters and stuff .txt',
-            'output_data/emperor/some_other_file_that_foo_wants_to_compare.txt',
+            'output_data/emperor/another_file with some characters and '
+            'stuff .txt',
+            'output_data/emperor/some_other_file_that_foo_wants_to_'
+            'compare.txt',
             'output_data/emperor/bray_qurtis_pc_transformed_q1.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q2.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q3.txt',
@@ -180,7 +192,8 @@ class TopLevelTests(TestCase):
             'output_data/emperor/bray_curtis_pc_transformed_q12.txt',
             'output_data/emperor/qqq2223_curtis_qc_transformed_q13.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q14.txt',
-            'output_data/emperor/bray_curtis_pc_transformed_reference.txtoutput_data/emperor/bray_curtis_pc_transformed_q15.txt',
+            'output_data/emperor/bray_curtis_pc_transformed_reference.'
+            'txtoutput_data/emperor/bray_curtis_pc_transformed_q15.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q16.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q17.txt',
             'output_data/emperor/bray_curtis_pc_transformed_q18.txt',
@@ -200,7 +213,7 @@ class TopLevelTests(TestCase):
             'output_data_q44.txt/emperor/bray_curtis_pc_transformed_q11.txt',
             'output_dataq-5.txt/emperor/bray_curtis_pc_transformed_q3.txt',
             'output_data_q511.txt/emperor/bray_curtis_pc_transformed_q1.txt'])
-        self.assertEquals(out_sorted, [
+        self.assertEqual(out_sorted, [
             'output_data_q511.txt/emperor/bray_curtis_pc_transformed_q1.txt',
             'output_data/emperorq11.txt/bray_curtis_pc_transformed_q2.txt',
             'output_dataq-5.txt/emperor/bray_curtis_pc_transformed_q3.txt',
@@ -208,27 +221,52 @@ class TopLevelTests(TestCase):
             'output_data_q44.txt/emperor/bray_curtis_pc_transformed_q11.txt'])
 
         # make sure nothing happens when an empty list is passed
-        self.assertEquals(sort_comparison_filenames([]), [])
-
-
-COORDS = array([[0.280399117569, -0.0060128286014, 0.0234854344148, -0.0468109474823, -0.146624450094, 0.00566979124596, -0.0354299634191, -0.255785794275, -4.84141986706e-09],
-[0.228820399536, -0.130142097093, -0.287149447883, 0.0864498846421, 0.0442951919304, 0.20604260722, 0.0310003571386, 0.0719920436501, -4.84141986706e-09],
-[0.0422628480532, -0.0139681511889, 0.0635314615517, -0.346120552134, -0.127813807608, 0.0139350721063, 0.0300206887328, 0.140147849223, -4.84141986706e-09],
-[0.232872767451, 0.139788385269, 0.322871079774, 0.18334700682, 0.0204661596818, 0.0540589147147, -0.0366250872041, 0.0998235721267, -4.84141986706e-09],
-[0.170517581885, -0.194113268955, -0.0308965283066, 0.0198086158783, 0.155100062794, -0.279923941712, 0.0576092515759, 0.0242481862127, -4.84141986706e-09],
-[-0.0913299284215, 0.424147148265, -0.135627421345, -0.057519480907, 0.151363490722, -0.0253935675552, 0.0517306152066, -0.038738217609, -4.84141986706e-09],
-[-0.349339228244, -0.120787589539, 0.115274502117, 0.0694953933826, -0.0253722182853, 0.067853201946, 0.244447634756, -0.0598827706386, -4.84141986706e-09],
-[-0.276542163845, -0.144964375408, 0.0666467344429, -0.0677109454288, 0.176070269506, 0.072969390136, -0.229889463523, -0.0465989416581, -4.84141986706e-09],
-[-0.237661393984, 0.0460527772512, -0.138135814766, 0.159061025229, -0.247484698646, -0.115211468101, -0.112864033263, 0.0647940729676, -4.84141986706e-09]])
-
-OTU_TABLE_A = array([[ 0.01, 0.02, 0.04697987, 0.02027027, 0.01360544, 0.01342282, 0.02666667, 0.02739726, 0.04697987],
-[ 0., 0.02, 0.00671141, 0.00675676, 0., 0., 0., 0.00684932, 0.02013423],
-[ 0.38926174, 0.65333333, 0.52348993, 0.69594595, 0.28571429, 0.0738255, 0.19333333, 0.14383562, 0.27516779],
-[ 0., 0.03333333, 0.01342282, 0.0472973, 0., 0., 0., 0., 0.02013423],
-[ 0.41610738, 0.22, 0.39597315, 0.20945946, 0.70068027, 0.89932886, 0.77333333, 0.78767123, 0.45637584],
-[ 0.03355705, 0.01333333, 0.00671141, 0.00675676, 0., 0., 0., 0., 0.02013423],
-[ 0., 0.01333333, 0., 0., 0., 0., 0., 0., 0.],
-[ 0.14765101, 0.02666667, 0.00671141, 0.01351351, 0., 0.01342282, 0.00666667, 0.03424658, 0.16107383]])
+        self.assertEqual(sort_comparison_filenames([]), [])
+
+
+COORDS = array(
+    [[0.280399117569, -0.0060128286014, 0.0234854344148, -0.0468109474823,
+      -0.146624450094, 0.00566979124596, -0.0354299634191, -0.255785794275,
+      -4.84141986706e-09],
+     [0.228820399536, -0.130142097093, -0.287149447883, 0.0864498846421,
+      0.0442951919304, 0.20604260722, 0.0310003571386, 0.0719920436501,
+      -4.84141986706e-09],
+     [0.0422628480532, -0.0139681511889, 0.0635314615517, -0.346120552134,
+      -0.127813807608, 0.0139350721063, 0.0300206887328, 0.140147849223,
+      -4.84141986706e-09],
+     [0.232872767451, 0.139788385269, 0.322871079774, 0.18334700682,
+      0.0204661596818, 0.0540589147147, -0.0366250872041, 0.0998235721267,
+      -4.84141986706e-09],
+     [0.170517581885, -0.194113268955, -0.0308965283066, 0.0198086158783,
+      0.155100062794, -0.279923941712, 0.0576092515759, 0.0242481862127,
+      -4.84141986706e-09],
+     [-0.0913299284215, 0.424147148265, -0.135627421345, -0.057519480907,
+      0.151363490722, -0.0253935675552, 0.0517306152066, -0.038738217609,
+      -4.84141986706e-09],
+     [-0.349339228244, -0.120787589539, 0.115274502117, 0.0694953933826,
+      -0.0253722182853, 0.067853201946, 0.244447634756, -0.0598827706386,
+      -4.84141986706e-09],
+     [-0.276542163845, -0.144964375408, 0.0666467344429, -0.0677109454288,
+      0.176070269506, 0.072969390136, -0.229889463523, -0.0465989416581,
+      -4.84141986706e-09],
+     [-0.237661393984, 0.0460527772512, -0.138135814766, 0.159061025229,
+      -0.247484698646, -0.115211468101, -0.112864033263, 0.0647940729676,
+      -4.84141986706e-09]])
+
+OTU_TABLE_A = array(
+    [[0.01, 0.02, 0.04697987, 0.02027027, 0.01360544, 0.01342282, 0.02666667,
+      0.02739726, 0.04697987],
+     [0., 0.02, 0.00671141, 0.00675676, 0., 0., 0., 0.00684932, 0.02013423],
+     [0.38926174, 0.65333333, 0.52348993, 0.69594595, 0.28571429, 0.0738255,
+      0.19333333, 0.14383562, 0.27516779],
+     [0., 0.03333333, 0.01342282, 0.0472973, 0., 0., 0., 0., 0.02013423],
+     [0.41610738, 0.22, 0.39597315, 0.20945946, 0.70068027, 0.89932886,
+      0.77333333, 0.78767123, 0.45637584],
+     [0.03355705, 0.01333333, 0.00671141, 0.00675676, 0., 0., 0., 0.,
+      0.02013423],
+     [0., 0.01333333, 0., 0., 0., 0., 0., 0., 0.],
+     [0.14765101, 0.02666667, 0.00671141, 0.01351351, 0., 0.01342282,
+      0.00666667, 0.03424658, 0.16107383]])
 
 
 if __name__ == "__main__":
diff --git a/tests/test_util.py b/tests/test_util.py
old mode 100755
new mode 100644
index 74426f3..573bb02
--- a/tests/test_util.py
+++ b/tests/test_util.py
@@ -1,44 +1,47 @@
-#!/usr/bin/env python
-# File created on 25 Jan 2013
+# ----------------------------------------------------------------------------
+# Copyright (c) 2013--, emperor development team.
+#
+# Distributed under the terms of the Modified BSD License.
+#
+# The full license is in the file LICENSE.md, distributed with this software.
+# ----------------------------------------------------------------------------
 from __future__ import division
 
-__author__ = "Yoshiki Vazquez Baeza"
-__copyright__ = "Copyright 2013, The Emperor Project"
-__credits__ = ["Yoshiki Vazquez Baeza"]
-__license__ = "BSD"
-__version__ = "0.9.3"
-__maintainer__ = "Yoshiki Vazquez Baeza"
-__email__ = "yoshiki89 at gmail.com"
-__status__ = "Release"
-
-
 from unittest import TestCase, main
+from os.path import exists, join, abspath, dirname
 from shutil import rmtree
-from os.path import exists, join
 from tempfile import gettempdir
 
+import pandas as pd
 from numpy import array
 from numpy.testing import assert_almost_equal
 
-from emperor.util import (copy_support_files, keep_columns_from_mapping_file,
-    preprocess_mapping_file, preprocess_coords_file, EmperorInputFilesError,
-    fill_mapping_field_from_mapping_file, sanitize_mapping_file)
+from emperor.util import (keep_columns_from_mapping_file,
+                          preprocess_mapping_file, preprocess_coords_file,
+                          EmperorInputFilesError,
+                          fill_mapping_field_from_mapping_file,
+                          sanitize_mapping_file, guess_coordinates_files,
+                          nbinstall, validate_and_process_custom_axes)
+
 
 class TopLevelTests(TestCase):
 
     def setUp(self):
+        self.files_to_delete = []
+
         self.mapping_file_data = MAPPING_FILE_DATA
         self.mapping_file_headers = ['SampleID', 'BarcodeSequence',
-            'LinkerPrimerSequence', 'Treatment', 'DOB', 'Description']
+                                     'LinkerPrimerSequence', 'Treatment',
+                                     'DOB', 'Description']
         self.valid_columns = ['Treatment', 'DOB']
         self.support_files_filename = gettempdir()
-        self.support_files_filename_spaces = join(gettempdir(),
-            'Directory With Spaces/AndNoSpaces')
+        self.support_files_filename_spaces = join(
+            gettempdir(), 'Directory With Spaces/AndNoSpaces')
 
         # data for the custom axes, contains columns that are gradients
         self.mapping_file_data_gradient = MAPPING_FILE_DATA_GRADIENT
         self.mapping_file_headers_gradient = ['SampleID', 'Treatment', 'Time',
-            'Weight', 'Description']
+                                              'Weight', 'Description']
 
         self.coords_header = ['PC.355', 'PC.635', 'PC.636', 'PC.354']
         self.coords_data = COORDS_DATA
@@ -47,110 +50,191 @@ class TopLevelTests(TestCase):
 
         # jackknifed test data
         self.jk_mapping_file_headers = ['SampleID', 'C2', 'C3', 'C4']
-        self.jk_mapping_file_data = [['1', 'a', 'b', 'c'], ['2', 'd', 'e', 'f'],
-            ['3', 'g', 'h', 'i']]
+        self.jk_mapping_file_data = [['1', 'a', 'b', 'c'],
+                                     ['2', 'd', 'e', 'f'],
+                                     ['3', 'g', 'h', 'i']]
         self.jk_coords_header = [['1', '2', '3'], ['1', '2', '3'],
-            ['1', '2', '3'], ['1', '2', '3']]
-        self.jk_coords_data = [array([[1.2, 0.1, -1.2],[-2.5, -4.0, 4.5]]),
-            array([[-1.4, 0.05, 1.3],[2.6, 4.1, -4.7]]),
-            array([[-1.5, 0.05, 1.6],[2.4, 4.0, -4.8]]),
-            array([[-1.5, 0.05, 1.6],[2.4, 4.0, -4.8]])]
-        self.jk_coords_eigenvalues = [array([0.80, .11, 0.09]), array([0.76,
-            .20,0.04]), array([0.84, .14, 0.02]), array([0.84, .11, 0.05])]
-        self.jk_coords_pcts = [array([0.80, .10, 0.10]), array([0.76, .21,
-            0.03]), array([0.84, .11, 0.05]), array([0.84, .15, 0.01])]
+                                 ['1', '2', '3'], ['1', '2', '3']]
+        self.jk_coords_data = [
+            array([[1.2, 0.1, -1.2], [-2.5, -4.0, 4.5]]),
+            array([[-1.4, 0.05, 1.3], [2.6, 4.1, -4.7]]),
+            array([[-1.5, 0.05, 1.6], [2.4, 4.0, -4.8]]),
+            array([[-1.5, 0.05, 1.6], [2.4, 4.0, -4.8]])]
+        self.jk_coords_eigenvalues = [
+            array([0.80, .11, 0.09]),
+            array([0.76, .20, 0.04]),
+            array([0.84, .14, 0.02]),
+            array([0.84, .11, 0.05])]
+        self.jk_coords_pcts = [
+            array([0.80, .10, 0.10]),
+            array([0.76, .21, 0.03]),
+            array([0.84, .11, 0.05]),
+            array([0.84, .15, 0.01])]
 
         self.jk_mapping_file_data_gradient = MAPPING_FILE_DATA_GRADIENT
-        self.jk_mapping_file_headers_gradient = ['SampleID', 'Treatment','Time',
-            'Weight', 'Description']
-        self.jk_coords_header_gradient = [['PC.354','PC.355','PC.635','PC.636'],
-            ['PC.354','PC.355','PC.635','PC.636'], ['PC.354','PC.355','PC.635',
-            'PC.636'], ['PC.354','PC.355','PC.635','PC.636']]
-        self.jk_coords_data_gradient = [array([[1.2, 0.1, -1.2, 1.1],[-2.5,
-            -4.0, 4.5, 0.3], [.5, -0.4, 3.5, 1.001], [0.67, 0.23, 1.01, 2.2]]),
-            array([[1.2, 1, -0.2, 0.1],[-2.5, -4.0, 4.5, 3.2], [.5, -0.4, 3.5,
-            1.00], [0.57, 0.27, 0.95, 2.1]]), array([[1.0, 1, -1.2, 1.1],[-2.1,
-            -2.0, 3.5, 0.3], [.5, 3, 3.5, 2], [0.60, 0.33, 1.3, 2.0]]), array([
-            [1.2, 0.1, -1.2, 1.1],[-2.5,-4.0, 4.5, 0.3], [.5, -0.4, 3.5, 1.001],
-            [0.69, 0.20, 1.01, 2.2]])]
-        self.jk_coords_eigenvalues_gradient = [array([0.80, .11, 0.09, 0.0]),
-            array([0.76, .20,0.04, 0.0]), array([0.84, .14, 0.02, 0.0]), array([
-            0.84, .11, 0.05, 0.0])]
-        self.jk_coords_pcts_gradient = [array([0.80, .10, 0.10, 0.0]), array(
-            [0.76, .21, 0.03, 0.0]), array([0.84, .11, 0.05, 0.0]), array([0.84,
-            .15, 0.01, 0])]
+        self.jk_mapping_file_headers_gradient = ['SampleID', 'Treatment',
+                                                 'Time', 'Weight',
+                                                 'Description']
+        self.jk_coords_header_gradient = [
+            ['PC.354', 'PC.355', 'PC.635', 'PC.636'],
+            ['PC.354', 'PC.355', 'PC.635', 'PC.636'],
+            ['PC.354', 'PC.355', 'PC.635', 'PC.636'],
+            ['PC.354', 'PC.355', 'PC.635', 'PC.636']]
+        self.jk_coords_data_gradient = [
+            array([[1.2, 0.1, -1.2, 1.1],
+                   [-2.5, -4.0, 4.5, 0.3],
+                   [.5, -0.4, 3.5, 1.001],
+                   [0.67, 0.23, 1.01, 2.2]]),
+            array([[1.2, 1, -0.2, 0.1],
+                   [-2.5, -4.0, 4.5, 3.2],
+                   [.5, -0.4, 3.5, 1.00],
+                   [0.57, 0.27, 0.95, 2.1]]),
+            array([[1.0, 1, -1.2, 1.1],
+                   [-2.1, -2.0, 3.5, 0.3],
+                   [.5, 3, 3.5, 2],
+                   [0.60, 0.33, 1.3, 2.0]]),
+            array([[1.2, 0.1, -1.2, 1.1],
+                   [-2.5, -4.0, 4.5, 0.3],
+                   [.5, -0.4, 3.5, 1.001],
+                   [0.69, 0.20, 1.01, 2.2]])]
+        self.jk_coords_eigenvalues_gradient = [
+            array([0.80, .11, 0.09, 0.0]),
+            array([0.76, .20, 0.04, 0.0]),
+            array([0.84, .14, 0.02, 0.0]),
+            array([0.84, .11, 0.05, 0.0])]
+        self.jk_coords_pcts_gradient = [
+            array([0.80, .10, 0.10, 0.0]),
+            array([0.76, .21, 0.03, 0.0]),
+            array([0.84, .11, 0.05, 0.0]),
+            array([0.84, .15, 0.01, 0])]
 
         self.broken_mapping_file_data = BROKEN_MAPPING_FILE
         self.broken_mapping_file_data_2_values = BROKEN_MAPPING_FILE_2_VALUES
 
-    def test_copy_support_files(self):
-        """Test the support files are correctly copied to a file path"""
-        copy_support_files(self.support_files_filename)
-        self.assertTrue(exists(join(self.support_files_filename,
-            'emperor_required_resources/')))
-
-        # related to https://github.com/qiime/emperor/issues/66
-        # the target path has spaces, the support files function will work fine
-        copy_support_files(self.support_files_filename_spaces)
-        self.assertTrue(exists(join(self.support_files_filename_spaces,
-            'emperor_required_resources/')))
+    def tearDown(self):
+        for f in self.files_to_delete:
+            rmtree(f)
 
     def test_preprocess_mapping_file(self):
         """Check correct preprocessing of metadata is done"""
 
         # test it concatenates columns together correctly
-        out_data, out_headers = preprocess_mapping_file(self.mapping_file_data,
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
             self.mapping_file_headers, ['Treatment', 'DOB', 'Treatment&&DOB'])
-        self.assertEquals(out_headers, ['SampleID', 'Treatment', 'DOB',
-            'Treatment&&DOB'])
-        self.assertEquals(out_data, MAPPING_FILE_DATA_CAT_A)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'Treatment', 'DOB', 'Treatment&&DOB'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_A)
 
         # test it has a different order in the concatenated columns i. e. the
         # value of DOB comes before the value of Treatment in the result
-        out_data, out_headers = preprocess_mapping_file(self.mapping_file_data,
-            self.mapping_file_headers, ['Treatment', 'DOB', 'DOB&&Treatment'])
-        self.assertEquals(out_headers, ['SampleID', 'Treatment', 'DOB',
-            'DOB&&Treatment'])
-        self.assertEquals(out_data, MAPPING_FILE_DATA_CAT_B)
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['Treatment', 'DOB', 'DOB&&Treatment'])
+        self.assertEqual(out_headers,
+                         ['SampleID', 'Treatment', 'DOB', 'DOB&&Treatment'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_B)
 
         # test it filter columns properly
-        out_data, out_headers = preprocess_mapping_file(self.mapping_file_data,
-            self.mapping_file_headers, ['Treatment'])
-        self.assertEquals(out_headers, ['SampleID', 'Treatment'])
-        self.assertEquals(out_data, MAPPING_FILE_DATA_CAT_C)
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['Treatment'])
+        self.assertEqual(out_headers, ['SampleID', 'Treatment'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_C)
 
         # check it removes columns with unique values
-        out_data, out_headers = preprocess_mapping_file(self.mapping_file_data,
-            self.mapping_file_headers, ['SampleID', 'BarcodeSequence',
-            'LinkerPrimerSequence', 'Treatment', 'DOB', 'Description'],
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['SampleID', 'LinkerPrimerSequence', 'Treatment', 'DOB'],
             unique=True)
-        self.assertEquals(out_headers, ['SampleID', 'LinkerPrimerSequence',
-            'Treatment', 'DOB'])
-        self.assertEquals(out_data, MAPPING_FILE_DATA_CAT_D)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'LinkerPrimerSequence', 'Treatment',
+                          'DOB'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_D)
 
         # check it removes columns where there is only one value
-        out_data, out_headers = preprocess_mapping_file(self.mapping_file_data,
-            self.mapping_file_headers, ['SampleID', 'BarcodeSequence',
-            'LinkerPrimerSequence', 'Treatment', 'DOB', 'Description'],
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['SampleID', 'BarcodeSequence', 'Treatment', 'DOB', 'Description'],
             single=True)
-        self.assertEquals(out_headers,['SampleID', 'BarcodeSequence',
-            'Treatment', 'DOB', 'Description'])
-        self.assertEquals(out_data, MAPPING_FILE_DATA_CAT_E)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'BarcodeSequence', 'Treatment', 'DOB',
+                          'Description'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_E)
 
         # keep only treatment concat treatment and DOB and remove all
         # categories with only one value and all with unique values for field
-        out_data, out_headers = preprocess_mapping_file(self.mapping_file_data,
-            self.mapping_file_headers, ['Treatment', 'Treatment&&DOB'],
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['Treatment', 'Treatment&&DOB'],
             unique=True, single=True)
-        self.assertEquals(out_headers, ['SampleID', 'Treatment',
-            'Treatment&&DOB'])
-        self.assertEquals(out_data, MAPPING_FILE_DATA_CAT_F)
-
-        out_data, out_headers = preprocess_mapping_file(self.mapping_file_data,
-            self.mapping_file_headers, ['Treatment', 'DOB'], clones=3)
-        self.assertEquals(out_data, MAPPING_FILE_DATA_DUPLICATED)
-        self.assertEquals(out_headers, ['SampleID', 'Treatment', 'DOB'])
-
+        self.assertEqual(out_headers,
+                         ['SampleID', 'Treatment', 'Treatment&&DOB'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_F)
+
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['Treatment', 'DOB'], clones=3)
+        self.assertEqual(out_data, MAPPING_FILE_DATA_DUPLICATED)
+        self.assertEqual(out_headers, ['SampleID', 'Treatment', 'DOB'])
+
+        # check it doesn't remove columns because all are included in the list
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+             'Treatment', 'DOB', 'Description'],
+            unique=True)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'BarcodeSequence',
+                          'LinkerPrimerSequence', 'Treatment', 'DOB',
+                          'Description'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_G)
+
+        # check it doesn't remove columns because all are included in the list
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+             'Treatment', 'DOB', 'Description'],
+            single=True)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'BarcodeSequence',
+                          'LinkerPrimerSequence', 'Treatment', 'DOB',
+                          'Description'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_G)
+
+        # check it doesn't remove columns because all are included in the list
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            self.mapping_file_headers,
+            ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+             'Treatment', 'DOB', 'Description'],
+            unique=True, single=True)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'BarcodeSequence',
+                          'LinkerPrimerSequence', 'Treatment', 'DOB',
+                          'Description'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_G)
+
+        # make sure that when keeping columns that are all unique the
+        # columns are basically intact i. e. everything in the dataset is kept
+        out_data, out_headers = preprocess_mapping_file(
+            self.mapping_file_data,
+            ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+             'Treatment', 'DOB', 'Description'],
+            [None], unique=False)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'BarcodeSequence',
+                          'LinkerPrimerSequence', 'Treatment', 'DOB',
+                          'Description'])
+        self.assertEqual(out_data, MAPPING_FILE_DATA_CAT_G)
 
     def test_keep_columns_from_mapping_file(self):
         """Check correct selection of metadata is being done"""
@@ -158,24 +242,24 @@ class TopLevelTests(TestCase):
         # test it returns the same data
         out_data, out_headers = keep_columns_from_mapping_file(
             self.mapping_file_data, self.mapping_file_headers, [])
-        self.assertEquals(out_data, [[], [], [], [], [], [], [], [], []])
-        self.assertEquals(out_headers, [])
+        self.assertEqual(out_data, [[], [], [], [], [], [], [], [], []])
+        self.assertEqual(out_headers, [])
 
         # test it can filter a list of columns
         out_data, out_headers = keep_columns_from_mapping_file(
-            self.mapping_file_data, self.mapping_file_headers, [
-            'SampleID', 'LinkerPrimerSequence', 'Description'])
-        self.assertEquals(out_headers, ['SampleID', 'LinkerPrimerSequence',
-            'Description'])
-        self.assertEquals(out_data, PRE_PROCESS_B)
+            self.mapping_file_data, self.mapping_file_headers,
+            ['SampleID', 'LinkerPrimerSequence', 'Description'])
+        self.assertEqual(out_headers,
+                         ['SampleID', 'LinkerPrimerSequence', 'Description'])
+        self.assertEqual(out_data, PRE_PROCESS_B)
 
         # test correct negation of filtering
         out_data, out_headers = keep_columns_from_mapping_file(
             self.mapping_file_data, self.mapping_file_headers,
             ['LinkerPrimerSequence', 'Description'], True)
-        self.assertEquals(out_data, PRE_PROCESS_A)
-        self.assertEquals(out_headers,  ['SampleID', 'BarcodeSequence',
-            'Treatment', 'DOB'])
+        self.assertEqual(out_data, PRE_PROCESS_A)
+        self.assertEqual(out_headers,
+                         ['SampleID', 'BarcodeSequence', 'Treatment', 'DOB'])
 
     def test_preprocess_coords_file(self):
         """Check correct processing is applied to the coords"""
@@ -183,102 +267,146 @@ class TopLevelTests(TestCase):
         # case with custom axes
         out_coords_header, out_coords_data, out_eigenvals, out_pcts,\
             out_coords_low, out_coords_high, o_clones = preprocess_coords_file(
-            self.coords_header, self.coords_data, self.coords_eigenvalues,
-            self.coords_pct, self.mapping_file_headers_gradient,
-            self.mapping_file_data_gradient, ['Time'])
-
-        expected_coords_data = array([[ 0.03333333, -0.2, -0.1,0.06, -0.06],
-           [0.03333333, -0.3, 0.04, -0.1,0.15],
-           [0.2, 0.1, -0.1, -0.2, 0.08],
-           [-0.3, 0.04, -0.01,  0.06, -0.34]])
-
-        self.assertEquals(out_coords_header, self.coords_header)
-        self.assertEquals(out_coords_high, None)
-        self.assertEquals(out_coords_low, None)
+                self.coords_header, self.coords_data, self.coords_eigenvalues,
+                self.coords_pct, self.mapping_file_headers_gradient,
+                self.mapping_file_data_gradient, ['Time'])
+
+        expected_coords_data = array(
+            [[0.03333333, -0.2, -0.1, 0.06, -0.06],
+             [0.03333333, -0.3, 0.04, -0.1, 0.15],
+             [0.2, 0.1, -0.1, -0.2, 0.08],
+             [-0.3, 0.04, -0.01,  0.06, -0.34]])
+
+        self.assertEqual(out_coords_header, self.coords_header)
+        self.assertEqual(out_coords_high, None)
+        self.assertEqual(out_coords_low, None)
         assert_almost_equal(self.coords_eigenvalues, array([1, 2, 3, 4]))
         assert_almost_equal(self.coords_pct, array([40, 30, 20, 10]))
-        self.assertEquals(o_clones, 0)
+        self.assertEqual(o_clones, 0)
 
         # check each individual value because currently cogent assertEquals
         # fails when comparing the whole matrix at once
         for out_el, exp_el in zip(out_coords_data, expected_coords_data):
             for out_el_sub, exp_el_sub in zip(out_el, exp_el):
-                self.assertAlmostEquals(out_el_sub, exp_el_sub)        
+                self.assertAlmostEqual(out_el_sub, exp_el_sub)
 
         # case for jackknifing, based on qiime/tests/test_util.summarize_pcoas
         out_coords_header, out_coords_data, out_eigenvals, out_pcts,\
             out_coords_low, out_coords_high, o_clones = preprocess_coords_file(
-            self.jk_coords_header, self.jk_coords_data,
-            self.jk_coords_eigenvalues, self.jk_coords_pcts,
-            self.jk_mapping_file_headers, self.jk_mapping_file_data,
-            jackknifing_method='sdev')
-
-        self.assertEquals(out_coords_header, ['1', '2', '3'])
-        assert_almost_equal(out_coords_data, array([[ 1.4, -0.0125, -1.425],
-            [-2.475, -4.025, 4.7]]))
-        assert_almost_equal(out_eigenvals, array([ 0.81, 0.14, 0.05]))
+                self.jk_coords_header, self.jk_coords_data,
+                self.jk_coords_eigenvalues, self.jk_coords_pcts,
+                self.jk_mapping_file_headers, self.jk_mapping_file_data,
+                jackknifing_method='sdev', pct_variation_below_one=True)
+
+        self.assertEqual(out_coords_header, ['1', '2', '3'])
+        assert_almost_equal(out_coords_data, array([[1.4, -0.0125, -1.425],
+                                                    [-2.475, -4.025, 4.7]]))
+        assert_almost_equal(out_eigenvals, array([0.81, 0.14, 0.05]))
         assert_almost_equal(out_pcts, array([0.8, 0.1, 0.1]))
-        self.assertEquals(o_clones, 0)
+        self.assertEqual(o_clones, 0)
 
         # test the coords are working fine
-        assert_almost_equal(out_coords_low, array([[-0.07071068, -0.0375,
-            -0.10307764], [-0.04787136, -0.025, -0.07071068]]))
-        assert_almost_equal(out_coords_high, array([[ 0.07071068, 0.0375, 
-            0.10307764], [0.04787136, 0.025, 0.07071068]]))
+        assert_almost_equal(out_coords_low,
+                            array([[-0.07071068, -0.0375, -0.10307764],
+                                   [-0.04787136, -0.025, -0.07071068]]))
+        assert_almost_equal(out_coords_high,
+                            array([[0.07071068, 0.0375, 0.10307764],
+                                   [0.04787136, 0.025, 0.07071068]]))
 
         # test custom axes and jackknifed plots
         out_coords_header, out_coords_data, out_eigenvals, out_pcts,\
             out_coords_low, out_coords_high, o_clones = preprocess_coords_file(
-            self.jk_coords_header_gradient, self.jk_coords_data_gradient,
-            self.jk_coords_eigenvalues_gradient, self.jk_coords_pcts_gradient,
-            self.jk_mapping_file_headers_gradient,
-            self.jk_mapping_file_data_gradient, custom_axes=['Time'],
-            jackknifing_method='sdev')
-
-        self.assertEquals(out_coords_header, ['PC.354', 'PC.355', 'PC.635',
-            'PC.636'])
-        assert_almost_equal(out_coords_data, array([[-2.4, 1.15, 0.55, -0.95,
-            0.85], [0.73333333, -2.4, -3.5, 4.25, 1.025], [0.73333333, 0.5,
-            0.45, 3.5, 1.2505], [2.3, 0.6325, 0.2575, 1.0675, 2.125]]))
-        assert_almost_equal(out_eigenvals, array([ 0.81, 0.14, 0.05, 0.]))
-        assert_almost_equal(out_pcts, array([ 0.8,  0.1,  0.1,  0. ]))
+                self.jk_coords_header_gradient, self.jk_coords_data_gradient,
+                self.jk_coords_eigenvalues_gradient,
+                self.jk_coords_pcts_gradient,
+                self.jk_mapping_file_headers_gradient,
+                self.jk_mapping_file_data_gradient, custom_axes=['Time'],
+                jackknifing_method='sdev', pct_variation_below_one=True)
+
+        self.assertEqual(out_coords_header,
+                         ['PC.354', 'PC.355', 'PC.635', 'PC.636'])
+        assert_almost_equal(out_coords_data,
+                            array([[-2.4, 1.15, 0.55, -0.95, 0.85],
+                                   [0.73333333, -2.4, -3.5, 4.25, 1.025],
+                                   [0.73333333, 0.5, 0.45, 3.5, 1.2505],
+                                   [2.3, 0.6325, 0.2575, 1.0675, 2.125]]))
+        assert_almost_equal(out_eigenvals, array([0.81, 0.14, 0.05, 0.]))
+        assert_almost_equal(out_pcts, array([0.8, 0.1, 0.1, 0.]))
 
         # test the coords are working fine
-        assert_almost_equal(out_coords_low, array([[ 0., -0.25980762, -0.25,
-            -0.25], [ 0., -0.5, -0.25, -0.725], [ 0., -0.85, -0., -0.24983344],
-            [ 0., -0.02809953, -0.07877976, -0.04787136]]))
-        assert_almost_equal(out_coords_high, array([[1.00000000e-05, 
-            2.59807621e-01, 2.50000000e-01, 2.50000000e-01], [1.00000000e-05,
-            5.00000000e-01, 2.50000000e-01, 7.25000000e-01], [1.00000000e-05,
-            8.50000000e-01, 0.00000000e+00, 2.49833445e-01], [1.00000000e-05,
-            2.80995255e-02, 7.87797563e-02, 4.78713554e-02]]))
-        self.assertEquals(o_clones, 0)
+        assert_almost_equal(
+            out_coords_low,
+            array([[0., -0.25980762, -0.25, -0.25],
+                   [0., -0.5, -0.25, -0.725],
+                   [0., -0.85, -0., -0.24983344],
+                   [0., -0.02809953, -0.07877976, -0.04787136]]))
+        assert_almost_equal(
+            out_coords_high,
+            array([[1.00000000e-05, 2.59807621e-01, 2.50000000e-01,
+                    2.50000000e-01],
+                   [1.00000000e-05, 5.00000000e-01, 2.50000000e-01,
+                    7.25000000e-01],
+                   [1.00000000e-05, 8.50000000e-01, 0.00000000e+00,
+                    2.49833445e-01],
+                   [1.00000000e-05, 2.80995255e-02, 7.87797563e-02,
+                    4.78713554e-02]]))
+        self.assertEqual(o_clones, 0)
+
+        # test that pct_variation_below_one is working
+        out_coords_header, out_coords_data, out_eigenvals, out_pcts,\
+            out_coords_low, out_coords_high, o_clones = preprocess_coords_file(
+                self.jk_coords_header_gradient, self.jk_coords_data_gradient,
+                self.jk_coords_eigenvalues_gradient,
+                self.jk_coords_pcts_gradient,
+                self.jk_mapping_file_headers_gradient,
+                self.jk_mapping_file_data_gradient, custom_axes=['Time'],
+                jackknifing_method='sdev', pct_variation_below_one=False)
+
+        self.assertEqual(out_coords_header,
+                         ['PC.354', 'PC.355', 'PC.635', 'PC.636'])
+        assert_almost_equal(
+            out_coords_data,
+            array([[-2.4, 1.15, 0.55, -0.95, 0.85],
+                   [0.73333333, -2.4, -3.5, 4.25, 1.025],
+                   [0.73333333, 0.5, 0.45, 3.5, 1.2505],
+                   [2.3, 0.6325, 0.2575, 1.0675, 2.125]]))
+        assert_almost_equal(out_eigenvals, array([0.81, 0.14, 0.05, 0.]))
+        assert_almost_equal(out_pcts, array([80, 10, 10, 0]))
 
     def test_preprocess_coords_file_comparison(self):
         """Check the cases for comparisons plots and the special usages"""
         # shouldn't allow a comparison computation with only one file
-        self.assertRaises(AssertionError, preprocess_coords_file,
+        self.assertRaises(
+            AssertionError, preprocess_coords_file,
             self.coords_header, self.coords_data, self.coords_eigenvalues,
             self.coords_pct, self.mapping_file_headers_gradient,
             self.mapping_file_data_gradient, None, None, True)
 
         out_coords_header, out_coords_data, out_eigenvals, out_pcts,\
             out_coords_low, out_coords_high, o_clones = preprocess_coords_file(
-            self.jk_coords_header, self.jk_coords_data,
-            self.jk_coords_eigenvalues, self.jk_coords_pcts,
-            self.jk_mapping_file_headers, self.jk_mapping_file_data,
-            is_comparison=True)
-
-        self.assertEquals(out_coords_header, ['1_0', '2_0', '3_0', '1_1', '2_1',
-            '3_1', '1_2', '2_2', '3_2', '1_3', '2_3', '3_3'])
-        assert_almost_equal(out_coords_data, array([[ 1.2 , 0.1 , -1.2],[-2.5,
-            -4., 4.5], [-1.4, 0.05, 1.3], [ 2.6, 4.1, -4.7], [-1.5, 0.05, 1.6],
-            [ 2.4, 4., -4.8], [-1.5, 0.05, 1.6], [ 2.4, 4., -4.8]]))
+                self.jk_coords_header, self.jk_coords_data,
+                self.jk_coords_eigenvalues, self.jk_coords_pcts,
+                self.jk_mapping_file_headers, self.jk_mapping_file_data,
+                is_comparison=True, pct_variation_below_one=True)
+
+        self.assertEqual(out_coords_header,
+                         ['1_0', '2_0', '3_0', '1_1', '2_1', '3_1', '1_2',
+                          '2_2', '3_2', '1_3', '2_3', '3_3'])
+        assert_almost_equal(
+            out_coords_data,
+            array([[1.2, 0.1, -1.2],
+                   [-2.5, -4., 4.5],
+                   [-1.4, 0.05, 1.3],
+                   [2.6, 4.1, -4.7],
+                   [-1.5, 0.05, 1.6],
+                   [2.4, 4., -4.8],
+                   [-1.5, 0.05, 1.6],
+                   [2.4, 4., -4.8]]))
         assert_almost_equal(out_eigenvals, self.jk_coords_eigenvalues[0])
         assert_almost_equal(out_pcts, self.jk_coords_pcts[0])
-        self.assertEquals(out_coords_low, None)
-        self.assertEquals(out_coords_high, None)
-        self.assertEquals(o_clones, 4)
+        self.assertEqual(out_coords_low, None)
+        self.assertEqual(out_coords_high, None)
+        self.assertEqual(o_clones, 4)
 
     def test_fill_mapping_field_from_mapping_file(self):
         """Check the values are being correctly filled in"""
@@ -287,85 +415,202 @@ class TopLevelTests(TestCase):
         out_data = fill_mapping_field_from_mapping_file(
             self.broken_mapping_file_data, self.mapping_file_headers_gradient,
             'Time:200;Weight:800')
-        self.assertEquals(out_data, [
-            ['PC.354', 'Control','3', '40', 'Control20061218'],
-            ['PC.355', 'Control','200', '44', 'Control20061218'],
-            ['PC.635', 'Fast','9', '800', 'Fast20080116'],
-            ['PC.636', 'Fast','12', '37.22', 'Fast20080116']])
+        self.assertEqual(out_data, [
+            ['PC.354', 'Control', '3', '40', 'Control20061218'],
+            ['PC.355', 'Control', '200', '44', 'Control20061218'],
+            ['PC.635', 'Fast', '9', '800', 'Fast20080116'],
+            ['PC.636', 'Fast', '12', '37.22', 'Fast20080116']])
 
         # more than one value to fill empty values with
-        self.assertRaises(AssertionError, fill_mapping_field_from_mapping_file,
+        self.assertRaises(
+            AssertionError, fill_mapping_field_from_mapping_file,
             self.broken_mapping_file_data, self.mapping_file_headers_gradient,
             'Time:200,300;Weight:800')
 
         # non-existing header in mapping file
-        self.assertRaises(EmperorInputFilesError, fill_mapping_field_from_mapping_file,
+        self.assertRaises(
+            EmperorInputFilesError, fill_mapping_field_from_mapping_file,
             self.broken_mapping_file_data, self.mapping_file_headers_gradient,
             'Spam:Foo')
-        
+
         # testing multiple values
         out_data = fill_mapping_field_from_mapping_file(
-            self.broken_mapping_file_data_2_values, self.mapping_file_headers_gradient,
+            self.broken_mapping_file_data_2_values,
+            self.mapping_file_headers_gradient,
             'Time:Treatment==Control=444;Time:Treatment==Fast=888')
-        self.assertEquals(out_data, [
-            ['PC.354', 'Control', '3', '40', 'Control20061218'], 
-            ['PC.355', 'Control', '444', '44', 'Control20061218'], 
-            ['PC.635', 'Fast', '888', 'x', 'Fast20080116'], 
+        self.assertEqual(out_data, [
+            ['PC.354', 'Control', '3', '40', 'Control20061218'],
+            ['PC.355', 'Control', '444', '44', 'Control20061218'],
+            ['PC.635', 'Fast', '888', 'x', 'Fast20080116'],
             ['PC.636', 'Fast', '12', '37.22', 'Fast20080116']])
-        
+
         # testing multiple values: blank column name
-        self.assertRaises(AssertionError, fill_mapping_field_from_mapping_file,
-            self.broken_mapping_file_data_2_values, self.mapping_file_headers_gradient,
+        self.assertRaises(
+            AssertionError, fill_mapping_field_from_mapping_file,
+            self.broken_mapping_file_data_2_values,
+            self.mapping_file_headers_gradient,
             'Time:Treatment===200600020')
-        
+
         # testing multiple values: wrong order
-        self.assertRaises(AssertionError, fill_mapping_field_from_mapping_file,
-            self.broken_mapping_file_data_2_values, self.mapping_file_headers_gradient,
+        self.assertRaises(
+            AssertionError, fill_mapping_field_from_mapping_file,
+            self.broken_mapping_file_data_2_values,
+            self.mapping_file_headers_gradient,
             'Time:Treatment=Control==200600020')
-        
+
         # testing multiple values: error when more than 1 value is passed
-        self.assertRaises(AssertionError, fill_mapping_field_from_mapping_file,
-            self.broken_mapping_file_data_2_values, self.mapping_file_headers_gradient,
+        self.assertRaises(
+            AssertionError, fill_mapping_field_from_mapping_file,
+            self.broken_mapping_file_data_2_values,
+            self.mapping_file_headers_gradient,
             'Time:Treatment=Control==200600020,435')
- 
+
     def test_sanitize_mapping_file(self):
         """Check the mapping file strings are sanitized for it's use in JS"""
 
         o_sanitized_headers, o_sanitized_data = sanitize_mapping_file(
-            UNSANITZIED_MAPPING_DATA, ['SampleID', 'BarcodeSequence',
-            'LinkerPrimerSequence', 'Treatment', 'DOB', 'Descr"""""iption'])
-
-        self.assertEquals(o_sanitized_data, ['SampleID', 'BarcodeSequence',
-            'LinkerPrimerSequence', 'Treatment', 'DOB','Description'])
-        self.assertEquals(o_sanitized_headers, [
-['PC.354', "Dr. Bronners", 'Control', '20061218', 'Control_mouse_I.D._354'],
-['PC.355', 'AACTCGTCGATG', "Control", '20061218', 'Control_mouse_I.D._355'],
-["PC356", 'ACAGACCACTCA', 'Control', '20061126', 'Control_mouse_I.D._356'],
-['PC.481', 'ACAGCACTAG', 'Control', '20070314', 'Control_mouse_I.D._481'],
-['PC.593', 'AGCAGCACTTGT', 'Control', '20071210', 'Control_mouse_I.D._593']])
+            UNSANITZIED_MAPPING_DATA,
+            ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+             'Treatment', 'DOB', 'Descr"""""iption'])
+
+        self.assertEqual(
+            o_sanitized_data,
+            ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+             'Treatment', 'DOB', 'Description'])
+        self.assertEqual(o_sanitized_headers, [
+            ['PC.354', "Dr. Bronners", 'Control', '20061218',
+             'Control_mouse_I.D._354'],
+            ['PC.355', 'AACTCGTCGATG', 'Control', '20061218',
+             'Control_mouse_I.D._355'],
+            ["PC356", 'ACAGACCACTCA', 'Control', '20061126',
+             'Control_mouse_I.D._356'],
+            ['PC.481', 'ACAGCACTAG', 'Control', '20070314',
+             'Control_mouse_I.D._481'],
+            ['PC.593', 'AGCAGCACTTGT', 'Control', '20071210',
+             'Control_mouse_I.D._593']])
+
+    def test_guess_coordinates_files(self):
+        dir_path = join(abspath(dirname(__file__)), 'test_data')
+
+        fps = guess_coordinates_files(dir_path)
+        # get a list of the files we expect
+        exp = [join(dir_path,
+                    'unweighted_unifrac_pc_transformed_reference.txt'),
+               join(dir_path, 'weighted_unifrac_pc_transformed_q1.txt')]
+        try:
+            self.assertItemsEqual(fps, exp)
+        except AttributeError:
+            self.assertCountEqual(fps, exp)
+
+        # testing a directory with only files that should be ignored
+        dir_path = join(abspath(dirname(__file__)), 'test_data',
+                        'dir-with-only-hidden-files')
+        fps = guess_coordinates_files(dir_path)
+        self.assertEqual(fps, [])
+
+    def test_nbinstall(self):
+        temp_dir = gettempdir()
+        target_path = join(temp_dir, 'share/jupyter/nbextensions/emperor/'
+                           'support_files')
+
+        # remove the whole tree
+        self.files_to_delete.append(join(temp_dir, 'share'))
+
+        nbinstall(prefix=temp_dir, user=None)
+
+        self.assertTrue(exists(target_path))
+
+    def test_custom_axes(self):
+        columns = ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+                   'Treatment', 'DOB', 'Description']
+        mf = pd.DataFrame(data=MAPPING_FILE_DATA, columns=columns)
+        obs = validate_and_process_custom_axes(mf, ['DOB'])
+        exp = pd.DataFrame(data=MAPPING_FILE_DATA_CONVERTED, columns=columns)
+        pd.util.testing.assert_frame_equal(obs, exp)
+
+    def test_custom_axes_non_existent_names(self):
+        columns = ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+                   'Treatment', 'DOB', 'Description']
+        mf = pd.DataFrame(data=MAPPING_FILE_DATA, columns=columns)
+
+        with self.assertRaises(KeyError):
+            validate_and_process_custom_axes(mf, [':L'])
+
+        with self.assertRaises(KeyError):
+            validate_and_process_custom_axes(mf, ['D0B'])
+
+    def test_custom_axes_non_numeric_values(self):
+        columns = ['SampleID', 'BarcodeSequence', 'LinkerPrimerSequence',
+                   'Treatment', 'DOB', 'Description']
+        mf = pd.DataFrame(data=MAPPING_FILE_DATA, columns=columns)
+
+        with self.assertRaises(ValueError):
+            validate_and_process_custom_axes(mf, ['Treatment'])
+
+        with self.assertRaises(ValueError):
+            validate_and_process_custom_axes(mf, ['SampleID'])
+
+    def test_custom_axes_non_numeric_values_mixed(self):
+        columns = ['SampleID', 'huey', 'dewey', 'louie', 'Description']
+        mf = pd.DataFrame(data=BROKEN_MAPPING_FILE, columns=columns)
+
+        with self.assertRaises(ValueError):
+            validate_and_process_custom_axes(mf, ['louie'])
+
+        with self.assertRaises(ValueError):
+            validate_and_process_custom_axes(mf, ['louie', 'dewey'])
 
 
 MAPPING_FILE_DATA = [
-    ['PC.354','AGCACGAGCCTA','YATGCTGCCTCCCGTAGGAGT','Control','20061218','Control_mouse_I.D._354'],
-    ['PC.355','AACTCGTCGATG','YATGCTGCCTCCCGTAGGAGT','Control','20061218','Control_mouse_I.D._355'],
-    ['PC.356','ACAGACCACTCA','YATGCTGCCTCCCGTAGGAGT','Control','20061126','Control_mouse_I.D._356'],
-    ['PC.481','ACCAGCGACTAG','YATGCTGCCTCCCGTAGGAGT','Control','20070314','Control_mouse_I.D._481'],
-    ['PC.593','AGCAGCACTTGT','YATGCTGCCTCCCGTAGGAGT','Control','20071210','Control_mouse_I.D._593'],
-    ['PC.607','AACTGTGCGTAC','YATGCTGCCTCCCGTAGGAGT','Fast','20071112','Fasting_mouse_I.D._607'],
-    ['PC.634','ACAGAGTCGGCT','YATGCTGCCTCCCGTAGGAGT','Fast','20080116','Fasting_mouse_I.D._634'],
-    ['PC.635','ACCGCAGAGTCA','YATGCTGCCTCCCGTAGGAGT','Fast','20080116','Fasting_mouse_I.D._635'],
-    ['PC.636','ACGGTGAGTGTC','YATGCTGCCTCCCGTAGGAGT','Fast','20080116','Fasting_mouse_I.D._636']]
+    ['PC.354', 'AGCACGAGCCTA', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061218',
+     'Control_mouse_I.D._354'],
+    ['PC.355', 'AACTCGTCGATG', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061218',
+     'Control_mouse_I.D._355'],
+    ['PC.356', 'ACAGACCACTCA', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061126',
+     'Control_mouse_I.D._356'],
+    ['PC.481', 'ACCAGCGACTAG', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20070314',
+     'Control_mouse_I.D._481'],
+    ['PC.593', 'AGCAGCACTTGT', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20071210',
+     'Control_mouse_I.D._593'],
+    ['PC.607', 'AACTGTGCGTAC', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20071112',
+     'Fasting_mouse_I.D._607'],
+    ['PC.634', 'ACAGAGTCGGCT', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116',
+     'Fasting_mouse_I.D._634'],
+    ['PC.635', 'ACCGCAGAGTCA', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116',
+     'Fasting_mouse_I.D._635'],
+    ['PC.636', 'ACGGTGAGTGTC', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116',
+     'Fasting_mouse_I.D._636']]
+
+MAPPING_FILE_DATA_CONVERTED = [
+    ['PC.354', 'AGCACGAGCCTA', 'YATGCTGCCTCCCGTAGGAGT', 'Control', 20061218,
+     'Control_mouse_I.D._354'],
+    ['PC.355', 'AACTCGTCGATG', 'YATGCTGCCTCCCGTAGGAGT', 'Control', 20061218,
+     'Control_mouse_I.D._355'],
+    ['PC.356', 'ACAGACCACTCA', 'YATGCTGCCTCCCGTAGGAGT', 'Control', 20061126,
+     'Control_mouse_I.D._356'],
+    ['PC.481', 'ACCAGCGACTAG', 'YATGCTGCCTCCCGTAGGAGT', 'Control', 20070314,
+     'Control_mouse_I.D._481'],
+    ['PC.593', 'AGCAGCACTTGT', 'YATGCTGCCTCCCGTAGGAGT', 'Control', 20071210,
+     'Control_mouse_I.D._593'],
+    ['PC.607', 'AACTGTGCGTAC', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', 20071112,
+     'Fasting_mouse_I.D._607'],
+    ['PC.634', 'ACAGAGTCGGCT', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', 20080116,
+     'Fasting_mouse_I.D._634'],
+    ['PC.635', 'ACCGCAGAGTCA', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', 20080116,
+     'Fasting_mouse_I.D._635'],
+    ['PC.636', 'ACGGTGAGTGTC', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', 20080116,
+     'Fasting_mouse_I.D._636']]
 
 PRE_PROCESS_A = [
-    ['PC.354','AGCACGAGCCTA', 'Control','20061218'],
-    ['PC.355','AACTCGTCGATG', 'Control','20061218'],
-    ['PC.356','ACAGACCACTCA', 'Control','20061126'],
-    ['PC.481','ACCAGCGACTAG', 'Control','20070314'],
-    ['PC.593','AGCAGCACTTGT', 'Control','20071210'],
-    ['PC.607','AACTGTGCGTAC', 'Fast','20071112'],
-    ['PC.634','ACAGAGTCGGCT', 'Fast','20080116'],
-    ['PC.635','ACCGCAGAGTCA', 'Fast','20080116'],
-    ['PC.636','ACGGTGAGTGTC', 'Fast','20080116']]
+    ['PC.354', 'AGCACGAGCCTA', 'Control', '20061218'],
+    ['PC.355', 'AACTCGTCGATG', 'Control', '20061218'],
+    ['PC.356', 'ACAGACCACTCA', 'Control', '20061126'],
+    ['PC.481', 'ACCAGCGACTAG', 'Control', '20070314'],
+    ['PC.593', 'AGCAGCACTTGT', 'Control', '20071210'],
+    ['PC.607', 'AACTGTGCGTAC', 'Fast', '20071112'],
+    ['PC.634', 'ACAGAGTCGGCT', 'Fast', '20080116'],
+    ['PC.635', 'ACCGCAGAGTCA', 'Fast', '20080116'],
+    ['PC.636', 'ACGGTGAGTGTC', 'Fast', '20080116']]
 
 PRE_PROCESS_B = [
     ['PC.354', 'YATGCTGCCTCCCGTAGGAGT', 'Control_mouse_I.D._354'],
@@ -379,31 +624,31 @@ PRE_PROCESS_B = [
     ['PC.636', 'YATGCTGCCTCCCGTAGGAGT', 'Fasting_mouse_I.D._636']]
 
 MAPPING_FILE_DATA_CAT_A = [
-    ['PC.354', 'Control','20061218', 'Control20061218'],
-    ['PC.355', 'Control','20061218', 'Control20061218'],
-    ['PC.356', 'Control','20061126', 'Control20061126'],
-    ['PC.481', 'Control','20070314', 'Control20070314'],
-    ['PC.593', 'Control','20071210', 'Control20071210'],
-    ['PC.607', 'Fast','20071112', 'Fast20071112'],
-    ['PC.634', 'Fast','20080116', 'Fast20080116'],
-    ['PC.635', 'Fast','20080116', 'Fast20080116'],
-    ['PC.636', 'Fast','20080116', 'Fast20080116']]
+    ['PC.354', 'Control', '20061218', 'Control20061218'],
+    ['PC.355', 'Control', '20061218', 'Control20061218'],
+    ['PC.356', 'Control', '20061126', 'Control20061126'],
+    ['PC.481', 'Control', '20070314', 'Control20070314'],
+    ['PC.593', 'Control', '20071210', 'Control20071210'],
+    ['PC.607', 'Fast', '20071112', 'Fast20071112'],
+    ['PC.634', 'Fast', '20080116', 'Fast20080116'],
+    ['PC.635', 'Fast', '20080116', 'Fast20080116'],
+    ['PC.636', 'Fast', '20080116', 'Fast20080116']]
 
 MAPPING_FILE_DATA_CAT_B = [
-    ['PC.354', 'Control','20061218', '20061218Control'],
-    ['PC.355', 'Control','20061218', '20061218Control'],
-    ['PC.356', 'Control','20061126', '20061126Control'],
-    ['PC.481', 'Control','20070314', '20070314Control'],
-    ['PC.593', 'Control','20071210', '20071210Control'],
-    ['PC.607', 'Fast','20071112', '20071112Fast'],
-    ['PC.634', 'Fast','20080116', '20080116Fast'],
-    ['PC.635', 'Fast','20080116', '20080116Fast'],
-    ['PC.636', 'Fast','20080116', '20080116Fast']]
-
-MAPPING_FILE_DATA_CAT_C = [['PC.354', 'Control'], ['PC.355', 'Control'],
-    ['PC.356', 'Control'], ['PC.481', 'Control'], ['PC.593', 'Control'],
-    ['PC.607', 'Fast'], ['PC.634', 'Fast'], ['PC.635', 'Fast'],
-    ['PC.636', 'Fast']]
+    ['PC.354', 'Control', '20061218', '20061218Control'],
+    ['PC.355', 'Control', '20061218', '20061218Control'],
+    ['PC.356', 'Control', '20061126', '20061126Control'],
+    ['PC.481', 'Control', '20070314', '20070314Control'],
+    ['PC.593', 'Control', '20071210', '20071210Control'],
+    ['PC.607', 'Fast', '20071112', '20071112Fast'],
+    ['PC.634', 'Fast', '20080116', '20080116Fast'],
+    ['PC.635', 'Fast', '20080116', '20080116Fast'],
+    ['PC.636', 'Fast', '20080116', '20080116Fast']]
+
+MAPPING_FILE_DATA_CAT_C = [
+    ['PC.354', 'Control'], ['PC.355', 'Control'], ['PC.356', 'Control'],
+    ['PC.481', 'Control'], ['PC.593', 'Control'], ['PC.607', 'Fast'],
+    ['PC.634', 'Fast'], ['PC.635', 'Fast'], ['PC.636', 'Fast']]
 
 MAPPING_FILE_DATA_CAT_D = [
     ['PC.354', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061218'],
@@ -417,11 +662,16 @@ MAPPING_FILE_DATA_CAT_D = [
     ['PC.636', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116']]
 
 MAPPING_FILE_DATA_CAT_E = [
-    ['PC.354', 'AGCACGAGCCTA', 'Control', '20061218', 'Control_mouse_I.D._354'],
-    ['PC.355', 'AACTCGTCGATG', 'Control', '20061218', 'Control_mouse_I.D._355'],
-    ['PC.356', 'ACAGACCACTCA', 'Control', '20061126', 'Control_mouse_I.D._356'],
-    ['PC.481', 'ACCAGCGACTAG', 'Control', '20070314', 'Control_mouse_I.D._481'],
-    ['PC.593', 'AGCAGCACTTGT', 'Control', '20071210', 'Control_mouse_I.D._593'],
+    ['PC.354', 'AGCACGAGCCTA', 'Control', '20061218',
+     'Control_mouse_I.D._354'],
+    ['PC.355', 'AACTCGTCGATG', 'Control', '20061218',
+     'Control_mouse_I.D._355'],
+    ['PC.356', 'ACAGACCACTCA', 'Control', '20061126',
+     'Control_mouse_I.D._356'],
+    ['PC.481', 'ACCAGCGACTAG', 'Control', '20070314',
+     'Control_mouse_I.D._481'],
+    ['PC.593', 'AGCAGCACTTGT', 'Control', '20071210',
+     'Control_mouse_I.D._593'],
     ['PC.607', 'AACTGTGCGTAC', 'Fast', '20071112', 'Fasting_mouse_I.D._607'],
     ['PC.634', 'ACAGAGTCGGCT', 'Fast', '20080116', 'Fasting_mouse_I.D._634'],
     ['PC.635', 'ACCGCAGAGTCA', 'Fast', '20080116', 'Fasting_mouse_I.D._635'],
@@ -438,39 +688,71 @@ MAPPING_FILE_DATA_CAT_F = [
     ['PC.635', 'Fast', 'Fast20080116'],
     ['PC.636', 'Fast', 'Fast20080116']]
 
+MAPPING_FILE_DATA_CAT_G = [
+    ['PC.354', 'AGCACGAGCCTA', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061218',
+     'Control_mouse_I.D._354'],
+    ['PC.355', 'AACTCGTCGATG', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061218',
+     'Control_mouse_I.D._355'],
+    ['PC.356', 'ACAGACCACTCA', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061126',
+     'Control_mouse_I.D._356'],
+    ['PC.481', 'ACCAGCGACTAG', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20070314',
+     'Control_mouse_I.D._481'],
+    ['PC.593', 'AGCAGCACTTGT', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20071210',
+     'Control_mouse_I.D._593'],
+    ['PC.607', 'AACTGTGCGTAC', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20071112',
+     'Fasting_mouse_I.D._607'],
+    ['PC.634', 'ACAGAGTCGGCT', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116',
+     'Fasting_mouse_I.D._634'],
+    ['PC.635', 'ACCGCAGAGTCA', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116',
+     'Fasting_mouse_I.D._635'],
+    ['PC.636', 'ACGGTGAGTGTC', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116',
+     'Fasting_mouse_I.D._636']]
+
+MAPPING_FILE_DATA_CAT_H = [
+    ['PC.354', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061218'],
+    ['PC.355', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061218'],
+    ['PC.356', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20061126'],
+    ['PC.481', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20070314'],
+    ['PC.593', 'YATGCTGCCTCCCGTAGGAGT', 'Control', '20071210'],
+    ['PC.607', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20071112'],
+    ['PC.634', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116'],
+    ['PC.635', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116'],
+    ['PC.636', 'YATGCTGCCTCCCGTAGGAGT', 'Fast', '20080116']]
+
 MAPPING_FILE_DATA_GRADIENT = [
-    ['PC.354', 'Control','3', '40', 'Control20061218'],
-    ['PC.355', 'Control','9', '44', 'Control20061218'],
-    ['PC.635', 'Fast','9', '44', 'Fast20080116'],
-    ['PC.636', 'Fast','12', '37.22', 'Fast20080116']]
-
-MAPPING_FILE_DATA_DUPLICATED = [['PC.354_0', 'Control', '20061218'],
-['PC.355_0', 'Control', '20061218'],
-['PC.356_0', 'Control', '20061126'],
-['PC.481_0', 'Control', '20070314'],
-['PC.593_0', 'Control', '20071210'],
-['PC.607_0', 'Fast', '20071112'],
-['PC.634_0', 'Fast', '20080116'],
-['PC.635_0', 'Fast', '20080116'],
-['PC.636_0', 'Fast', '20080116'],
-['PC.354_1', 'Control', '20061218'],
-['PC.355_1', 'Control', '20061218'],
-['PC.356_1', 'Control', '20061126'],
-['PC.481_1', 'Control', '20070314'],
-['PC.593_1', 'Control', '20071210'],
-['PC.607_1', 'Fast', '20071112'],
-['PC.634_1', 'Fast', '20080116'],
-['PC.635_1', 'Fast', '20080116'],
-['PC.636_1', 'Fast', '20080116'],
-['PC.354_2', 'Control', '20061218'],
-['PC.355_2', 'Control', '20061218'],
-['PC.356_2', 'Control', '20061126'],
-['PC.481_2', 'Control', '20070314'],
-['PC.593_2', 'Control', '20071210'],
-['PC.607_2', 'Fast', '20071112'],
-['PC.634_2', 'Fast', '20080116'],
-['PC.635_2', 'Fast', '20080116'],
-['PC.636_2', 'Fast', '20080116']]
+    ['PC.354', 'Control', '3', '40', 'Control20061218'],
+    ['PC.355', 'Control', '9', '44', 'Control20061218'],
+    ['PC.635', 'Fast', '9', '44', 'Fast20080116'],
+    ['PC.636', 'Fast', '12', '37.22', 'Fast20080116']]
+
+MAPPING_FILE_DATA_DUPLICATED = [
+    ['PC.354_0', 'Control', '20061218'],
+    ['PC.355_0', 'Control', '20061218'],
+    ['PC.356_0', 'Control', '20061126'],
+    ['PC.481_0', 'Control', '20070314'],
+    ['PC.593_0', 'Control', '20071210'],
+    ['PC.607_0', 'Fast', '20071112'],
+    ['PC.634_0', 'Fast', '20080116'],
+    ['PC.635_0', 'Fast', '20080116'],
+    ['PC.636_0', 'Fast', '20080116'],
+    ['PC.354_1', 'Control', '20061218'],
+    ['PC.355_1', 'Control', '20061218'],
+    ['PC.356_1', 'Control', '20061126'],
+    ['PC.481_1', 'Control', '20070314'],
+    ['PC.593_1', 'Control', '20071210'],
+    ['PC.607_1', 'Fast', '20071112'],
+    ['PC.634_1', 'Fast', '20080116'],
+    ['PC.635_1', 'Fast', '20080116'],
+    ['PC.636_1', 'Fast', '20080116'],
+    ['PC.354_2', 'Control', '20061218'],
+    ['PC.355_2', 'Control', '20061218'],
+    ['PC.356_2', 'Control', '20061126'],
+    ['PC.481_2', 'Control', '20070314'],
+    ['PC.593_2', 'Control', '20071210'],
+    ['PC.607_2', 'Fast', '20071112'],
+    ['PC.634_2', 'Fast', '20080116'],
+    ['PC.635_2', 'Fast', '20080116'],
+    ['PC.636_2', 'Fast', '20080116']]
 
 COORDS_DATA = array([
     [-0.2, -0.1, 0.06, -0.06],
@@ -479,23 +761,28 @@ COORDS_DATA = array([
     [0.04, -0.01, 0.06, -0.34]])
 
 BROKEN_MAPPING_FILE = [
-    ['PC.354', 'Control','3', '40', 'Control20061218'],
-    ['PC.355', 'Control','y', '44', 'Control20061218'],
-    ['PC.635', 'Fast','9', 'x', 'Fast20080116'],
-    ['PC.636', 'Fast','12', '37.22', 'Fast20080116']]
-    
+    ['PC.354', 'Control', '3', '40', 'Control20061218'],
+    ['PC.355', 'Control', 'y', '44', 'Control20061218'],
+    ['PC.635', 'Fast', '9', 'x', 'Fast20080116'],
+    ['PC.636', 'Fast', '12', '37.22', 'Fast20080116']]
+
 BROKEN_MAPPING_FILE_2_VALUES = [
-    ['PC.354', 'Control','3', '40', 'Control20061218'],
-    ['PC.355', 'Control','NA', '44', 'Control20061218'],
+    ['PC.354', 'Control', '3', '40', 'Control20061218'],
+    ['PC.355', 'Control', 'NA', '44', 'Control20061218'],
     ['PC.635', 'Fast', 'NA', 'x', 'Fast20080116'],
-    ['PC.636', 'Fast','12', '37.22', 'Fast20080116']]
+    ['PC.636', 'Fast', '12', '37.22', 'Fast20080116']]
 
 UNSANITZIED_MAPPING_DATA = [
-['PC.354', "Dr. Bronner's", 'Cont"rol', '20061218', 'Control_mouse_I.D._354'],
-['PC.355', 'AACTCGTCGATG', "Con''trol", '20061218', 'Control_mouse_I.D._355'],
-["PC'356", 'ACAGACCACTCA', 'Control', '20061126', 'Control_mouse_I.D._"356'],
-['PC.481', 'AC"AGC"ACTAG', 'Control', '20070314', 'Control_mouse_I.D._481'],
-['PC.593', 'AGCAGCACTTGT', 'Control', '20071210', 'Control_mouse_I.D._593']]
+    ['PC.354', "Dr. Bronner's", 'Cont"rol', '20061218',
+     'Control_mouse_I.D._354'],
+    ['PC.355', 'AACTCGTCGATG', "Con''trol", '20061218',
+     'Control_mouse_I.D._355'],
+    ["PC'356", 'ACAGACCACTCA', 'Control', '20061126',
+     'Control_mouse_I.D._"356'],
+    ['PC.481', 'AC"AGC"ACTAG', 'Control', '20070314',
+     'Control_mouse_I.D._481'],
+    ['PC.593', 'AGCAGCACTTGT', 'Control', '20071210',
+     'Control_mouse_I.D._593']]
 
 if __name__ == "__main__":
     main()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/emperor.git



More information about the debian-med-commit mailing list